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

Side by Side Diff: pkg/unittest/lib/interactive_html_config.dart

Issue 12598008: pkg/unittest: fixed deprecations in alt configs (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: variable name tweaks Created 7 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 | Annotate | Revision Log
« no previous file with comments | « pkg/unittest/lib/html_layout_config.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * This configuration can be used to rerun selected tests, as well 6 * This configuration can be used to rerun selected tests, as well
7 * as see diagnostic output from tests. It runs each test in its own 7 * as see diagnostic output from tests. It runs each test in its own
8 * IFrame, so the configuration consists of two parts - a 'parent' 8 * IFrame, so the configuration consists of two parts - a 'parent'
9 * config that manages all the tests, and a 'child' config for the 9 * config that manages all the tests, and a 'child' config for the
10 * IFrame that runs the individual tests. 10 * IFrame that runs the individual tests.
11 */ 11 */
12 library unittest_interactive_html_config; 12 library unittest_interactive_html_config;
13 13
14 // TODO(gram) - add options for: remove IFrame on done/keep 14 // TODO(gram) - add options for: remove IFrame on done/keep
15 // IFrame for failed tests/keep IFrame for all tests. 15 // IFrame for failed tests/keep IFrame for all tests.
16 16
17 import 'dart:html'; 17 import 'dart:html';
18 import 'dart:async';
18 import 'dart:math'; 19 import 'dart:math';
19 import 'unittest.dart'; 20 import 'unittest.dart';
20 21
21 /** The messages exchanged between parent and child. */ 22 /** The messages exchanged between parent and child. */
22 23
23 class _Message { 24 class _Message {
24 static const START = 'start'; 25 static const START = 'start';
25 static const LOG = 'log'; 26 static const LOG = 'log';
26 static const STACK = 'stack'; 27 static const STACK = 'stack';
27 static const PASS = 'pass'; 28 static const PASS = 'pass';
(...skipping 18 matching lines...) Expand all
46 elapsed = int.parse(msg.substring(idx, idx2)); 47 elapsed = int.parse(msg.substring(idx, idx2));
47 ++idx2; 48 ++idx2;
48 body = msg.substring(idx2); 49 body = msg.substring(idx2);
49 } 50 }
50 51
51 String toString() => text(messageType, elapsed, body); 52 String toString() => text(messageType, elapsed, body);
52 } 53 }
53 54
54 55
55 class HtmlConfiguration extends Configuration { 56 class HtmlConfiguration extends Configuration {
56 // TODO(rnystrom): Get rid of this if we get canonical closures for methods. 57 StreamSubscription _errorSubscription;
57 EventListener _onErrorClosure;
58 58
59 void _installErrorHandler() { 59 void _installErrorHandler() {
60 if (_onErrorClosure == null) { 60 if (_errorSubscription == null) {
61 _onErrorClosure = 61 assert(_errorSubscription == null);
gram 2013/03/12 22:44:46 This assert seems superfluous, given the if guard.
62 (e) => handleExternalError(e, '(DOM callback has errors)'); 62
63 // Listen for uncaught errors. 63 // Listen for uncaught errors.
64 window.on.error.add(_onErrorClosure); 64 _errorSubscription = window.onError.listen((e) {
65 handleExternalError(e, '(DOM callback has errors)');
66 });
65 } 67 }
66 } 68 }
67 69
68 void _uninstallErrorHandler() { 70 void _uninstallErrorHandler() {
69 if (_onErrorClosure != null) { 71 if (_errorSubscription != null) {
70 window.on.error.remove(_onErrorClosure); 72 _errorSubscription.cancel();
71 _onErrorClosure = null; 73 _errorSubscription = null;
72 } 74 }
73 } 75 }
74 } 76 }
75 77
76 /** 78 /**
77 * The child configuration that is used to run individual tests in 79 * The child configuration that is used to run individual tests in
78 * an IFrame and post the results back to the parent. In principle 80 * an IFrame and post the results back to the parent. In principle
79 * this can run more than one test in the IFrame but currently only 81 * this can run more than one test in the IFrame but currently only
80 * one is used. 82 * one is used.
81 */ 83 */
82 class ChildInteractiveHtmlConfiguration extends HtmlConfiguration { 84 class ChildInteractiveHtmlConfiguration extends HtmlConfiguration {
83 85
84 /** The window to which results must be posted. */ 86 /** The window to which results must be posted. */
85 Window parentWindow; 87 WindowBase parentWindow;
86 88
87 /** The time at which tests start. */ 89 /** The time at which tests start. */
88 Map<int,DateTime> _testStarts; 90 Map<int,DateTime> _testStarts;
89 91
90 ChildInteractiveHtmlConfiguration() : 92 ChildInteractiveHtmlConfiguration() :
91 _testStarts = new Map<int,DateTime>(); 93 _testStarts = new Map<int,DateTime>();
92 94
93 /** Don't start running tests automatically. */ 95 /** Don't start running tests automatically. */
94 get autoStart => false; 96 get autoStart => false;
95 97
96 void onInit() { 98 void onInit() {
97 _installErrorHandler(); 99 _installErrorHandler();
98 100
99 /** 101 /**
100 * The parent posts a 'start' message to kick things off, 102 * The parent posts a 'start' message to kick things off,
101 * which is handled by this handler. It saves the parent 103 * which is handled by this handler. It saves the parent
102 * window, gets the test ID from the query parameter in the 104 * window, gets the test ID from the query parameter in the
103 * IFrame URL, sets that as a solo test and starts test execution. 105 * IFrame URL, sets that as a solo test and starts test execution.
104 */ 106 */
105 window.on.message.add((MessageEvent e) { 107 window.onMessage.listen((MessageEvent e) {
106 // Get the result, do any logging, then do a pass/fail. 108 // Get the result, do any logging, then do a pass/fail.
107 var m = new _Message.fromString(e.data); 109 var m = new _Message.fromString(e.data);
108 if (m.messageType == _Message.START) { 110 if (m.messageType == _Message.START) {
109 parentWindow = e.source; 111 parentWindow = e.source;
110 String search = window.location.search; 112 String search = window.location.search;
111 int pos = search.indexOf('t='); 113 int pos = search.indexOf('t=');
112 String ids = search.substring(pos+2); 114 String ids = search.substring(pos+2);
113 int id = int.parse(ids); 115 int id = int.parse(ids);
114 setSoloTest(id); 116 setSoloTest(id);
115 runTests(); 117 runTests();
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 String _stack; 183 String _stack;
182 184
183 int _testTime; 185 int _testTime;
184 /** 186 /**
185 * Whether or not we have already wrapped the TestCase test functions 187 * Whether or not we have already wrapped the TestCase test functions
186 * in new closures that instead create an IFrame and get it to run the 188 * in new closures that instead create an IFrame and get it to run the
187 * test. 189 * test.
188 */ 190 */
189 bool _doneWrap = false; 191 bool _doneWrap = false;
190 192
191 /** 193 StreamSubscription _messageSubscription;
192 * We use this to make a single closure from _handleMessage so we
193 * can remove the handler later.
194 */
195 Function _messageHandler;
196 194
197 ParentInteractiveHtmlConfiguration() : 195 ParentInteractiveHtmlConfiguration() :
198 _testStarts = new Map<int,DateTime>(); 196 _testStarts = new Map<int,DateTime>();
199 197
200 // We need to block until the test is done, so we make a 198 // We need to block until the test is done, so we make a
201 // dummy async callback that we will use to flag completion. 199 // dummy async callback that we will use to flag completion.
202 Function completeTest = null; 200 Function completeTest = null;
203 201
204 wrapTest(TestCase testCase) { 202 wrapTest(TestCase testCase) {
205 String baseUrl = window.location.toString(); 203 String baseUrl = window.location.toString();
206 String url = '${baseUrl}?t=${testCase.id}'; 204 String url = '${baseUrl}?t=${testCase.id}';
207 return () { 205 return () {
208 // Rebuild the child IFrame. 206 // Rebuild the child IFrame.
209 Element childDiv = document.query('#child'); 207 Element childDiv = document.query('#child');
210 childDiv.nodes.clear(); 208 childDiv.nodes.clear();
211 IFrameElement child = new Element.html(""" 209 IFrameElement child = new Element.html("""
212 <iframe id='childFrame${testCase.id}' src='$url' style='display:none'> 210 <iframe id='childFrame${testCase.id}' src='$url' style='display:none'>
213 </iframe>"""); 211 </iframe>""");
214 childDiv.nodes.add(child); 212 childDiv.nodes.add(child);
215 completeTest = expectAsync0((){ }); 213 completeTest = expectAsync0((){ });
216 // Kick off the test when the IFrame is loaded. 214 // Kick off the test when the IFrame is loaded.
217 child.on.load.add((e) { 215 child.onLoad.listen((e) {
218 child.contentWindow.postMessage(_Message.text(_Message.START), '*'); 216 child.contentWindow.postMessage(_Message.text(_Message.START), '*');
219 }); 217 });
220 }; 218 };
221 } 219 }
222 220
223 void _handleMessage(MessageEvent e) { 221 void _handleMessage(MessageEvent e) {
224 // Get the result, do any logging, then do a pass/fail. 222 // Get the result, do any logging, then do a pass/fail.
225 var msg = new _Message.fromString(e.data); 223 var msg = new _Message.fromString(e.data);
226 if (msg.messageType == _Message.LOG) { 224 if (msg.messageType == _Message.LOG) {
227 logMessage(e.data); 225 logMessage(e.data);
228 } else if (msg.messageType == _Message.STACK) { 226 } else if (msg.messageType == _Message.STACK) {
229 _stack = msg.body; 227 _stack = msg.body;
230 } else { 228 } else {
231 _testTime = msg.elapsed; 229 _testTime = msg.elapsed;
232 logMessage(_Message.text(_Message.LOG, _testTime, 'Complete')); 230 logMessage(_Message.text(_Message.LOG, _testTime, 'Complete'));
233 if (msg.messageType == _Message.PASS) { 231 if (msg.messageType == _Message.PASS) {
234 currentTestCase.pass(); 232 currentTestCase.pass();
235 } else if (msg.messageType == _Message.FAIL) { 233 } else if (msg.messageType == _Message.FAIL) {
236 currentTestCase.fail(msg.body, _stack); 234 currentTestCase.fail(msg.body, _stack);
237 } else if (msg.messageType == _Message.ERROR) { 235 } else if (msg.messageType == _Message.ERROR) {
238 currentTestCase.error(msg.body, _stack); 236 currentTestCase.error(msg.body, _stack);
239 } 237 }
240 completeTest(); 238 completeTest();
241 } 239 }
242 } 240 }
243 241
244 void onInit() { 242 void onInit() {
245 _installErrorHandler(); 243 _installErrorHandler();
246 _messageHandler = _handleMessage; // We need to make just one closure.
247 document.query('#group-divs').innerHtml = ""; 244 document.query('#group-divs').innerHtml = "";
248 } 245 }
249 246
250 void onStart() { 247 void onStart() {
251 _installErrorHandler(); 248 _installErrorHandler();
252 if (!_doneWrap) { 249 if (!_doneWrap) {
253 _doneWrap = true; 250 _doneWrap = true;
254 for (int i = 0; i < testCases.length; i++) { 251 for (int i = 0; i < testCases.length; i++) {
255 testCases[i].test = wrapTest(testCases[i]); 252 testCases[i].test = wrapTest(testCases[i]);
256 testCases[i].setUp = null; 253 testCases[i].setUp = null;
257 testCases[i].tearDown = null; 254 testCases[i].tearDown = null;
258 } 255 }
259 } 256 }
260 window.on.message.add(_messageHandler); 257 assert(_messageSubscription == null);
258 _messageSubscription = window.onMessage.listen(_handleMessage);
261 } 259 }
262 260
263 static final _notAlphaNumeric = new RegExp('[^a-z0-9A-Z]'); 261 static final _notAlphaNumeric = new RegExp('[^a-z0-9A-Z]');
264 262
265 String _stringToDomId(String s) { 263 String _stringToDomId(String s) {
266 if (s.length == 0) { 264 if (s.length == 0) {
267 return '-None-'; 265 return '-None-';
268 } 266 }
269 return s.trim().replaceAll(_notAlphaNumeric, '-'); 267 return s.trim().replaceAll(_notAlphaNumeric, '-');
270 } 268 }
(...skipping 19 matching lines...) Expand all
290 groupDiv = new Element.html(""" 288 groupDiv = new Element.html("""
291 <div class='test-describe' id='$groupId'> 289 <div class='test-describe' id='$groupId'>
292 <h2> 290 <h2>
293 <input type='checkbox' checked='true' class='groupselect'> 291 <input type='checkbox' checked='true' class='groupselect'>
294 Group: ${testCase.currentGroup} 292 Group: ${testCase.currentGroup}
295 </h2> 293 </h2>
296 <ul class='tests'> 294 <ul class='tests'>
297 </ul> 295 </ul>
298 </div>"""); 296 </div>""");
299 document.query('#group-divs').nodes.add(groupDiv); 297 document.query('#group-divs').nodes.add(groupDiv);
300 groupDiv.query('.groupselect').on.click.add((e) { 298 groupDiv.query('.groupselect').onClick.listen((e) {
301 var parent = document.query('#$groupId'); 299 var parent = document.query('#$groupId');
302 InputElement cb = parent.query('.groupselect'); 300 InputElement cb = parent.query('.groupselect');
303 var state = cb.checked; 301 var state = cb.checked;
304 var tests = parent.query('.tests'); 302 var tests = parent.query('.tests');
305 for (Element t in tests.elements) { 303 for (Element t in tests.children) {
306 cb = t.query('.testselect') as InputElement; 304 cb = t.query('.testselect') as InputElement;
307 cb.checked = state; 305 cb.checked = state;
308 var testId = int.parse(t.id.substring(_testIdPrefix.length)); 306 var testId = int.parse(t.id.substring(_testIdPrefix.length));
309 if (state) { 307 if (state) {
310 enableTest(testId); 308 enableTest(testId);
311 } else { 309 } else {
312 disableTest(testId); 310 disableTest(testId);
313 } 311 }
314 } 312 }
315 }); 313 });
(...skipping 12 matching lines...) Expand all
328 <span class='timer-result test-timer-result'></span> 326 <span class='timer-result test-timer-result'></span>
329 <span class='test-name closed'>${testCase.description}</span> 327 <span class='test-name closed'>${testCase.description}</span>
330 </span> 328 </span>
331 </p> 329 </p>
332 </div> 330 </div>
333 <div class='scrollpane'> 331 <div class='scrollpane'>
334 <ol class='test-actions' id='$_actionIdPrefix$id'></ol> 332 <ol class='test-actions' id='$_actionIdPrefix$id'></ol>
335 </div> 333 </div>
336 </li>"""); 334 </li>""");
337 list.nodes.add(testItem); 335 list.nodes.add(testItem);
338 testItem.query('#$_selectedIdPrefix$id').on.change.add((e) { 336 testItem.query('#$_selectedIdPrefix$id').onChange.listen((e) {
339 InputElement cb = testItem.query('#$_selectedIdPrefix$id'); 337 InputElement cb = testItem.query('#$_selectedIdPrefix$id');
340 testCase.enabled = cb.checked; 338 testCase.enabled = cb.checked;
341 }); 339 });
342 testItem.query('.test-label').on.click.add((e) { 340 testItem.query('.test-label').onClick.listen((e) {
343 var _testItem = document.query('#$_testIdPrefix$id'); 341 var _testItem = document.query('#$_testIdPrefix$id');
344 var _actions = _testItem.query('#$_actionIdPrefix$id'); 342 var _actions = _testItem.query('#$_actionIdPrefix$id');
345 var _label = _testItem.query('.test-name'); 343 var _label = _testItem.query('.test-name');
346 if (_actions.style.display == 'none') { 344 if (_actions.style.display == 'none') {
347 _actions.style.display = 'table'; 345 _actions.style.display = 'table';
348 _label.classes.remove('closed'); 346 _label.classes.remove('closed');
349 _label.classes.add('open'); 347 _label.classes.add('open');
350 } else { 348 } else {
351 _actions.style.display = 'none'; 349 _actions.style.display = 'none';
352 _label.classes.remove('open'); 350 _label.classes.remove('open');
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 e.classes.add(result); 405 e.classes.add(result);
408 } 406 }
409 actions.style.display = 'none'; 407 actions.style.display = 'none';
410 } 408 }
411 409
412 void onSummary(int passed, int failed, int errors, List<TestCase> results, 410 void onSummary(int passed, int failed, int errors, List<TestCase> results,
413 String uncaughtError) { 411 String uncaughtError) {
414 } 412 }
415 413
416 void onDone(bool success) { 414 void onDone(bool success) {
417 window.on.message.remove(_messageHandler); 415 assert(_messageSubscription != null);
416 _messageSubscription.cancel();
417 _messageSubscription = null;
418 _uninstallErrorHandler(); 418 _uninstallErrorHandler();
419 document.query('#busy').style.display = 'none'; 419 document.query('#busy').style.display = 'none';
420 InputElement startButton = document.query('#start'); 420 InputElement startButton = document.query('#start');
421 startButton.disabled = false; 421 startButton.disabled = false;
422 } 422 }
423 } 423 }
424 424
425 /** 425 /**
426 * Add the divs to the DOM if they are not present. We have a 'controls' 426 * Add the divs to the DOM if they are not present. We have a 'controls'
427 * div for control, 'specs' div with test results, a 'busy' div for the 427 * div for control, 'specs' div with test results, a 'busy' div for the
428 * animated GIF used to indicate tests are running, and a 'child' div to 428 * animated GIF used to indicate tests are running, and a 'child' div to
429 * hold the iframe for the test. 429 * hold the iframe for the test.
430 */ 430 */
431 void _prepareDom() { 431 void _prepareDom() {
432 if (document.query('#control') == null) { 432 if (document.query('#control') == null) {
433 // Use this as an opportunity for adding the CSS too. 433 // Use this as an opportunity for adding the CSS too.
434 // I wanted to avoid having to include a css element explicitly 434 // I wanted to avoid having to include a css element explicitly
435 // in the main html file. I considered moving all the styles 435 // in the main html file. I considered moving all the styles
436 // inline as attributes but that started getting very messy, 436 // inline as attributes but that started getting very messy,
437 // so we do it this way. 437 // so we do it this way.
438 document.body.nodes.add(new Element.html("<style>$_CSS</style>")); 438 document.body.nodes.add(new Element.html("<style>$_CSS</style>"));
439 document.body.nodes.add(new Element.html( 439 document.body.nodes.add(new Element.html(
440 "<div id='control'>" 440 "<div id='control'>"
441 "<input id='start' disabled='true' type='button' value='Run'>" 441 "<input id='start' disabled='true' type='button' value='Run'>"
442 "</div>")); 442 "</div>"));
443 document.query('#start').on.click.add((e) { 443 document.query('#start').onClick.listen((e) {
444 InputElement startButton = document.query('#start'); 444 InputElement startButton = document.query('#start');
445 startButton.disabled = true; 445 startButton.disabled = true;
446 rerunTests(); 446 rerunTests();
447 }); 447 });
448 } 448 }
449 if (document.query('#otherlogs') == null) { 449 if (document.query('#otherlogs') == null) {
450 document.body.nodes.add(new Element.html( 450 document.body.nodes.add(new Element.html(
451 "<div id='otherlogs'></div>")); 451 "<div id='otherlogs'></div>"));
452 } 452 }
453 if (document.query('#specs') == null) { 453 if (document.query('#specs') == null) {
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 display: block; 670 display: block;
671 list-style-type: disc; 671 list-style-type: disc;
672 -webkit-margin-before: 1em; 672 -webkit-margin-before: 1em;
673 -webkit-margin-after: 1em; 673 -webkit-margin-after: 1em;
674 -webkit-margin-start: 0px; 674 -webkit-margin-start: 0px;
675 -webkit-margin-end: 0px; 675 -webkit-margin-end: 0px;
676 -webkit-padding-start: 40px; 676 -webkit-padding-start: 40px;
677 } 677 }
678 678
679 """; 679 """;
OLDNEW
« no previous file with comments | « pkg/unittest/lib/html_layout_config.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698