Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions css/css-display/order-dynamic.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html class="reftest-wait">
<meta charset="utf-8">
<title>CSS Test: order - dynamic changes</title>
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
<link rel="help" href="https://www.w3.org/TR/css-display-3/#order-property">
<link rel="match" href="../reference/ref-filled-green-200px-square.html">
<meta name="assert" content="Order can be changed dynamically.">

<style>
main {
display: flex;
}
div {
height: 200px;
width: 200px;
}
#red {
position: absolute;
z-index: -1;
background: red;
}
#green {
background: green;
}
</style>

<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<main>
<div id="red"></div>
<div id="target"></div>
<div id="green"></div>
</main>

<script src="/common/reftest-wait.js"></script>
<script src="/common/rendering-utils.js"></script>
<script>
waitForAtLeastOneFrame().then(() => {
document.getElementById("target").style.order = "1";
takeScreenshot();
});
</script>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// META: title=Assure microtasks posted by pagehide event handler are dispatched as page is BFCached
// META: script=/common/dispatcher/dispatcher.js
// META: script=/common/utils.js
// META: script=./resources/test-helper.js

'use strict';

promise_test(async t => {
const uuid = token();
const url = remoteExecutorUrl(uuid, {protocol: 'http:'});
const win = window.open(url, '_blank', 'noopener');
const context = new RemoteContext(uuid);

// Navigate within the same eval, as (1) we can't navigate externally
// because of potential race against the eval, and (2) we can't navigate
// as a separate eval step as it would block on this one returning,
// which would only happen upon `pagehide`.
const {persisted} = await context.execute_script(
() => new Promise(resolve => {
window.addEventListener('pagehide', async (event) => {
await Promise.resolve(); // ... so the rest will run as a microtask.
resolve({persisted: event.persisted});
}, false);
location.href += '&navigated';
}));

assert_true(persisted); // Validate we're BFCached.
}, 'Assure microtasks posted by pagehide event handler are dispatched');
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[prefetch_status_updated.https.html]
expected:
if product != "chrome": ERROR
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<!DOCTYPE html>
<meta charset="utf-8"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="/common/utils.js"></script>
<script src="/resources/testdriver.js?feature=bidi"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="resources/bidi-speculation-helper.js"></script>
<script>
promise_setup(async () => {
await waitForDocumentReady();
});
promise_test(async t => {
// Subscribe for this test only
const unsubscribe = await test_driver.bidi.speculation.prefetch_status_updated.subscribe();
const receivedStatuses = [];
const expectedStatuses = ['pending', 'ready'];
const targetUrl = window.location.origin + "/infrastructure/testdriver/bidi/speculation/resources/target.html";
// Create a promise that resolves when we receive the 'ready' event
const readyEventPromise = new Promise((resolve, reject) => {
const removeHandler = test_driver.bidi.speculation.prefetch_status_updated.on((event) => {
// Multiple events for the same status can be sent in cases of network retries, etc.
if (!receivedStatuses.includes(event.status)) {
receivedStatuses.push(event.status);
}
// When we receive the ready event, clean up and resolve
if (event.status === 'ready') {
removeHandler();
resolve();
}
});
});
// Create prefetch rules for our target page in resources
const speculationRules = {
prefetch: [{
source: "list",
urls: [targetUrl]
}]
};
// Use helper function to add both speculation rules and link
const { script, link } = addSpeculationRulesAndLink(speculationRules, targetUrl);
// Await the ready event
await readyEventPromise;
// Assert that we received the expected events
assert_array_equals(receivedStatuses, expectedStatuses, 'Should have received pending and ready events');
t.add_cleanup(async () => {
await unsubscribe();
});
}, "prefetch_status_updated event subscription and structure validation");
promise_test(async t => {
// Subscribe for this test only
const unsubscribe = await test_driver.bidi.speculation.prefetch_status_updated.subscribe();
const receivedStatuses = [];
const expectedStatuses = ['pending', 'ready', 'success'];
let newWindow = null;
// Create prefetch rules for our target page in resources (different URL to avoid caching)
const targetUrl = window.location.origin + "/infrastructure/testdriver/bidi/speculation/resources/target.html?test=2";
// Create a promise that resolves when we receive the 'success' event
const successEventPromise = new Promise((resolve, reject) => {
const removeHandler = test_driver.bidi.speculation.prefetch_status_updated.on((event) => {
// Multiple events for the same status can be sent for network retries, etc.
if (!receivedStatuses.includes(event.status)) {
receivedStatuses.push(event.status);
}
// When we receive the ready event, navigate to trigger success
if (event.status === 'ready') {
// Open the prefetched page in a new window to trigger success
newWindow = window.open(event.url, '_blank');
} else if (event.status === 'success') {
removeHandler();
resolve();
}
});
});
const speculationRules = {
prefetch: [{
source: "list",
urls: [targetUrl]
}]
};
// Use helper function to add both speculation rules and link
const { script, link } = addSpeculationRulesAndLink(speculationRules, targetUrl);
// Await the success event
await successEventPromise;
// Assert that we received the expected events
assert_array_equals(receivedStatuses, expectedStatuses, 'Should have received pending, ready, and success events');
t.add_cleanup(async () => {
await unsubscribe();
if (newWindow && !newWindow.closed) {
newWindow.close();
}
});
}, "prefetch_status_updated event with navigation to success");
promise_test(async t => {
// Subscribe for this test only
const unsubscribe = await test_driver.bidi.speculation.prefetch_status_updated.subscribe();
const receivedStatuses = [];
const expectedStatuses = ['failure'];
// Set error url to fail at network layer and only expect failure event
const errorUrl = "http://0.0.0.0:1/test.html";
// Create a promise that resolves when we receive the 'failure' event
const failureEventPromise = new Promise((resolve, reject) => {
const removeHandler = test_driver.bidi.speculation.prefetch_status_updated.on((event) => {
// Multiple events for the same status can be sent for network retries, etc.
if (!receivedStatuses.includes(event.status)) {
receivedStatuses.push(event.status);
}
// When we receive the failure event, we're done
if (event.status === 'failure') {
removeHandler();
resolve();
}
});
});
const speculationRules = {
prefetch: [{
source: "list",
urls: [errorUrl]
}]
};
// Use helper function to add both speculation rules and link
const { script, link } = addSpeculationRulesAndLink(speculationRules, errorUrl);
// Await the failure event
await failureEventPromise;
// Assert that we received the expected events
assert_array_equals(receivedStatuses, expectedStatuses, 'Should have received only failure event');
t.add_cleanup(async () => {
await unsubscribe();
});
}, "prefetch_status_updated event with prefetch failure");
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict';
/**
* Helper functions for speculation rules BiDi testdriver tests
*/
/**
* Waits until the document has finished loading.
* @returns {Promise<void>} Resolves if the document is already completely
* loaded or when the 'onload' event is fired.
*/
function waitForDocumentReady() {
return new Promise(resolve => {
if (document.readyState === 'complete') {
resolve();
}
window.addEventListener('load', () => {
resolve();
}, {once: true});
});
}
/**
* Adds speculation rules and a corresponding link to the page.
* @param {Object} speculationRules - The speculation rules object to add
* @param {string} targetUrl - The URL to add as a link
* @param {string} linkText - The text content of the link (optional)
* @returns {Object} Object containing the created script and link elements
*/
function addSpeculationRulesAndLink(speculationRules, targetUrl, linkText = 'Test Link') {
// Add speculation rules script exactly like the working test
const script = document.createElement('script');
script.type = 'speculationrules';
script.textContent = JSON.stringify(speculationRules);
document.head.appendChild(script);
// Also add a link to the page (some implementations might need this)
const link = document.createElement('a');
link.href = targetUrl;
link.textContent = linkText;
document.body.appendChild(link);
return { script, link };
}
10 changes: 10 additions & 0 deletions infrastructure/testdriver/bidi/speculation/resources/target.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>Prefetch Target Page</title>
</head>
<body>
<h1>This is a prefetch target page</h1>
<p>This page is used as a target for prefetch testing.</p>
</body>
</html>
84 changes: 84 additions & 0 deletions resources/testdriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,78 @@
},
}
},
/**
* `speculation <https://wicg.github.io/nav-speculation/prefetch.html>`_ module.
*/
speculation: {
/**
* `speculation.PrefetchStatusUpdated <https://wicg.github.io/nav-speculation/prefetch.html#speculation-prefetchstatusupdated-event>`_
* event.
*/
prefetch_status_updated: {
/**
* @typedef {object} PrefetchStatusUpdated
* `speculation.PrefetchStatusUpdatedParameters <https://wicg.github.io/nav-speculation/prefetch.html#cddl-type-speculationprefetchstatusupdatedparameters>`_
* event.
*/

/**
* Subscribes to the event. Events will be emitted only if
* there is a subscription for the event. This method does
* not add actual listeners. To listen to the event, use the
* `on` or `once` methods. The buffered events will be
* emitted before the command promise is resolved.
*
* @param {object} [params] Parameters for the subscription.
* @param {null|Array.<(Context)>} [params.contexts] The
* optional contexts parameter specifies which browsing
* contexts to subscribe to the event on. It should be
* either an array of Context objects, or null. If null, the
* event will be subscribed to globally. If omitted, the
* event will be subscribed to on the current browsing
* context.
* @returns {Promise<(function(): Promise<void>)>} Callback
* for unsubscribing from the created subscription.
*/
subscribe: async function(params = {}) {
assertBidiIsEnabled();
return window.test_driver_internal.bidi.speculation
.prefetch_status_updated.subscribe(params);
},
/**
* Adds an event listener for the event.
*
* @param {function(PrefetchStatusUpdated): void} callback The
* callback to be called when the event is emitted. The
* callback is called with the event object as a parameter.
* @returns {function(): void} A function that removes the
* added event listener when called.
*/
on: function(callback) {
assertBidiIsEnabled();
return window.test_driver_internal.bidi.speculation
.prefetch_status_updated.on(callback);
},
/**
* Adds an event listener for the event that is only called
* once and removed afterward.
*
* @return {Promise<PrefetchStatusUpdated>} The promise which
* is resolved with the event object when the event is emitted.
*/
once: function() {
assertBidiIsEnabled();
return new Promise(resolve => {
const remove_handler =
window.test_driver_internal.bidi.speculation
.prefetch_status_updated.on(event => {
resolve(event);
remove_handler();
});
});
}
}
},
/**
* `emulation <https://www.w3.org/TR/webdriver-bidi/#module-emulation>`_ module.
*/
Expand Down Expand Up @@ -2337,6 +2409,18 @@
throw new Error(
"bidi.permissions.set_permission() is not implemented by testdriver-vendor.js");
}
},
speculation: {
prefetch_status_updated: {
async subscribe() {
throw new Error(
'bidi.speculation.prefetch_status_updated.subscribe is not implemented by testdriver-vendor.js');
},
on() {
throw new Error(
'bidi.speculation.prefetch_status_updated.on is not implemented by testdriver-vendor.js');
}
},
}
},

Expand Down
20 changes: 18 additions & 2 deletions tools/wptrunner/wptrunner/testdriver-extra.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,12 @@
const subscription_id = action_result["subscription"];

return async ()=>{
console.log("!!@@## unsubscribing")
await create_action("bidi.session.unsubscribe", {
// Default to subscribing to the window's events.
subscriptions: [subscription_id]
});
}
};

window.test_driver_internal.in_automation = true;

window.test_driver_internal.bidi.bluetooth.handle_request_device_prompt =
Expand Down Expand Up @@ -673,4 +671,22 @@
window.test_driver_internal.set_global_privacy_control = function(gpc, context=null) {
return create_action("set_global_privacy_control", {gpc});
};


window.test_driver_internal.bidi.speculation.prefetch_status_updated.subscribe =
function(params) {
return subscribe(
{...params, events: ['speculation.prefetchStatusUpdated']})
};

window.test_driver_internal.bidi.speculation.prefetch_status_updated.on =
function(callback) {
const on_event = (event) => {
callback(event.payload);
};
event_target.addEventListener(
'speculation.prefetchStatusUpdated', on_event);
return () => event_target.removeEventListener(
'speculation.prefetchStatusUpdated', on_event);
};
})();
Empty file.
Loading
Loading