Merge pull request #5323 from jdfreder/slimerjs

Add support for Firefox JS testing
Thomas Kluyver 12 years ago
commit 82e2ea7e47

@ -15,6 +15,14 @@ casper.notebook_test(function () {
this.execute_cell_then(index);
this.then(function () {
if (this.slimerjs) {
// When running in xvfb, the Slimer window doesn't always have focus
// immediately. By clicking on a new element on the page we can force
// it to gain focus.
this.click_cell_editor(1);
this.click_cell_editor(0);
}
this.validate_notebook_state('initial state', 'edit', 0);
this.trigger_keydown('esc');
this.validate_notebook_state('esc', 'command', 0);

@ -3,37 +3,35 @@
casper.notebook_test(function () {
var a = 'print("a")';
var index = this.append_cell(a);
this.execute_cell_then(index);
this.then(function () {
this.execute_cell_then(index, function(index) {
// Markdown rendering / unredering
this.select_cell(1);
this.validate_notebook_state('select 1', 'command', 1);
this.select_cell(index);
this.validate_notebook_state('select ' + index, 'command', index);
this.trigger_keydown('m');
this.test.assertEquals(this.get_cell(1).cell_type, 'markdown', 'm; cell is markdown');
this.test.assertEquals(this.get_cell(1).rendered, false, 'm; cell is rendered');
this.test.assertEquals(this.get_cell(index).cell_type, 'markdown', 'm; cell is markdown');
this.test.assert(!this.is_cell_rendered(index), 'm; cell is unrendered');
this.trigger_keydown('enter');
this.test.assertEquals(this.get_cell(1).rendered, false, 'enter; cell is unrendered');
this.validate_notebook_state('enter', 'edit', 1);
this.test.assert(!this.is_cell_rendered(index), 'enter; cell is unrendered');
this.validate_notebook_state('enter', 'edit', index);
this.trigger_keydown('ctrl-enter');
this.test.assertEquals(this.get_cell(1).rendered, true, 'ctrl-enter; cell is rendered');
this.validate_notebook_state('enter', 'command', 1);
this.test.assert(this.is_cell_rendered(index), 'ctrl-enter; cell is rendered');
this.validate_notebook_state('enter', 'command', index);
this.trigger_keydown('enter');
this.test.assertEquals(this.get_cell(1).rendered, false, 'enter; cell is unrendered');
this.select_cell(0);
this.test.assertEquals(this.get_cell(1).rendered, false, 'select 0; cell 1 is still unrendered');
this.validate_notebook_state('select 0', 'command', 0);
this.select_cell(1);
this.validate_notebook_state('select 1', 'command', 1);
this.test.assert(!this.is_cell_rendered(index), 'enter; cell is unrendered');
this.select_cell(index-1);
this.test.assert(!this.is_cell_rendered(index), 'select ' + (index-1) + '; cell ' + index + ' is still unrendered');
this.validate_notebook_state('select ' + (index-1), 'command', index-1);
this.select_cell(index);
this.validate_notebook_state('select ' + index, 'command', index);
this.trigger_keydown('ctrl-enter');
this.test.assertEquals(this.get_cell(1).rendered, true, 'ctrl-enter; cell is rendered');
this.select_cell(0);
this.validate_notebook_state('select 0', 'command', 0);
this.test.assert(this.is_cell_rendered(index), 'ctrl-enter; cell is rendered');
this.select_cell(index-1);
this.validate_notebook_state('select ' + (index-1), 'command', index-1);
this.trigger_keydown('shift-enter');
this.validate_notebook_state('shift-enter', 'command', 1);
this.test.assertEquals(this.get_cell(1).rendered, true, 'shift-enter; cell is rendered');
this.validate_notebook_state('shift-enter', 'command', index);
this.test.assert(this.is_cell_rendered(index), 'shift-enter; cell is rendered');
this.trigger_keydown('shift-enter'); // Creates one cell
this.validate_notebook_state('shift-enter', 'edit', 2);
this.test.assertEquals(this.get_cell(1).rendered, true, 'shift-enter; cell is rendered');
this.validate_notebook_state('shift-enter', 'edit', index+1);
this.test.assert(this.is_cell_rendered(index), 'shift-enter; cell is rendered');
});
});

@ -9,16 +9,16 @@
casper.notebook_test(function () {
this.evaluate(function () {
var cell = IPython.notebook.get_cell(0);
cell.set_text( "from IPython.core.display import SVG, display_svg\n"
+ "s1 = '''<svg width='1cm' height='1cm' viewBox='0 0 1000 500'>"
+ "<defs><style>rect {fill:red;}; </style></defs>"
+ "<rect id='r1' x='200' y='100' width='600' height='300' /></svg>"
+ "'''\n"
+ "s2 = '''<svg width='1cm' height='1cm' viewBox='0 0 1000 500'>"
+ "<rect id='r2' x='200' y='100' width='600' height='300' /></svg>"
+ "'''\n"
+ "display_svg(SVG(s1), metadata=dict(isolated=True))\n"
+ "display_svg(SVG(s2), metadata=dict(isolated=True))\n"
cell.set_text( "from IPython.core.display import SVG, display_svg\n" +
"s1 = '''<svg width='1cm' height='1cm' viewBox='0 0 1000 500'>" +
"<defs><style>rect {fill:red;}; </style></defs>" +
"<rect id='r1' x='200' y='100' width='600' height='300' /></svg>" +
"'''\n" +
"s2 = '''<svg width='1cm' height='1cm' viewBox='0 0 1000 500'>" +
"<rect id='r2' x='200' y='100' width='600' height='300' /></svg>" +
"'''\n" +
"display_svg(SVG(s1), metadata=dict(isolated=True))\n" +
"display_svg(SVG(s2), metadata=dict(isolated=True))\n"
);
cell.execute();
console.log("hello" );
@ -26,14 +26,14 @@ casper.notebook_test(function () {
this.then(function() {
var fname=this.test.currentTestFile.split('/').pop().toLowerCase();
this.echo(fname)
this.echo(this.currentUrl)
this.echo(fname);
this.echo(this.currentUrl);
this.evaluate(function (n) {
IPython.notebook.rename(n);
console.write("hello" + n);
IPython.notebook.save_notebook();
}, {n : fname});
this.echo(this.currentUrl)
this.echo(this.currentUrl);
});
this.then(function() {
@ -44,7 +44,7 @@ casper.notebook_test(function () {
//$("input")[0].value = "please-work";
//$(".btn-primary")[0].click();
return document.location.href;
})
});
this.echo("renamed" + url);
this.echo(this.currentUrl);
});
@ -56,23 +56,22 @@ casper.notebook_test(function () {
var colors = [];
var ifr = __utils__.findAll("iframe");
var svg1 = ifr[0].contentWindow.document.getElementById('r1');
colors[0] = window.getComputedStyle(svg1)["fill"];
colors[0] = window.getComputedStyle(svg1).fill;
var svg2 = ifr[1].contentWindow.document.getElementById('r2');
colors[1] = window.getComputedStyle(svg2)["fill"];
colors[1] = window.getComputedStyle(svg2).fill;
return colors;
});
this.test.assertEquals(colors && colors[0], '#ff0000', 'display_svg() First svg should be red');
this.test.assertEquals(colors && colors[1], '#000000', 'display_svg() Second svg should be black');
this.assert_colors_equal('#ff0000', colors && colors[0], 'display_svg() First svg should be red');
this.assert_colors_equal('#000000', colors && colors[1], 'display_svg() Second svg should be black');
});
// now ensure that we can pass the same metadata dict to plain old display()
this.thenEvaluate(function () {
var cell = IPython.notebook.get_cell(0);
cell.clear_output();
cell.set_text( "from IPython.display import display\n"
+ "display(SVG(s1), metadata=dict(isolated=True))\n"
+ "display(SVG(s2), metadata=dict(isolated=True))\n"
cell.set_text( "from IPython.display import display\n" +
"display(SVG(s1), metadata=dict(isolated=True))\n" +
"display(SVG(s2), metadata=dict(isolated=True))\n"
);
cell.execute();
});
@ -85,13 +84,12 @@ casper.notebook_test(function () {
var colors = [];
var ifr = __utils__.findAll("iframe");
var svg1 = ifr[0].contentWindow.document.getElementById('r1');
colors[0] = window.getComputedStyle(svg1)["fill"];
colors[0] = window.getComputedStyle(svg1).fill;
var svg2 = ifr[1].contentWindow.document.getElementById('r2');
colors[1] = window.getComputedStyle(svg2)["fill"];
colors[1] = window.getComputedStyle(svg2).fill;
return colors;
});
this.test.assertEquals(colors && colors[0], '#ff0000', 'display() First svg should be red');
this.test.assertEquals(colors && colors[1], '#000000', 'display() Second svg should be black');
this.assert_colors_equal('#ff0000', colors && colors[0], 'display() First svg should be red');
this.assert_colors_equal('#000000', colors && colors[1], 'display() Second svg should be black');
});
});

@ -25,7 +25,7 @@ casper.notebook_test(function () {
this.then(function () {
var output = this.get_output_cell(0);
this.test.assert(messages.length > 0, "Captured log message");
this.test.assertEquals(messages[messages.length-1], "Invalid type for image/png 5", "Logged Invalid type message");
this.test.assertEquals(messages[messages.length-1].substr(0,26), "Invalid type for image/png", "Logged Invalid type message");
this.test.assertEquals(output['image/png'], undefined, "Non-string png data was stripped");
this.test.assertEquals(output['text/plain'], '5', "text data is fine");
});

@ -1,7 +1,6 @@
//
// Utility functions for the HTML notebook's CasperJS tests.
//
casper.get_notebook_server = function () {
// Get the URL of a notebook server on which to run tests.
port = casper.cli.get("port");
@ -32,6 +31,15 @@ casper.open_new_notebook = function () {
IPython._status = 'busy';
});
});
// Because of the asynchronous nature of SlimerJS (Gecko), we need to make
// sure the notebook has actually been loaded into the IPython namespace
// before running any tests.
this.waitFor(function() {
return this.evaluate(function () {
return IPython.notebook;
});
});
};
casper.kernel_running = function kernel_running() {
@ -409,11 +417,63 @@ casper.cell_has_class = function(index, classes) {
}, {i : index, c: classes});
};
casper.is_cell_rendered = function (index) {
return this.evaluate(function(i) {
return !!IPython.notebook.get_cell(i).rendered;
}, {i:index});
};
casper.assert_colors_equal = function (hex_color, local_color, msg) {
// Tests to see if two colors are equal.
//
// Parameters
// hex_color: string
// Hexadecimal color code, with or without preceeding hash character.
// local_color: string
// Local color representation. Can either be hexadecimal (default for
// phantom) or rgb (default for slimer).
// Remove parentheses, hashes, semi-colons, and space characters.
hex_color = hex_color.replace(/[\(\); #]/, '');
local_color = local_color.replace(/[\(\); #]/, '');
// If the local color is rgb, clean it up and replace
if (local_color.substr(0,3).toLowerCase() == 'rgb') {
components = local_color.substr(3).split(',');
local_color = '';
for (var i = 0; i < components.length; i++) {
var part = parseInt(components[i]).toString(16);
while (part.length < 2) part = '0' + part;
local_color += part;
}
}
this.test.assertEquals(hex_color.toUpperCase(), local_color.toUpperCase(), msg);
};
casper.notebook_test = function(test) {
// Wrap a notebook test to reduce boilerplate.
this.open_new_notebook();
this.then(test);
// Echo whether or not we are running this test using SlimerJS
if (this.evaluate(function(){
return typeof InstallTrigger !== 'undefined'; // Firefox 1.0+
})) {
console.log('This test is running in SlimerJS.');
this.slimerjs = true;
}
// Make sure to remove the onbeforeunload callback. This callback is
// responsible for the "Are you sure you want to quit?" type messages.
// PhantomJS ignores these prompts, SlimerJS does not which causes hangs.
this.then(function(){
this.evaluate(function(){
window.onbeforeunload = function(){};
});
});
this.then(test);
// Kill the kernel and delete the notebook.
this.shutdown_current_kernel();
// This is still broken but shouldn't be a problem for now.

@ -1,9 +1,15 @@
var xor = function (a, b) {return !a ^ !b;};
var isArray = function (a) {return toString.call(a) === "[object Array]" || toString.call(a) === "[object RuntimeArray]";};
var isArray = function (a) {
try {
return Object.toString.call(a) === "[object Array]" || Object.toString.call(a) === "[object RuntimeArray]";
} catch (e) {
return Array.isArray(a);
}
};
var recursive_compare = function(a, b) {
// Recursively compare two objects.
var same = true;
same = same && !xor(a instanceof Object, b instanceof Object);
same = same && !xor(a instanceof Object || typeof a == 'object', b instanceof Object || typeof b == 'object');
same = same && !xor(isArray(a), isArray(b));
if (same) {

@ -14,7 +14,11 @@ casper.notebook_test(function () {
});
test_jpg = '/9j/4AAQSkZJRgABAQEASABIAAD//gATQ3JlYXRlZCB3aXRoIEdJTVD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wgARCAABAAEDAREAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAAA//EABUBAQEAAAAAAAAAAAAAAAAAAAME/9oADAMBAAIQAxAAAAECv//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAQUCf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Bf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Bf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEABj8Cf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAT8hf//aAAwDAQACAAMAAAAQn//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Qf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Qf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAT8Qf//Z';
test_results = '/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAyADIDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDi6KKK+ZP3EKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA//Z';
// It has been verified that both of the following are the correct image.
// Unfortunately, SlimerJS and PhantomJS disagree on a byte by byte level.
test_results_phantom = '/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAyADIDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDi6KKK+ZP3EKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA//Z';
test_results_slimer = '/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAyADIDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDzqiiivjz+kQooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD//2Q==';
var image_index = this.append_cell(
'import base64\n' +
@ -55,6 +59,7 @@ casper.notebook_test(function () {
// Uncomment line below to output captured image data to a text file.
// fs.write('./captured.txt', captured, 'w');
this.test.assertEquals(test_results, captured, "Red image data displayed correctly.");
var match = captured == test_results_phantom || captured == test_results_slimer;
this.test.assert(match, "Red image data displayed correctly.");
});
});

@ -108,8 +108,11 @@ casper.notebook_test(function () {
// Clear the int textbox value and then set it to 1 by emulating
// keyboard presses.
this.cell_element_function(int_text2.index, int_text2.query, 'val', ['']);
this.sendKeys(int_text2.query, '1');
this.evaluate(function(q){
var textbox = IPython.notebook.element.find(q);
textbox.val('1');
textbox.trigger('keyup');
}, {q: int_text2.query});
});
this.wait_for_widget(int_text2);
@ -121,8 +124,11 @@ casper.notebook_test(function () {
// Clear the int textbox value and then set it to 120 by emulating
// keyboard presses.
this.cell_element_function(int_text2.index, int_text2.query, 'val', ['']);
this.sendKeys(int_text2.query, '120');
this.evaluate(function(q){
var textbox = IPython.notebook.element.find(q);
textbox.val('120');
textbox.trigger('keyup');
}, {q: int_text2.query});
});
this.wait_for_widget(int_text2);
@ -134,8 +140,11 @@ casper.notebook_test(function () {
// Clear the int textbox value and then set it to 'hello world' by
// emulating keyboard presses. 'hello world' should get filtered...
this.cell_element_function(int_text2.index, int_text2.query, 'val', ['']);
this.sendKeys(int_text2.query, 'hello world');
this.evaluate(function(q){
var textbox = IPython.notebook.element.find(q);
textbox.val('hello world');
textbox.trigger('keyup');
}, {q: int_text2.query});
});
this.wait_for_widget(int_text2);

@ -148,6 +148,8 @@ have['jinja2'] = test_for('jinja2')
have['requests'] = test_for('requests')
have['sphinx'] = test_for('sphinx')
have['casperjs'] = is_cmd_found('casperjs')
have['phantomjs'] = is_cmd_found('phantomjs')
have['slimerjs'] = is_cmd_found('slimerjs')
min_zmq = (2,1,11)

@ -20,12 +20,14 @@ import signal
import sys
import subprocess
import time
import re
from .iptest import have, test_group_names as py_test_group_names, test_sections, StreamCapturer
from IPython.utils.path import compress_user
from IPython.utils.py3compat import bytes_to_str
from IPython.utils.sysinfo import get_sys_info
from IPython.utils.tempdir import TemporaryDirectory
from IPython.nbconvert.filters.ansi import strip_ansi
try:
# Python >= 3.3
@ -133,6 +135,7 @@ class TestController(object):
__del__ = cleanup
class PyTestController(TestController):
"""Run Python tests using IPython.testing.iptest"""
#: str, Python command to execute in subprocess
@ -199,6 +202,7 @@ class PyTestController(TestController):
self.cmd[2] = self.pycmd
super(PyTestController, self).launch(buffer_output=buffer_output)
js_prefix = 'js/'
def get_js_test_dir():
@ -214,15 +218,19 @@ def all_js_groups():
class JSController(TestController):
"""Run CasperJS tests """
requirements = ['zmq', 'tornado', 'jinja2', 'casperjs', 'sqlite3']
def __init__(self, section, enabled=True):
display_slimer_output = False
def __init__(self, section, enabled=True, engine='phantomjs'):
"""Create new test runner."""
TestController.__init__(self)
self.engine = engine
self.section = section
self.enabled = enabled
self.slimer_failure = re.compile('^FAIL.*', flags=re.MULTILINE)
js_test_dir = get_js_test_dir()
includes = '--includes=' + os.path.join(js_test_dir,'util.js')
test_cases = os.path.join(js_test_dir, self.section[len(js_prefix):])
self.cmd = ['casperjs', 'test', includes, test_cases]
self.cmd = ['casperjs', 'test', includes, test_cases, '--engine=%s' % self.engine]
def setup(self):
self.ipydir = TemporaryDirectory()
@ -240,13 +248,39 @@ class JSController(TestController):
else:
# don't launch tests if the server didn't start
self.cmd = [sys.executable, '-c', 'raise SystemExit(1)']
def launch(self, buffer_output):
# If the engine is SlimerJS, we need to buffer the output because
# SlimerJS does not support exit codes, so CasperJS always returns 0.
if self.engine == 'slimerjs' and not buffer_output:
self.display_slimer_output = True
return super(JSController, self).launch(buffer_output=True)
else:
return super(JSController, self).launch(buffer_output=buffer_output)
def wait(self, *pargs, **kwargs):
"""Wait for the JSController to finish"""
ret = super(JSController, self).wait(*pargs, **kwargs)
# If this is a SlimerJS controller, check the captured stdout for
# errors. Otherwise, just return the return code.
if self.engine == 'slimerjs':
stdout = bytes_to_str(self.stdout)
if self.display_slimer_output:
print(stdout)
if ret != 0:
# This could still happen e.g. if it's stopped by SIGINT
return ret
return bool(self.slimer_failure.search(strip_ansi(stdout)))
else:
return ret
def print_extra_info(self):
print("Running tests with notebook directory %r" % self.nbdir.name)
@property
def will_run(self):
return self.enabled and all(have[a] for a in self.requirements)
return self.enabled and all(have[a] for a in self.requirements + [self.engine])
def _init_server(self):
"Start the notebook server in a separate process"
@ -350,7 +384,8 @@ def prepare_controllers(options):
else:
js_testgroups = all_js_groups()
c_js = [JSController(name) for name in js_testgroups]
engine = 'slimerjs' if options.slimerjs else 'phantomjs'
c_js = [JSController(name, engine=engine) for name in js_testgroups]
c_py = [PyTestController(name, options) for name in py_testgroups]
controllers = c_py + c_js
@ -455,6 +490,9 @@ def run_iptestall(options):
Include slow tests, like IPython.parallel. By default, these tests aren't
run.
slimerjs : bool
Use slimerjs if it's installed instead of phantomjs for casperjs tests.
xunit : bool
Produce Xunit XML output. This is written to multiple foo.xunit.xml files.
@ -581,6 +619,8 @@ argparser.add_argument('testgroups', nargs='*',
'all tests.')
argparser.add_argument('--all', action='store_true',
help='Include slow tests not run by default.')
argparser.add_argument('--slimerjs', action='store_true',
help="Use slimerjs if it's installed instead of phantomjs for casperjs tests.")
argparser.add_argument('-j', '--fast', nargs='?', const=None, default=1, type=int,
help='Run test sections in parallel. This starts as many '
'processes as you have cores, or you can specify a number.')

Loading…
Cancel
Save