Skip to content

Commit 46708ff

Browse files
committed
Add special-case support for Polymer tests.
Polymer tests use a special wrapper that we need to be aware of. Closes #128 [email protected] Review URL: https://codereview.chromium.org//1152083008
1 parent cebcb3d commit 46708ff

File tree

4 files changed

+128
-1
lines changed

4 files changed

+128
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
string. This allows such errors to be captured using the Zone API and improves
66
formatting.
77

8+
* Improve support for Polymer tests. This fixes a flaky time-out error and adds
9+
support for Dartifying JavaScript stack traces when running Polymer tests via
10+
`pub serve`.
11+
812
* In order to be more extensible, all exception handling within tests now uses
913
the Zone API.
1014

lib/src/runner/browser/polymer.dart

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
library test.runner.browser.polymer;
6+
7+
import 'dart:io';
8+
9+
import 'package:glob/glob.dart';
10+
import 'package:path/path.dart' as p;
11+
import 'package:pub_semver/pub_semver.dart';
12+
import 'package:yaml/yaml.dart';
13+
14+
/// Whether the package being tested uses the Polymer transforemrs at all.
15+
///
16+
/// This will be `null` until [_initialize] is called.
17+
bool _usesPolymer;
18+
19+
/// The set of entry points passed in to the polymer transformer's config.
20+
///
21+
/// This will be `null` if no entrypoints are declared, indicating that all
22+
/// entrypoints are supported.
23+
Set<String> _entrypoints;
24+
25+
/// The $includes for the polymer transformer.
26+
Set<Glob> _includes;
27+
28+
/// The $excludes for the polymer transformer.
29+
Set<Glob> _excludes;
30+
31+
/// Returns whether [path] is an entrypoint transformed by the Polymer
32+
/// transformer.
33+
///
34+
/// The Polymer transformer creates a bootstrapping wrapper script around the
35+
/// entrypoints it's run on, so we need to know that so we can fetch the correct
36+
/// source map file.
37+
bool isPolymerEntrypoint(String path) {
38+
if (_usesPolymer == null) _initialize();
39+
if (!_usesPolymer) return false;
40+
41+
if (_excludes != null) {
42+
// If there are any excludes, it must not match any of them.
43+
for (var exclude in _excludes) {
44+
if (exclude.matches(path)) return false;
45+
}
46+
}
47+
48+
// If there are any includes, it must match one of them.
49+
if (_includes != null && !_includes.any((include) => include.matches(path))) {
50+
return false;
51+
}
52+
53+
if (_entrypoints == null) return true;
54+
return _entrypoints.contains(path);
55+
}
56+
57+
/// Initializes [_usesPolymer], [_entrypoints], [_includes], and [_excludes]
58+
/// based on the contents of the pubspec.
59+
///
60+
/// This doesn't need to do any validation of the pubspec, since pub itself does
61+
/// that before running the test executable.
62+
void _initialize() {
63+
_usesPolymer = false;
64+
65+
var pubspec = loadYaml(new File("pubspec.yaml").readAsStringSync());
66+
67+
var transformers = pubspec['transformers'];
68+
if (transformers == null) {
69+
return;
70+
}
71+
72+
for (var phase in transformers) {
73+
var phases = phase is List ? phase : [phase];
74+
for (var transformer in phases) {
75+
if (transformer is String) {
76+
if (transformer != "polymer") continue;
77+
_usesPolymer = true;
78+
return;
79+
}
80+
81+
if (transformer.keys.single != "polymer") continue;
82+
_usesPolymer = true;
83+
84+
var configuration = transformer.values.single;
85+
86+
var entrypoints = configuration["entry_points"];
87+
if (entrypoints != null) _entrypoints = entrypoints.toSet();
88+
89+
_includes = _parseGlobField(configuration, r"$includes");
90+
_excludes = _parseGlobField(configuration, r"$excludes");
91+
return;
92+
}
93+
}
94+
}
95+
96+
/// Parses a glob field (either `$include` or `$exclude`).
97+
Set<Glob> _parseGlobField(YamlMap configuration, String name) {
98+
if (!configuration.containsKey(name)) return null;
99+
var field = configuration[name];
100+
101+
if (field is String) {
102+
return new Set.from([new Glob(field, context: p.url, recursive: true)]);
103+
}
104+
105+
return new Set.from(field.map((node) {
106+
return new Glob(node, context: p.url, recursive: true);
107+
}));
108+
}

lib/src/runner/browser/server.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import 'dartium.dart';
3636
import 'firefox.dart';
3737
import 'internet_explorer.dart';
3838
import 'phantom_js.dart';
39+
import 'polymer.dart';
3940
import 'safari.dart';
4041

4142
/// A server that serves JS-compiled tests to browsers.
@@ -263,8 +264,21 @@ void main() {
263264
if (_pubServeUrl != null) {
264265
var suitePrefix = p.withoutExtension(
265266
p.relative(path, from: p.join(_root, 'test')));
266-
var jsUrl = _pubServeUrl.resolve(
267+
268+
var jsUrl;
269+
// Polymer generates a bootstrap entrypoint that wraps the entrypoint we
270+
// see on disk, and modifies the HTML file to point to the bootstrap
271+
// instead. To make sure we get the right source maps and wait for the
272+
// right file to compile, we have some Polymer-specific logic here to load
273+
// the boostrap instead of the unwrapped file.
274+
if (isPolymerEntrypoint(path)) {
275+
jsUrl = _pubServeUrl.resolve(
276+
"$suitePrefix.html.polymer.bootstrap.dart.browser_test.dart.js");
277+
} else {
278+
jsUrl = _pubServeUrl.resolve(
267279
'$suitePrefix.dart.browser_test.dart.js');
280+
}
281+
268282
await _pubServeSuite(path, jsUrl);
269283
suiteUrl = _pubServeUrl.resolveUri(p.toUri('$suitePrefix.html'));
270284
} else {

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ dependencies:
1010
args: '>=0.12.1 <0.14.0'
1111
barback: '>=0.14.0 <0.16.0'
1212
crypto: '^0.9.0'
13+
glob: '^1.0.0'
1314
http_multi_server: '^1.0.0'
1415
http_parser: '^0.0.2'
1516
path: '^1.2.0'

0 commit comments

Comments
 (0)