Add support for headless testing

This commit adds support to the `wasm-bindgen-test-runner` binary to
perform headless testing via browsers. The previous commit introduced a
local server to serve up files and run tests in a browser, and this
commit adds support for executing that in an automated fashion.

The general idea here is that each browser has a binary that implements
the WebDriver specification. These binaries (typically `foodriver` for
the browser "Foo") are interfaced with using HTTP and JSON messages. The
implementation was simple enough and the crates.io support was lacking
enough that a small implementation of the WebDriver protocol was added
directly to this crate.

Currently Firefox (`geckodriver`), Chrome (`chromedriver`), and Safari
(`safaridriver`) are supported for running tests. The test harness will
recognize env vars like `GECKODRIVER=foo` to specifically use one or
otherwise detects the first driver in `PATH`. Eventually we may wish to
automatically download a driver if one isn't found, but that isn't
implemented yet.

Headless testing is turned on with the `CI=1` env var currently to be
amenable with things like Travis and AppVeyor, but this may wish to grow
an explicit option to run headless tests in the future.
This commit is contained in:
Alex Crichton
2018-07-25 03:34:35 -07:00
parent 8fc40e4c0f
commit 7b4f0072c8
11 changed files with 674 additions and 83 deletions

View File

@ -0,0 +1,3 @@
export function is_array_values_supported() {
return typeof Array.prototype.values === 'function';
}

View File

@ -1,61 +1,48 @@
#![cfg(not(target_arch = "wasm32"))]
#![allow(non_snake_case)]
#![feature(use_extern_macros)]
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test_project_builder as project_builder;
extern crate wasm_bindgen_test;
extern crate wasm_bindgen;
extern crate js_sys;
fn project() -> project_builder::Project {
let mut p = project_builder::project();
p.add_local_dependency("js-sys", env!("CARGO_MANIFEST_DIR"));
return p
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;
use js_sys::Array;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen(module = "./tests/headless.js")]
extern {
fn is_array_values_supported()-> bool;
}
// NB: currently this older test suite is only used for tests which require
// headless browser support, otherwise all new tests should go in the `wasm`
// test suite next to this one.
#[wasm_bindgen]
extern {
type ValuesIterator;
#[wasm_bindgen(method, structural)]
fn next(this: &ValuesIterator) -> IterNext;
#[test]
fn ArrayIterator_values() {
let mut project = project();
project.file(
"src/lib.rs",
r#"
#![feature(use_extern_macros)]
type IterNext;
extern crate wasm_bindgen;
extern crate js_sys;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn get_values(this: &js_sys::Array) -> js_sys::Iterator {
this.values()
}
"#,
)
.file(
"test.js",
r#"
import * as assert from "assert";
import * as wasm from "./out";
export function test() {
if (typeof Array.prototype.values !== "function") {
return;
}
let numbers = [8, 3, 2];
let wasmIterator = wasm.get_values(numbers);
assert.equal(wasmIterator.next().value, 8);
assert.equal(wasmIterator.next().value, 3);
assert.equal(wasmIterator.next().value, 2);
assert.ok(wasmIterator.next().done);
}
"#,
);
let mut headless = project.clone();
headless.headless(true);
project.test();
headless.test();
#[wasm_bindgen(method, getter, structural)]
fn value(this: &IterNext) -> JsValue;
#[wasm_bindgen(method, getter, structural)]
fn done(this: &IterNext) -> bool;
}
#[wasm_bindgen_test]
fn array_iterator_values() {
if !is_array_values_supported() {
return
}
let array = Array::new();
array.push(&8.into());
array.push(&3.into());
array.push(&2.into());
let iter = ValuesIterator::from(JsValue::from(array.values()));
assert_eq!(iter.next().value(), 8);
assert_eq!(iter.next().value(), 3);
assert_eq!(iter.next().value(), 2);
assert!(iter.next().done());
}

View File

@ -11,7 +11,7 @@ extern {
#[wasm_bindgen(method, getter, structural)]
pub fn push(this: &ArrayPrototype) -> Function;
#[wasm_bindgen(js_name = prototype, js_namespace = Array)]
static ARRAY_PROTOTYPE: ArrayPrototype;
static ARRAY_PROTOTYPE2: ArrayPrototype;
}
#[wasm_bindgen_test]
@ -25,7 +25,7 @@ fn apply() {
let arr = JsValue::from(Array::new());
let args = Array::new();
args.push(&1.into());
ARRAY_PROTOTYPE.push().apply(&arr, &args).unwrap();
ARRAY_PROTOTYPE2.push().apply(&arr, &args).unwrap();
assert_eq!(Array::from(&arr).length(), 1);
}
@ -47,13 +47,13 @@ fn bind() {
#[wasm_bindgen_test]
fn length() {
assert_eq!(MAX.length(), 2);
assert_eq!(ARRAY_PROTOTYPE.push().length(), 1);
assert_eq!(ARRAY_PROTOTYPE2.push().length(), 1);
}
#[wasm_bindgen_test]
fn name() {
assert_eq!(JsValue::from(MAX.name()), "max");
assert_eq!(JsValue::from(ARRAY_PROTOTYPE.push().name()), "push");
assert_eq!(JsValue::from(ARRAY_PROTOTYPE2.push().name()), "push");
}
#[wasm_bindgen_test]