diff --git a/tests/wpt/metadata/FileAPI/url/url-in-tags-revoke.window.js.ini b/tests/wpt/metadata/FileAPI/url/url-in-tags-revoke.window.js.ini index d4f62ed7113..faa00f45ecf 100644 --- a/tests/wpt/metadata/FileAPI/url/url-in-tags-revoke.window.js.ini +++ b/tests/wpt/metadata/FileAPI/url/url-in-tags-revoke.window.js.ini @@ -7,7 +7,7 @@ expected: FAIL [Opening a blob URL in a new window immediately before revoking it works.] - expected: FAIL + expected: TIMEOUT [Opening a blob URL in a noopener about:blank window immediately before revoking it works.] expected: TIMEOUT diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index 38ead3071d5..548eb63cd89 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -17305,7 +17305,7 @@ ] }, "rejects_if_not_active-manual.https.html": [ - "d03032d0498fc482a7ab45d42f291daf2dcdf59d", + "8e214cb6094a25436374da984deaade660ccc191", [ null, {} @@ -143222,6 +143222,19 @@ ], {} ] + ], + "grid-placement-using-named-grid-lines-003.html": [ + "31173e0a455a04156ca8755779d7a2ae4b24b103", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] ] }, "subgrid": { @@ -225921,6 +225934,19 @@ ], {} ] + ], + "iframe-scrolling-attribute.html": [ + "cc7df7b43a06219350f14ad007cbc649e5cc0046", + [ + null, + [ + [ + "/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-ref.html", + "==" + ] + ], + {} + ] ] } }, @@ -320319,6 +320345,10 @@ "c907a119f8b786aa070c2d1951670c56060a2d64", [] ], + "iframe-scrolling-attribute-ref.html": [ + "fe72b9f9380fecfa75f1477541d0e1513c0cbd12", + [] + ], "support": { "body-marginwidth-marginheight.html": [ "5d825e3455664970097b913146b4b51669bf8e58", @@ -328823,7 +328853,7 @@ [] ], "app-respond-with-minimal-ui.js": [ - "0e6b1b78b9197d8d1582c8eb70bbcc15ba3861c4", + "45ac57c2279b1136322001bfd42e827378a2e776", [] ], "app-supports-shipping-contact-delegation.js": [ @@ -338125,7 +338155,7 @@ [] ], "testharness.js": [ - "0ec232c1d27d792b1dc000a9cf7899e011217698", + "ce043a287f758338e1564e86bc6908ce8388638e", [] ], "testharness.js.headers": [ @@ -341996,7 +342026,7 @@ }, "styling": { "presentation-attributes.js": [ - "552041496f187e97b4e17bfa445826d8cd278b99", + "7bf77cb77bcf08af3d72efe63317b189abac5d2a", [] ], "render": { @@ -342330,7 +342360,7 @@ [] ], "pr_preview.py": [ - "4b76b37f87e1d6b7eede89376e72e8bdd9c7aa3e", + "ba5997f68a615f49322ac009a15aebf0a5a071f3", [] ], "run_tc.py": [ @@ -342407,7 +342437,7 @@ [] ], "test_pr_preview.py": [ - "cdf3c9528eaaa8dd3ac2d82d2f457dc12a647a82", + "2d9966fc8cf4187913adce8609ee750ade1b9797", [] ] }, @@ -348032,12 +348062,12 @@ [] ], "chromium.py": [ - "03e674eb2e8008179712758464e1360df90eb54a", + "62ed53865d7825da8fd81608cf7e1302cf0650bc", [] ], "tests": { "test_chromium.py": [ - "f9ae80b0be54a27b4f846aabf206551589c1d978", + "cb6f1ad370f2faafaa8311b82e9126ce9afd327d", [] ] }, @@ -349410,7 +349440,7 @@ [] ], "urltestdata.json": [ - "32ed1959430c135bf5910b643e553296b8cd3a00", + "b2f8964c440dad8d1399127848185aec3edd025f", [] ] } @@ -350229,7 +350259,7 @@ [] ], "helpers.js": [ - "0fc64c8b522cfd7fce2ec585e2ec1d6bd839b855", + "27abaaf4766c4a2fe85f1034be8df9145b712f75", [] ], "resources": { @@ -438664,6 +438694,13 @@ {} ] ], + "image-loading-lazy-crossorigin-change.sub.html": [ + "13560324854dceeca26bda3433301cafe07fb62a", + [ + null, + {} + ] + ], "image-loading-lazy-in-cross-origin-ifame-001.sub.html": [ "a4627cb8c25dc3f57581dcaea14b2ea4cfccea40", [ @@ -438818,13 +438855,6 @@ {} ] ], - "original-crossorigin-applied.sub.html": [ - "2cf076e75f79b465e58166248c323331418ed0bd", - [ - null, - {} - ] - ], "original-referrer-policy-applied.sub.html": [ "c300119f72fbd3742d6dbf7e2439d967911303a5", [ @@ -472874,7 +472904,7 @@ }, "portals": { "about-blank-cannot-host.html": [ - "6a721c32e6807cbd615b3adbffd7422467375525", + "7aba015e69b85a173c7a63dc277aedafeefc63a2", [ null, {} @@ -472922,7 +472952,7 @@ ] ], "portal-activate-data.html": [ - "cefb0eae3dc9a8b10880687fc084d44991f8f26f", + "004fa97e55c05049a32657450a22af090466f4a4", [ null, {} @@ -472964,7 +472994,7 @@ ] ], "portals-activate-inside-iframe.html": [ - "5234babfdf9528c5b9d7861ba90ffe6ceebaccce", + "587e483479cf8e616694de345ecb681a69214e61", [ null, {} @@ -524883,6 +524913,13 @@ {} ] ], + "scroll-timeline-phases.tentative.html": [ + "0cc4e12864e209602b8c3ad57106deb3927e5be8", + [ + null, + {} + ] + ], "setting-current-time.html": [ "069a7cc149eaa69234580345854e1560804d5c1a", [ @@ -537169,7 +537206,7 @@ ] ], "presentation-attributes-special-cases.html": [ - "8fa045984d9ad55097768e6608146bbe2b37e8bf", + "c99ed704cf1dde83a26ed4dd52f537bc8805165e", [ null, {} @@ -544644,7 +544681,7 @@ ] ], "wakelock-active-document.https.window.js": [ - "53f9fb56fa8d7754fa61e11f018e17188228d678", + "53745ea3c60e7322720d9082919950c798259f0f", [ "wake-lock/wakelock-active-document.https.window.html", {} @@ -547512,6 +547549,13 @@ {} ] ], + "document-timeline-phases.tentative.html": [ + "9b86a7105d5dcfafc7e5d7f1f63593f7b1063f33", + [ + null, + {} + ] + ], "style-change-events.html": [ "c1607e6fb92943c580802025e4a4cc617a747144", [ diff --git a/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-002.html.ini b/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-002.html.ini new file mode 100644 index 00000000000..f64b45fea6b --- /dev/null +++ b/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-002.html.ini @@ -0,0 +1,4 @@ +[hit-test-floats-002.html] + [Hit test float] + expected: FAIL + diff --git a/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-004.html.ini b/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-004.html.ini new file mode 100644 index 00000000000..4bfb0c2053a --- /dev/null +++ b/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-004.html.ini @@ -0,0 +1,4 @@ +[hit-test-floats-004.html] + [Miss float below something else] + expected: FAIL + diff --git a/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-005.html.ini b/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-005.html.ini new file mode 100644 index 00000000000..baa9f1a7541 --- /dev/null +++ b/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-005.html.ini @@ -0,0 +1,4 @@ +[hit-test-floats-005.html] + [Miss clipped float] + expected: FAIL + diff --git a/tests/wpt/metadata/css/CSS2/text/bidi-span-001.html.ini b/tests/wpt/metadata/css/CSS2/text/bidi-span-001.html.ini new file mode 100644 index 00000000000..ddd426ef4bb --- /dev/null +++ b/tests/wpt/metadata/css/CSS2/text/bidi-span-001.html.ini @@ -0,0 +1,2 @@ +[bidi-span-001.html] + expected: CRASH diff --git a/tests/wpt/metadata/css/css-transforms/transform-scale-hittest.html.ini b/tests/wpt/metadata/css/css-transforms/transform-scale-hittest.html.ini index f8e7e539aae..4a1e8110f6f 100644 --- a/tests/wpt/metadata/css/css-transforms/transform-scale-hittest.html.ini +++ b/tests/wpt/metadata/css/css-transforms/transform-scale-hittest.html.ini @@ -2,6 +2,3 @@ [Hit test intersecting scaled box] expected: FAIL - [Hit test within unscaled box] - expected: FAIL - diff --git a/tests/wpt/metadata/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini b/tests/wpt/metadata/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini index c884dc82eab..628b1fab770 100644 --- a/tests/wpt/metadata/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini +++ b/tests/wpt/metadata/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini @@ -2,6 +2,3 @@ [listeners are called when + diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute.html new file mode 100644 index 00000000000..cc7df7b43a0 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute.html @@ -0,0 +1,19 @@ + +iframe and the scrolling attributes + + + + +

These two iframes should *both* render with scrollbars:

+ + + + diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/image-loading-lazy-crossorigin-change.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/image-loading-lazy-crossorigin-change.sub.html new file mode 100644 index 00000000000..13560324854 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/image-loading-lazy-crossorigin-change.sub.html @@ -0,0 +1,30 @@ + + + Deferred images with loading='lazy' use the latest crossorigin attribute + + + + + + + + + + +
+ + diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/original-crossorigin-applied.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/original-crossorigin-applied.sub.html deleted file mode 100644 index 2cf076e75f7..00000000000 --- a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/original-crossorigin-applied.sub.html +++ /dev/null @@ -1,42 +0,0 @@ - - - Deferred images with loading='lazy' use the original crossorigin attribute specified at the parse time - - - - - - - - - -
- - diff --git a/tests/wpt/web-platform-tests/payment-handler/app-respond-with-minimal-ui.js b/tests/wpt/web-platform-tests/payment-handler/app-respond-with-minimal-ui.js index 0e6b1b78b91..45ac57c2279 100644 --- a/tests/wpt/web-platform-tests/payment-handler/app-respond-with-minimal-ui.js +++ b/tests/wpt/web-platform-tests/payment-handler/app-respond-with-minimal-ui.js @@ -1,3 +1,18 @@ self.addEventListener('canmakepayment', event => { + if (!event.currency) { + event.respondWith(false); + return; + } + + if (event.currency !== 'USD') { + event.respondWith(false); + return; + } + + if (!event.respondWithMinimalUI) { + event.respondWith(false); + return; + } + event.respondWithMinimalUI(event.methodData[0].data.test); }); diff --git a/tests/wpt/web-platform-tests/payment-request/rejects_if_not_active-manual.https.html b/tests/wpt/web-platform-tests/payment-request/rejects_if_not_active-manual.https.html index d03032d0498..8e214cb6094 100644 --- a/tests/wpt/web-platform-tests/payment-request/rejects_if_not_active-manual.https.html +++ b/tests/wpt/web-platform-tests/payment-request/rejects_if_not_active-manual.https.html @@ -61,6 +61,8 @@ function testAbortShowIfDocumentIsNotActive() { iframe, "/payment-request/resources/page1.html" ); + // Save the DOMException of page1.html before navigating away. + const frameDOMException1 = iframe.contentWindow.DOMException; // We navigate the iframe again, putting request1's document into an inactive state. const request2 = await getLoadedPaymentRequest( iframe, @@ -71,6 +73,7 @@ function testAbortShowIfDocumentIsNotActive() { await promise_rejects_dom( t, "AbortError", + frameDOMException1, request1.show(), "Inactive document, so must throw AbortError" ); @@ -80,6 +83,7 @@ function testAbortShowIfDocumentIsNotActive() { await promise_rejects_dom( t, "InvalidStateError", + iframe.contentWindow.DOMException, request2.show(), "Abort already called, so InvalidStateError" ); @@ -112,6 +116,8 @@ function testAbortShowIfDocumentIsNotFullyActive() { innerIframe, "/payment-request/resources/page2.html" ); + // Save DOMException from innerIframe before navigating away. + const innerIframeDOMException = innerIframe.contentWindow.DOMException; // Navigate the outer iframe to a new location. // Wait for the load event to fire. @@ -128,6 +134,7 @@ function testAbortShowIfDocumentIsNotFullyActive() { await promise_rejects_dom( t, "AbortError", + innerIframeDOMException, showPromise, "Active, but not fully active, so must throw AbortError" ); diff --git a/tests/wpt/web-platform-tests/portals/about-blank-cannot-host.html b/tests/wpt/web-platform-tests/portals/about-blank-cannot-host.html index 6a721c32e68..7aba015e69b 100644 --- a/tests/wpt/web-platform-tests/portals/about-blank-cannot-host.html +++ b/tests/wpt/web-platform-tests/portals/about-blank-cannot-host.html @@ -12,7 +12,7 @@ promise_test(async (t) => { portal.src = "resources/simple-portal.html"; hostWindow.document.body.appendChild(portal); - await promise_rejects_dom(t, "InvalidStateError", portal.activate()); + await promise_rejects_dom(t, "InvalidStateError", hostWindow.DOMException, portal.activate()); }, "about:blank cannot host a portal"); diff --git a/tests/wpt/web-platform-tests/portals/portal-activate-data.html b/tests/wpt/web-platform-tests/portals/portal-activate-data.html index cefb0eae3dc..004fa97e55c 100644 --- a/tests/wpt/web-platform-tests/portals/portal-activate-data.html +++ b/tests/wpt/web-platform-tests/portals/portal-activate-data.html @@ -12,9 +12,9 @@ function nextMessage(target) { }); } -async function openPortalAndActivate(logic, activateOptions) { +async function openPortalAndActivate(logic, activateOptions, testWindow) { assert_precondition("HTMLPortalElement" in self); - const w = await openBlankPortalHost(); + const w = testWindow || await openBlankPortalHost(); try { const portal = w.document.createElement('portal'); portal.src = new URL('resources/portal-activate-data-portal.html?logic=' + encodeURIComponent(logic), location.href); @@ -71,9 +71,10 @@ promise_test(async () => { }, "A message port can be passed through activate data."); promise_test(async t => { -await promise_rejects_dom( - t, 'DataCloneError', - openPortalAndActivate('', {data: new SharedArrayBuffer})); + const w = await openBlankPortalHost(); + await promise_rejects_dom( + t, 'DataCloneError', w.DOMException, + openPortalAndActivate('', {data: new SharedArrayBuffer}, w)); }, "A SharedArrayBuffer cannot be passed through activate data."); promise_test(async t => { @@ -83,9 +84,10 @@ promise_test(async t => { }, "Uncloneable data has its exception propagated."); promise_test(async t => { + const w = await openBlankPortalHost(); await promise_rejects_js( - t, TypeError, - openPortalAndActivate('', {data: null, transfer: [null]})); + t, w.TypeError, + openPortalAndActivate('', {data: null, transfer: [null]}, w)); }, "Errors during transfer list processing are propagated."); diff --git a/tests/wpt/web-platform-tests/portals/portals-activate-inside-iframe.html b/tests/wpt/web-platform-tests/portals/portals-activate-inside-iframe.html index 5234babfdf9..587e483479c 100644 --- a/tests/wpt/web-platform-tests/portals/portals-activate-inside-iframe.html +++ b/tests/wpt/web-platform-tests/portals/portals-activate-inside-iframe.html @@ -13,7 +13,9 @@ document.body.appendChild(iframe); await waitForLoad; const portal = iframe.contentDocument.getElementById("portal"); - return promise_rejects_dom(t, "InvalidStateError", portal.activate()); + return promise_rejects_dom(t, "InvalidStateError", + iframe.contentWindow.DOMException, + portal.activate()); }, "activating portal inside iframe should fail"); diff --git a/tests/wpt/web-platform-tests/resources/testharness.js b/tests/wpt/web-platform-tests/resources/testharness.js index 0ec232c1d27..ce043a287f7 100644 --- a/tests/wpt/web-platform-tests/resources/testharness.js +++ b/tests/wpt/web-platform-tests/resources/testharness.js @@ -638,11 +638,37 @@ policies and contribution forms [3]. }); } + /** + * Make a copy of a Promise in the current realm. + * + * @param {Promise} promise the given promise that may be from a different + * realm + * @returns {Promise} + * + * An arbitrary promise provided by the caller may have originated in + * another frame that have since navigated away, rendering the frame's + * document inactive. Such a promise cannot be used with `await` or + * Promise.resolve(), as microtasks associated with it may be prevented + * from being run. See https://github.com/whatwg/html/issues/5319 for a + * particular case. + * + * In functions we define here, there is an expectation from the caller + * that the promise is from the current realm, that can always be used with + * `await`, etc. We therefore create a new promise in this realm that + * inherit the value and status from the given promise. + */ + + function bring_promise_to_current_realm(promise) { + return new Promise(promise.then.bind(promise)); + } + function promise_rejects_js(test, constructor, promise, description) { - return promise.then(test.unreached_func("Should have rejected: " + description)).catch(function(e) { - assert_throws_js_impl(constructor, function() { throw e }, - description, "promise_rejects_js"); - }); + return bring_promise_to_current_realm(promise) + .then(test.unreached_func("Should have rejected: " + description)) + .catch(function(e) { + assert_throws_js_impl(constructor, function() { throw e }, + description, "promise_rejects_js"); + }); } /** @@ -678,17 +704,21 @@ policies and contribution forms [3]. assert(maybeDescription === undefined, "Too many args pased to no-constructor version of promise_rejects_dom"); } - return promise.then(test.unreached_func("Should have rejected: " + description)).catch(function(e) { - assert_throws_dom_impl(type, function() { throw e }, description, - "promise_rejects_dom", constructor); - }); + return bring_promise_to_current_realm(promise) + .then(test.unreached_func("Should have rejected: " + description)) + .catch(function(e) { + assert_throws_dom_impl(type, function() { throw e }, description, + "promise_rejects_dom", constructor); + }); } function promise_rejects_exactly(test, exception, promise, description) { - return promise.then(test.unreached_func("Should have rejected: " + description)).catch(function(e) { - assert_throws_exactly_impl(exception, function() { throw e }, - description, "promise_rejects_exactly"); - }); + return bring_promise_to_current_realm(promise) + .then(test.unreached_func("Should have rejected: " + description)) + .catch(function(e) { + assert_throws_exactly_impl(exception, function() { throw e }, + description, "promise_rejects_exactly"); + }); } /** @@ -2808,24 +2838,8 @@ policies and contribution forms [3]. var message_port; if (is_service_worker(worker)) { - if (window.MessageChannel) { - // The ServiceWorker's implicit MessagePort is currently not - // reliably accessible from the ServiceWorkerGlobalScope due to - // Blink setting MessageEvent.source to null for messages sent - // via ServiceWorker.postMessage(). Until that's resolved, - // create an explicit MessageChannel and pass one end to the - // worker. - var message_channel = new MessageChannel(); - message_port = message_channel.port1; - message_port.start(); - worker.postMessage({type: "connect"}, [message_channel.port2]); - } else { - // If MessageChannel is not available, then try the - // ServiceWorker.postMessage() approach using MessageEvent.source - // on the other end. - message_port = navigator.serviceWorker; - worker.postMessage({type: "connect"}); - } + message_port = navigator.serviceWorker; + worker.postMessage({type: "connect"}); } else if (is_shared_worker(worker)) { message_port = worker.port; message_port.start(); diff --git a/tests/wpt/web-platform-tests/scroll-animations/scroll-timeline-phases.tentative.html b/tests/wpt/web-platform-tests/scroll-animations/scroll-timeline-phases.tentative.html new file mode 100644 index 00000000000..0cc4e12864e --- /dev/null +++ b/tests/wpt/web-platform-tests/scroll-animations/scroll-timeline-phases.tentative.html @@ -0,0 +1,34 @@ + + +Test basic functionality of scroll timeline phases. + + + + + +
+ \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/svg/styling/presentation-attributes-special-cases.html b/tests/wpt/web-platform-tests/svg/styling/presentation-attributes-special-cases.html index 8fa045984d9..c99ed704cf1 100644 --- a/tests/wpt/web-platform-tests/svg/styling/presentation-attributes-special-cases.html +++ b/tests/wpt/web-platform-tests/svg/styling/presentation-attributes-special-cases.html @@ -98,11 +98,11 @@ if (CSS.supports("d", "initial")) { // animation elements. if (CSS.supports("fill", "initial")) { - test(function() { - for (let e of ["animate", "animateMotion", "animateTransform", "discard", "set"]) { + for (let e of ["animate", "animateMotion", "animateTransform", "discard", "set"]) { + test(function() { assertPresentationAttributeIsNotSupported(e, "fill", "blue", "fill"); - } - }, `fill presentation attribute not supported on animation elements`); + }, `fill presentation attribute not supported on ${e}`); + } } diff --git a/tests/wpt/web-platform-tests/svg/styling/presentation-attributes.js b/tests/wpt/web-platform-tests/svg/styling/presentation-attributes.js index 552041496f1..7bf77cb77bc 100644 --- a/tests/wpt/web-platform-tests/svg/styling/presentation-attributes.js +++ b/tests/wpt/web-platform-tests/svg/styling/presentation-attributes.js @@ -145,7 +145,7 @@ const PROPERTIES = { irrelevantElement: null, }, "image-rendering": { - value: "optimizeSpeed", + value: ["optimizeSpeed", "pixelated"], relevantElement: "image", irrelevantElement: "path", }, @@ -361,17 +361,25 @@ function presentationAttributeIsSupported(element, attribute, value, property) { return propertyValueBefore != propertyValueAfter; } -function assertPresentationAttributeIsSupported(element, attribute, value, property) { +function assertPresentationAttributeIsSupported(element, attribute, values, property) { + if (typeof values === 'string') + values = [values]; + let supported = values.some( + value => presentationAttributeIsSupported(element, attribute, value, property)); assert_true( - presentationAttributeIsSupported(element, attribute, value, property), - `Presentation attribute ${attribute}="${value}" should be supported on ${element} element` + supported, + `Presentation attribute ${attribute}="${values.join(" | ")}" should be supported on ${element} element` ); } -function assertPresentationAttributeIsNotSupported(element, attribute, value, property) { +function assertPresentationAttributeIsNotSupported(element, attribute, values, property) { + if (typeof values === 'string') + values = [values]; + let supported = values.some( + value => presentationAttributeIsSupported(element, attribute, value, property)); assert_false( - presentationAttributeIsSupported(element, attribute, value, property), - `Presentation attribute ${attribute}="${value}" should be supported on ${element} element` + supported, + `Presentation attribute ${attribute}="${values.join(" | ")}" should not be supported on ${element} element` ); } diff --git a/tests/wpt/web-platform-tests/tools/ci/pr_preview.py b/tests/wpt/web-platform-tests/tools/ci/pr_preview.py index 4b76b37f87e..ba5997f68a6 100755 --- a/tests/wpt/web-platform-tests/tools/ci/pr_preview.py +++ b/tests/wpt/web-platform-tests/tools/ci/pr_preview.py @@ -268,10 +268,11 @@ def has_mirroring_label(pull_request): def should_be_mirrored(project, pull_request): return ( - is_open(pull_request) and - pull_request['user']['login'] not in AUTOMATION_GITHUB_USERS and ( - pull_request['author_association'] in TRUSTED_AUTHOR_ASSOCIATIONS or - has_mirroring_label(pull_request) + is_open(pull_request) and ( + has_mirroring_label(pull_request) or ( + pull_request['user']['login'] not in AUTOMATION_GITHUB_USERS and + pull_request['author_association'] in TRUSTED_AUTHOR_ASSOCIATIONS + ) ) and # Query this last as it requires another API call to verify not project.pull_request_is_from_fork(pull_request) diff --git a/tests/wpt/web-platform-tests/tools/ci/tests/test_pr_preview.py b/tests/wpt/web-platform-tests/tools/ci/tests/test_pr_preview.py index cdf3c9528ea..2d9966fc8cf 100644 --- a/tests/wpt/web-platform-tests/tools/ci/tests/test_pr_preview.py +++ b/tests/wpt/web-platform-tests/tools/ci/tests/test_pr_preview.py @@ -512,6 +512,8 @@ def test_synchronize_sync_trusted_contributor(): 'items': [ { 'number': 23, + # user here is a contributor (untrusted), but the issue + # has been labelled as safe. 'labels': [{'name': 'safe for preview'}], 'closed_at': None, 'user': {'login': 'Hexcles'}, @@ -541,6 +543,51 @@ def test_synchronize_sync_trusted_contributor(): assert returncode == 0 assert same_members(expected_traffic, actual_traffic) +def test_synchronize_sync_bot_with_label(): + expected_traffic = [ + (Requests.get_rate, Responses.no_limit), + (Requests.get_rate, Responses.no_limit), + (Requests.get_rate, Responses.no_limit), + (Requests.get_rate, Responses.no_limit), + (Requests.get_rate, Responses.no_limit), + (Requests.get_rate, Responses.no_limit), + (Requests.search, ( + 200, + { + 'items': [ + { + 'number': 23, + # user here is a bot which is normally not mirrored, + # but the issue has been labelled as safe. + 'labels': [{'name': 'safe for preview'}], + 'closed_at': None, + 'user': {'login': 'chromium-wpt-export-bot'}, + 'author_association': 'COLLABORATOR' + } + ], + 'incomplete_results': False + } + )), + (Requests.pr_details, (200, + { + 'head': { + 'repo': { + 'full_name': 'test-org/test-repo' + } + } + } + )), + (Requests.ref_create_open, (200, {})), + (Requests.ref_create_trusted, (200, {})), + (Requests.deployment_get, (200, [])), + (Requests.deployment_create, (200, {})) + ] + + returncode, actual_traffic, remote_refs = synchronize(expected_traffic) + + assert returncode == 0 + assert same_members(expected_traffic, actual_traffic) + def test_synchronize_update_collaborator(): expected_traffic = [ (Requests.get_rate, Responses.no_limit), diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/formatters/chromium.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/formatters/chromium.py index 03e674eb2e8..62ed53865d7 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/formatters/chromium.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/formatters/chromium.py @@ -55,13 +55,25 @@ class ChromiumFormatter(base.BaseFormatter): prefix += "%s: " % subtest self.messages[test] += prefix + message + "\n" - def _store_test_result(self, name, actual, expected, message, subtest_failure=False): + def _append_artifact(self, cur_dict, artifact_name, artifact_value): + """ + Appends artifacts to the specified dictionary. + :param dict cur_dict: the test leaf dictionary to append to + :param str artifact_name: the name of the artifact + :param str artifact_value: the value of the artifact + """ + if "artifacts" not in cur_dict.keys(): + cur_dict["artifacts"] = {} + cur_dict["artifacts"][artifact_name] = artifact_value + + def _store_test_result(self, name, actual, expected, message, wpt_actual, subtest_failure): """ Stores the result of a single test in |self.tests| :param str name: name of the test. :param str actual: actual status of the test. :param str expected: expected statuses of the test. :param str message: test output, such as status, subtest, errors etc. + :param str wpt_actual: actual status reported by wpt, may differ from |actual|. :param bool subtest_failure: whether this test failed because of subtests """ # The test name can contain a leading / which will produce an empty @@ -73,12 +85,12 @@ class ChromiumFormatter(base.BaseFormatter): cur_dict = cur_dict.setdefault(name_part, {}) cur_dict["actual"] = actual cur_dict["expected"] = expected - if subtest_failure or message: - cur_dict["artifacts"] = {"log": ""} - if subtest_failure: - cur_dict["artifacts"]["log"] += "subtest_failure\n" - if message != "": - cur_dict["artifacts"]["log"] += message + if subtest_failure: + self._append_artifact(cur_dict, "wpt_subtest_failure", "true") + if wpt_actual != actual: + self._append_artifact(cur_dict, "wpt_actual_status", wpt_actual) + if message != "": + self._append_artifact(cur_dict, "log", message) # Figure out if there was a regression or unexpected status. This only # happens for tests that were run @@ -108,7 +120,7 @@ class ChromiumFormatter(base.BaseFormatter): return "SKIP" if status == "EXTERNAL-TIMEOUT": return "TIMEOUT" - if status in ("ERROR", "CRASH"): + if status in ("ERROR", "CRASH", "PRECONDITION_FAILED"): # CRASH in WPT means a browser crash, which Chromium treats as a # test failure. return "FAIL" @@ -161,20 +173,28 @@ class ChromiumFormatter(base.BaseFormatter): def test_end(self, data): test_name = data["test"] - actual_status = self._map_status_name(data["status"]) + # Save the status reported by WPT since we might change it when reporting + # to Chromium. + wpt_actual_status = data["status"] + actual_status = self._map_status_name(wpt_actual_status) expected_statuses = self._get_expected_status_from_data(actual_status, data) subtest_failure = False - if actual_status == "PASS" and test_name in self.tests_with_subtest_fails: - # This test passed but it has failing subtests, so we flip the status - # to FAIL. - actual_status = "FAIL" + if test_name in self.tests_with_subtest_fails: subtest_failure = True # Clean up the test list to avoid accumulating too many. self.tests_with_subtest_fails.remove(test_name) + # This test passed but it has failing subtests. Since we can only + # report a single status to Chromium, we choose FAIL to indicate + # that something about this test did not run correctly. + if actual_status == "PASS": + actual_status = "FAIL" if "message" in data: - self._append_test_message(test_name, None, actual_status, expected_statuses, data["message"]) - self._store_test_result(test_name, actual_status, expected_statuses, self.messages[test_name], subtest_failure) + self._append_test_message(test_name, None, actual_status, + expected_statuses, data["message"]) + self._store_test_result(test_name, actual_status, expected_statuses, + self.messages[test_name], wpt_actual_status, + subtest_failure) # Remove the test from messages dict to avoid accumulating too many. self.messages.pop(test_name) diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py index f9ae80b0be5..cb6f1ad370f 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py @@ -156,13 +156,13 @@ def test_subtest_messages(capfd): output.seek(0) output_json = json.load(output) - t1_log = output_json["tests"]["t1"]["artifacts"]["log"] - assert t1_log == "subtest_failure\n" \ - "[FAIL expected PASS] t1_a: t1_a_message\n" \ - "[PASS] t1_b: t1_b_message\n" - - t2_log = output_json["tests"]["t2"]["artifacts"]["log"] - assert t2_log == "[TIMEOUT expected PASS] t2_message\n" + t1_artifacts = output_json["tests"]["t1"]["artifacts"] + assert t1_artifacts["log"] == "[FAIL expected PASS] t1_a: t1_a_message\n" \ + "[PASS] t1_b: t1_b_message\n" + assert t1_artifacts["wpt_subtest_failure"] == "true" + t2_artifacts = output_json["tests"]["t2"]["artifacts"] + assert t2_artifacts["log"] == "[TIMEOUT expected PASS] t2_message\n" + assert "wpt_subtest_failure" not in t2_artifacts.keys() def test_subtest_failure(capfd): @@ -203,13 +203,15 @@ def test_subtest_failure(capfd): output_json = json.load(output) test_obj = output_json["tests"]["t1"] - t1_log = test_obj["artifacts"]["log"] - assert t1_log == "subtest_failure\n" \ - "[FAIL expected PASS] t1_a: t1_a_message\n" \ - "[PASS] t1_b: t1_b_message\n" \ - "[TIMEOUT expected PASS] t1_c: t1_c_message\n" + t1_artifacts = test_obj["artifacts"] + assert t1_artifacts["log"] == "[FAIL expected PASS] t1_a: t1_a_message\n" \ + "[PASS] t1_b: t1_b_message\n" \ + "[TIMEOUT expected PASS] t1_c: t1_c_message\n" + assert t1_artifacts["wpt_subtest_failure"] == "true" # The status of the test in the output is a failure because subtests failed, - # despite the harness reporting that the test passed. + # despite the harness reporting that the test passed. But the harness status + # is logged as an artifact. + assert t1_artifacts["wpt_actual_status"] == "PASS" assert test_obj["actual"] == "FAIL" assert test_obj["expected"] == "PASS" # Also ensure that the formatter cleaned up its internal state @@ -300,10 +302,12 @@ def test_unexpected_subtest_pass(capfd): output_json = json.load(output) test_obj = output_json["tests"]["t1"] - t1_log = test_obj["artifacts"]["log"] - assert t1_log == "subtest_failure\n" \ - "[PASS expected FAIL] t1_a: t1_a_message\n" - # Since the subtest status is unexpected, we fail the test. + t1_artifacts = test_obj["artifacts"] + assert t1_artifacts["log"] == "[PASS expected FAIL] t1_a: t1_a_message\n" + assert t1_artifacts["wpt_subtest_failure"] == "true" + # Since the subtest status is unexpected, we fail the test. But we report + # wpt_actual_status as an artifact + assert t1_artifacts["wpt_actual_status"] == "PASS" assert test_obj["actual"] == "FAIL" assert test_obj["expected"] == "PASS" # Also ensure that the formatter cleaned up its internal state @@ -448,3 +452,37 @@ def test_flaky_test_unexpected(capfd): # one of the expected ones assert test_obj["is_regression"] is True assert test_obj["is_unexpected"] is True + + +def test_precondition_failed(capfd): + # Check that a failed precondition gets properly handled. + + # set up the handler. + output = StringIO() + logger = structuredlog.StructuredLogger("test_a") + logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter())) + + # Run a test with a precondition failure + logger.suite_start(["t1"], run_info={}, time=123) + logger.test_start("t1") + logger.test_end("t1", status="PRECONDITION_FAILED", expected="OK") + logger.suite_end() + + # check nothing got output to stdout/stderr + # (note that mozlog outputs exceptions during handling to stderr!) + captured = capfd.readouterr() + assert captured.out == "" + assert captured.err == "" + + # check the actual output of the formatter + output.seek(0) + output_json = json.load(output) + + test_obj = output_json["tests"]["t1"] + # The precondition failure should map to FAIL status, but we should also + # have an artifact containing the original PRECONDITION_FAILED status. + assert test_obj["actual"] == "FAIL" + assert test_obj["artifacts"]["wpt_actual_status"] == "PRECONDITION_FAILED" + # ...this is an unexpected regression because we expected a pass but failed + assert test_obj["is_regression"] is True + assert test_obj["is_unexpected"] is True diff --git a/tests/wpt/web-platform-tests/url/resources/urltestdata.json b/tests/wpt/web-platform-tests/url/resources/urltestdata.json index 32ed1959430..b2f8964c440 100644 --- a/tests/wpt/web-platform-tests/url/resources/urltestdata.json +++ b/tests/wpt/web-platform-tests/url/resources/urltestdata.json @@ -6682,5 +6682,50 @@ "pathname": "/test", "search": "?a", "hash": "#bc" + }, + "First scheme char - not allowed: https://github.com/whatwg/url/issues/464", + { + "input": "10.0.0.7:8080/foo.html", + "base": "file:///some/dir/bar.html", + "href": "file:///some/dir/10.0.0.7:8080/foo.html", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/some/dir/10.0.0.7:8080/foo.html", + "search": "", + "hash": "" + }, + "Subsequent scheme chars - not allowed", + { + "input": "a!@$*=/foo.html", + "base": "file:///some/dir/bar.html", + "href": "file:///some/dir/a!@$*=/foo.html", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/some/dir/a!@$*=/foo.html", + "search": "", + "hash": "" + }, + "First and subsequent scheme chars - allowed", + { + "input": "a1234567890-+.:foo/bar", + "base": "http://example.com/dir/file", + "href": "a1234567890-+.:foo/bar", + "protocol": "a1234567890-+.:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "foo/bar", + "search": "", + "hash": "" } ] diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-active-document.https.window.js b/tests/wpt/web-platform-tests/wake-lock/wakelock-active-document.https.window.js index 53f9fb56fa8..53745ea3c60 100644 --- a/tests/wpt/web-platform-tests/wake-lock/wakelock-active-document.https.window.js +++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-active-document.https.window.js @@ -20,6 +20,8 @@ promise_test(async t => { iframe, "/wake-lock/resources/page1.html" ); + // Save the DOMException of page1.html before navigating away. + const frameDOMException1 = iframe.contentWindow.DOMException; // We navigate the iframe again, putting wakeLock1's document into an inactive state. const wakeLock2 = await getWakeLockObject( iframe, @@ -30,6 +32,7 @@ promise_test(async t => { await promise_rejects_dom( t, "NotAllowedError", + frameDOMException1, wakeLock1.request('screen'), "Inactive document, so must throw NotAllowedError" ); @@ -58,6 +61,8 @@ promise_test(async t => { innerIframe, "/wake-lock/resources/page2.html" ); + // Save DOMException from innerIframe before navigating away. + const innerIframeDOMException = innerIframe.contentWindow.DOMException; // Navigate the outer iframe to a new location. // Wait for the load event to fire. @@ -73,6 +78,7 @@ promise_test(async t => { await promise_rejects_dom( t, "NotAllowedError", + innerIframeDOMException, wakeLock.request('screen'), "Active, but not fully active, so must throw NotAllowedError" ); diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/document-timeline-phases.tentative.html b/tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/document-timeline-phases.tentative.html new file mode 100644 index 00000000000..9b86a7105d5 --- /dev/null +++ b/tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/document-timeline-phases.tentative.html @@ -0,0 +1,19 @@ + + +Test basic functionality of document timeline phases. + + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webauthn/helpers.js b/tests/wpt/web-platform-tests/webauthn/helpers.js index 0fc64c8b522..27abaaf4766 100644 --- a/tests/wpt/web-platform-tests/webauthn/helpers.js +++ b/tests/wpt/web-platform-tests/webauthn/helpers.js @@ -537,28 +537,22 @@ function validateAuthenticatorAssertionResponse(assert) { function standardSetup(cb) { // Setup an automated testing environment if available. - let authenticator; - promise_test(async t => { - try { - authenticator = await window.test_driver.add_virtual_authenticator({ - protocol: "ctap1/u2f", - transport: "usb" - }); - } catch (error) { - if (error !== "error: Action add_virtual_authenticator not implemented") { - throw error; - } - // The protocol is not available. Continue manually. + window.test_driver.add_virtual_authenticator({ + protocol: "ctap1/u2f", + transport: "usb" + }).then(authenticator => { + cb(); + // XXX add a subtest to clean up the virtual authenticator since + // testharness does not support waiting for promises on cleanup. + promise_test(() => window.test_driver.remove_virtual_authenticator(authenticator), + "Clean up the test environment"); + }).catch(error => { + if (error !== "error: Action add_virtual_authenticator not implemented") { + throw error; } - }, "Set up the test environment"); - - cb(); - - promise_test(t => { - if (authenticator) { - return window.test_driver.remove_virtual_authenticator(authenticator); - } - }, "Clean up the test environment"); + // The protocol is not available. Continue manually. + cb(); + }); } /* JSHINT */