Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Unified Diff: lib/src/runner/browser/iframe_listener.dart

Issue 1704773002: Load web tests using the plugin infrastructure. (Closed) Base URL: git@github.com:dart-lang/test@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/src/runner/browser/iframe_listener.dart
diff --git a/lib/src/runner/browser/iframe_listener.dart b/lib/src/runner/browser/iframe_listener.dart
deleted file mode 100644
index 9e49dfca4930456279920dd682bb7e17c5ff96b4..0000000000000000000000000000000000000000
--- a/lib/src/runner/browser/iframe_listener.dart
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:html' hide Metadata;
-
-import 'package:stream_channel/stream_channel.dart';
-
-import '../../backend/declarer.dart';
-import '../../backend/group.dart';
-import '../../backend/live_test.dart';
-import '../../backend/metadata.dart';
-import '../../backend/suite.dart';
-import '../../backend/test.dart';
-import '../../backend/test_platform.dart';
-import '../../util/remote_exception.dart';
-import '../../utils.dart';
-
-/// A class that runs tests in a separate iframe.
-///
-/// This indirectly communicates with the test server. It uses `postMessage` to
-/// relay communication through the host page, which has a WebSocket connection
-/// to the test server.
-class IframeListener {
- /// The test suite to run.
- final Suite _suite;
-
- /// Extracts metadata about all the tests in the function returned by
- /// [getMain] and sends information about them over the `postMessage`
- /// connection.
- ///
- /// The main function is wrapped in a closure so that we can handle it being
- /// undefined here rather than in the generated code.
- ///
- /// Once that's done, this starts listening for commands about which tests to
- /// run.
- static Future start(Function getMain()) async {
- var channel = _postMessageChannel();
-
- // Send periodic pings to the test runner so it can know when the suite is
- // paused for debugging.
- new Timer.periodic(new Duration(seconds: 1),
- (_) => channel.sink.add({"type": "ping"}));
-
- var main;
- try {
- main = getMain();
- } on NoSuchMethodError catch (_) {
- _sendLoadException(channel, "No top-level main() function defined.");
- return;
- }
-
- if (main is! Function) {
- _sendLoadException(channel, "Top-level main getter is not a function.");
- return;
- } else if (main is! AsyncFunction) {
- _sendLoadException(channel, "Top-level main() function takes arguments.");
- return;
- }
-
- var url = Uri.parse(window.location.href);
- var message = JSON.decode(Uri.decodeFull(url.fragment));
- var metadata = new Metadata.deserialize(message['metadata']);
-
- var declarer = new Declarer(metadata);
- try {
- await declarer.declare(() {
- return runZoned(() => new Future.sync(main),
- zoneSpecification: new ZoneSpecification(print: (_, __, ___, line) {
- channel.sink.add({"type": "print", "line": line});
- }));
- });
- } catch (error, stackTrace) {
- channel.sink.add({
- "type": "error",
- "error": RemoteException.serialize(error, stackTrace)
- });
- return;
- }
-
- var browser = TestPlatform.find(message['browser']);
- var suite = new Suite(declarer.build(), platform: browser);
- new IframeListener._(suite)._listen(channel);
-
- return;
- }
-
- /// Constructs a [MultiChannel] wrapping the `postMessage` communication with
- /// the host page.
- ///
- /// This [MultiChannel] corresponds to a [MultiChannel] in the server's
- /// [IframeTest] class.
- static MultiChannel _postMessageChannel() {
- var inputController = new StreamController(sync: true);
- var outputController = new StreamController(sync: true);
-
- window.onMessage.listen((message) {
- // A message on the Window can theoretically come from any website. It's
- // very unlikely that a malicious site would care about hacking someone's
- // unit tests, let alone be able to find the test server while it's
- // running, but it's good practice to check the origin anyway.
- if (message.origin != window.location.origin) return;
- message.stopPropagation();
- inputController.add(message.data);
- });
-
- outputController.stream.listen((data) {
- // TODO(nweiz): Stop manually adding href here once issue 22554 is
- // fixed.
- window.parent.postMessage({
- "href": window.location.href,
- "data": data
- }, window.location.origin);
- });
-
- return new MultiChannel(new StreamChannel(
- inputController.stream, outputController.sink));
- }
-
- /// Sends a message over [channel] indicating that the tests failed to load.
- ///
- /// [message] should describe the failure.
- static void _sendLoadException(MultiChannel channel, String message) {
- channel.sink.add({"type": "loadException", "message": message});
- }
-
- IframeListener._(this._suite);
-
- /// Send information about [_suite] across [channel] and start listening for
- /// commands to run the tests.
- void _listen(MultiChannel channel) {
- channel.sink.add({
- "type": "success",
- "root": _serializeGroup(channel, _suite.group, [])
- });
- }
-
- /// Serializes [group] into a JSON-safe map.
- ///
- /// [parents] lists the groups that contain [group].
- Map _serializeGroup(MultiChannel channel, Group group,
- Iterable<Group> parents) {
- parents = parents.toList()..add(group);
- return {
- "type": "group",
- "name": group.name,
- "metadata": group.metadata.serialize(),
- "setUpAll": _serializeTest(channel, group.setUpAll, parents),
- "tearDownAll": _serializeTest(channel, group.tearDownAll, parents),
- "entries": group.entries.map((entry) {
- return entry is Group
- ? _serializeGroup(channel, entry, parents)
- : _serializeTest(channel, entry, parents);
- }).toList()
- };
- }
-
- /// Serializes [test] into a JSON-safe map.
- ///
- /// [groups] lists the groups that contain [test]. Returns `null` if [test]
- /// is `null`.
- Map _serializeTest(MultiChannel channel, Test test, Iterable<Group> groups) {
- if (test == null) return null;
-
- var testChannel = channel.virtualChannel();
- testChannel.stream.listen((message) {
- assert(message['command'] == 'run');
- _runLiveTest(
- test.load(_suite, groups: groups),
- channel.virtualChannel(message['channel']));
- });
-
- return {
- "type": "test",
- "name": test.name,
- "metadata": test.metadata.serialize(),
- "channel": testChannel.id
- };
- }
-
- /// Runs [liveTest] and sends the results across [channel].
- void _runLiveTest(LiveTest liveTest, MultiChannel channel) {
- channel.stream.listen((message) {
- assert(message['command'] == 'close');
- liveTest.close();
- });
-
- liveTest.onStateChange.listen((state) {
- channel.sink.add({
- "type": "state-change",
- "status": state.status.name,
- "result": state.result.name
- });
- });
-
- liveTest.onError.listen((asyncError) {
- channel.sink.add({
- "type": "error",
- "error": RemoteException.serialize(
- asyncError.error, asyncError.stackTrace)
- });
- });
-
- liveTest.onPrint.listen((line) {
- print(line);
- channel.sink.add({"type": "print", "line": line});
- });
-
- liveTest.run().then((_) => channel.sink.add({"type": "complete"}));
- }
-}

Powered by Google App Engine
This is Rietveld 408576698