Dart Cookbook
上QQ阅读APP看书,第一时间看更新

Unit testing a Polymer web app

A project should contain a number of automated tests that can be run after every code change to ensure that the previous functionality still works. Dart's unittest framework is the best tool for the job, and the Dart website has some excellent articles to get you started. However, testing Polymer web applications is a lot trickier because of the way Polymer works, as it hides HTML in shadow DOM and also because it works in an asynchronous fashion, independent of the testing code.

Getting ready

We will create some tests in the ClickCounter example (the standard web application template using the polymer library). You can find the code in the polymer1 app. We include the unittest library in the pubspec.yaml file, and create a test folder.

How to do it...

In the test folder, we create a test_polymer1.html page; a web page that loads the Polymer component required to test this functionality. The following is the minimum content required for the component:

<head>
    <title>test_polymer1</title>
 <link rel="import" href="../web/polymer1.html">
 <script type="application/dart" src="test_polymer1.dart"></script>
   </head>

test_polymer1.dart contains the test script:
import 'package:unittest/unittest.dart';
import 'dart:html';
import 'package:polymer/polymer.dart';
import '../web/clickcounter.dart';

main() {
 initPolymer();
  var _el;

  setUp((){
 _el = createElement('<click-counter>Click counter test</click-counter>');
    document.body.append(_el);
  });

  tearDown((){
    _el.remove();
  });

  // tests:
   test('shadowroot elements are created', (){
expect(querySelector('click-counter').children, isNotNull); 
expect(querySelector('click-counter').shadowRoot.text, isNotNull);
  });
   test('initial text ok', (){
 expect(querySelector('click-counter').shadowRoot.text.contains('click count: 0'), isTrue);
    });
   // test button with text Transaction:
   test('button with id click exists', (){
var button = querySelector('click-counter').shadowRoot.querySelector('#click');
 expect(button, isNotNull);
     });
   test('button click() increments counter', (){
ButtonElement button = querySelector('click-counter').shadowRoot.querySelector('#click');
         button.click();
         button.click();
         button.click();
         // get counter value:
         ClickCounter cc = querySelector('click-counter');
         expect(cc.count, 3);  // after 3 clicks
   });
}

createElement(String html) =>
  new Element.html(html, treeSanitizer: new NullTreeSanitizer());

class NullTreeSanitizer implements NodeTreeSanitizer {
  void sanitizeTree(node) {}
}

When the script is run, the following output appears:

unittest-suite-wait-for-done

PASS: shadowroot elements are created

PASS: initial text ok

PASS: button with id click exists

PASS: button click() increments counter

All 4 tests passed.

unittest-suite-success

How it works...

The test web page loads the Polymer component, and the test script loads the unittest and polymer packages and component classes (clickcounter.dart). In main(), we load the polymer package with initPolymer(); in setup(), we use a helper method createElement(), with an HTML string containing the polymer tag <clickcounter> as argument to instantiate the Polymer component and add it to the page. This was done in order to avoid the default HTML sanitization createElement(), which uses a null sanitizer instead of the built-in sanitizer (refer to Chapter 5, Handling Web Applications, for more information on this topic). Then, we start testing, for example:

  • expect(querySelector('click-counter').children, isNotNull); so that the Polymer component tree is created
  • var button = querySelector('click-counter').shadowRoot.querySelector('#click'); expect(button, isNotNull); so that the button with the ID 'click' is created
  • expect(querySelector('click-counter').shadowRoot.text.contains('click count: 0'), isTrue); so that the text initially displayed is 'click count: 0'.

Notice how we have to dig into shadowRoot of the Polymer component to get this information as follows:

  • Verify that after clicking the button three times invoked by button.click(), our count property has the value 3:
    ClickCounter cc = querySelector('click-counter');
    expect(cc.count, 3);

See also

  • To discover more information about the Dart unittest library, refer to the book Learning Dart, Ivo Balbaert, Dzenan Ridjanovic, Packt Publishing, or the excellent articles at background knowledge and information on how to extend the use of Dart Unittest in your own work.