Bug 1617651 [wpt PR 21936] - Add preconditions to all the portals tests, a=testonly
authorJames Graham <james@hoppipolla.co.uk>
Wed, 26 Feb 2020 10:39:54 +0000
changeset 515786 848464cb19b8c7b1e88386f9a45290154e4cfb04
parent 515785 6c64f7ad2c095f94c33190c5658d4d95cdffabf3
child 515787 9b41293a45e73afb947cc1d88a087bb356cdf6c5
push id37162
push usernbeleuzu@mozilla.com
push dateThu, 27 Feb 2020 09:49:56 +0000
treeherdermozilla-central@9e8d5431c412 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1617651, 21936
milestone75.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1617651 [wpt PR 21936] - Add preconditions to all the portals tests, a=testonly Automatic update from web-platform-tests Add preconditions to all the portals tests This means that they don't time out in cases where the feature isn't supported, saving a bunch of time in CI. -- wpt-commits: 160a34e72bcc7c077002e597bd4c03cdc4675442 wpt-pr: 21936
testing/web-platform/tests/portals/about-blank-cannot-host.html
testing/web-platform/tests/portals/csp/frame-src.sub.html
testing/web-platform/tests/portals/history/history-manipulation-inside-portal.html
testing/web-platform/tests/portals/htmlportalelement-event-handler-content-attributes.html
testing/web-platform/tests/portals/portal-activate-data.html
testing/web-platform/tests/portals/portal-activate-event.html
testing/web-platform/tests/portals/portal-non-http-navigation.html
testing/web-platform/tests/portals/portal-onload-event.html
testing/web-platform/tests/portals/portals-activate-empty-browsing-context.html
testing/web-platform/tests/portals/portals-activate-inside-iframe.html
testing/web-platform/tests/portals/portals-activate-inside-portal.html
testing/web-platform/tests/portals/portals-activate-no-browsing-context.html
testing/web-platform/tests/portals/portals-activate-resolution.html
testing/web-platform/tests/portals/portals-activate-twice.html
testing/web-platform/tests/portals/portals-adopt-predecessor.html
testing/web-platform/tests/portals/portals-cross-origin-load.sub.html
testing/web-platform/tests/portals/portals-focus.sub.html
testing/web-platform/tests/portals/portals-host-exposure.sub.html
testing/web-platform/tests/portals/portals-host-hidden-after-activation.html
testing/web-platform/tests/portals/portals-host-post-message.sub.html
testing/web-platform/tests/portals/portals-navigate-after-adoption.html
testing/web-platform/tests/portals/portals-nested.html
testing/web-platform/tests/portals/portals-post-message.sub.html
testing/web-platform/tests/portals/portals-referrer-inherit-header.html
testing/web-platform/tests/portals/portals-referrer-inherit-meta.html
testing/web-platform/tests/portals/portals-referrer.html
testing/web-platform/tests/portals/portals-rendering.html
testing/web-platform/tests/portals/portals-repeated-activate.html
testing/web-platform/tests/portals/portals-set-src-after-activate.html
testing/web-platform/tests/portals/predecessor-fires-unload.html
testing/web-platform/tests/portals/xfo/portals-xfo-deny.sub.html
--- a/testing/web-platform/tests/portals/about-blank-cannot-host.html
+++ b/testing/web-platform/tests/portals/about-blank-cannot-host.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
 
 promise_test(async (t) => {
+  assert_precondition("HTMLPortalElement" in self);
   let hostWindow = window.open();
   assert_equals(hostWindow.location.href, "about:blank");
 
   let portal = hostWindow.document.createElement("portal");
   portal.src = "resources/simple-portal.html";
   hostWindow.document.body.appendChild(portal);
 
   await promise_rejects_dom(t, "InvalidStateError", portal.activate());
--- a/testing/web-platform/tests/portals/csp/frame-src.sub.html
+++ b/testing/web-platform/tests/portals/csp/frame-src.sub.html
@@ -1,41 +1,43 @@
 <!doctype html>
 <title>Tests that portals respect the frame-src</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <body>
 </body>
 <script>
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     var w = window.open("resources/frame-src.sub.html?frame_src_policy=%27none%27");
     w.onload = function() {
       w.document.addEventListener("securitypolicyviolation",
         t.step_func_done(function(e) {
           assert_equals("frame-src", e.violatedDirective);
       }));
       var portal = w.document.createElement("portal");
       portal.src = new URL("/portals/resources/simple-portal.html", location.href);
       portal.onmessage = t.unreached_func("Portal should not load.");
       w.document.body.appendChild(portal);
     }
   }, "Tests that a portal can't be loaded when it violates frame-src");
 
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     var w = window.open(`resources/frame-src.sub.html?frame_src_policy=http://{{hosts[][www]}}:{{ports[http][0]}}`);
     w.onload = function() {
       w.document.onsecuritypolicyviolation = t.unreached_func("Portal should load.");
       var portal = w.document.createElement("portal");
       portal.src = new URL("http://{{hosts[][www]}}:{{ports[http][0]}}/portals/resources/simple-portal.html", location.href);
       portal.onmessage = t.step_func_done();
       w.document.body.appendChild(portal);
     }
   }, "Tests that a portal can be loaded when the origin matches the frame-src CSP header.");
   async_test(function(t) {
-
+    assert_precondition("HTMLPortalElement" in self);
     var w = window.open(`resources/frame-src.sub.html?frame_src_policy=http://{{hosts[][www]}}:{{ports[http][0]}}`);
     w.onload = function() {
       var portal = w.document.createElement("portal");
       portal.src = new URL("http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/simple-portal.html", location.href);
       w.document.onsecuritypolicyviolation = t.step_func(function(e) {
         w.document.onsecuritypolicyviolation = null;
         assert_equals("frame-src", e.violatedDirective);
         portal.src = new URL("http://{{hosts[][www]}}:{{ports[http][0]}}/portals/resources/simple-portal.html", location.href);
--- a/testing/web-platform/tests/portals/history/history-manipulation-inside-portal.html
+++ b/testing/web-platform/tests/portals/history/history-manipulation-inside-portal.html
@@ -11,44 +11,50 @@
   // that the session history of the portal host is not affected by any history
   // changes in the portal.
   function assertInitialHistoryState() {
     assert_equals(history.length, 1);
     assert_false(!!history.state);
   }
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     assertInitialHistoryState();
     await runTestInPortal(portalSrc, 'testHistoryPushStateInPortal');
     assertInitialHistoryState();
   }, 'history.pushState navigates independently with replacement in a portal');
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     assertInitialHistoryState();
     await runTestInPortal(portalSrc, 'testHistoryReplaceStateInPortal');
     assertInitialHistoryState();
   }, 'history.replaceState navigates independently in a portal');
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     assertInitialHistoryState();
     await runTestInPortal(portalSrc, 'testLocationAssignInPortal');
     assertInitialHistoryState();
   }, 'location.assign navigates independently with replacement in a portal');
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     assertInitialHistoryState();
     await runTestInPortal(portalSrc, 'testLocationReplaceInPortal');
     assertInitialHistoryState();
   }, 'location.replace navigates independently in a portal');
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     assertInitialHistoryState();
     await runTestInPortal(portalSrc, 'testSetLocationHrefInPortal');
     assertInitialHistoryState();
   }, 'Setting location.href navigates independently with replacement in a portal');
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     assertInitialHistoryState();
     await runTestInPortal(portalSrc, 'testSyntheticAnchorClickInPortal');
     assertInitialHistoryState();
   }, 'Synthetic anchor click navigates independently with replacement in a portal');
 </script>
 </body>
--- a/testing/web-platform/tests/portals/htmlportalelement-event-handler-content-attributes.html
+++ b/testing/web-platform/tests/portals/htmlportalelement-event-handler-content-attributes.html
@@ -2,16 +2,17 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
 // Dispatch of these events is tested elsewhere.
 // This test merely ensures that the event handler content attributes work.
 let eventNames = ["load", "message", "messageerror"];
 test(() => {
   try {
+    assert_precondition("HTMLPortalElement" in self);
     let portal = document.createElement("portal");
     for (let eventName of eventNames) {
       window.testValue = "not fired";
       portal.setAttribute("on" + eventName, "window.testValue = 'fired'");
       portal.dispatchEvent(new Event(eventName));
       assert_equals(window.testValue, "fired", `${eventName} should have fired`);
 
       window.testValue = "not fired";
--- a/testing/web-platform/tests/portals/portal-activate-data.html
+++ b/testing/web-platform/tests/portals/portal-activate-data.html
@@ -8,16 +8,17 @@
 <script>
 function nextMessage(target) {
   return new Promise((resolve, reject) => {
     target.addEventListener('message', e => resolve(e), {once: true});
   });
 }
 
 async function openPortalAndActivate(logic, activateOptions) {
+  assert_precondition("HTMLPortalElement" in self);
   const w = await openBlankPortalHost();
   try {
     const portal = w.document.createElement('portal');
     portal.src = new URL('resources/portal-activate-data-portal.html?logic=' + encodeURIComponent(logic), location.href);
     w.document.body.appendChild(portal);
     assert_equals((await nextMessage(portal)).data, 'ready');
     await portal.activate(activateOptions);
     return (await nextMessage(w.portalHost)).data;
--- a/testing/web-platform/tests/portals/portal-activate-event.html
+++ b/testing/web-platform/tests/portals/portal-activate-event.html
@@ -1,36 +1,39 @@
 <!DOCTYPE html>
 <title>Tests that the PortalActivateEvent is dispatched when a portal is activated</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     let test = "eventlistener";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
       assert_equals(e.data, "passed");
       bc.close();
     });
     const portalUrl = encodeURIComponent(`portal-activate-event-portal.html?test=${test}`);
     window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}`);
   }, "Tests that the PortalActivateEvent is dispatched when a portal is activated.");
 
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     let test = "eventhandler";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
       assert_equals(e.data, "passed");
       bc.close();
     });
     const portalUrl = encodeURIComponent(`portal-activate-event-portal.html?test=${test}`);
     window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}`);
   }, "Tests that the portalactivate event handler is dispatched when a portal is activated.");
 
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     let test = "bodyeventhandler";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
       assert_equals(e.data, "passed");
       bc.close();
     });
     const portalUrl = encodeURIComponent(`portal-activate-event-portal.html?test=${test}`);
     window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}`);
--- a/testing/web-platform/tests/portals/portal-non-http-navigation.html
+++ b/testing/web-platform/tests/portals/portal-non-http-navigation.html
@@ -1,31 +1,34 @@
 <!DOCTYPE html>
 <title>Tests that portal don't navigate to non-http schemes.</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <body>
 <script>
 async_test(t => {
+  assert_precondition("HTMLPortalElement" in self);
   var portal = document.createElement("portal");
   portal.src = "data:text/html,empty portal";
   portal.onload = t.unreached_func("Portal loaded data URL.");
   document.body.appendChild(portal);
   t.step_timeout(() => { portal.remove(); t.done(); }, 3000);
 }, "Tests that a portal can't navigate to a data URL.");
 
 async_test(t => {
+  assert_precondition("HTMLPortalElement" in self);
   var portal = document.createElement("portal");
   portal.src = "about:blank";
   portal.onload = t.unreached_func("Portal loaded about:blank.");
   document.body.appendChild(portal);
   t.step_timeout(() => { portal.remove(); t.done(); }, 3000);
 }, "Tests that a portal can't navigate to about:blank.");
 
 async_test(t => {
+  assert_precondition("HTMLPortalElement" in self);
   var portal = document.createElement("portal");
   portal.src = "resources/simple-portal.html";
   portal.onload = t.step_func(() => {
     portal.onmessage = t.unreached_func("Portal execute javascript.");
     portal.src = "javascript:window.portalHost.postMessage('executed', '*')";
     t.step_timeout(() => { portal.remove(); t.done(); }, 3000);
   });
   document.body.appendChild(portal);
--- a/testing/web-platform/tests/portals/portal-onload-event.html
+++ b/testing/web-platform/tests/portals/portal-onload-event.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <title>Tests that the load is dispatched when a portal finishes loading.</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     var w = window.open("resources/simple-portal.html");
     w.onload = function() {
       var portal = w.document.createElement("portal");
       portal.src = "resources/simple-portal.html";
       portal.onload = t.step_func_done();
       w.document.body.appendChild(portal);
     }
   }, "Tests that the load event is dispatched when a portal finishes loading.");
--- a/testing/web-platform/tests/portals/portals-activate-empty-browsing-context.html
+++ b/testing/web-platform/tests/portals/portals-activate-empty-browsing-context.html
@@ -1,22 +1,24 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <body>
 <script>
 promise_test(async t => {
+  assert_precondition("HTMLPortalElement" in self);
   let portal = document.createElement('portal');
   document.body.appendChild(portal);
   t.add_cleanup(() => { document.body.removeChild(portal); });
 
   await promise_rejects_dom(t, 'InvalidStateError', portal.activate());
 }, "A portal that has never been navigated cannot be activated");
 
 promise_test(async t => {
+  assert_precondition("HTMLPortalElement" in self);
   let portal = document.createElement('portal');
   document.body.appendChild(portal);
   t.add_cleanup(() => { document.body.removeChild(portal); });
 
   // We use a status of 204 (No Content) as that couldn't possibly mature.
   portal.src = "resources/204-no-content.asis";
   await promise_rejects_dom(t, 'InvalidStateError', portal.activate());
 }, "A portal that has not completed an initial navigation cannot be activated");
--- a/testing/web-platform/tests/portals/portals-activate-inside-iframe.html
+++ b/testing/web-platform/tests/portals/portals-activate-inside-iframe.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <body>
   <script>
     promise_test(async t => {
+      assert_precondition("HTMLPortalElement" in self);
       var iframe = document.createElement("iframe");
       iframe.src = "resources/portal-inside-iframe.html"
       var waitForLoad = new Promise((resolve, reject) => {
         iframe.onload = resolve;
       });
       document.body.appendChild(iframe);
       await waitForLoad;
       const portal = iframe.contentDocument.getElementById("portal");
--- a/testing/web-platform/tests/portals/portals-activate-inside-portal.html
+++ b/testing/web-platform/tests/portals/portals-activate-inside-portal.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <body>
   <script>
     promise_test(async () => {
+      assert_precondition("HTMLPortalElement" in self);
       var portal = document.createElement("portal");
       portal.src = "resources/portal-activate-inside-portal.html";
       let waitForMessage = new Promise((resolve, reject) => {
         portal.onmessage = e => resolve(e.data);
         document.body.appendChild(portal);
       });
       var error = await waitForMessage;
       assert_equals(error, "InvalidStateError");
--- a/testing/web-platform/tests/portals/portals-activate-no-browsing-context.html
+++ b/testing/web-platform/tests/portals/portals-activate-no-browsing-context.html
@@ -1,9 +1,10 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
 promise_test(async t => {
+  assert_precondition("HTMLPortalElement" in self);
   let activatePromise = document.createElement('portal').activate();
   await promise_rejects_dom(t, 'InvalidStateError', activatePromise);
 }, "A portal with nothing in it cannot be activated");
 </script>
--- a/testing/web-platform/tests/portals/portals-activate-resolution.html
+++ b/testing/web-platform/tests/portals/portals-activate-resolution.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/open-blank-host.js"></script>
 <script>
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     var win = await openBlankPortalHost();
     var portal = win.document.createElement("portal");
     portal.src = new URL("resources/simple-portal.html", location.href)
 
     await new Promise((resolve, reject) => {
       portal.onload = resolve;
       win.document.body.appendChild(portal);
     });
--- a/testing/web-platform/tests/portals/portals-activate-twice.html
+++ b/testing/web-platform/tests/portals/portals-activate-twice.html
@@ -1,22 +1,24 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
 promise_test(async t => {
+  assert_precondition("HTMLPortalElement" in self);
   let waitForMessage = new Promise((resolve, reject) => {
     window.onmessage = e => resolve(e.data);
   });
   window.open("resources/portal-activate-twice-window-1.html");
   let error = await waitForMessage;
   assert_equals(error, "InvalidStateError");
 }, "Calling activate when a portal is already activating should fail");
 
 promise_test(async t => {
+  assert_precondition("HTMLPortalElement" in self);
   let waitForMessage = new Promise((resolve, reject) => {
     window.onmessage = e => resolve(e.data);
   });
   window.open("resources/portal-activate-twice-window-2.html");
   let error = await waitForMessage;
   assert_equals(error, "InvalidStateError");
 });
 </script>
--- a/testing/web-platform/tests/portals/portals-adopt-predecessor.html
+++ b/testing/web-platform/tests/portals/portals-adopt-predecessor.html
@@ -8,67 +8,74 @@
       window.addEventListener("message", ({data: {test, message}}) => {
          if (test === targetTest)
            resolve(message);
       });
     });
   }
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-once";
     window.open(`resources/portals-adopt-predecessor.html?test=${test}`);
     var message = await waitForCompletion(test);
     assert_equals(message, "adopted");
   }, "Tests that a portal can adopt its predecessor.");
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-twice";
     window.open(`resources/portals-adopt-predecessor.html?test=${test}`);
     var message = await waitForCompletion(test);
     assert_equals(message, "passed");
   }, "Tests that trying to adopt the predecessor twice will throw an exception.");
 
   async_test(function(t) {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-after-event";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
       assert_equals(e.data, "passed");
       bc.close();
     });
     window.open(`resources/portals-adopt-predecessor.html?test=${test}`);
   }, "Tests that trying to adopt the predecessor after the PortalActivateEvent will throw an exception.");
 
   promise_test(async t => {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-and-activate";
     window.open(`resources/portals-adopt-predecessor.html?test=${test}`);
     var message = await waitForCompletion(test);
     assert_equals(message, "passed");
   }, "Tests that activating an adopted predecessor without inserting it works");
 
   async_test(t => {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-attach-remove";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
       assert_equals(e.data, "passed");
       bc.close();
     });
     window.open(`resources/portals-adopt-predecessor.html?test=${test}`);
   }, "Tests that an adopting, inserting and then removing a predecessor works correctly");
 
   async_test(t => {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-and-discard";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
       assert_equals(e.data, "passed");
       bc.close();
     });
     window.open(`resources/portals-adopt-predecessor.html?test=${test}`);
   }, "Tests that the adopted predecessor is destroyed if it isn't inserted");
 
   async_test(t => {
+    assert_precondition("HTMLPortalElement" in self);
     var test = "adopt-to-disconnected-node";
     var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
       assert_equals(e.data, "passed");
       bc.close();
     });
     window.open(`resources/portals-adopt-predecessor.html?test=${test}`);
   }, "Tests that an adopted portal can be inserted into a disconnected node.");
--- a/testing/web-platform/tests/portals/portals-cross-origin-load.sub.html
+++ b/testing/web-platform/tests/portals/portals-cross-origin-load.sub.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <body>
 <script>
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     var portal = document.createElement("portal");
     portal.src = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/simple-portal.html";
     return new Promise((resolve, reject) => {
       portal.onload = resolve;
       document.body.appendChild(portal);
     });
   });
 </script>
--- a/testing/web-platform/tests/portals/portals-focus.sub.html
+++ b/testing/web-platform/tests/portals/portals-focus.sub.html
@@ -3,16 +3,17 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/resources/testdriver.js"></script>
 <script src="/resources/testdriver-vendor.js"></script>
 <script src="resources/open-blank-host.js"></script>
 <body>
 <script>
   async function createPortal(doc, url) {
+    assert_precondition("HTMLPortalElement" in self);
     let portal = doc.createElement("portal");
     portal.src = url;
     doc.body.appendChild(portal);
     await new Promise(r => portal.onload = r);
     return portal;
   }
 
   promise_test(async t => {
--- a/testing/web-platform/tests/portals/portals-host-exposure.sub.html
+++ b/testing/web-platform/tests/portals/portals-host-exposure.sub.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <body>
 <script>
   function openPortalAndReceiveMessage(portalSrc) {
+    assert_precondition("HTMLPortalElement" in self);
     let portal = document.createElement('portal');
     portal.src = portalSrc;
     let received = new Promise((resolve, reject) => {
       portal.onmessage = resolve;
       document.body.appendChild(portal);
     });
     return received;
   }
--- a/testing/web-platform/tests/portals/portals-host-hidden-after-activation.html
+++ b/testing/web-platform/tests/portals/portals-host-hidden-after-activation.html
@@ -14,16 +14,17 @@
           bc.close();
           resolve(results);
         }
       };
     });
   }
 
   promise_test(async () => {
+    assert_precondition("HTMLPortalElement" in self);
     const portalUrl = encodeURIComponent("portal-host-hidden-after-activation-portal.html");
     window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}`);
     var results = await waitForMessages();
     assert_true(results[0], "portalHost exposed before calling activate()");
     assert_false(results[1], "portalHost hidden after receiving portalactivate event");
   }, "window.portalHost should be null after portal is activated");
 </script>
 </body>
--- a/testing/web-platform/tests/portals/portals-host-post-message.sub.html
+++ b/testing/web-platform/tests/portals/portals-host-post-message.sub.html
@@ -12,16 +12,17 @@
         portal.onload = () => {
           resolve(portal);
         };
         document.body.appendChild(portal);
       });
     }
 
     async function createPortalAndLoopMessage(portalSrc, params) {
+      assert_precondition("HTMLPortalElement" in self);
       var portal = await createPortal(portalSrc);
       var waitForResponse = new Promise((resolve, reject) => {
         portal.addEventListener("message", e => { resolve(e); });
       });
       portal.postMessage(params, "*");
       return waitForResponse;
     }
 
@@ -67,16 +68,17 @@
         "resources/portal-host-post-message.sub.html", [message]);
       assert_object_equals(data, message);
       var {data} = await createPortalAndLoopMessage(crossOriginUrl,
                                                     [message, "*"]);
       assert_object_equals(data, message);
     }, "postMessage with object message");
 
     promise_test(async () => {
+      assert_precondition("HTMLPortalElement" in self);
       function checkPort(port) {
         return new Promise((resolve, reject) => {
           var channel = new MessageChannel();
           channel.port1.onmessage = resolve;
           port.postMessage("sending port", [channel.port2]);
         });
       }
 
@@ -131,28 +133,30 @@
     promise_test(async () => {
       var {data} = await createPortalAndLoopMessage(
         "resources/portal-host-post-message.sub.html",
         {type: "invalid-port"});
       assert_equals(data.errorType, "TypeError");
     }, "postMessage with invalid transferable should throw error");
 
     promise_test(async () => {
+      assert_precondition("HTMLPortalElement" in self);
        var receiveMessage = new Promise((resolve, reject) => {
          var bc = new BroadcastChannel("portal-host-post-message-after-activate");
          bc.onmessage = e => { resolve(e); };
        });
        const portalUrl = encodeURIComponent(
           "portal-host-post-message-after-activate.html");
        window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}`);
        var message = await receiveMessage;
        assert_equals(message.data, "InvalidStateError");
     }, "Calling postMessage after receiving onactivate event should fail");
 
     promise_test(() => {
+      assert_precondition("HTMLPortalElement" in self);
       var portal = document.createElement("portal");
       portal.src = "resources/portal-host-post-message-navigate-1.html";
       var count = 0;
       var waitForMessages = new Promise((resolve, reject) => {
         portal.addEventListener("message", e => {
           count++;
           if (count == 2)
             resolve();
--- a/testing/web-platform/tests/portals/portals-navigate-after-adoption.html
+++ b/testing/web-platform/tests/portals/portals-navigate-after-adoption.html
@@ -22,16 +22,17 @@ async function openPortalAndActivate(log
     port2.start();
     return (await nextMessage(port2)).data;
   } finally {
     w.close();
   }
 }
 
 promise_test(async () => {
+  assert_precondition("HTMLPortalElement" in self);
   let messageFromNewSrc = await openPortalAndActivate(
       'let predecessor = event.adoptPredecessor();' +
       'let readyPromise = new Promise((resolve, reject) => {' +
       '  predecessor.onmessage = e => resolve(e.data + " via new src");' +
       '});' +
       'predecessor.src = "/portals/resources/eval-portal.html";' +
       'document.body.appendChild(predecessor);' +
       'return readyPromise;');
--- a/testing/web-platform/tests/portals/portals-nested.html
+++ b/testing/web-platform/tests/portals/portals-nested.html
@@ -1,14 +1,15 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <body>
   <script>
     promise_test(() => {
+      assert_precondition("HTMLPortalElement" in self);
       var portal = document.createElement("portal");
       portal.src = "resources/portals-nested-portal.html";
       document.body.appendChild(portal);
       var waitForMessage = new Promise((resolve, reject) => {
         portal.onmessage = resolve;
       });
       return waitForMessage;
     }, "nested portals shouldn't crash");
--- a/testing/web-platform/tests/portals/portals-post-message.sub.html
+++ b/testing/web-platform/tests/portals/portals-post-message.sub.html
@@ -7,16 +7,17 @@
 <script src="/resources/testdriver-vendor.js"></script>
 <body>
   <input id="input"/>
   <script>
     const sameOriginUrl = "resources/portal-post-message-portal.html"
     const crossOriginUrl = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/portal-post-message-portal.html"
 
     async function createAndInsertPortal(portalSrc) {
+      assert_precondition("HTMLPortalElement" in self);
       var portal = document.createElement("portal");
       portal.src = portalSrc;
       document.body.append(portal);
 
       var loadPromise = new Promise((resolve, reject) => {
         portal.onload = resolve;
       });
       await loadPromise;
@@ -179,29 +180,32 @@
         bc.onmessage = e => {
           bc.close();
           resolve(e.data);
         }
       });
     }
 
     promise_test(async t => {
+      assert_precondition("HTMLPortalElement" in self);
       window.open("resources/portal-post-message-before-activate-window.html");
       let {postMessageTS, activateTS} = await waitForMessage(
           "portals-post-message-before-activate");
       assert_less_than_equal(postMessageTS, activateTS);
     }, "postMessage before activate should work and preserve order");
 
     promise_test(async t => {
+      assert_precondition("HTMLPortalElement" in self);
       window.open("resources/portal-post-message-during-activate-window.html");
       let error = await waitForMessage("portals-post-message-during-activate");
       assert_equals(error, "InvalidStateError");
     }, "postMessage during activate throws error");
 
     promise_test(async t => {
+      assert_precondition("HTMLPortalElement" in self);
       window.open("resources/portal-post-message-after-activate-window.html");
       let error = await waitForMessage("portals-post-message-after-activate");
       assert_equals(error, "InvalidStateError");
     }, "postMessage after activate throws error");
 
     // TODO(adithyas): Use async_test instead of promise_test (for tests that
     // use a timeout) once we implement postMessage in the other direction and
     // no longer need to use broadcast channel.
--- a/testing/web-platform/tests/portals/portals-referrer-inherit-header.html
+++ b/testing/web-platform/tests/portals/portals-referrer-inherit-header.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <body>
 <script>
 promise_test(async () => {
-  assert_true('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
+  assert_precondition('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
   let portal = document.createElement('portal');
   let referrerPromise = new Promise((resolve, reject) => {
     portal.addEventListener('message', e => resolve(e.data), {once: true});
   });
   portal.src = 'resources/postmessage-referrer.sub.html';
   document.body.appendChild(portal);
   try {
     let {httpReferrer, documentReferrer} = await referrerPromise;
--- a/testing/web-platform/tests/portals/portals-referrer-inherit-meta.html
+++ b/testing/web-platform/tests/portals/portals-referrer-inherit-meta.html
@@ -1,16 +1,16 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <meta name="referrer" content="no-referrer">
 <body>
 <script>
 promise_test(async () => {
-  assert_true('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
+  assert_precondition('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
   let portal = document.createElement('portal');
   let referrerPromise = new Promise((resolve, reject) => {
     portal.addEventListener('message', e => resolve(e.data), {once: true});
   });
   portal.src = 'resources/postmessage-referrer.sub.html';
   document.body.appendChild(portal);
   try {
     let {httpReferrer, documentReferrer} = await referrerPromise;
--- a/testing/web-platform/tests/portals/portals-referrer.html
+++ b/testing/web-platform/tests/portals/portals-referrer.html
@@ -1,32 +1,32 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <body>
 <script>
 promise_test(async () => {
-  assert_true('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
+  assert_precondition('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
   let portal = document.createElement('portal');
   let referrerPromise = new Promise((resolve, reject) => {
     portal.addEventListener('message', e => resolve(e.data), {once: true});
   });
   portal.src = 'resources/postmessage-referrer.sub.html';
   document.body.appendChild(portal);
   try {
     let {httpReferrer, documentReferrer} = await referrerPromise;
     assert_equals(httpReferrer, location.href, 'HTTP Referer header should be sent by default');
     assert_equals(documentReferrer, location.href, 'document.referrer should be present by default');
   } finally {
     document.body.removeChild(portal);
   }
 }, "portal contents should be loaded with referrer");
 
 promise_test(async () => {
-  assert_true('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
+  assert_precondition('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
   let portal = document.createElement('portal');
   portal.referrerPolicy = 'no-referrer';
   let referrerPromise = new Promise((resolve, reject) => {
     portal.addEventListener('message', e => resolve(e.data), {once: true});
   });
   portal.src = 'resources/postmessage-referrer.sub.html';
   document.body.appendChild(portal);
   try {
@@ -34,17 +34,17 @@ promise_test(async () => {
     assert_equals(httpReferrer, 'no-http-referrer', 'No HTTP Referer header should be sent');
     assert_equals(documentReferrer, 'no-document-referrer', 'No document.referrer should be present');
   } finally {
     document.body.removeChild(portal);
   }
 }, "portal contents should be loaded with no referrer if referrerpolicy=no-referrer");
 
 promise_test(async () => {
-  assert_true('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
+  assert_precondition('HTMLPortalElement' in self, 'HTMLPortalElement is required for this test');
   let portal = document.createElement('portal');
   portal.referrerPolicy = 'origin';
   let referrerPromise = new Promise((resolve, reject) => {
     portal.addEventListener('message', e => resolve(e.data), {once: true});
   });
   portal.src = 'resources/postmessage-referrer.sub.html';
   document.body.appendChild(portal);
   try {
--- a/testing/web-platform/tests/portals/portals-rendering.html
+++ b/testing/web-platform/tests/portals/portals-rendering.html
@@ -1,17 +1,22 @@
 <!DOCTYPE html>
 <html class="reftest-wait">
 <title>Portals rendering test</title>
 <link rel="match" href="references/portals-rendering.html">
-<body>
-  <script>
-    var portal = document.createElement('portal');
-    portal.src = 'resources/portals-rendering-portal.html';
-    portal.style = 'background-color: red; width: 100px; height: 100px';
-    portal.onmessage = e => {
-      window.requestAnimationFrame(function(ts) {
-        document.documentElement.classList.remove('reftest-wait');
-      });
-    }
-    document.body.appendChild(portal);
-  </script>
-</body>
+<body></body>
+<script>
+if (!("HTMLPortalElement" in self)) {
+  document.body.textContent = "PRECONDITION FAILED";
+  document.documentElement.classList.remove('reftest-wait');
+} else {
+  var portal = document.createElement('portal');
+  portal.src = 'resources/portals-rendering-portal.html';
+  portal.style = 'background-color: red; width: 100px; height: 100px';
+  portal.onmessage = e => {
+    window.requestAnimationFrame(function(ts) {
+      document.documentElement.classList.remove('reftest-wait');
+    });
+  };
+  document.body.appendChild(portal);
+}
+</script>
+
--- a/testing/web-platform/tests/portals/portals-repeated-activate.html
+++ b/testing/web-platform/tests/portals/portals-repeated-activate.html
@@ -1,10 +1,11 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
-  async_test(async t => {
+  async_test(t => {
+    assert_precondition("HTMLPortalElement" in self);
     let win = window.open("resources/portal-repeated-activate-window.html");
     win.onload = () => win.activate();
     window.onmessage = t.step_func_done(() => {});
   }, "test activation in page that has been reactivated")
 </script>
--- a/testing/web-platform/tests/portals/portals-set-src-after-activate.html
+++ b/testing/web-platform/tests/portals/portals-set-src-after-activate.html
@@ -5,16 +5,17 @@
 <script>
 function nextMessage(target) {
   return new Promise((resolve, reject) => {
     target.addEventListener('message', e => resolve(e), {once: true});
   });
 }
 
 promise_test(async () => {
+  assert_precondition("HTMLPortalElement" in self);
   const w = await openBlankPortalHost();
   try {
     const portal = w.document.createElement('portal');
     portal.src = new URL('resources/simple-portal-adopts-predecessor.html', location.href);
     w.document.body.appendChild(portal);
     assert_equals((await nextMessage(portal)).data, 'ready');
 
     // Intentionally don't await activation finishing; this should work
--- a/testing/web-platform/tests/portals/predecessor-fires-unload.html
+++ b/testing/web-platform/tests/portals/predecessor-fires-unload.html
@@ -7,16 +7,17 @@ function nextEvent(target, type) {
   return new Promise((resolve, reject) => target.addEventListener(type, e => resolve(e), {once: true}));
 }
 
 function timePasses(delay) {
   return new Promise((resolve, reject) => step_timeout(() => resolve(), delay));
 }
 
 promise_test(async () => {
+  assert_precondition("HTMLPortalElement" in self);
   const w = await openBlankPortalHost();
   try {
     const portal = w.document.createElement('portal');
     portal.src = new URL('resources/simple-portal.html', location.href);
     w.document.body.appendChild(portal);
     await nextEvent(portal, 'load');
     const pagehideFired = nextEvent(w, 'pagehide');
     const unloadFired = nextEvent(w, 'unload');
@@ -24,15 +25,16 @@ promise_test(async () => {
     assert_true((await pagehideFired) instanceof w.PageTransitionEvent);
     assert_true((await unloadFired) instanceof w.Event);
   } finally {
     w.close();
   }
 }, "pagehide and unload should fire if the predecessor is not adopted");
 
 promise_test(async () => {
+  assert_precondition("HTMLPortalElement" in self);
   localStorage.setItem('predecessor-fires-unload-events', '');
   window.open('resources/predecessor-fires-unload-watch-unload.html', '_blank', 'noopener');
   while (localStorage.getItem('predecessor-fires-unload-events') != 'pagehide unload') {
     await timePasses(50);
   }
 }, "pagehide and unload should fire if the predecessor is not adopted, even without a window/opener association");
 </script>
--- a/testing/web-platform/tests/portals/xfo/portals-xfo-deny.sub.html
+++ b/testing/web-platform/tests/portals/xfo/portals-xfo-deny.sub.html
@@ -3,25 +3,27 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <body>
 <script>
 // TODO(jbroman): Ideally these would also check that the portal element gets a
 // completion event.
 
 async_test(t => {
+  assert_precondition("HTMLPortalElement" in self);
   var portal = document.createElement('portal');
   portal.src = "/portals/xfo/resources/xfo-deny.asis";
   portal.onmessage = t.unreached_func("should not have received a message");
   document.body.appendChild(portal);
   t.add_cleanup(() => portal.remove());
   t.step_timeout(() => t.done(), 2000);
 }, "`XFO: DENY` blocks same-origin portals.");
 
 async_test(t => {
+  assert_precondition("HTMLPortalElement" in self);
   var portal = document.createElement('portal');
   portal.src = "http://{{domains[www]}}:{{ports[http][0]}}/portals/xfo/resources/xfo-deny.asis";
   portal.onmessage = t.unreached_func("should not have received a message");
   document.body.appendChild(portal);
   t.add_cleanup(() => portal.remove());
   t.step_timeout(() => t.done(), 2000);
 }, "`XFO: DENY` blocks cross-origin portals.");
 </script>