I remain skeptical that Page Objects are a good idea for long term maintenance of a test suite. But after last night, they sure seem like they can come in handy.
So tonight, I give them a try in my Dart test suite for a simple
<x-pizza> Polymer element:
I start a new test.dart with a Page Object wrapper for
<x-pizza> elements. To begin with, I only need a getter that extracts the current pizza state from a pre#state element inside the Polymer element:class XPizzaComponent {
PolymerElement el;
XPizzaComponent(this.el);
String get currentPizzaStateDisplay => el.$['state'].text;
}
Then, I do the usual Polymer.dart test setup, calling initPolymer(), adding my <x-pizza> element to the test page, and finally creating a Page Objects instance:main() {
initPolymer();
PolymerElement _el;
XPizzaComponent xPizza;
setUp((){
_el = createElement('<x-pizza></x-pizza>');
document.body.append(_el);
xPizza = new XPizzaComponent(_el);
});
// ...
}With that, I can write my first Page Object test as: group("[defaults]", (){
test('it has no toppings', (){
var no_toppings = JSON.encode({
'firstHalfToppings': [],
'secondHalfToppings': [],
'wholeToppings': []
});
expect(
xPizza.currentPizzaStateDisplay,
no_toppings
);
});
});That fails because this is an older version of the Polymer element that is not JSON encoding the pizza state:CONSOLE MESSAGE: FAIL: [defaults] it has no toppigns
Expected: '{"firstHalfToppings":[],"secondHalfToppings":[],"wholeToppings":[]}'
Actual: 'First Half: []
'
'Second Half: []
' To get the test passing, I update my Polymer class to properly JSON encode the pizza state:import 'package:polymer/polymer.dart';
import 'dart:convert';
@CustomTag('x-pizza')
class XPizza extends PolymerElement {
// ...
Pizza model;
@observable String pizzaState;
XPizza.created(): super.created() {
// ...
updatePizzaState();
}
updatePizzaState([_]) {
pizzaState = JSON.encode({
'firstHalfToppings': model.firstHalfToppings,
'secondHalfToppings': model.secondHalfToppings,
'wholeToppings': model.wholeToppings
});
}
// ...
}Now comes the fun part.I need to be able to select items from the
<select> list in my Polymer element. That was a pain in the JavaScript version of this element. Thankfully, the Page Object version of the addWholeTopping() method in Dart is pretty straight-forward. At least, it is straight-forward having the JavaScript version to reference. The Dart version is:class XPizzaComponent {
PolymerElement el;
XPizzaComponent(this.el);
String get currentPizzaStateDisplay => el.$['state'].text;
XPizzaComponent addWholeTopping(String topping) {
var toppings = el.$['wholeToppings'],
select = toppings.query('select'),
button = toppings.query('button');
var index = -1;
for (var i=0; i<select.length; i++) {
if (select.options[i].value == topping) index = i;
}
select.selectedIndex = index;
var event = new Event.eventType('Event', 'change');
select.dispatchEvent(event);
button.click();
return this;
}
}
That is more or less copied-and-pasted from the JavaScript version of the Page Object. As in JavaScript, I find that I have to dispatch a change event to the <select> element. That aside, this method is straight procedural code selecting an item and clicking a button.Armed with that, I can write the next test as:
group("[adding toppings]", (){
setUp((){
var _completer = new Completer();
Timer.run(_completer.complete);
return _completer.future;
});
test('updates the pizza state accordingly', (){
xPizza.addWholeTopping('green peppers');
var toppings = JSON.encode({
'firstHalfToppings': [],
'secondHalfToppings': [],
'wholeToppings': ['green peppers']
});
new Timer(
new Duration(milliseconds: 100),
expectAsync((){
expect(
xPizza.currentPizzaStateDisplay,
toppings
);
})
);
});
});As I found in the JavaScript version of the tests, I have to introduce some minor time delays to allow the Polymer element to draw or update itself. But with carefully placed Timer runs, I have a second passing test:PASS: [defaults] it has no toppings PASS: [adding toppings] updates the pizza state accordinglyThose
Timer delays are a little on the ugly side, but Page Objects again play very well with testing my Polymer element. There may be something to these Page Object things after all.Day #10
No comments:
Post a Comment