Skip to content

Commit

Permalink
Add tests for WasmQueue JS module (#141)
Browse files Browse the repository at this point in the history
* Merge WASM Loader and WASM Queue

* Add tests for WasmQueue module
  • Loading branch information
jameslittle230 committed Feb 2, 2021
1 parent 10073f3 commit 33a9f9d
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 41 deletions.
10 changes: 10 additions & 0 deletions js/__mocks__/stork-search.ts
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
export const wasm_search = jest.fn;
export default jest.fn().mockImplementation((input: string) => {
return new Promise((res, rej) => {
if (input.includes("stork-search.net")) {
res();
return;
} else {
rej();
}
});
});
4 changes: 2 additions & 2 deletions js/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class Entity {
const query = this.domManager.getQuery();
if (this.error) {
return "Error! Check the browser console.";
} else if (this.progress < 1 || !this.wasmQueue.loaded) {
} else if (this.progress < 1 || !this.wasmQueue.wasmIsLoaded) {
return "Loading...";
} else if (query?.length < this.config.minimumQueryLength) {
return "Filtering...";
Expand Down Expand Up @@ -129,7 +129,7 @@ export class Entity {
}

performSearch(query: string): void {
if (!this.wasmQueue.loaded || this.error) {
if (!this.wasmQueue.wasmIsLoaded || this.error) {
this.render();
return;
}
Expand Down
13 changes: 3 additions & 10 deletions js/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Configuration } from "./config";
import { createWasmQueue } from "./wasmLoader";
import { EntityManager } from "./entityManager";
import WasmQueue from "./wasmQueue";
import { resolveSearch, SearchData } from "./searchData";
Expand All @@ -17,15 +16,9 @@ let entityManager: EntityManager | null = null;
function initialize(wasmOverrideUrl: string | null = null): Promise<void> {
return new Promise((res, rej) => {
if (!wasmQueue) {
wasmQueue = createWasmQueue(wasmOverrideUrl);

wasmQueue.runAfterWasmLoaded(() => {
res();
});

wasmQueue.runOnWasmLoadFailure(e => {
rej(e);
});
wasmQueue = new WasmQueue(wasmOverrideUrl)
.runAfterWasmLoaded(res)
.runOnWasmLoadFailure(rej);
} else if (wasmQueue.state === "failed") {
rej();
} else {
Expand Down
22 changes: 0 additions & 22 deletions js/wasmLoader.ts

This file was deleted.

31 changes: 31 additions & 0 deletions js/wasmQueue.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import WasmQueue from "./wasmQueue";

// eslint-disable-next-line @typescript-eslint/no-empty-function
jest.mock("stork-search", undefined, { virtual: true });

test.each([
[null, true, [true, true, false, false]],
["https://google.com", false, [false, false, false, true]]
])(
"Test WasmQueue Loads %s %s",
async (initValue, expectedIsLoaded, expectedMockCalls) => {
const successFxns = [jest.fn(), jest.fn()];
const failureFxns = [jest.fn(), jest.fn()];
const queue = new WasmQueue(initValue)
.runAfterWasmLoaded(successFxns[0])
.runAfterWasmLoaded(successFxns[1])
.runOnWasmLoadFailure(failureFxns[0])
.runOnWasmLoadFailure(failureFxns[1]);

await queue.wasmLoadPromise;

expect(queue.wasmIsLoaded).toBe(expectedIsLoaded);

const computed = [...successFxns, ...failureFxns].map(
// Did the function get called exactly once?
fn => fn.mock.calls.length === 1
);

expect(computed).toEqual(expectedMockCalls);
}
);
45 changes: 38 additions & 7 deletions js/wasmQueue.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@
import init from "stork-search";

type WasmQueueState = "queueing" | "loaded" | "failed";

// const version = process.env.VERSION;
const version = null;
const DEFAULT_WASM_URL = version
? `https://files.stork-search.net/stork-${version}.wasm`
: `https://files.stork-search.net/stork.wasm`;

export default class WasmQueue {
private _wasmIsLoaded = false;

public get wasmIsLoaded(): boolean {
return this._wasmIsLoaded;
}

wasmUrl: string;
wasmLoadPromise: Promise<void>;
state: WasmQueueState = "queueing";
loaded = false;
queue: { (): void }[] = [];
failureMethod: { (e: Error): void };
failureMethod: { (e: Error): void } | null = null;

constructor(wasmOverrideUrl: string | null = null) {
this.wasmUrl = wasmOverrideUrl || DEFAULT_WASM_URL;
this.wasmLoadPromise = init(this.wasmUrl)
.then(() => {
this.handleWasmLoad();
})
.catch(e => {
this.handleWasmFailure(e);
});
}

/**
* Caller should use this to queue up a function to be run only when the
Expand All @@ -13,12 +39,14 @@ export default class WasmQueue {
*
* @param fn Function to be run once WASM is loaded
*/
runAfterWasmLoaded(fn: { (): void; (): void }): void {
if (this.loaded) {
runAfterWasmLoaded(fn: { (): void; (): void }): WasmQueue {
if (this.wasmIsLoaded) {
fn();
} else {
this.queue.push(fn);
}

return this;
}

/**
Expand All @@ -29,19 +57,22 @@ export default class WasmQueue {
* @param fn The function to be called when the WASM fails to load. The function
* should take an optional Error parameter.
*/
runOnWasmLoadFailure(fn: { (e: Error | null): void }): void {
runOnWasmLoadFailure(fn: { (e: Error | null): void }): WasmQueue {
if (this.state === "failed") {
fn(null);
} else {
this.failureMethod = fn;
}

return this;
}

/**
* WASM loader should use this to signal to the queue that the WASM has been
* loaded.
*/
handleWasmLoad(): void {
private handleWasmLoad(): void {
this._wasmIsLoaded = true;
for (const fn of this.queue) {
fn();
}
Expand All @@ -55,7 +86,7 @@ export default class WasmQueue {
*
* @param e The error that was recieved while loading the WASM.
*/
handleWasmFailure(e: Error): void {
private handleWasmFailure(e: Error): void {
if (this.failureMethod) this.failureMethod(e);
}
}

0 comments on commit 33a9f9d

Please sign in to comment.