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