##// END OF EJS Templates
Merge pull request #6768 from jdfreder/remotetestfix...
Min RK -
r18451:ba9c9748 merge
parent child Browse files
Show More
@@ -1,704 +1,707 b''
1 1 //
2 2 // Utility functions for the HTML notebook's CasperJS tests.
3 3 //
4 4 casper.get_notebook_server = function () {
5 5 // Get the URL of a notebook server on which to run tests.
6 6 var port = casper.cli.get("port");
7 7 port = (typeof port === 'undefined') ? '8888' : port;
8 8 return casper.cli.get("url") || ('http://127.0.0.1:' + port);
9 9 };
10 10
11 11 casper.open_new_notebook = function () {
12 12 // Create and open a new notebook.
13 13 var baseUrl = this.get_notebook_server();
14 14 this.start(baseUrl);
15 15 this.waitFor(this.page_loaded);
16 16 this.thenClick('button#new_notebook');
17 17 this.waitForPopup('');
18 18
19 19 this.withPopup('', function () {this.waitForSelector('.CodeMirror-code');});
20 20 this.then(function () {
21 21 this.open(this.popups[0].url);
22 22 });
23 23 this.waitFor(this.page_loaded);
24 24
25 25 // Make sure the kernel has started
26 26 this.waitFor(this.kernel_running);
27 27 // track the IPython busy/idle state
28 28 this.thenEvaluate(function () {
29 29 require(['base/js/namespace', 'base/js/events'], function (IPython, events) {
30 30
31 31 events.on('kernel_idle.Kernel',function () {
32 32 IPython._status = 'idle';
33 33 });
34 34 events.on('kernel_busy.Kernel',function () {
35 35 IPython._status = 'busy';
36 36 });
37 37 });
38 38 });
39 39
40 40 // Because of the asynchronous nature of SlimerJS (Gecko), we need to make
41 41 // sure the notebook has actually been loaded into the IPython namespace
42 42 // before running any tests.
43 43 this.waitFor(function() {
44 44 return this.evaluate(function () {
45 45 return IPython.notebook;
46 46 });
47 47 });
48 48 };
49 49
50 50 casper.page_loaded = function() {
51 51 // Return whether or not the kernel is running.
52 52 return this.evaluate(function() {
53 53 return typeof IPython !== "undefined" &&
54 54 IPython.page !== undefined;
55 55 });
56 56 };
57 57
58 58 casper.kernel_running = function() {
59 59 // Return whether or not the kernel is running.
60 60 return this.evaluate(function() {
61 return IPython.notebook.kernel.is_connected();
61 return IPython &&
62 IPython.notebook &&
63 IPython.notebook.kernel &&
64 IPython.notebook.kernel.is_connected();
62 65 });
63 66 };
64 67
65 68 casper.kernel_disconnected = function() {
66 69 return this.evaluate(function() {
67 70 return IPython.notebook.kernel.is_fully_disconnected();
68 71 });
69 72 };
70 73
71 74 casper.wait_for_kernel_ready = function () {
72 75 this.waitFor(this.kernel_running);
73 76 this.thenEvaluate(function () {
74 77 IPython._kernel_ready = false;
75 78 IPython.notebook.kernel.kernel_info(
76 79 function () {
77 80 IPython._kernel_ready = true;
78 81 });
79 82 });
80 83 this.waitFor(function () {
81 84 return this.evaluate(function () {
82 85 return IPython._kernel_ready;
83 86 });
84 87 });
85 88 };
86 89
87 90 casper.shutdown_current_kernel = function () {
88 91 // Shut down the current notebook's kernel.
89 92 this.thenEvaluate(function() {
90 93 IPython.notebook.session.delete();
91 94 });
92 95 // We close the page right after this so we need to give it time to complete.
93 96 this.wait(1000);
94 97 };
95 98
96 99 casper.delete_current_notebook = function () {
97 100 // Delete created notebook.
98 101
99 102 // For some unknown reason, this doesn't work?!?
100 103 this.thenEvaluate(function() {
101 104 IPython.notebook.delete();
102 105 });
103 106 };
104 107
105 108 casper.wait_for_busy = function () {
106 109 // Waits for the notebook to enter a busy state.
107 110 this.waitFor(function () {
108 111 return this.evaluate(function () {
109 112 return IPython._status == 'busy';
110 113 });
111 114 });
112 115 };
113 116
114 117 casper.wait_for_idle = function () {
115 118 // Waits for the notebook to idle.
116 119 this.waitFor(function () {
117 120 return this.evaluate(function () {
118 121 return IPython._status == 'idle';
119 122 });
120 123 });
121 124 };
122 125
123 126 casper.wait_for_output = function (cell_num, out_num) {
124 127 // wait for the nth output in a given cell
125 128 this.wait_for_idle();
126 129 out_num = out_num || 0;
127 130 this.then(function() {
128 131 this.waitFor(function (c, o) {
129 132 return this.evaluate(function get_output(c, o) {
130 133 var cell = IPython.notebook.get_cell(c);
131 134 return cell.output_area.outputs.length > o;
132 135 },
133 136 // pass parameter from the test suite js to the browser code js
134 137 {c : cell_num, o : out_num});
135 138 });
136 139 },
137 140 function then() { },
138 141 function timeout() {
139 142 this.echo("wait_for_output timed out!");
140 143 });
141 144 };
142 145
143 146 casper.wait_for_widget = function (widget_info) {
144 147 // wait for a widget msg que to reach 0
145 148 //
146 149 // Parameters
147 150 // ----------
148 151 // widget_info : object
149 152 // Object which contains info related to the widget. The model_id property
150 153 // is used to identify the widget.
151 154 this.waitFor(function () {
152 155 var pending = this.evaluate(function (m) {
153 156 return IPython.notebook.kernel.widget_manager.get_model(m).pending_msgs;
154 157 }, {m: widget_info.model_id});
155 158
156 159 if (pending === 0) {
157 160 return true;
158 161 } else {
159 162 return false;
160 163 }
161 164 });
162 165 };
163 166
164 167 casper.get_output_cell = function (cell_num, out_num) {
165 168 // return an output of a given cell
166 169 out_num = out_num || 0;
167 170 var result = casper.evaluate(function (c, o) {
168 171 var cell = IPython.notebook.get_cell(c);
169 172 return cell.output_area.outputs[o];
170 173 },
171 174 {c : cell_num, o : out_num});
172 175 if (!result) {
173 176 var num_outputs = casper.evaluate(function (c) {
174 177 var cell = IPython.notebook.get_cell(c);
175 178 return cell.output_area.outputs.length;
176 179 },
177 180 {c : cell_num});
178 181 this.test.assertTrue(false,
179 182 "Cell " + cell_num + " has no output #" + out_num + " (" + num_outputs + " total)"
180 183 );
181 184 } else {
182 185 return result;
183 186 }
184 187 };
185 188
186 189 casper.get_cells_length = function () {
187 190 // return the number of cells in the notebook
188 191 var result = casper.evaluate(function () {
189 192 return IPython.notebook.get_cells().length;
190 193 });
191 194 return result;
192 195 };
193 196
194 197 casper.set_cell_text = function(index, text){
195 198 // Set the text content of a cell.
196 199 this.evaluate(function (index, text) {
197 200 var cell = IPython.notebook.get_cell(index);
198 201 cell.set_text(text);
199 202 }, index, text);
200 203 };
201 204
202 205 casper.get_cell_text = function(index){
203 206 // Get the text content of a cell.
204 207 return this.evaluate(function (index) {
205 208 var cell = IPython.notebook.get_cell(index);
206 209 return cell.get_text();
207 210 }, index);
208 211 };
209 212
210 213 casper.insert_cell_at_bottom = function(cell_type){
211 214 // Inserts a cell at the bottom of the notebook
212 215 // Returns the new cell's index.
213 216 return this.evaluate(function (cell_type) {
214 217 var cell = IPython.notebook.insert_cell_at_bottom(cell_type);
215 218 return IPython.notebook.find_cell_index(cell);
216 219 }, cell_type);
217 220 };
218 221
219 222 casper.append_cell = function(text, cell_type) {
220 223 // Insert a cell at the bottom of the notebook and set the cells text.
221 224 // Returns the new cell's index.
222 225 var index = this.insert_cell_at_bottom(cell_type);
223 226 if (text !== undefined) {
224 227 this.set_cell_text(index, text);
225 228 }
226 229 return index;
227 230 };
228 231
229 232 casper.execute_cell = function(index, expect_failure){
230 233 // Asynchronously executes a cell by index.
231 234 // Returns the cell's index.
232 235
233 236 if (expect_failure === undefined) expect_failure = false;
234 237 var that = this;
235 238 this.then(function(){
236 239 that.evaluate(function (index) {
237 240 var cell = IPython.notebook.get_cell(index);
238 241 cell.execute();
239 242 }, index);
240 243 });
241 244 this.wait_for_idle();
242 245
243 246 this.then(function () {
244 247 var error = that.evaluate(function (index) {
245 248 var cell = IPython.notebook.get_cell(index);
246 249 var outputs = cell.output_area.outputs;
247 250 for (var i = 0; i < outputs.length; i++) {
248 251 if (outputs[i].output_type == 'error') {
249 252 return outputs[i];
250 253 }
251 254 }
252 255 return false;
253 256 }, index);
254 257 if (error === null) {
255 258 this.test.fail("Failed to check for error output");
256 259 }
257 260 if (expect_failure && error === false) {
258 261 this.test.fail("Expected error while running cell");
259 262 } else if (!expect_failure && error !== false) {
260 263 this.test.fail("Error running cell:\n" + error.traceback.join('\n'));
261 264 }
262 265 });
263 266 return index;
264 267 };
265 268
266 269 casper.execute_cell_then = function(index, then_callback, expect_failure) {
267 270 // Synchronously executes a cell by index.
268 271 // Optionally accepts a then_callback parameter. then_callback will get called
269 272 // when the cell has finished executing.
270 273 // Returns the cell's index.
271 274 var return_val = this.execute_cell(index, expect_failure);
272 275
273 276 this.wait_for_idle();
274 277
275 278 var that = this;
276 279 this.then(function(){
277 280 if (then_callback!==undefined) {
278 281 then_callback.apply(that, [index]);
279 282 }
280 283 });
281 284
282 285 return return_val;
283 286 };
284 287
285 288 casper.cell_element_exists = function(index, selector){
286 289 // Utility function that allows us to easily check if an element exists
287 290 // within a cell. Uses JQuery selector to look for the element.
288 291 return casper.evaluate(function (index, selector) {
289 292 var $cell = IPython.notebook.get_cell(index).element;
290 293 return $cell.find(selector).length > 0;
291 294 }, index, selector);
292 295 };
293 296
294 297 casper.cell_element_function = function(index, selector, function_name, function_args){
295 298 // Utility function that allows us to execute a jQuery function on an
296 299 // element within a cell.
297 300 return casper.evaluate(function (index, selector, function_name, function_args) {
298 301 var $cell = IPython.notebook.get_cell(index).element;
299 302 var $el = $cell.find(selector);
300 303 return $el[function_name].apply($el, function_args);
301 304 }, index, selector, function_name, function_args);
302 305 };
303 306
304 307 casper.validate_notebook_state = function(message, mode, cell_index) {
305 308 // Validate the entire dual mode state of the notebook. Make sure no more than
306 309 // one cell is selected, focused, in edit mode, etc...
307 310
308 311 // General tests.
309 312 this.test.assertEquals(this.get_keyboard_mode(), this.get_notebook_mode(),
310 313 message + '; keyboard and notebook modes match');
311 314 // Is the selected cell the only cell that is selected?
312 315 if (cell_index!==undefined) {
313 316 this.test.assert(this.is_only_cell_selected(cell_index),
314 317 message + '; cell ' + cell_index + ' is the only cell selected');
315 318 }
316 319
317 320 // Mode specific tests.
318 321 if (mode==='command') {
319 322 // Are the notebook and keyboard manager in command mode?
320 323 this.test.assertEquals(this.get_keyboard_mode(), 'command',
321 324 message + '; in command mode');
322 325 // Make sure there isn't a single cell in edit mode.
323 326 this.test.assert(this.is_only_cell_edit(null),
324 327 message + '; all cells in command mode');
325 328 this.test.assert(this.is_cell_editor_focused(null),
326 329 message + '; no cell editors are focused while in command mode');
327 330
328 331 } else if (mode==='edit') {
329 332 // Are the notebook and keyboard manager in edit mode?
330 333 this.test.assertEquals(this.get_keyboard_mode(), 'edit',
331 334 message + '; in edit mode');
332 335 if (cell_index!==undefined) {
333 336 // Is the specified cell the only cell in edit mode?
334 337 this.test.assert(this.is_only_cell_edit(cell_index),
335 338 message + '; cell ' + cell_index + ' is the only cell in edit mode');
336 339 // Is the specified cell the only cell with a focused code mirror?
337 340 this.test.assert(this.is_cell_editor_focused(cell_index),
338 341 message + '; cell ' + cell_index + '\'s editor is appropriately focused');
339 342 }
340 343
341 344 } else {
342 345 this.test.assert(false, message + '; ' + mode + ' is an unknown mode');
343 346 }
344 347 };
345 348
346 349 casper.select_cell = function(index) {
347 350 // Select a cell in the notebook.
348 351 this.evaluate(function (i) {
349 352 IPython.notebook.select(i);
350 353 }, {i: index});
351 354 };
352 355
353 356 casper.click_cell_editor = function(index) {
354 357 // Emulate a click on a cell's editor.
355 358
356 359 // Code Mirror does not play nicely with emulated brower events.
357 360 // Instead of trying to emulate a click, here we run code similar to
358 361 // the code used in Code Mirror that handles the mousedown event on a
359 362 // region of codemirror that the user can focus.
360 363 this.evaluate(function (i) {
361 364 var cm = IPython.notebook.get_cell(i).code_mirror;
362 365 if (cm.options.readOnly != "nocursor" && (document.activeElement != cm.display.input))
363 366 cm.display.input.focus();
364 367 }, {i: index});
365 368 };
366 369
367 370 casper.set_cell_editor_cursor = function(index, line_index, char_index) {
368 371 // Set the Code Mirror instance cursor's location.
369 372 this.evaluate(function (i, l, c) {
370 373 IPython.notebook.get_cell(i).code_mirror.setCursor(l, c);
371 374 }, {i: index, l: line_index, c: char_index});
372 375 };
373 376
374 377 casper.focus_notebook = function() {
375 378 // Focus the notebook div.
376 379 this.evaluate(function (){
377 380 $('#notebook').focus();
378 381 }, {});
379 382 };
380 383
381 384 casper.trigger_keydown = function() {
382 385 // Emulate a keydown in the notebook.
383 386 for (var i = 0; i < arguments.length; i++) {
384 387 this.evaluate(function (k) {
385 388 var element = $(document);
386 389 var event = IPython.keyboard.shortcut_to_event(k, 'keydown');
387 390 element.trigger(event);
388 391 }, {k: arguments[i]});
389 392 }
390 393 };
391 394
392 395 casper.get_keyboard_mode = function() {
393 396 // Get the mode of the keyboard manager.
394 397 return this.evaluate(function() {
395 398 return IPython.keyboard_manager.mode;
396 399 }, {});
397 400 };
398 401
399 402 casper.get_notebook_mode = function() {
400 403 // Get the mode of the notebook.
401 404 return this.evaluate(function() {
402 405 return IPython.notebook.mode;
403 406 }, {});
404 407 };
405 408
406 409 casper.get_cell = function(index) {
407 410 // Get a single cell.
408 411 //
409 412 // Note: Handles to DOM elements stored in the cell will be useless once in
410 413 // CasperJS context.
411 414 return this.evaluate(function(i) {
412 415 var cell = IPython.notebook.get_cell(i);
413 416 if (cell) {
414 417 return cell;
415 418 }
416 419 return null;
417 420 }, {i : index});
418 421 };
419 422
420 423 casper.is_cell_editor_focused = function(index) {
421 424 // Make sure a cell's editor is the only editor focused on the page.
422 425 return this.evaluate(function(i) {
423 426 var focused_textarea = $('#notebook .CodeMirror-focused textarea');
424 427 if (focused_textarea.length > 1) { throw 'More than one Code Mirror editor is focused at once!'; }
425 428 if (i === null) {
426 429 return focused_textarea.length === 0;
427 430 } else {
428 431 var cell = IPython.notebook.get_cell(i);
429 432 if (cell) {
430 433 return cell.code_mirror.getInputField() == focused_textarea[0];
431 434 }
432 435 }
433 436 return false;
434 437 }, {i : index});
435 438 };
436 439
437 440 casper.is_only_cell_selected = function(index) {
438 441 // Check if a cell is the only cell selected.
439 442 // Pass null as the index to check if no cells are selected.
440 443 return this.is_only_cell_on(index, 'selected', 'unselected');
441 444 };
442 445
443 446 casper.is_only_cell_edit = function(index) {
444 447 // Check if a cell is the only cell in edit mode.
445 448 // Pass null as the index to check if all of the cells are in command mode.
446 449 return this.is_only_cell_on(index, 'edit_mode', 'command_mode');
447 450 };
448 451
449 452 casper.is_only_cell_on = function(i, on_class, off_class) {
450 453 // Check if a cell is the only cell with the `on_class` DOM class applied to it.
451 454 // All of the other cells are checked for the `off_class` DOM class.
452 455 // Pass null as the index to check if all of the cells have the `off_class`.
453 456 var cells_length = this.get_cells_length();
454 457 for (var j = 0; j < cells_length; j++) {
455 458 if (j === i) {
456 459 if (this.cell_has_class(j, off_class) || !this.cell_has_class(j, on_class)) {
457 460 return false;
458 461 }
459 462 } else {
460 463 if (!this.cell_has_class(j, off_class) || this.cell_has_class(j, on_class)) {
461 464 return false;
462 465 }
463 466 }
464 467 }
465 468 return true;
466 469 };
467 470
468 471 casper.cell_has_class = function(index, classes) {
469 472 // Check if a cell has a class.
470 473 return this.evaluate(function(i, c) {
471 474 var cell = IPython.notebook.get_cell(i);
472 475 if (cell) {
473 476 return cell.element.hasClass(c);
474 477 }
475 478 return false;
476 479 }, {i : index, c: classes});
477 480 };
478 481
479 482 casper.is_cell_rendered = function (index) {
480 483 return this.evaluate(function(i) {
481 484 return !!IPython.notebook.get_cell(i).rendered;
482 485 }, {i:index});
483 486 };
484 487
485 488 casper.assert_colors_equal = function (hex_color, local_color, msg) {
486 489 // Tests to see if two colors are equal.
487 490 //
488 491 // Parameters
489 492 // hex_color: string
490 493 // Hexadecimal color code, with or without preceeding hash character.
491 494 // local_color: string
492 495 // Local color representation. Can either be hexadecimal (default for
493 496 // phantom) or rgb (default for slimer).
494 497
495 498 // Remove parentheses, hashes, semi-colons, and space characters.
496 499 hex_color = hex_color.replace(/[\(\); #]/, '');
497 500 local_color = local_color.replace(/[\(\); #]/, '');
498 501
499 502 // If the local color is rgb, clean it up and replace
500 503 if (local_color.substr(0,3).toLowerCase() == 'rgb') {
501 504 components = local_color.substr(3).split(',');
502 505 local_color = '';
503 506 for (var i = 0; i < components.length; i++) {
504 507 var part = parseInt(components[i]).toString(16);
505 508 while (part.length < 2) part = '0' + part;
506 509 local_color += part;
507 510 }
508 511 }
509 512
510 513 this.test.assertEquals(hex_color.toUpperCase(), local_color.toUpperCase(), msg);
511 514 };
512 515
513 516 casper.notebook_test = function(test) {
514 517 // Wrap a notebook test to reduce boilerplate.
515 518 this.open_new_notebook();
516 519
517 520 // Echo whether or not we are running this test using SlimerJS
518 521 if (this.evaluate(function(){
519 522 return typeof InstallTrigger !== 'undefined'; // Firefox 1.0+
520 523 })) {
521 524 console.log('This test is running in SlimerJS.');
522 525 this.slimerjs = true;
523 526 }
524 527
525 528 // Make sure to remove the onbeforeunload callback. This callback is
526 529 // responsible for the "Are you sure you want to quit?" type messages.
527 530 // PhantomJS ignores these prompts, SlimerJS does not which causes hangs.
528 531 this.then(function(){
529 532 this.evaluate(function(){
530 533 window.onbeforeunload = function(){};
531 534 });
532 535 });
533 536
534 537 this.then(test);
535 538
536 539 // Kill the kernel and delete the notebook.
537 540 this.shutdown_current_kernel();
538 541 // This is still broken but shouldn't be a problem for now.
539 542 // this.delete_current_notebook();
540 543
541 544 // This is required to clean up the page we just finished with. If we don't call this
542 545 // casperjs will leak file descriptors of all the open WebSockets in that page. We
543 546 // have to set this.page=null so that next time casper.start runs, it will create a
544 547 // new page from scratch.
545 548 this.then(function () {
546 549 this.page.close();
547 550 this.page = null;
548 551 });
549 552
550 553 // Run the browser automation.
551 554 this.run(function() {
552 555 this.test.done();
553 556 });
554 557 };
555 558
556 559 casper.wait_for_dashboard = function () {
557 560 // Wait for the dashboard list to load.
558 561 casper.waitForSelector('.list_item');
559 562 };
560 563
561 564 casper.open_dashboard = function () {
562 565 // Start casper by opening the dashboard page.
563 566 var baseUrl = this.get_notebook_server();
564 567 this.start(baseUrl);
565 568 this.waitFor(this.page_loaded);
566 569 this.wait_for_dashboard();
567 570 };
568 571
569 572 casper.dashboard_test = function (test) {
570 573 // Open the dashboard page and run a test.
571 574 this.open_dashboard();
572 575 this.then(test);
573 576
574 577 this.then(function () {
575 578 this.page.close();
576 579 this.page = null;
577 580 });
578 581
579 582 // Run the browser automation.
580 583 this.run(function() {
581 584 this.test.done();
582 585 });
583 586 };
584 587
585 588 // note that this will only work for UNIQUE events -- if you want to
586 589 // listen for the same event twice, this will not work!
587 590 casper.event_test = function (name, events, action, timeout) {
588 591
589 592 // set up handlers to listen for each of the events
590 593 this.thenEvaluate(function (events) {
591 594 var make_handler = function (event) {
592 595 return function () {
593 596 IPython._events_triggered.push(event);
594 597 IPython.notebook.events.off(event, null, IPython._event_handlers[event]);
595 598 delete IPython._event_handlers[event];
596 599 };
597 600 };
598 601 IPython._event_handlers = {};
599 602 IPython._events_triggered = [];
600 603 for (var i=0; i < events.length; i++) {
601 604 IPython._event_handlers[events[i]] = make_handler(events[i]);
602 605 IPython.notebook.events.on(events[i], IPython._event_handlers[events[i]]);
603 606 }
604 607 }, [events]);
605 608
606 609 // execute the requested action
607 610 this.then(action);
608 611
609 612 // wait for all the events to be triggered
610 613 this.waitFor(function () {
611 614 return this.evaluate(function (events) {
612 615 return IPython._events_triggered.length >= events.length;
613 616 }, [events]);
614 617 }, undefined, undefined, timeout);
615 618
616 619 // test that the events were triggered in the proper order
617 620 this.then(function () {
618 621 var triggered = this.evaluate(function () {
619 622 return IPython._events_triggered;
620 623 });
621 624 var handlers = this.evaluate(function () {
622 625 return Object.keys(IPython._event_handlers);
623 626 });
624 627 this.test.assertEquals(triggered.length, events.length, name + ': ' + events.length + ' events were triggered');
625 628 this.test.assertEquals(handlers.length, 0, name + ': all handlers triggered');
626 629 for (var i=0; i < events.length; i++) {
627 630 this.test.assertEquals(triggered[i], events[i], name + ': ' + events[i] + ' was triggered');
628 631 }
629 632 });
630 633
631 634 // turn off any remaining event listeners
632 635 this.thenEvaluate(function () {
633 636 for (var event in IPython._event_handlers) {
634 637 IPython.notebook.events.off(event, null, IPython._event_handlers[event]);
635 638 delete IPython._event_handlers[event];
636 639 }
637 640 });
638 641 };
639 642
640 643 casper.options.waitTimeout=10000;
641 644 casper.on('waitFor.timeout', function onWaitForTimeout(timeout) {
642 645 this.echo("Timeout for " + casper.get_notebook_server());
643 646 this.echo("Is the notebook server running?");
644 647 });
645 648
646 649 casper.print_log = function () {
647 650 // Pass `console.log` calls from page JS to casper.
648 651 this.on('remote.message', function(msg) {
649 652 this.echo('Remote message caught: ' + msg);
650 653 });
651 654 };
652 655
653 656 casper.on("page.error", function onError(msg, trace) {
654 657 // show errors in the browser
655 658 this.echo("Page Error!");
656 659 for (var i = 0; i < trace.length; i++) {
657 660 var frame = trace[i];
658 661 var file = frame.file;
659 662 // shorten common phantomjs evaluate url
660 663 // this will have a different value on slimerjs
661 664 if (file === "phantomjs://webpage.evaluate()") {
662 665 file = "evaluate";
663 666 }
664 667 this.echo("line " + frame.line + " of " + file);
665 668 if (frame.function.length > 0) {
666 669 this.echo("in " + frame.function);
667 670 }
668 671 }
669 672 this.echo(msg);
670 673 });
671 674
672 675
673 676 casper.capture_log = function () {
674 677 // show captured errors
675 678 var captured_log = [];
676 679 var seen_errors = 0;
677 680 this.on('remote.message', function(msg) {
678 681 captured_log.push(msg);
679 682 });
680 683
681 684 this.test.on("test.done", function (result) {
682 685 // test.done runs per-file,
683 686 // but suiteResults is per-suite (directory)
684 687 var current_errors;
685 688 if (this.suiteResults) {
686 689 // casper 1.1 has suiteResults
687 690 current_errors = this.suiteResults.countErrors() + this.suiteResults.countFailed();
688 691 } else {
689 692 // casper 1.0 has testResults instead
690 693 current_errors = this.testResults.failed;
691 694 }
692 695
693 696 if (current_errors > seen_errors && captured_log.length > 0) {
694 697 casper.echo("\nCaptured console.log:");
695 698 for (var i = 0; i < captured_log.length; i++) {
696 699 casper.echo(" " + captured_log[i]);
697 700 }
698 701 }
699 702 seen_errors = current_errors;
700 703 captured_log = [];
701 704 });
702 705 };
703 706
704 707 casper.capture_log();
General Comments 0
You need to be logged in to leave comments. Login now