mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2025-01-05 19:53:55 +03:00
Add support for testing in more worker types (#3804)
Co-authored-by: Liam Murphy <43807659+Liamolucko@users.noreply.github.com>
This commit is contained in:
parent
1942791d88
commit
0979fea92b
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@ yarn.lock
|
||||
/publish
|
||||
/publish.exe
|
||||
.vscode
|
||||
webdriver.json
|
||||
|
@ -3,6 +3,11 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
* Added support for running tests in shared and service workers with ``wasm_bindgen_test_configure!` `run_in_shared_worker` and `run_in_service_worker`.
|
||||
[#3804](https://github.com/rustwasm/wasm-bindgen/pull/3804)
|
||||
|
||||
### Changed
|
||||
|
||||
* Stabilize `ClipboardEvent`.
|
||||
@ -11,6 +16,9 @@
|
||||
* Use immutable buffers in `SubtleCrypto` methods.
|
||||
[#3797](https://github.com/rustwasm/wasm-bindgen/pull/3797)
|
||||
|
||||
* Deprecate `wasm_bindgen_test_configure!`s `run_in_worker` in favor of `run_in_dedicated_worker`.
|
||||
[#3804](https://github.com/rustwasm/wasm-bindgen/pull/3804)
|
||||
|
||||
## [0.2.90](https://github.com/rustwasm/wasm-bindgen/compare/0.2.89...0.2.90)
|
||||
|
||||
Released 2024-01-06
|
||||
|
@ -30,7 +30,29 @@ enum TestMode {
|
||||
Node,
|
||||
Deno,
|
||||
Browser { no_modules: bool },
|
||||
Worker { no_modules: bool },
|
||||
DedicatedWorker { no_modules: bool },
|
||||
SharedWorker { no_modules: bool },
|
||||
ServiceWorker { no_modules: bool },
|
||||
}
|
||||
|
||||
impl TestMode {
|
||||
fn is_worker(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::DedicatedWorker { .. } | Self::SharedWorker { .. } | Self::ServiceWorker { .. }
|
||||
)
|
||||
}
|
||||
|
||||
fn no_modules(self) -> bool {
|
||||
match self {
|
||||
Self::Node => true,
|
||||
Self::Deno => true,
|
||||
Self::Browser { no_modules }
|
||||
| Self::DedicatedWorker { no_modules }
|
||||
| Self::SharedWorker { no_modules }
|
||||
| Self::ServiceWorker { no_modules } => no_modules,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TmpDirDeleteGuard(PathBuf);
|
||||
@ -120,7 +142,13 @@ fn main() -> anyhow::Result<()> {
|
||||
Some(section) if section.data.contains(&0x01) => TestMode::Browser {
|
||||
no_modules: std::env::var("WASM_BINDGEN_USE_NO_MODULE").is_ok(),
|
||||
},
|
||||
Some(section) if section.data.contains(&0x10) => TestMode::Worker {
|
||||
Some(section) if section.data.contains(&0x02) => TestMode::DedicatedWorker {
|
||||
no_modules: std::env::var("WASM_BINDGEN_USE_NO_MODULE").is_ok(),
|
||||
},
|
||||
Some(section) if section.data.contains(&0x03) => TestMode::SharedWorker {
|
||||
no_modules: std::env::var("WASM_BINDGEN_USE_NO_MODULE").is_ok(),
|
||||
},
|
||||
Some(section) if section.data.contains(&0x04) => TestMode::ServiceWorker {
|
||||
no_modules: std::env::var("WASM_BINDGEN_USE_NO_MODULE").is_ok(),
|
||||
},
|
||||
Some(_) => bail!("invalid __wasm_bingen_test_unstable value"),
|
||||
@ -175,11 +203,15 @@ fn main() -> anyhow::Result<()> {
|
||||
match test_mode {
|
||||
TestMode::Node => b.nodejs(true)?,
|
||||
TestMode::Deno => b.deno(true)?,
|
||||
TestMode::Browser { no_modules: false } | TestMode::Worker { no_modules: false } => {
|
||||
b.web(true)?
|
||||
}
|
||||
TestMode::Browser { no_modules: true } | TestMode::Worker { no_modules: true } => {
|
||||
b.no_modules(true)?
|
||||
TestMode::Browser { .. }
|
||||
| TestMode::DedicatedWorker { .. }
|
||||
| TestMode::SharedWorker { .. }
|
||||
| TestMode::ServiceWorker { .. } => {
|
||||
if test_mode.no_modules() {
|
||||
b.no_modules(true)?
|
||||
} else {
|
||||
b.web(true)?
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -200,7 +232,10 @@ fn main() -> anyhow::Result<()> {
|
||||
match test_mode {
|
||||
TestMode::Node => node::execute(module, &tmpdir, &args, &tests)?,
|
||||
TestMode::Deno => deno::execute(module, &tmpdir, &args, &tests)?,
|
||||
TestMode::Browser { no_modules } | TestMode::Worker { no_modules } => {
|
||||
TestMode::Browser { .. }
|
||||
| TestMode::DedicatedWorker { .. }
|
||||
| TestMode::SharedWorker { .. }
|
||||
| TestMode::ServiceWorker { .. } => {
|
||||
let srv = server::spawn(
|
||||
&if headless {
|
||||
"127.0.0.1:0".parse().unwrap()
|
||||
@ -214,8 +249,7 @@ fn main() -> anyhow::Result<()> {
|
||||
&tmpdir,
|
||||
&args,
|
||||
&tests,
|
||||
no_modules,
|
||||
matches!(test_mode, TestMode::Worker { no_modules: _ }),
|
||||
test_mode,
|
||||
)
|
||||
.context("failed to spawn server")?;
|
||||
let addr = srv.server_addr();
|
||||
|
@ -7,19 +7,20 @@ use std::path::Path;
|
||||
use anyhow::{anyhow, Context, Error};
|
||||
use rouille::{Request, Response, Server};
|
||||
|
||||
pub fn spawn(
|
||||
use crate::TestMode;
|
||||
|
||||
pub(crate) fn spawn(
|
||||
addr: &SocketAddr,
|
||||
headless: bool,
|
||||
module: &'static str,
|
||||
tmpdir: &Path,
|
||||
args: &[OsString],
|
||||
tests: &[String],
|
||||
no_module: bool,
|
||||
worker: bool,
|
||||
test_mode: TestMode,
|
||||
) -> Result<Server<impl Fn(&Request) -> Response + Send + Sync>, Error> {
|
||||
let mut js_to_execute = String::new();
|
||||
|
||||
let wbg_import_script = if no_module {
|
||||
let wbg_import_script = if test_mode.no_modules() {
|
||||
String::from(
|
||||
r#"
|
||||
let Context = wasm_bindgen.WasmBindgenTestContext;
|
||||
@ -48,8 +49,8 @@ pub fn spawn(
|
||||
)
|
||||
};
|
||||
|
||||
if worker {
|
||||
let mut worker_script = if no_module {
|
||||
if test_mode.is_worker() {
|
||||
let mut worker_script = if test_mode.no_modules() {
|
||||
format!(r#"importScripts("{0}.js");"#, module)
|
||||
} else {
|
||||
String::new()
|
||||
@ -57,6 +58,25 @@ pub fn spawn(
|
||||
|
||||
worker_script.push_str(&wbg_import_script);
|
||||
|
||||
match test_mode {
|
||||
TestMode::DedicatedWorker { .. } => worker_script.push_str("const port = self\n"),
|
||||
TestMode::SharedWorker { .. } => worker_script.push_str(
|
||||
r#"
|
||||
addEventListener('connect', (e) => {
|
||||
const port = e.ports[0]
|
||||
"#,
|
||||
),
|
||||
TestMode::ServiceWorker { .. } => worker_script.push_str(
|
||||
r#"
|
||||
addEventListener('install', (e) => skipWaiting());
|
||||
addEventListener('activate', (e) => e.waitUntil(clients.claim()));
|
||||
addEventListener('message', (e) => {
|
||||
const port = e.ports[0]
|
||||
"#,
|
||||
),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
worker_script.push_str(&format!(
|
||||
r#"
|
||||
const wrap = method => {{
|
||||
@ -65,7 +85,7 @@ pub fn spawn(
|
||||
if (self[on_method]) {{
|
||||
self[on_method](args);
|
||||
}}
|
||||
postMessage(["__wbgtest_" + method, args]);
|
||||
port.postMessage(["__wbgtest_" + method, args]);
|
||||
}};
|
||||
}};
|
||||
|
||||
@ -73,7 +93,7 @@ pub fn spawn(
|
||||
self.__wbg_test_output = "";
|
||||
self.__wbg_test_output_writeln = function (line) {{
|
||||
self.__wbg_test_output += line + "\n";
|
||||
postMessage(["__wbgtest_output", self.__wbg_test_output]);
|
||||
port.postMessage(["__wbgtest_output", self.__wbg_test_output]);
|
||||
}}
|
||||
|
||||
wrap("debug");
|
||||
@ -97,7 +117,7 @@ pub fn spawn(
|
||||
await cx.run(tests.map(s => wasm[s]));
|
||||
}}
|
||||
|
||||
onmessage = function(e) {{
|
||||
port.onmessage = function(e) {{
|
||||
let tests = e.data;
|
||||
run_in_worker(tests);
|
||||
}}
|
||||
@ -105,7 +125,19 @@ pub fn spawn(
|
||||
module, args,
|
||||
));
|
||||
|
||||
let worker_js_path = tmpdir.join("worker.js");
|
||||
if matches!(
|
||||
test_mode,
|
||||
TestMode::SharedWorker { .. } | TestMode::ServiceWorker { .. }
|
||||
) {
|
||||
worker_script.push_str("})");
|
||||
}
|
||||
|
||||
let name = if matches!(test_mode, TestMode::ServiceWorker { .. }) {
|
||||
"service.js"
|
||||
} else {
|
||||
"worker.js"
|
||||
};
|
||||
let worker_js_path = tmpdir.join(name);
|
||||
fs::write(worker_js_path, worker_script).context("failed to write JS file")?;
|
||||
|
||||
js_to_execute.push_str(&format!(
|
||||
@ -114,9 +146,9 @@ pub fn spawn(
|
||||
// status text as at this point we should be asynchronously fetching the
|
||||
// wasm module.
|
||||
document.getElementById('output').textContent = "Loading wasm module...";
|
||||
const worker = new Worker("worker.js", {{type: "{}"}});
|
||||
{}
|
||||
|
||||
worker.addEventListener("message", function(e) {{
|
||||
port.addEventListener("message", function(e) {{
|
||||
// Checking the whether the message is from wasm_bindgen_test
|
||||
if(
|
||||
e.data &&
|
||||
@ -141,12 +173,54 @@ pub fn spawn(
|
||||
}});
|
||||
|
||||
async function main(test) {{
|
||||
worker.postMessage(test)
|
||||
port.postMessage(test)
|
||||
}}
|
||||
|
||||
const tests = [];
|
||||
"#,
|
||||
if no_module { "classic" } else { "module" }
|
||||
{
|
||||
let module = if test_mode.no_modules() {
|
||||
"classic"
|
||||
} else {
|
||||
"module"
|
||||
};
|
||||
|
||||
match test_mode {
|
||||
TestMode::DedicatedWorker { .. } => {
|
||||
format!("const port = new Worker('worker.js', {{type: '{module}'}});\n")
|
||||
}
|
||||
TestMode::SharedWorker { .. } => {
|
||||
format!(
|
||||
r#"
|
||||
const worker = new SharedWorker("worker.js?random=" + crypto.randomUUID(), {{type: "{module}"}});
|
||||
const port = worker.port;
|
||||
port.start();
|
||||
"#
|
||||
)
|
||||
}
|
||||
TestMode::ServiceWorker { .. } => {
|
||||
format!(
|
||||
r#"
|
||||
const url = "service.js?random=" + crypto.randomUUID();
|
||||
await navigator.serviceWorker.register(url, {{type: "{module}"}});
|
||||
await new Promise((resolve) => {{
|
||||
navigator.serviceWorker.addEventListener('controllerchange', () => {{
|
||||
if (navigator.serviceWorker.controller.scriptURL != location.href + url) {{
|
||||
throw "`wasm-bindgen-test-runner` does not support running multiple service worker tests at the same time"
|
||||
}}
|
||||
resolve();
|
||||
}});
|
||||
}});
|
||||
const channel = new MessageChannel();
|
||||
navigator.serviceWorker.controller.postMessage(undefined, [channel.port2]);
|
||||
const port = channel.port1;
|
||||
port.start();
|
||||
"#
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
));
|
||||
} else {
|
||||
js_to_execute.push_str(&wbg_import_script);
|
||||
@ -203,7 +277,7 @@ pub fn spawn(
|
||||
} else {
|
||||
include_str!("index.html")
|
||||
};
|
||||
let s = if no_module {
|
||||
let s = if !test_mode.is_worker() && test_mode.no_modules() {
|
||||
s.replace(
|
||||
"<!-- {IMPORT_SCRIPTS} -->",
|
||||
&format!(
|
||||
|
@ -35,7 +35,11 @@ macro_rules! console_log {
|
||||
///
|
||||
/// * `run_in_browser` - requires that this test is run in a browser rather than
|
||||
/// node.js, which is the default for executing tests.
|
||||
/// * `run_in_worker` - requires that this test is run in a web worker rather than
|
||||
/// * `run_in_dedicated_worker` - requires that this test is run in a web worker rather than
|
||||
/// node.js, which is the default for executing tests.
|
||||
/// * `run_in_shared_worker` - requires that this test is run in a shared worker rather than
|
||||
/// node.js, which is the default for executing tests.
|
||||
/// * `run_in_service_worker` - requires that this test is run in a service worker rather than
|
||||
/// node.js, which is the default for executing tests.
|
||||
///
|
||||
/// This macro may be invoked at most one time per test suite (an entire binary
|
||||
@ -51,7 +55,25 @@ macro_rules! wasm_bindgen_test_configure {
|
||||
(run_in_worker $($others:tt)*) => (
|
||||
#[link_section = "__wasm_bindgen_test_unstable"]
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub static __WBG_TEST_RUN_IN_WORKER: [u8; 1] = [0x10];
|
||||
pub static __WBG_TEST_RUN_IN_DEDICATED_WORKER: [u8; 1] = [0x02];
|
||||
$crate::wasm_bindgen_test_configure!($($others)*);
|
||||
);
|
||||
(run_in_dedicated_worker $($others:tt)*) => (
|
||||
#[link_section = "__wasm_bindgen_test_unstable"]
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub static __WBG_TEST_RUN_IN_DEDICATED_WORKER: [u8; 1] = [0x02];
|
||||
$crate::wasm_bindgen_test_configure!($($others)*);
|
||||
);
|
||||
(run_in_shared_worker $($others:tt)*) => (
|
||||
#[link_section = "__wasm_bindgen_test_unstable"]
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub static __WBG_TEST_RUN_IN_SHARED_WORKER: [u8; 1] = [0x03];
|
||||
$crate::wasm_bindgen_test_configure!($($others)*);
|
||||
);
|
||||
(run_in_service_worker $($others:tt)*) => (
|
||||
#[link_section = "__wasm_bindgen_test_unstable"]
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub static __WBG_TEST_RUN_IN_SERVICE_WORKER: [u8; 1] = [0x04];
|
||||
$crate::wasm_bindgen_test_configure!($($others)*);
|
||||
);
|
||||
() => ()
|
||||
|
@ -24,7 +24,9 @@ pub fn detect() -> Runtime {
|
||||
// only be true in browsers.
|
||||
match js_sys::global().unchecked_into::<This>().self_() {
|
||||
Some(scope) => match scope.constructor().name().as_str() {
|
||||
"DedicatedWorkerGlobalScope" | "SharedWorkerGlobalScope" => Runtime::Worker,
|
||||
"DedicatedWorkerGlobalScope"
|
||||
| "SharedWorkerGlobalScope"
|
||||
| "ServiceWorkerGlobalScope" => Runtime::Worker,
|
||||
_ => Runtime::Browser,
|
||||
},
|
||||
None => Runtime::Node,
|
||||
|
@ -17,7 +17,12 @@ snippet.
|
||||
```rust
|
||||
use wasm_bindgen_test::wasm_bindgen_test_configure;
|
||||
|
||||
wasm_bindgen_test_configure!(run_in_worker);
|
||||
// Run in dedicated worker.
|
||||
wasm_bindgen_test_configure!(run_in_dedicated_worker);
|
||||
// Or run in shared worker.
|
||||
wasm_bindgen_test_configure!(run_in_shared_worker);
|
||||
// Or run in service worker.
|
||||
wasm_bindgen_test_configure!(run_in_service_worker);
|
||||
```
|
||||
|
||||
Note that although a particular test crate must target either headless browsers
|
||||
@ -27,9 +32,11 @@ project by using multiple test crates. For example:
|
||||
```
|
||||
$MY_CRATE/
|
||||
`-- tests
|
||||
|-- node.rs # The tests in this suite use the default Node.js.
|
||||
|-- worker.rs # The tests in this suite are configured for workers.
|
||||
`-- web.rs # The tests in this suite are configured for browsers.
|
||||
|-- node.rs # The tests in this suite use the default Node.js.
|
||||
|-- dedicated_worker.rs # The tests in this suite are configured for dedicated workers.
|
||||
|-- shared_worker.rs # The tests in this suite are configured for shared workers.
|
||||
|-- service_worker.rs # The tests in this suite are configured for service workers.
|
||||
`-- web.rs # The tests in this suite are configured for browsers.
|
||||
```
|
||||
|
||||
## Configuring Which Browser is Used
|
||||
@ -86,12 +93,6 @@ Full list supported capabilities can be found:
|
||||
|
||||
Note that the `headless` argument is always enabled for both browsers.
|
||||
|
||||
You have to enable the special preference `dom.workers.modules.enabled` for
|
||||
firefox when running the tests in Web Workers without using
|
||||
`WASM_BINDGEN_USE_NO_MODULE` variable. Because firefox supported
|
||||
ECMAScript modules in last release (2023-03-14) behind a special
|
||||
preference.
|
||||
|
||||
### Debugging Headless Browser Tests
|
||||
|
||||
Omitting the `--headless` flag will disable headless mode, and allow you to
|
||||
|
18
tests/worker/dedicated.rs
Normal file
18
tests/worker/dedicated.rs
Normal file
@ -0,0 +1,18 @@
|
||||
#![cfg(target_arch = "wasm32")]
|
||||
|
||||
extern crate js_sys;
|
||||
extern crate wasm_bindgen;
|
||||
extern crate wasm_bindgen_test;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_test::wasm_bindgen_test_configure;
|
||||
|
||||
wasm_bindgen_test_configure!(run_in_dedicated_worker);
|
||||
|
||||
pub mod modules;
|
||||
|
||||
// should not be executed
|
||||
#[wasm_bindgen(start)]
|
||||
fn start() {
|
||||
panic!();
|
||||
}
|
18
tests/worker/service.rs
Normal file
18
tests/worker/service.rs
Normal file
@ -0,0 +1,18 @@
|
||||
#![cfg(target_arch = "wasm32")]
|
||||
|
||||
extern crate js_sys;
|
||||
extern crate wasm_bindgen;
|
||||
extern crate wasm_bindgen_test;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_test::wasm_bindgen_test_configure;
|
||||
|
||||
wasm_bindgen_test_configure!(run_in_service_worker);
|
||||
|
||||
pub mod modules;
|
||||
|
||||
// should not be executed
|
||||
#[wasm_bindgen(start)]
|
||||
fn start() {
|
||||
panic!();
|
||||
}
|
@ -7,7 +7,7 @@ extern crate wasm_bindgen_test;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen_test::wasm_bindgen_test_configure;
|
||||
|
||||
wasm_bindgen_test_configure!(run_in_worker);
|
||||
wasm_bindgen_test_configure!(run_in_shared_worker);
|
||||
|
||||
pub mod modules;
|
||||
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"moz:firefoxOptions": {
|
||||
"prefs": {
|
||||
"dom.workers.modules.enabled": true
|
||||
},
|
||||
"args": []
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user