Look, this isn't that hard. In order to test my
<apply-author-styles> Polymer element, I need a test page that:- holds a test Polymer element that uses
<apply-author-styles> - Can run in a server so that XHR request can be made
- Has custom styles that can be pulled from the page into the test custom element
So you know what? I give up. I'm testing with Dart.
I already have Grunt setup in this project, so I stick with it here. In this case, I want a simple static server against which to run my tests (there is a simple Ajax component). I already have that in the form of
grunt-contrib-connect. Now I need a way to run Dart tests against this JavaScript element (yes, I'm serious). Since there is no grunt-contrib-dart yet (why not?!), I install
grunt-shell:$ npm install --save-dev grunt-shellThen I add this to the imported tasks in my
Gruntfile.js and define my test_runner.sh shell task that will run my Dart tests:module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// ...
connect: {
server: {
options: {
port: 8100,
keepalive: false
}
}
},
shell: {
test: {
command: 'test/test_runner.sh'
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.registerTask('default', ['connect', 'shell:test']);
};
The test_runner.sh script is a simple fork of content_shell that comes bundled with Dart for headless testing—but real headless testing with an actual browser. The test_runner.sh script looks like:#!/bin/bash
# Run a set of Dart Unit tests
results=$(content_shell --dump-render-tree http://localhost:8100/test/ 2>&1)
echo -e "$results"
# check to see if DumpRenderTree tests
# fails, since it always returns 0
if [[ "$results" == *"Some tests failed"* ]]
then
exit 1
fi
echo
echo "Looks good!"
OK with that, I have my runner in place. Grunt will start grunt-contrib-connect as part of the default task and content_shell will run my test at http://localhost:8100/test/. Now I just need to define the test.I start with a test context page that *I* can write:
<head>
<!-- Load Polymer -->
<script src="/bower_components/platform/platform.js"></script>
<!-- Load component(s) -->
<link rel="import" href="x-foo.html">
<!-- Style that will apply to both page and Polymer elements -->
<style>
button { border: 5px solid orange; }
</style>
</head>
<body>
<div id=test><!-- Test element -->
<x-foo></x-foo>
</div>
<div id=page><!-- Page element -->
<button type=button>Test in Main Page</button>
</div>
</body>
In there, I have the page style—orange buttons—that I want to apply to my <x-foo> test element that makes use of <apply-author-styles>. The <x-foo> element was defined a couple of days ago as:<link rel="import" href="polymer/polymer.html">
<link rel="import" href="apply-author-styles/apply-author-styles.html">
<polymer-element name="x-foo" noscript>
<template>
<apply-author-styles></apply-author-styles>
<button id=test type=button>Test</button>
</template>
</polymer-element>
That <apply-author-styles> should change the style of the button inside the element (something the old, deprecated applyAuthorStyles Polymer property used to do). I don't need to actually test that the button is orange. I may try that another day, but for now, I just need to know that that page style has been copied to the shadow DOM of my element. Or, in test form:library main_test;
import 'package:scheduled_test/scheduled_test.dart';
import 'dart:html';
main(){
group("[styles]", (){
test('the app returns OK', (){
var xFoo = query('x-foo');
expect(xFoo.shadowRoot.text, contains('orange'));
});
});
}Which does the trick:CONSOLE MESSAGE: unittest-suite-wait-for-done CONSOLE MESSAGE: PASS: [styles] the app returns OK CONSOLE MESSAGE: All 1 tests passed. CONSOLE MESSAGE: unittest-suite-successThat is not quite perfect—there is some discrepancy between running it in the browser and from content_shell that bears some investigation. Still, it is so very nice to have a testing framework that runs in the browser, can test easily against a custom page context, and actually passes.
As crazy as it might seem to run a Dart test runner for JavaScript code, the crazier thing might be fighting ever more obscure JavaScript testing frameworks. So I may end up sticking with this.
Day #98
Soon you too will join the Dart side.
ReplyDelete