mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-28 07:33:16 +00:00
Improve async tests
testing.async(...) is pretty lame. It works for simple cases, where the microtask is very quickly resolved, but otherwise can't block the test from exiting. This adds an overload to testing.async and leverages the new Runner https://github.com/lightpanda-io/browser/pull/1958 to "tick" until completion (or timeout). The overloaded version of testing.async() (called without a callback) will increment a counter which is only decremented with the promise is resolved. The test runner will now `tick` until the counter == 0.
This commit is contained in:
@@ -3585,12 +3585,7 @@ test "WebApi: Page" {
|
||||
}
|
||||
|
||||
test "WebApi: Frames" {
|
||||
// TOO FLAKY, disabled for now
|
||||
|
||||
// const filter: testing.LogFilter = .init(&.{.js});
|
||||
// defer filter.deinit();
|
||||
|
||||
// try testing.htmlRunner("frames", .{});
|
||||
try testing.htmlRunner("frames", .{});
|
||||
}
|
||||
|
||||
test "WebApi: Integration" {
|
||||
|
||||
@@ -118,23 +118,24 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id=link_click>
|
||||
testing.async(async (restore) => {
|
||||
await new Promise((resolve) => {
|
||||
<script id=link_click type=module>
|
||||
const state = await testing.async();
|
||||
|
||||
let count = 0;
|
||||
let f6 = document.createElement('iframe');
|
||||
f6.id = 'f6';
|
||||
f6.addEventListener('load', () => {
|
||||
if (++count == 2) {
|
||||
resolve();
|
||||
state.resolve();
|
||||
return;
|
||||
}
|
||||
f6.contentDocument.querySelector('#link').click();
|
||||
});
|
||||
f6.src = "support/with_link.html";
|
||||
|
||||
f6.src = 'support/with_link.html';
|
||||
document.documentElement.appendChild(f6);
|
||||
});
|
||||
restore();
|
||||
|
||||
await state.done(() => {
|
||||
testing.expectEqual("<html><head></head><body>It was clicked!\n</body></html>", f6.contentDocument.documentElement.outerHTML);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
{
|
||||
let reply = null;
|
||||
window.addEventListener('message', (e) => {
|
||||
console.warn('reply')
|
||||
reply = e.data;
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<script>
|
||||
window.addEventListener('message', (e) => {
|
||||
console.warn('Frame Message', e.data);
|
||||
if (e.data === 'ping') {
|
||||
window.top.postMessage({data: 'pong', origin: e.origin}, '*');
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
let eventuallies = [];
|
||||
let async_capture = null;
|
||||
let current_script_id = null;
|
||||
let async_pending = 0;
|
||||
|
||||
function expectTrue(actual) {
|
||||
expectEqual(true, actual);
|
||||
@@ -64,6 +65,25 @@
|
||||
}
|
||||
|
||||
async function async(cb) {
|
||||
if (cb == undefined) {
|
||||
let resolve = null
|
||||
const promise = new Promise((r) => { resolve = r});
|
||||
async_pending += 1;
|
||||
|
||||
return {
|
||||
promise: promise,
|
||||
resolve: resolve,
|
||||
capture: {script_id: document.currentScript.id, stack: new Error().stack},
|
||||
done: async function(cb) {
|
||||
await this.promise;
|
||||
async_pending -= 1;
|
||||
async_capture = this.capture;
|
||||
cb();
|
||||
async_capture = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let capture = {script_id: document.currentScript.id, stack: new Error().stack};
|
||||
await cb(() => { async_capture = capture; });
|
||||
async_capture = null;
|
||||
@@ -74,6 +94,10 @@
|
||||
throw new Error('Failed');
|
||||
}
|
||||
|
||||
if (async_pending > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let e of eventuallies) {
|
||||
current_script_id = e.script_id;
|
||||
e.callback();
|
||||
@@ -97,6 +121,8 @@
|
||||
throw new Error(`script id: '${script_id}' failed: ${status || 'no assertions'}`);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const IS_TEST_RUNNER = window.navigator.userAgent.startsWith("Lightpanda/");
|
||||
|
||||
@@ -410,21 +410,46 @@ fn runWebApiTest(test_file: [:0]const u8) !void {
|
||||
page.js.localScope(&ls);
|
||||
defer ls.deinit();
|
||||
|
||||
{
|
||||
var try_catch: js.TryCatch = undefined;
|
||||
try_catch.init(&ls.local);
|
||||
defer try_catch.deinit();
|
||||
|
||||
try page.navigate(url, .{});
|
||||
}
|
||||
|
||||
var runner = try test_session.runner(.{});
|
||||
try runner.wait(.{ .ms = 2000 });
|
||||
|
||||
test_browser.runMicrotasks();
|
||||
var wait_ms: u32 = 2000;
|
||||
var timer = try std.time.Timer.start();
|
||||
while (true) {
|
||||
var try_catch: js.TryCatch = undefined;
|
||||
try_catch.init(&ls.local);
|
||||
defer try_catch.deinit();
|
||||
|
||||
ls.local.eval("testing.assertOk()", "testing.assertOk()") catch |err| {
|
||||
const js_val = ls.local.exec("testing.assertOk()", "testing.assertOk()") catch |err| {
|
||||
const caught = try_catch.caughtOrError(arena_allocator, err);
|
||||
std.debug.print("{s}: test failure\nError: {f}\n", .{ test_file, caught });
|
||||
return err;
|
||||
};
|
||||
if (js_val.isTrue()) {
|
||||
return;
|
||||
}
|
||||
switch (try runner.tick(.{ .ms = 20 })) {
|
||||
.done => return error.TestNeverSignaledCompletion,
|
||||
.ok => |next_ms| {
|
||||
const ms_elapsed = timer.lap() / 1_000_000;
|
||||
if (ms_elapsed >= wait_ms) {
|
||||
return error.TestTimedOut;
|
||||
}
|
||||
wait_ms -= @intCast(ms_elapsed);
|
||||
if (next_ms > 0) {
|
||||
std.Thread.sleep(std.time.ns_per_ms * next_ms);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Used by a few CDP tests - wouldn't be sad to see this go.
|
||||
|
||||
Reference in New Issue
Block a user