deno/cli/tests/workers_test.ts
Bartek Iwańczuk ee452ad883
add assertOps sanitizer in cli/js/ unit tests (#4209)
* add "assertOps" test assertion which makes sure test case
  is not "leaking" ops - ie. after test finishes there are no 
  pending async ops

* apply "assertOps" to all tests in "cli/js/"

* fix numerous tests leaking ops

* document problem with edge case in "clearInterval"
   and "clearTimeout" implementation where they
   may leak async ops

* move "cli/js/worker_test.ts" to "cli/tests/worker_test.ts" and 
  run as integration test; workers leak ops because of missing
  "terminate" implementation
2020-03-03 18:22:53 +01:00

116 lines
3.2 KiB
TypeScript

// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
// Requires to be run with `--allow-net` flag
// FIXME(bartlomieju): this file is an integration test only because
// workers are leaking ops at the moment - `worker.terminate()` is not
// yet implemented. Once it gets implemented this file should be
// again moved to `cli/js/` as an unit test file.
import { assert, assertEquals } from "../../std/testing/asserts.ts";
export interface ResolvableMethods<T> {
resolve: (value?: T | PromiseLike<T>) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
reject: (reason?: any) => void;
}
export type Resolvable<T> = Promise<T> & ResolvableMethods<T>;
export function createResolvable<T>(): Resolvable<T> {
let methods: ResolvableMethods<T>;
const promise = new Promise<T>((resolve, reject): void => {
methods = { resolve, reject };
});
// TypeScript doesn't know that the Promise callback occurs synchronously
// therefore use of not null assertion (`!`)
return Object.assign(promise, methods!) as Resolvable<T>;
}
Deno.test(async function workersBasic(): Promise<void> {
const promise = createResolvable();
const jsWorker = new Worker("../tests/subdir/test_worker.js", {
type: "module",
name: "jsWorker"
});
const tsWorker = new Worker("../tests/subdir/test_worker.ts", {
type: "module",
name: "tsWorker"
});
tsWorker.onmessage = (e): void => {
assertEquals(e.data, "Hello World");
promise.resolve();
};
jsWorker.onmessage = (e): void => {
assertEquals(e.data, "Hello World");
tsWorker.postMessage("Hello World");
};
jsWorker.onerror = (e: Event): void => {
e.preventDefault();
jsWorker.postMessage("Hello World");
};
jsWorker.postMessage("Hello World");
await promise;
});
Deno.test(async function nestedWorker(): Promise<void> {
const promise = createResolvable();
const nestedWorker = new Worker("../tests/subdir/nested_worker.js", {
type: "module",
name: "nested"
});
nestedWorker.onmessage = (e): void => {
assert(e.data.type !== "error");
promise.resolve();
};
nestedWorker.postMessage("Hello World");
await promise;
});
Deno.test(async function workerThrowsWhenExecuting(): Promise<void> {
const promise = createResolvable();
const throwingWorker = new Worker("../tests/subdir/throwing_worker.js", {
type: "module"
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
throwingWorker.onerror = (e: any): void => {
e.preventDefault();
assert(/Uncaught Error: Thrown error/.test(e.message));
promise.resolve();
};
await promise;
});
Deno.test(async function workerCanUseFetch(): Promise<void> {
const promise = createResolvable();
const fetchingWorker = new Worker("../tests/subdir/fetching_worker.js", {
type: "module"
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fetchingWorker.onerror = (e: any): void => {
e.preventDefault();
promise.reject(e.message);
};
// Defer promise.resolve() to allow worker to shut down
fetchingWorker.onmessage = (e): void => {
assert(e.data === "Done!");
promise.resolve();
};
await promise;
});
await Deno.runTests();