summaryrefslogtreecommitdiffstats
path: root/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js')
-rw-r--r--tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js137
1 files changed, 137 insertions, 0 deletions
diff --git a/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js b/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js
new file mode 100644
index 0000000000..d4f815b887
--- /dev/null
+++ b/tests/manual/wasm/qtwasmtestlib/qtwasmtestlib.js
@@ -0,0 +1,137 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+// A minimal async test runner for Qt async auto tests.
+//
+// Usage: Call runTest(name, testFunctionCompleted), where "name" is the name of the app
+// (the .wasm file name), and testFunctionCompleted is a test-function-complete
+// callback. The test runner will then instantiate the app and run tests.
+//
+// The test runner expects that the app instance defines the following
+// functions:
+//
+// void cleanupTestCase()
+// string getTestFunctions()
+// runTestFunction(string)
+//
+// Further, the test runner expects that the app instance calls
+// completeTestFunction() (below - note that both the instance and this
+// file have a function with that name) when a test function finishes. This
+// can be done during runTestFunction(), or after it has returned (this
+// is the part which enables async testing). Test functions which fail
+// to call completeTestFunction() will time out after 2000ms.
+//
+const g_maxTime = 2000;
+
+class TestFunction {
+ constructor(instance, name) {
+ this.instance = instance;
+ this.name = name;
+ this.resolve = undefined;
+ this.reject = undefined;
+ this.timeoutId = undefined;
+ }
+
+ complete(result, details) {
+ // Reset timeout
+ clearTimeout(this.timeoutId);
+ this.timeoutId = undefined;
+
+ const callback = result.startsWith('FAIL') ? this.reject : this.resolve;
+ callback(`${result}${details ? ': ' + details : ''}`);
+ }
+
+ run() {
+ // Set timer which will catch test functions
+ // which fail to call completeTestFunction()
+ this.timeoutId = setTimeout(() => {
+ completeTestFunction(this.name, 'FAIL', `Timeout after ${g_maxTime} ms`)
+ }, g_maxTime);
+
+ return new Promise((resolve, reject) => {
+ this.resolve = resolve;
+ this.reject = reject;
+
+ this.instance.runTestFunction(this.name);
+ });
+ }
+};
+
+function completeTestFunction(testFunctionName, result, details) {
+ if (!window.currentTestFunction || testFunctionName !== window.currentTestFunction.name)
+ return;
+
+ window.currentTestFunction.complete(result, details);
+}
+
+async function runTestFunction(instance, name) {
+ if (window.currentTestFunction) {
+ throw new Error(`While trying to run ${name}: Last function hasn't yet finished`);
+ }
+ window.currentTestFunction = new TestFunction(instance, name);
+ try {
+ const result = await window.currentTestFunction.run();
+ return result;
+ } finally {
+ delete window.currentTestFunction;
+ }
+}
+
+async function runTestCaseImpl(entryFunction, testFunctionStarted, testFunctionCompleted, qtContainers)
+{
+ // Create test case instance
+ const config = {
+ qtContainerElements: qtContainers || []
+ }
+ const instance = await entryFunction(config);
+
+ // Run all test functions
+ const functionsString = instance.getTestFunctions();
+ const functions = functionsString.split(" ").filter(Boolean);
+ for (const name of functions) {
+ testFunctionStarted(name);
+ try {
+ const result = await runTestFunction(instance, name);
+ testFunctionCompleted(result);
+ } catch (err) {
+ testFunctionCompleted(err.message ?? err);
+ }
+ }
+
+ // Cleanup
+ instance.cleanupTestCase();
+}
+
+var g_htmlLogElement = undefined;
+
+function testFunctionStarted(name) {
+ let line = name + ": ";
+ g_htmlLogElement.innerHTML += line;
+}
+
+function testFunctionCompleted(status) {
+
+ const color = (status) => {
+ if (status.startsWith("PASS"))
+ return "green";
+ if (status.startsWith("FAIL"))
+ return "red";
+ if (status.startsWith("SKIP"))
+ return "tan";
+ return "black";
+ };
+
+ const line = `<span style='color: ${color(status)};'>${status}</text><br>`;
+ g_htmlLogElement.innerHTML += line;
+}
+
+async function runTestCase(entryFunction, htmlLogElement, qtContainers)
+{
+ g_htmlLogElement = htmlLogElement;
+ try {
+ await runTestCaseImpl(entryFunction, testFunctionStarted, testFunctionCompleted, qtContainers);
+ g_htmlLogElement.innerHTML += "<br> DONE"
+ } catch (err) {
+ g_htmlLogElement.innerHTML += err
+ }
+}