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

Side by Side Diff: lib/src/runner/browser/server.dart

Issue 979513002: pkg/unittest: Add a server for serving test assets to browsers. (Closed) Base URL: git@github.com:dart-lang/unittest@master
Patch Set: Fix loader_test. Created 5 years, 9 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 unified diff | Download patch
« no previous file with comments | « no previous file | lib/src/runner/browser/static/host.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 unittest.runner.browser.server;
6
7 import 'dart:async';
8 import 'dart:convert';
9 import 'dart:io';
10
11 import 'package:path/path.dart' as p;
12 import 'package:shelf/shelf.dart' as shelf;
13 import 'package:shelf/shelf_io.dart' as shelf_io;
14 import 'package:shelf_static/shelf_static.dart';
15 import 'package:shelf_web_socket/shelf_web_socket.dart';
16
17 import '../../backend/suite.dart';
18 import '../../util/io.dart';
19 import '../../util/one_off_handler.dart';
20 import 'browser_manager.dart';
21 import 'compiler_pool.dart';
22 import 'chrome.dart';
23
24 /// A server that serves JS-compiled tests to browsers.
25 ///
26 /// A test suite may be loaded for a given file using [loadSuite].
27 class BrowserServer {
28 /// Starts the server.
29 ///
30 /// If [packageRoot] is passed, it's used for all package imports when
31 /// compiling tests to JS. Otherwise, the package root is inferred from the
32 /// location of the source file.
33 static Future<BrowserServer> start({String packageRoot}) {
34 var server = new BrowserServer._(packageRoot);
35 return server._load().then((_) => server);
36 }
37
38 /// The underlying HTTP server.
39 HttpServer _server;
40
41 /// The URL for this server.
42 Uri get url => baseUrlForAddress(_server.address, _server.port);
43
44 /// a [OneOffHandler] for servicing WebSocket connections for
45 /// [BrowserManager]s.
46 ///
47 /// This is one-off because each [BrowserManager] can only connect to a single
48 /// WebSocket,
49 final _webSocketHandler = new OneOffHandler();
50
51 /// The [CompilerPool] managing active instances of `dart2js`.
52 final _compilers = new CompilerPool();
53
54 /// The temporary directory in which compiled JS is emitted.
55 final String _compiledDir;
56
57 /// The package root which is passed to `dart2js`.
58 final String _packageRoot;
59
60 /// The browser in which test suites are loaded and run.
61 ///
62 /// This is `null` until a suite is loaded.
63 Chrome _browser;
64
65 /// A future that will complete to the [BrowserManager] for [_browser].
66 ///
67 /// The first time this is called, it will start both the browser and the
68 /// browser manager. Any further calls will return the existing manager.
69 Future<BrowserManager> get _browserManager {
70 if (_browserManagerCompleter == null) {
71 _browserManagerCompleter = new Completer();
72 var path = _webSocketHandler.create(webSocketHandler((webSocket) {
73 _browserManagerCompleter.complete(new BrowserManager(webSocket));
74 }));
75
76 var webSocketUrl = url.replace(scheme: 'ws', path: '/$path');
77 _browser = new Chrome(url.replace(queryParameters: {
78 'managerUrl': webSocketUrl.toString()
79 }));
80
81 // TODO(nweiz): Gracefully handle the browser being killed before the
82 // tests complete.
83 _browser.onExit.catchError((error, stackTrace) {
84 if (_browserManagerCompleter.isCompleted) return;
85 _browserManagerCompleter.completeError(error, stackTrace);
86 });
87 }
88 return _browserManagerCompleter.future;
89 }
90 Completer<BrowserManager> _browserManagerCompleter;
91
92 BrowserServer._(this._packageRoot)
93 : _compiledDir = Directory.systemTemp.createTempSync('unittest_').path;
94
95 /// Starts the underlying server.
96 Future _load() {
97 var cascade = new shelf.Cascade()
98 .add(_webSocketHandler.handler)
99 .add(createStaticHandler(p.join(libDir, 'src/runner/browser/static'),
kevmoo 2015/03/04 20:30:37 Call the method - libDir()
100 defaultDocument: 'index.html'))
101 .add(createStaticHandler(_compiledDir, defaultDocument: 'index.html'));
102
103 return shelf_io.serve(cascade.handler, 'localhost', 0).then((server) {
104 _server = server;
105 });
106 }
107
108 /// Loads the test suite at [path].
109 ///
110 /// This will start a browser to load the suite if one isn't already running.
111 Future<Suite> loadSuite(String path) {
112 return _compileSuite(path).then((dir) {
113 // TODO(nweiz): Don't start the browser until all the suites are compiled.
114 return _browserManager.then((browserManager) {
115 // Add a trailing slash because at least on Chrome, the iframe's
116 // window.location.href will do so automatically, and if that differs
117 // from the original URL communication will fail.
118 var suiteUrl = url.resolve(
119 "/" + p.toUri(p.relative(dir, from: _compiledDir)).path + "/");
120 return browserManager.loadSuite(path, suiteUrl);
121 });
122 });
123 }
124
125 /// Compile the test suite at [dartPath] to JavaScript.
126 ///
127 /// Returns a [Future] that completes to the path to the JavaScript.
128 Future<String> _compileSuite(String dartPath) {
129 var dir = new Directory(_compiledDir).createTempSync('test_').path;
130 var jsPath = p.join(dir, p.basename(dartPath) + ".js");
131 return _compilers.compile(dartPath, jsPath,
132 packageRoot: packageRootFor(dartPath, _packageRoot))
133 .then((_) {
134 // TODO(nweiz): support user-authored HTML files.
135 new File(p.join(dir, "index.html")).writeAsStringSync('''
136 <!DOCTYPE html>
137 <html>
138 <head>
139 <title>${HTML_ESCAPE.convert(dartPath)} Test</title>
140 <script src="${HTML_ESCAPE.convert(p.basename(jsPath))}"></script>
141 </head>
142 </html>
143 ''');
144 return dir;
145 });
146 }
147
148 /// Closes the server and releases all its resources.
149 ///
150 /// Returns a [Future] that completes once the server is closed and its
151 /// resources have been fully released.
152 Future close() {
153 new Directory(_compiledDir).deleteSync(recursive: true);
154 return _server.close().then((_) {
155 if (_browserManagerCompleter == null) return null;
156 return _browserManager.then((_) => _browser.close());
157 });
158 }
159 }
OLDNEW
« no previous file with comments | « no previous file | lib/src/runner/browser/static/host.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698