aboutsummaryrefslogtreecommitdiffstats
path: root/tests/wpt/web-platform-tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/wpt/web-platform-tests')
-rw-r--r--tests/wpt/web-platform-tests/.taskcluster.yml14
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-serializable.html42
-rw-r--r--tests/wpt/web-platform-tests/common/security-features/resources/common.sub.js2
-rw-r--r--tests/wpt/web-platform-tests/compat/webkit-box-removing-triggering-anonymous-merge.html14
-rw-r--r--tests/wpt/web-platform-tests/contacts/contacts-select.https.window.js11
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/floats/adjoining-floats-dynamic.html35
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-001-ref.html9
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-001.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-002-ref.html2
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-002.html24
-rw-r--r--tests/wpt/web-platform-tests/css/css-masking/animations/clip-interpolation.html117
-rw-r--r--tests/wpt/web-platform-tests/css/css-masking/parsing/mask-invalid.html35
-rw-r--r--tests/wpt/web-platform-tests/css/css-masking/parsing/mask-valid.sub.html62
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-006-ref.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-006.html1
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-008-ref.html49
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-008.html46
-rw-r--r--tests/wpt/web-platform-tests/css/css-overflow/float-with-relpos-and-transform.html24
-rw-r--r--tests/wpt/web-platform-tests/css/css-paint-api/geometry-border-image-005-ref.html18
-rw-r--r--tests/wpt/web-platform-tests/css/css-paint-api/geometry-border-image-005.https.html37
-rw-r--r--tests/wpt/web-platform-tests/css/css-position/position-absolute-replaced-minmax.html9
-rw-r--r--tests/wpt/web-platform-tests/docs/running-tests/webkitgtk_minibrowser.md12
-rw-r--r--tests/wpt/web-platform-tests/html/dom/idlharness.https.html1
-rw-r--r--tests/wpt/web-platform-tests/interfaces/feature-policy.idl1
-rw-r--r--tests/wpt/web-platform-tests/interfaces/webrtc-stats.idl2
-rw-r--r--tests/wpt/web-platform-tests/mathml/presentation-markup/menclose/legacy-menclose-radical-notation-ref.html5
-rw-r--r--tests/wpt/web-platform-tests/mathml/presentation-markup/menclose/legacy-menclose-radical-notation.html5
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/html5-tree/tabindex-001.html4
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-bitrate.https.html226
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-creation.https.html4
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-events-and-exceptions.html28
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-mimetype.html147
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-pause-resume.html7
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-record/idlharness.window.js6
-rw-r--r--tests/wpt/web-platform-tests/resources/chromium/webxr-test.js28
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-add-async.https.html11
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/global-serviceworker.https.any.js2
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-add-async-worker.js6
-rwxr-xr-xtests/wpt/web-platform-tests/tools/ci/run_tc.py25
-rw-r--r--tests/wpt/web-platform-tests/tools/docker/Dockerfile.webkitgtk23
-rw-r--r--tests/wpt/web-platform-tests/tools/docker/README.md2
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/base.py14
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/epiphany.py7
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py2
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py19
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/processing-model/cycle-witout-delay.html35
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/processing-model/delay-time-clamping.html38
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/processing-model/feedback-delay-time.html36
48 files changed, 1184 insertions, 78 deletions
diff --git a/tests/wpt/web-platform-tests/.taskcluster.yml b/tests/wpt/web-platform-tests/.taskcluster.yml
index b23cc93e633..adb81d6c027 100644
--- a/tests/wpt/web-platform-tests/.taskcluster.yml
+++ b/tests/wpt/web-platform-tests/.taskcluster.yml
@@ -12,15 +12,16 @@ tasks:
$flatten:
$match: {
event.ref == "refs/heads/master": [{name: firefox, channel: nightly}, {name: chrome, channel: dev}],
- event.ref == "refs/heads/epochs/daily": [{name: firefox, channel: stable}, {name: chrome, channel: stable}],
+ event.ref == "refs/heads/epochs/daily": [{name: firefox, channel: stable}, {name: chrome, channel: stable}, {name: webkitgtk_minibrowser, channel: stable}],
event.ref == "refs/heads/epochs/weekly": [{name: firefox, channel: beta}, {name: chrome, channel: beta}],
event.ref == "refs/heads/triggers/chrome_stable": [{name: chrome, channel: stable}],
event.ref == "refs/heads/triggers/chrome_beta": [{name: chrome, channel: beta}],
event.ref == "refs/heads/triggers/chrome_dev": [{name: chrome, channel: dev}],
event.ref == "refs/heads/triggers/firefox_stable": [{name: firefox, channel: stable}],
event.ref == "refs/heads/triggers/firefox_beta": [{name: firefox, channel: beta}],
- event.ref == "refs/heads/triggers/firefox_nightly": [{name: firefox, channel: nightly}]
- }
+ event.ref == "refs/heads/triggers/firefox_nightly": [{name: firefox, channel: nightly}],
+ event.ref == "refs/heads/triggers/webkitgtk_minibrowser_stable": [{name: webkitgtk_minibrowser, channel: stable}]
+ }
each(browser):
$map:
- [testharness, 1, 15]
@@ -70,7 +71,12 @@ tasks:
owner: ${event.pusher.email}
source: ${event.repository.url}
payload:
- image: harjgam/web-platform-tests:0.33
+ image:
+ $if: browser.name == 'webkitgtk_minibrowser'
+ then:
+ cl0p3z/web-platform-tests:0.1
+ else:
+ harjgam/web-platform-tests:0.33
maxRunTime: 7200
artifacts:
public/results:
diff --git a/tests/wpt/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-serializable.html b/tests/wpt/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-serializable.html
new file mode 100644
index 00000000000..44e7a403510
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-serializable.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>createImageBitmap serialize test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/namespaces.js"></script>
+<script src="common.sub.js"></script>
+<div id=log></div>
+<script>
+let worker, continuations = {};
+setup(function() {
+ worker = new Worker("transfer-worker.js");
+ worker.addEventListener("message", function(event) {
+ let { name, bitmap } = event.data;
+ if (continuations.hasOwnProperty(name)) {
+ continuations[name](bitmap);
+ }
+ });
+});
+
+for (let { name, factory } of imageSourceTypes) {
+ promise_test(function(t) {
+ return factory().then(createImageBitmap).then(function(bitmap) {
+ assert_equals(bitmap.width, 20);
+ assert_equals(bitmap.height, 20);
+
+ worker.postMessage({ name: t.name, bitmap: bitmap });
+
+ assert_equals(bitmap.width, 20);
+ assert_equals(bitmap.height, 20);
+
+ return new Promise(function(resolve) {
+ continuations[t.name] = resolve;
+ });
+ }).then(function(bitmap) {
+ assert_class_string(bitmap, "ImageBitmap");
+ assert_equals(bitmap.width, 20);
+ assert_equals(bitmap.height, 20);
+ });
+ }, `Serialize ImageBitmap created from ${name}`);
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/common/security-features/resources/common.sub.js b/tests/wpt/web-platform-tests/common/security-features/resources/common.sub.js
index 12776b1a4b5..c974e83b960 100644
--- a/tests/wpt/web-platform-tests/common/security-features/resources/common.sub.js
+++ b/tests/wpt/web-platform-tests/common/security-features/resources/common.sub.js
@@ -1225,7 +1225,7 @@ function invokeFromIframe(subresource, sourceContextList) {
promise = fetch(frameUrl)
.then(r => r.text())
.then(t => {
- frameContnent = t;
+ frameContent = t;
iframe = createElement("iframe", {}, document.body, true);
return iframe.eventPromise;
})
diff --git a/tests/wpt/web-platform-tests/compat/webkit-box-removing-triggering-anonymous-merge.html b/tests/wpt/web-platform-tests/compat/webkit-box-removing-triggering-anonymous-merge.html
new file mode 100644
index 00000000000..8506425548b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/compat/webkit-box-removing-triggering-anonymous-merge.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div style="display: -webkit-box">
+ <span><div></div></span>
+ <div id="target"></div>
+ text
+</div>
+<script>
+// Force a layout before removing.
+document.body.offsetTop;
+document.getElementById('target').remove();
+done();
+</script>
diff --git a/tests/wpt/web-platform-tests/contacts/contacts-select.https.window.js b/tests/wpt/web-platform-tests/contacts/contacts-select.https.window.js
index 8d1fdfbfdff..5503ea6968a 100644
--- a/tests/wpt/web-platform-tests/contacts/contacts-select.https.window.js
+++ b/tests/wpt/web-platform-tests/contacts/contacts-select.https.window.js
@@ -48,6 +48,17 @@ contactsTestWithUserActivation(async (test, setSelectedContacts) => {
}, 'The Contact API can fail when the selector cannot be opened');
contactsTestWithUserActivation(async (test, setSelectedContacts) => {
+ setSelectedContacts([]);
+
+ const properties = await navigator.contacts.getProperties();
+ assert_true(properties.length > 0);
+
+ // Requesting the available properties should not fail.
+ await navigator.contacts.select(properties);
+
+}, 'Supported contact properties are exposed.');
+
+contactsTestWithUserActivation(async (test, setSelectedContacts) => {
// Returns two contacts with all information available.
setSelectedContacts([
{ name: ['Dwight Schrute'], email: ['dwight@schrutefarmsbnb.com'], tel: ['000-0000'] },
diff --git a/tests/wpt/web-platform-tests/css/CSS2/floats/adjoining-floats-dynamic.html b/tests/wpt/web-platform-tests/css/CSS2/floats/adjoining-floats-dynamic.html
new file mode 100644
index 00000000000..3446d972d72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/floats/adjoining-floats-dynamic.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1003558">
+<style>
+#target {
+ height: 50px;
+ width: 0;
+ background: green;
+ float: right;
+}
+
+span {
+ float: left;
+ width: 50px;
+ height: 50px;
+ background: green;
+}
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="display: flow-root; width: 100px; background: red;">
+ <div id="target"></div>
+ <div style="position: absolute; width: 50px; height: 50px; background: green;"></div>
+ <div>
+ <div style="clear: both; height: 10px;">
+ <div>
+ <span></span>
+ <span></span>
+ </div>
+ </div>
+ </div>
+</div>
+<script>
+document.body.offsetTop;
+document.getElementById('target').style.width = '50px';
+</script>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-001-ref.html b/tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-001-ref.html
new file mode 100644
index 00000000000..594847b1285
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-001-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<body>
+ <div>אבג</div>
+ <div>אבג</div>
+ <div>אבג</div>
+ <div>אבג</div>
+ <div>אבג</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-001.html b/tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-001.html
new file mode 100644
index 00000000000..b645a2b548c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-001.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test: Inline boxes should not affect bidi reordering</title>
+<link rel="match" href="bidi-span-001-ref.html">
+<link rel="help" href="https://drafts.csswg.org/css2/visuren.html#direction">
+<link rel="author" title="Koji Ishii" href="mailto:kojii@chromium.org">
+<body>
+ <div>א<span></span>בג</div>
+ <div>א<span style="background: white"></span>בג</div>
+ <div>א<span>ב</span>ג</div>
+ <div>א<span style="background: white">ב</span>ג</div>
+ <div>אבג</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-002-ref.html b/tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-002-ref.html
new file mode 100644
index 00000000000..6cc72c208a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-002-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<body>()</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-002.html b/tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-002.html
new file mode 100644
index 00000000000..d4fc6de070d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/text/bidi-span-002.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>CSS Test: Inline boxes should not affect bidi reordering</title>
+<link rel="match" href="bidi-span-002-ref.html">
+<link rel="help" href="https://drafts.csswg.org/css2/visuren.html#direction">
+<link rel="author" title="Koji Ishii" href="mailto:kojii@chromium.org">
+<style>
+body {
+ text-align: left;
+ direction: rtl;
+}
+
+.c1:before {
+ content: '(';
+}
+
+.c1:after {
+ content: ')';
+}
+
+.c2:after {
+ content: '';
+}
+</style>
+<body><span class="c1"><span class="c2"></span></span></body>
diff --git a/tests/wpt/web-platform-tests/css/css-masking/animations/clip-interpolation.html b/tests/wpt/web-platform-tests/css/css-masking/animations/clip-interpolation.html
new file mode 100644
index 00000000000..322ebd724e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-masking/animations/clip-interpolation.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>clip interpolation</title>
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/#clip-property">
+<meta name="assert" content="clip supports animation">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/interpolation-testcommon.js"></script>
+
+<style>
+.container {
+ width: 80px;
+ height: 80px;
+ background: black;
+ display: inline-block;
+ padding: 5px;
+}
+
+.container:nth-child(2n) {
+ background: green;
+}
+
+.parent {
+ clip: rect(100px, 0px, 100px, 0px);
+}
+
+.target {
+ width: 80px;
+ height: 80px;
+ display: inline-block;
+ position: absolute;
+ background: white;
+ clip: rect(0px, 100px, 0px, 100px);
+}
+</style>
+
+<body>
+<template id="target-template">
+<div class="container"><div class="target"></div></div>
+</template>
+<script>
+test_interpolation({
+ property: 'clip',
+ from: neutralKeyframe,
+ to: 'rect(20px, 20px, 20px, 20px)',
+}, [
+ {at: -1, expect: 'rect(-20px 180px -20px 180px)'},
+ {at: 0, expect: 'rect(0px 100px 0px 100px)'},
+ {at: 0.25, expect: 'rect(5px 80px 5px 80px)'},
+ {at: 0.75, expect: 'rect(15px 40px 15px 40px)'},
+ {at: 1, expect: 'rect(20px 20px 20px 20px)'},
+ {at: 2, expect: 'rect(40px -60px 40px -60px)'},
+]);
+
+test_no_interpolation({
+ property: 'clip',
+ from: 'initial',
+ to: 'rect(20px, 20px, 20px, 20px)',
+});
+
+test_interpolation({
+ property: 'clip',
+ from: 'inherit',
+ to: 'rect(20px, 20px, 20px, 20px)',
+}, [
+ {at: -1, expect: 'rect(180px -20px 180px -20px)'},
+ {at: 0, expect: 'rect(100px 0px 100px 0px)'},
+ {at: 0.25, expect: 'rect(80px 5px 80px 5px)'},
+ {at: 0.75, expect: 'rect(40px 15px 40px 15px)'},
+ {at: 1, expect: 'rect(20px 20px 20px 20px)'},
+ {at: 2, expect: 'rect(-60px 40px -60px 40px)'},
+]);
+
+test_no_interpolation({
+ property: 'clip',
+ from: 'unset',
+ to: 'rect(20px, 20px, 20px, 20px)',
+});
+
+test_interpolation({
+ property: 'clip',
+ from: 'rect(0px, 75px, 80px, 10px)',
+ to: 'rect(0px, 100px, 90px, 5px)'
+}, [
+ {at: -1, expect: 'rect(0px, 50px, 70px, 15px)'},
+ {at: 0, expect: 'rect(0px, 75px, 80px, 10px)'},
+ {at: 0.25, expect: 'rect(0px, 81.25px, 82.5px, 8.75px)'},
+ {at: 0.75, expect: 'rect(0px, 93.75px, 87.5px, 6.25px)'},
+ {at: 1, expect: 'rect(0px, 100px, 90px, 5px)'},
+ {at: 2, expect: 'rect(0px, 125px, 100px, 0px)'},
+]);
+
+test_no_interpolation({
+ property: 'clip',
+ from: 'rect(auto, auto, auto, 10px)',
+ to: 'rect(20px, 50px, 50px, auto)'
+});
+
+test_no_interpolation({
+ property: 'clip',
+ from: 'rect(auto, 0px, auto, 10px)',
+ to: 'rect(auto, 50px, 50px, auto)'
+});
+
+test_no_interpolation({
+ property: 'clip',
+ from: 'auto',
+ to: 'rect(0px, 50px, 50px, 0px)'
+});
+
+test_no_interpolation({
+ property: 'clip',
+ from: 'rect(0px, 50px, 50px, 0px)',
+ to: 'auto'
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-masking/parsing/mask-invalid.html b/tests/wpt/web-platform-tests/css/css-masking/parsing/mask-invalid.html
new file mode 100644
index 00000000000..367049cf19f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-masking/parsing/mask-invalid.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Masking Module Level 1: parsing mask with invalid values</title>
+<link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-mask">
+<meta name="assert" content="mask supports only the '<mask-layer>#' grammar.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_invalid_value('mask', 'none linear-gradient(to 0% 0%, rgb(0, 0, 0), rgb(0, 0, 255))');
+test_invalid_value('mask', 'none alpha luminance');
+test_invalid_value('mask', 'linear-gradient(to 0% 0%, rgb(0, 0, 0), rgb(0, 0, 255)) url("https://example.com/")');
+
+test_invalid_value('mask', '1px 2px 3px');
+test_invalid_value('mask', '1px 2px 3px 4px');
+test_invalid_value('mask', '1px 2px / contain / cover');
+
+test_invalid_value('mask', 'repeat-y repeat-x');
+
+test_invalid_value('mask', 'stroke-box no-clip view-box');
+
+test_invalid_value('mask', 'border-box view-box padding-box');
+
+test_invalid_value('mask', 'no-clip border-box content-box');
+
+test_invalid_value('mask', 'content-box stroke-box no-clip');
+
+test_invalid_value('mask', 'add intersect');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-masking/parsing/mask-valid.sub.html b/tests/wpt/web-platform-tests/css/css-masking/parsing/mask-valid.sub.html
new file mode 100644
index 00000000000..63aed3e33c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-masking/parsing/mask-valid.sub.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Masking Module Level 1: parsing mask with valid values</title>
+<link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-mask">
+<meta name="assert" content="mask supports the full '<mask-layer>#' grammar.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+// <mask-layer> = <mask-reference> <masking-mode>? || <position> [ / <bg-size> ]? ||
+// <repeat-style> || <geometry-box> || [ <geometry-box> | no-clip ] || <compositing-operator>
+
+// <mask-reference> <masking-mode>?
+// <mask-reference> = none | <image> | <mask-source>
+// <masking-mode> = alpha | luminance | auto
+test_valid_value('mask', 'none');
+test_valid_value('mask', 'none alpha');
+test_valid_value('mask', 'linear-gradient(to left bottom, red, blue)');
+test_valid_value('mask', 'linear-gradient(to left bottom, red, blue) luminance');
+test_valid_value('mask', 'url("https://{{host}}/")');
+test_valid_value('mask', 'url("https://{{host}}/") alpha');
+
+// <position> [ / <bg-size> ]?
+test_valid_value('mask', 'linear-gradient(to left bottom, red, blue) 1px 2px');
+test_valid_value('mask', 'url("https://{{host}}/") 1px 2px / contain');
+
+// <repeat-style> = repeat-x | repeat-y | [repeat | space | round | no-repeat]{1,2}
+test_valid_value('mask', 'none repeat-y');
+
+// <geometry-box> = <shape-box> | fill-box | stroke-box | view-box
+// <shape-box> = <box> | margin-box
+// <box> = border-box | padding-box | content-box
+test_valid_value('mask', 'none border-box', 'none');
+test_valid_value('mask', 'linear-gradient(to left bottom, red, blue) padding-box');
+test_valid_value('mask', 'none content-box');
+test_valid_value('mask', 'none margin-box');
+test_valid_value('mask', 'url("https://{{host}}/") fill-box');
+test_valid_value('mask', 'linear-gradient(to left bottom, red, blue) stroke-box');
+test_valid_value('mask', 'none view-box');
+
+// [ <geometry-box> | no-clip ]
+test_valid_value('mask', 'none no-clip', 'none border-box no-clip');
+
+// <compositing-operator> = add | subtract | intersect | exclude
+test_valid_value('mask', 'url("https://{{host}}/") add', 'url("https://{{host}}/")');
+test_valid_value('mask', 'none subtract');
+test_valid_value('mask', 'url("https://{{host}}/") intersect');
+test_valid_value('mask', 'linear-gradient(to left bottom, red, blue) exclude');
+
+
+// <mask-layer> = <mask-reference> <masking-mode>? || <position> [ / <bg-size> ]? ||
+// <repeat-style> || <geometry-box> || [ <geometry-box> | no-clip ] || <compositing-operator>
+test_valid_value('mask', 'intersect no-clip space round 1px 2px / contain stroke-box linear-gradient(to left bottom, red, blue) luminance', 'linear-gradient(to left bottom, red, blue) luminance 1px 2px / contain space round stroke-box no-clip intersect');
+
+test_valid_value('mask', 'intersect no-clip space round 1px 2px / contain view-box, stroke-box linear-gradient(to left bottom, red, blue) luminance', 'none 1px 2px / contain space round view-box no-clip intersect, linear-gradient(to left bottom, red, blue) luminance stroke-box');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-006-ref.html b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-006-ref.html
index 85dfa522c7d..261ff480c38 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-006-ref.html
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-006-ref.html
@@ -35,7 +35,7 @@
</article>
<div class="column-span">column-span1</div>
<article>
- <div class="container" style="border-top: none; height: 50px;">
+ <div class="container" style="border-top: none; height: 50px; margin-bottom: 1em;">
<div class="block">block2</div>
</div>
</article>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-006.html b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-006.html
index 479fb2d0ced..5c1e634c2b2 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-006.html
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-006.html
@@ -19,6 +19,7 @@
background-color: pink;
border: 20px solid purple;
margin-top: 1em;
+ margin-bottom: 1em;
}
div.block {
width: 100px;
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-008-ref.html b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-008-ref.html
new file mode 100644
index 00000000000..80d783283fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-008-ref.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+ <meta charset="utf-8">
+ <title>CSS Multi-column Layout Test Reference: Test the borders drawing for a block split by column-span</title>
+ <link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+
+ <style>
+ article {
+ column-count: 1;
+ column-fill: auto;
+ width: 200px;
+ background-color: lightgreen;
+ }
+ div.container {
+ height: auto;
+ background-color: pink;
+ border: 20px solid purple;
+ }
+ div.block {
+ width: 100px;
+ height: 100px;
+ background-color: yellow;
+ }
+ div.column-span {
+ width: 200px;
+ height: 50px;
+ background-color: lightblue;
+ }
+ </style>
+
+ <article>
+ <div class="container" style="border-bottom: 0;">
+ <div class="block">block1</div>
+ </div>
+ </article>
+ <div class="column-span">column-span1</div>
+ <article>
+ <div class="container" style="border-top: 0; border-bottom: 0;">
+ <div class="block">block2</div>
+ </div>
+ </article>
+ <div class="column-span">column-span2</div>
+ <article>
+ <div class="container" style="border-top: 0;">
+ <div class="block">block3</div>
+ </div>
+ </article>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-008.html b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-008.html
new file mode 100644
index 00000000000..0d7bd183841
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-children-height-008.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+ <meta charset="utf-8">
+ <title>CSS Multi-column Layout Test: Test the borders drawing for a block split by column-span</title>
+ <link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
+ <link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+ <link rel="help" href="https://drafts.csswg.org/css-multicol-1/#column-span">
+ <link rel="match" href="multicol-span-all-children-height-008-ref.html">
+ <meta name="assert" content="This test verifies that the borders of block container with an auto block-size, split by column-span, are skipped on the sides adjacent to column-span.">
+
+ <!-- This test is adapted from multicol-span-all-children-height-005. -->
+
+ <style>
+ article {
+ column-count: 1;
+ column-fill: auto;
+ width: 200px;
+ background-color: lightgreen;
+ }
+ div.container {
+ height: auto;
+ border: 20px solid purple;
+ background-color: pink;
+ }
+ div.block {
+ width: 100px;
+ height: 100px;
+ background-color: yellow;
+ }
+ div.column-span {
+ column-span: all;
+ height: 50px;
+ background-color: lightblue;
+ }
+ </style>
+
+ <article>
+ <div class="container">
+ <div class="block">block1</div>
+ <div class="column-span">column-span1</div>
+ <div class="block">block2</div>
+ <div class="column-span">column-span2</div>
+ <div class="block">block3</div>
+ </div>
+ </article>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-overflow/float-with-relpos-and-transform.html b/tests/wpt/web-platform-tests/css/css-overflow/float-with-relpos-and-transform.html
new file mode 100644
index 00000000000..6024b726175
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-overflow/float-with-relpos-and-transform.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<link rel="help" href="https://drafts.csswg.org/css-overflow/#scrollable">
+<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
+<style>
+.container {
+ background: green;
+ width: 100px;
+ height: 100px;
+ overflow: auto;
+}
+.float {
+ float: left;
+ position: relative;
+ width: 50px;
+ height: 50px;
+ top: calc(50% - 100vh);
+ transform: translateY(-50%) translateY(100vh);
+}
+</style>
+<p>Test passes if there is a filled green square.</p>
+<div class="container">
+ <div class="float"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/geometry-border-image-005-ref.html b/tests/wpt/web-platform-tests/css/css-paint-api/geometry-border-image-005-ref.html
new file mode 100644
index 00000000000..16d23041134
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-paint-api/geometry-border-image-005-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<style>
+html, body { margin: 0; padding: 0; }
+</style>
+<body>
+<canvas id ="canvas" width="308" height="308"></canvas>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext("2d");
+context.fillStyle = "green";
+context.fillRect(0, 0, 290, 18);
+context.fillRect(0, 0, 18, 290);
+context.fillRect(0, 254, 290, 36);
+context.fillRect(254, 0, 36, 290);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/geometry-border-image-005.https.html b/tests/wpt/web-platform-tests/css/css-paint-api/geometry-border-image-005.https.html
new file mode 100644
index 00000000000..efdd7fdf1b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-paint-api/geometry-border-image-005.https.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="geometry-border-image-005-ref.html">
+<style>
+html, body { margin: 0; padding: 0; }
+.container {
+ width: 200px;
+ height: 200px;
+ border: 36px solid orange;
+ border-image: paint(foo) /* source */
+ 1 / /* slice */
+ 36px 36px 36px 36px / /* width */
+ 18px 18px 18px 18px /* outset */
+ round;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="target" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('foo', class {
+ paint(ctx, geom) {
+ // Both geom.width and height are 200 + 36 *3 = 308px;
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, geom.width, geom.height);
+ }
+});
+</script>
+
+<script>
+ importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-position/position-absolute-replaced-minmax.html b/tests/wpt/web-platform-tests/css/css-position/position-absolute-replaced-minmax.html
index a5c0d516472..00780d650fa 100644
--- a/tests/wpt/web-platform-tests/css/css-position/position-absolute-replaced-minmax.html
+++ b/tests/wpt/web-platform-tests/css/css-position/position-absolute-replaced-minmax.html
@@ -261,7 +261,14 @@
<!-- Just viewbox. Has aspect_ratio, but no intrinsic size
inline_width is constrained by left/right, height computed proportionally -->
<div class="container">
- <img class="target" style="left:100px;right:100px" src="data:image/svg+xml,%3Csvg viewBox='0 0 100 10' xmlns='http://www.w3.org/2000/svg' %3E%3Crect width='100%' height='100%' style='fill:rgb(0,255,0);'/%3E%3C/svg%3E"
+ <img class="target" style="left:100px;right:100px;" src="data:image/svg+xml,%3Csvg viewBox='0 0 100 10' xmlns='http://www.w3.org/2000/svg' %3E%3Crect width='100%' height='100%' style='fill:rgb(0,255,0);'/%3E%3C/svg%3E"
+ data-expected-width="188" data-expected-height="47" data-offset-y="146" data-offset-x="109"
+ >
+</div>
+<!-- Same as previous test, but with max-width:fit-content. crbug.com/1010798
+ -->
+<div class="container">
+ <img class="target" style="left:100px;right:100px;max-width:fit-content" src="data:image/svg+xml,%3Csvg viewBox='0 0 100 10' xmlns='http://www.w3.org/2000/svg' %3E%3Crect width='100%' height='100%' style='fill:rgb(0,255,0);'/%3E%3C/svg%3E"
data-expected-width="188" data-expected-height="47" data-offset-y="146" data-offset-x="109"
>
</div>
diff --git a/tests/wpt/web-platform-tests/docs/running-tests/webkitgtk_minibrowser.md b/tests/wpt/web-platform-tests/docs/running-tests/webkitgtk_minibrowser.md
index b12859bcca9..7aac81e5fce 100644
--- a/tests/wpt/web-platform-tests/docs/running-tests/webkitgtk_minibrowser.md
+++ b/tests/wpt/web-platform-tests/docs/running-tests/webkitgtk_minibrowser.md
@@ -18,15 +18,3 @@ to run it manually you can find it on any of this paths:
inside:
`/usr/lib/${TRIPLET}/webkit2gtk-4.0/MiniBrowser`
where `TRIPLET=$(gcc -dumpmachine)`
-
-
-Known issues:
-
-* On a docker container WebKitWebDriver fails to listen on localhost,
-because the docker container doesn't provide an IPv6 localhost address.
-To workaround this issue, manually tell it to only listen on IPv4 localhost
-by passing this parameter to wpt run: `--webdriver-arg=--host=127.0.0.1`
-Example:
-```bash
-./wpt run --webdriver-arg=--host=127.0.0.1 webkitgtk_minibrowser TESTS
-```
diff --git a/tests/wpt/web-platform-tests/html/dom/idlharness.https.html b/tests/wpt/web-platform-tests/html/dom/idlharness.https.html
index 0d3f1160d28..33ad5c6f616 100644
--- a/tests/wpt/web-platform-tests/html/dom/idlharness.https.html
+++ b/tests/wpt/web-platform-tests/html/dom/idlharness.https.html
@@ -47,6 +47,7 @@ idl_test(
documentWithHandlers[callback.name] = handler;
}
}
+ idlArray.add_untested_idls('typedef Window WindowProxy;');
idlArray.add_objects({
NodeList: ['document.getElementsByName("name")'],
diff --git a/tests/wpt/web-platform-tests/interfaces/feature-policy.idl b/tests/wpt/web-platform-tests/interfaces/feature-policy.idl
index 85601321a17..6f0d69fc378 100644
--- a/tests/wpt/web-platform-tests/interfaces/feature-policy.idl
+++ b/tests/wpt/web-platform-tests/interfaces/feature-policy.idl
@@ -3,7 +3,6 @@
// (https://github.com/tidoust/reffy-reports)
// Source: Feature Policy (https://w3c.github.io/webappsec-feature-policy/)
-[NoInterfaceObject]
interface FeaturePolicy {
boolean allowsFeature(DOMString feature, optional DOMString origin);
sequence<DOMString> features();
diff --git a/tests/wpt/web-platform-tests/interfaces/webrtc-stats.idl b/tests/wpt/web-platform-tests/interfaces/webrtc-stats.idl
index e41d7357b1a..2b823047ff1 100644
--- a/tests/wpt/web-platform-tests/interfaces/webrtc-stats.idl
+++ b/tests/wpt/web-platform-tests/interfaces/webrtc-stats.idl
@@ -81,6 +81,7 @@ dictionary RTCInboundRtpStreamStats : RTCReceivedRtpStreamStats {
boolean voiceActivityFlag;
DOMHighResTimeStamp lastPacketReceivedTimestamp;
double averageRtcpInterval;
+ unsigned long long headerBytesReceived;
unsigned long long fecPacketsReceived;
unsigned long long fecPacketsDiscarded;
unsigned long long bytesReceived;
@@ -130,6 +131,7 @@ dictionary RTCOutboundRtpStreamStats : RTCSentRtpStreamStats {
DOMString remoteId;
DOMString rid;
DOMHighResTimeStamp lastPacketSentTimestamp;
+ unsigned long long headerBytesSent;
unsigned long packetsDiscardedOnSend;
unsigned long long bytesDiscardedOnSend;
unsigned long fecPacketsSent;
diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/menclose/legacy-menclose-radical-notation-ref.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/menclose/legacy-menclose-radical-notation-ref.html
index f0b5bdd9f04..c67ac03f5dc 100644
--- a/tests/wpt/web-platform-tests/mathml/presentation-markup/menclose/legacy-menclose-radical-notation-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/menclose/legacy-menclose-radical-notation-ref.html
@@ -12,7 +12,10 @@
</head>
<body>
<math>
- <menclose>
+ <menclose notation="">
+ <mn>123</mn>
+ </menclose>
+ <menclose notation="box">
<mn>123</mn>
</menclose>
</math>
diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/menclose/legacy-menclose-radical-notation.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/menclose/legacy-menclose-radical-notation.html
index d7f0627059a..9b71389e74d 100644
--- a/tests/wpt/web-platform-tests/mathml/presentation-markup/menclose/legacy-menclose-radical-notation.html
+++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/menclose/legacy-menclose-radical-notation.html
@@ -5,7 +5,7 @@
<title>Legacy menclose radical notation</title>
<link rel="help" href="https://www.w3.org/TR/MathML3/chapter3.html#presm.menclose">
<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#enclose-expression-inside-notation-menclose">
- <meta name="assert" content="Verify that the legacy menclose radical notation is not supported.">
+ <meta name="assert" content="Verify that the legacy menclose radical notation is ignored.">
<link rel="match" href="legacy-menclose-radical-notation-ref.html">
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
<style>
@@ -19,6 +19,9 @@
<menclose notation="radical">
<mn>123</mn>
</menclose>
+ <menclose notation="box radical">
+ <mn>123</mn>
+ </menclose>
</math>
<script src="/mathml/support/feature-detection.js"></script>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/html5-tree/tabindex-001.html b/tests/wpt/web-platform-tests/mathml/relations/html5-tree/tabindex-001.html
index aaf82f77caa..8f853688141 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/html5-tree/tabindex-001.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/html5-tree/tabindex-001.html
@@ -14,16 +14,20 @@
const mrow = document.getElementById('mrow');
assert_equals(mrow.tabIndex, -1, "no attribute");
mrow.setAttribute("tabindex", "invalid");
+ assert_equals(mrow.getAttribute("tabindex"), "invalid");
assert_equals(mrow.tabIndex, -1, "invalid");
mrow.setAttribute("tabindex", "9999999999");
+ assert_equals(mrow.getAttribute("tabindex"), "9999999999");
assert_equals(mrow.tabIndex, -1, "too large integer");
}, "default and invalid values on mrow");
test(() => {
const mrowLink = document.getElementById('mrow-link');
assert_equals(mrow.tabIndex, 0, "no attribute");
mrow.setAttribute("tabindex", "invalid");
+ assert_equals(mrow.getAttribute("tabindex"), "invalid");
assert_equals(mrow.tabIndex, 0, "invalid");
mrow.setAttribute("tabindex", "9999999999");
+ assert_equals(mrow.getAttribute("tabindex"), "9999999999");
assert_equals(mrow.tabIndex, 0, "too large integer");
}, "default and invalid values on MathML link");
});
diff --git a/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-bitrate.https.html b/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-bitrate.https.html
new file mode 100644
index 00000000000..472c0661cb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-bitrate.https.html
@@ -0,0 +1,226 @@
+<!doctype html>
+<html>
+<head>
+<title>MediaRecorder {audio|video}bitsPerSecond attributes</title>
+<link rel="help" href="https://w3c.github.io/mediacapture-record/MediaRecorder.html">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<script>
+
+/*
+ * The bitrate handling is difficult to test, given that the spec uses text such
+ * as: "values the User Agent deems reasonable" and "such that the sum of
+ * videoBitsPerSecond and audioBitsPerSecond is close to the value of recorder’s
+ * [[ConstrainedBitsPerSecond]] slot". For cases like that this test tries to
+ * use values that are reasonable for the tested track types. Should a UA vendor
+ * see a need to update this to fit their definition of reasonable, they should
+ * feel free to do so, doing their best to avoid regressing existing compliant
+ * implementations.
+ */
+
+async function getStream(t, constraints) {
+ const stream = await navigator.mediaDevices.getUserMedia(constraints);
+ const tracks = stream.getTracks();
+ t.add_cleanup(() => tracks.forEach(tr => tr.stop()));
+ return stream;
+}
+
+function getAudioStream(t) {
+ return getStream(t, {audio: true});
+}
+
+function getVideoStream(t) {
+ return getStream(t, {video: true});
+}
+
+function getAudioVideoStream(t) {
+ return getStream(t, {audio: true, video: true});
+}
+
+const AUDIO_BITRATE = 1e5; // 100kbps
+const VIDEO_BITRATE = 1e6; // 1Mbps
+const LOW_TOTAL_BITRATE = 5e5; // 500kbps
+const HIGH_TOTAL_BITRATE = 2e6; // 2Mbps
+const BITRATE_EPSILON = 1e5; // 100kbps
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioVideoStream(t));
+ assert_not_equals(rec.audioBitsPerSecond, 0);
+ assert_not_equals(rec.videoBitsPerSecond, 0);
+}, "Passing no bitrate config results in defaults");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioVideoStream(t), {
+ bitsPerSecond: 0,
+ });
+ assert_not_equals(rec.audioBitsPerSecond, 0);
+ assert_not_equals(rec.videoBitsPerSecond, 0);
+ assert_approx_equals(rec.audioBitsPerSecond + rec.videoBitsPerSecond, 0,
+ BITRATE_EPSILON);
+}, "Passing bitsPerSecond:0 results in targets close to 0");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioVideoStream(t), {
+ audioBitsPerSecond: 0,
+ });
+ assert_equals(rec.audioBitsPerSecond, 0);
+ assert_not_equals(rec.videoBitsPerSecond, 0);
+}, "Passing only audioBitsPerSecond:0 results in 0 for audio, default for video");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioVideoStream(t), {
+ videoBitsPerSecond: 0,
+ });
+ assert_not_equals(rec.audioBitsPerSecond, 0);
+ assert_equals(rec.videoBitsPerSecond, 0);
+}, "Passing only videoBitsPerSecond:0 results in 0 for video, default for audio");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioVideoStream(t), {
+ bitsPerSecond: 0,
+ audioBitsPerSecond: AUDIO_BITRATE,
+ videoBitsPerSecond: VIDEO_BITRATE,
+ });
+ assert_not_equals(rec.audioBitsPerSecond, 0);
+ assert_not_equals(rec.videoBitsPerSecond, 0);
+ assert_approx_equals(rec.audioBitsPerSecond + rec.videoBitsPerSecond, 0,
+ BITRATE_EPSILON);
+}, "Passing bitsPerSecond:0 overrides audio/video-specific values");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioVideoStream(t), {
+ bitsPerSecond: HIGH_TOTAL_BITRATE,
+ audioBitsPerSecond: 0,
+ videoBitsPerSecond: 0,
+ });
+ assert_not_equals(rec.audioBitsPerSecond, 0);
+ assert_not_equals(rec.videoBitsPerSecond, 0);
+ assert_approx_equals(rec.audioBitsPerSecond + rec.videoBitsPerSecond,
+ HIGH_TOTAL_BITRATE, BITRATE_EPSILON);
+}, "Passing bitsPerSecond overrides audio/video zero values");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioVideoStream(t), {
+ bitsPerSecond: HIGH_TOTAL_BITRATE,
+ });
+ assert_not_equals(rec.audioBitsPerSecond, 0);
+ assert_not_equals(rec.videoBitsPerSecond, 0);
+ assert_approx_equals(rec.audioBitsPerSecond + rec.videoBitsPerSecond,
+ HIGH_TOTAL_BITRATE, BITRATE_EPSILON);
+}, "Passing bitsPerSecond sets audio/video bitrate values");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioVideoStream(t), {
+ audioBitsPerSecond: AUDIO_BITRATE,
+ });
+ assert_equals(rec.audioBitsPerSecond, AUDIO_BITRATE);
+ assert_not_equals(rec.videoBitsPerSecond, 0);
+}, "Passing only audioBitsPerSecond results in default for video");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioVideoStream(t), {
+ videoBitsPerSecond: VIDEO_BITRATE,
+ });
+ assert_not_equals(rec.audioBitsPerSecond, 0);
+ assert_equals(rec.videoBitsPerSecond, VIDEO_BITRATE);
+}, "Passing only videoBitsPerSecond results in default for audio");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioStream(t), {
+ videoBitsPerSecond: VIDEO_BITRATE,
+ });
+ assert_not_equals(rec.audioBitsPerSecond, 0);
+ assert_equals(rec.videoBitsPerSecond, VIDEO_BITRATE);
+}, "Passing videoBitsPerSecond for audio-only stream still results in something for video");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getVideoStream(t), {
+ audioBitsPerSecond: AUDIO_BITRATE,
+ });
+ assert_equals(rec.audioBitsPerSecond, AUDIO_BITRATE);
+ assert_not_equals(rec.videoBitsPerSecond, 0);
+}, "Passing audioBitsPerSecond for video-only stream still results in something for audio");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioStream(t), {
+ bitsPerSecond: HIGH_TOTAL_BITRATE,
+ });
+ assert_not_equals(rec.audioBitsPerSecond, 0);
+ assert_not_equals(rec.videoBitsPerSecond, 0);
+}, "Passing bitsPerSecond for audio-only stream still results in something for video");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getVideoStream(t), {
+ bitsPerSecond: HIGH_TOTAL_BITRATE,
+ });
+ assert_not_equals(rec.audioBitsPerSecond, 0);
+ assert_not_equals(rec.videoBitsPerSecond, 0);
+}, "Passing bitsPerSecond for video-only stream still results in something for audio");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioVideoStream(t));
+ t.add_cleanup(() => rec.stop());
+ const abps = rec.audioBitsPerSecond;
+ const vbps = rec.videoBitsPerSecond;
+ rec.start();
+ assert_equals(rec.audioBitsPerSecond, abps);
+ assert_equals(rec.videoBitsPerSecond, vbps);
+}, "Selected default track bitrates are not changed by start()");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioVideoStream(t), {
+ audioBitsPerSecond: AUDIO_BITRATE,
+ videoBitsPerSecond: VIDEO_BITRATE,
+ });
+ t.add_cleanup(() => rec.stop());
+ const abps = rec.audioBitsPerSecond;
+ const vbps = rec.videoBitsPerSecond;
+ rec.start();
+ assert_equals(rec.audioBitsPerSecond, abps);
+ assert_equals(rec.videoBitsPerSecond, vbps);
+}, "Passed-in track bitrates are not changed by start()");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioVideoStream(t), {
+ bitsPerSecond: HIGH_TOTAL_BITRATE,
+ });
+ t.add_cleanup(() => rec.stop());
+ const abps = rec.audioBitsPerSecond;
+ const vbps = rec.videoBitsPerSecond;
+ rec.start();
+ assert_equals(rec.audioBitsPerSecond, abps);
+ assert_equals(rec.videoBitsPerSecond, vbps);
+}, "Passing bitsPerSecond for audio/video stream does not change track bitrates in start()");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getAudioStream(t), {
+ bitsPerSecond: LOW_TOTAL_BITRATE,
+ });
+ t.add_cleanup(() => rec.stop());
+ const abps = rec.audioBitsPerSecond;
+ const vbps = rec.videoBitsPerSecond;
+ rec.start();
+ assert_approx_equals(rec.audioBitsPerSecond, LOW_TOTAL_BITRATE,
+ BITRATE_EPSILON);
+ assert_equals(rec.videoBitsPerSecond, 0);
+ assert_not_equals(rec.audioBitsPerSecond, abps);
+ assert_not_equals(rec.videoBitsPerSecond, vbps);
+}, "Passing bitsPerSecond for audio stream sets video track bitrate to 0 in start()");
+
+promise_test(async t => {
+ const rec = new MediaRecorder(await getVideoStream(t), {
+ bitsPerSecond: HIGH_TOTAL_BITRATE,
+ });
+ t.add_cleanup(() => rec.stop());
+ const abps = rec.audioBitsPerSecond;
+ const vbps = rec.videoBitsPerSecond;
+ rec.start();
+ assert_equals(rec.audioBitsPerSecond, 0);
+ assert_approx_equals(rec.videoBitsPerSecond, HIGH_TOTAL_BITRATE,
+ BITRATE_EPSILON);
+ assert_not_equals(rec.audioBitsPerSecond, abps);
+ assert_not_equals(rec.videoBitsPerSecond, vbps);
+}, "Passing bitsPerSecond for video stream sets audio track bitrate to 0 in start()");
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-creation.https.html b/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-creation.https.html
index 419211c9dcf..b724ca14503 100644
--- a/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-creation.https.html
+++ b/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-creation.https.html
@@ -20,8 +20,8 @@
var recorder = new MediaRecorder(stream);
assert_equals(recorder.state, "inactive");
- assert_equals(recorder.videoBitsPerSecond, 0);
- assert_equals(recorder.audioBitsPerSecond, 0);
+ assert_not_equals(recorder.videoBitsPerSecond, 0);
+ assert_not_equals(recorder.audioBitsPerSecond, 0);
test.done();
});
diff --git a/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-events-and-exceptions.html b/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-events-and-exceptions.html
index 58b9c08ecab..cddc07e5079 100644
--- a/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-events-and-exceptions.html
+++ b/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-events-and-exceptions.html
@@ -36,23 +36,21 @@
});
recorderOnDataAvailable = test.step_func(event => {
- // TODO(mcasas): ondataavailable might never be pinged with an empty Blob
- // data on recorder.stop(), see http://crbug.com/54428
assert_equals(recorder.state, "inactive");
- assert_equals(event.data.size, 0, 'We should have gotten an empty Blob');
+ assert_not_equals(event.data.size, 0, 'We should get a Blob with data');
});
recorderOnStop = test.step_func(function() {
assert_equals(recorder.state, "inactive");
- assert_throws("InvalidStateError", function() { recorder.stop() },
- "recorder cannot be stop()ped in |inactive| state");
+ recorder.onstop = recorderOnUnexpectedEvent;
+ recorder.stop();
+ assert_equals(recorder.state, "inactive", "stop() is idempotent");
assert_throws("InvalidStateError", function() { recorder.pause() },
"recorder cannot be pause()ed in |inactive| state");
assert_throws("InvalidStateError", function() { recorder.resume() },
"recorder cannot be resume()d in |inactive| state");
assert_throws("InvalidStateError", function() { recorder.requestData() },
"cannot requestData() if recorder is in |inactive| state");
- recorder.onstop = recorderOnUnexpectedEvent;
test.done();
});
@@ -84,15 +82,15 @@
assert_throws("NotSupportedError",
function() {
- recorder =
- new MediaRecorder(stream, {mimeType : "video/invalid"});
+ recorder = new MediaRecorder(
+ new MediaStream(), {mimeType : "video/invalid"});
},
"recorder should throw() with unsupported mimeType");
- let recorder = new MediaRecorder(stream);
+ let recorder = new MediaRecorder(new MediaStream());
assert_equals(recorder.state, "inactive");
- assert_throws("InvalidStateError", function(){recorder.stop()},
- "recorder cannot be stop()ped in |inactive| state");
+ recorder.stop();
+ assert_equals(recorder.state, "inactive", "stop() is idempotent");
assert_throws("InvalidStateError", function(){recorder.pause()},
"recorder cannot be pause()ed in |inactive| state");
assert_throws("InvalidStateError", function(){recorder.resume()},
@@ -100,6 +98,14 @@
assert_throws("InvalidStateError", function(){recorder.requestData()},
"cannot requestData() if recorder is in |inactive| state");
+ assert_throws("NotSupportedError",
+ function() {
+ recorder.start();
+ },
+ "recorder should throw() when starting with inactive stream");
+
+ recorder.stream.addTrack(stream.getTracks()[0]);
+
drawSomethingOnCanvas();
recorder.onstop = recorderOnUnexpectedEvent;
diff --git a/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-mimetype.html b/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-mimetype.html
new file mode 100644
index 00000000000..ddc56e9cb75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-mimetype.html
@@ -0,0 +1,147 @@
+<!doctype html>
+<html>
+<head>
+ <title>MediaRecorder MIMEType</title>
+ <link rel="help" href="https://w3c.github.io/mediacapture-record/MediaRecorder.html#dom-mediarecorder-mimetype">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<canvas id="canvas" width="200" height="200">
+</canvas>
+<script>
+function createAudioStream(t) {
+ const ac = new AudioContext();
+ const {stream} = ac.createMediaStreamDestination();
+ const tracks = stream.getTracks();
+ t.add_cleanup(() => tracks.forEach(tr => tr.stop()));
+ return stream;
+}
+
+function createVideoStream(t) {
+ const canvas = document.getElementById("canvas");
+ canvas.getContext('2d');
+ const stream = canvas.captureStream();
+ const tracks = stream.getTracks();
+ t.add_cleanup(() => tracks.forEach(tr => tr.stop()));
+ return stream;
+}
+
+function createAudioVideoStream(t) {
+ return new MediaStream([
+ ...createAudioStream(t).getTracks(),
+ ...createVideoStream(t).getTracks(),
+ ]);
+}
+
+test(t => {
+ const recorder = new MediaRecorder(createAudioStream(t));
+ assert_equals(recorder.mimeType, "",
+ "MediaRecorder has no default MIMEtype");
+}, "MediaRecorder sets no default MIMEType in the constructor for audio");
+
+test(t => {
+ const recorder = new MediaRecorder(createVideoStream(t));
+ assert_equals(recorder.mimeType, "",
+ "MediaRecorder has no default MIMEtype");
+}, "MediaRecorder sets no default MIMEType in the constructor for video");
+
+test(t => {
+ const stream = createAudioVideoStream(t);
+ const recorder = new MediaRecorder(stream);
+ assert_equals(recorder.mimeType, "",
+ "MediaRecorder has no default MIMEtype");
+}, "MediaRecorder sets no default MIMEType in the constructor for audio/video");
+
+test(t => {
+ assert_throws("NotSupportedError",
+ () => new MediaRecorder(new MediaStream(), {mimeType: "audio/banana"}));
+}, "MediaRecorder invalid audio MIMEType throws");
+
+test(t => {
+ assert_false(MediaRecorder.isTypeSupported("audio/banana"));
+}, "MediaRecorder invalid audio MIMEType is unsupported");
+
+test(t => {
+ assert_throws("NotSupportedError",
+ () => new MediaRecorder(new MediaStream(), {mimeType: "video/pineapple"}));
+}, "MediaRecorder invalid video MIMEType throws");
+
+test(t => {
+ assert_false(MediaRecorder.isTypeSupported("video/pineapple"));
+}, "MediaRecorder invalid video MIMEType is unsupported");
+
+// New MIME types could be added to this list as needed.
+for (const mimeType of [
+ 'audio/mp4',
+ 'video/mp4',
+ 'audio/ogg',
+ 'audio/ogg; codecs="vorbis"',
+ 'audio/ogg; codecs="opus"',
+ 'audio/webm',
+ 'audio/webm; codecs="vorbis"',
+ 'audio/webm; codecs="opus"',
+ 'video/webm',
+ 'video/webm; codecs="vp8"',
+ 'video/webm; codecs="vp8, vorbis"',
+ 'video/webm; codecs="vp8, opus"',
+ 'video/webm; codecs="vp9"',
+ 'video/webm; codecs="vp9, vorbis"',
+ 'video/webm; codecs="vp9, opus"',
+ 'video/webm; codecs="av1"',
+ 'video/webm; codecs="av1, opus"',
+]) {
+ if (MediaRecorder.isTypeSupported(mimeType)) {
+ test(t => {
+ const recorder = new MediaRecorder(new MediaStream(), {mimeType});
+ assert_equals(recorder.mimeType, mimeType, "Supported MIMEType is set");
+ }, `Supported MIMEType ${mimeType} is set immediately after constructing`);
+ } else {
+ test(t => {
+ assert_throws("NotSupportedError",
+ () => new MediaRecorder(new MediaStream(), {mimeType}));
+ }, `Unsupported MIMEType ${mimeType} throws`);
+ }
+}
+
+test(t => {
+ const recorder = new MediaRecorder(createAudioStream(t));
+ recorder.start();
+ assert_not_equals(recorder.mimeType, "",
+ "MediaRecorder has a MIMEtype after start() for audio");
+ assert_regexp_match(recorder.mimeType, /^audio\//,
+ "MIMEtype has an expected media type");
+ assert_regexp_match(recorder.mimeType, /^[a-z]+\/[a-z]+/,
+ "MIMEtype has a container subtype");
+ assert_regexp_match(recorder.mimeType, /^[a-z]+\/[a-z]+; codecs=[^,]+$/,
+ "MIMEtype has one codec");
+}, "MediaRecorder sets a MIMEType after start() for audio");
+
+test(t => {
+ const recorder = new MediaRecorder(createVideoStream(t));
+ recorder.start();
+ assert_not_equals(recorder.mimeType, "",
+ "MediaRecorder has a MIMEtype after start() for video");
+ assert_regexp_match(recorder.mimeType, /^video\//,
+ "MIMEtype has an expected media type");
+ assert_regexp_match(recorder.mimeType, /^[a-z]+\/[a-z]+/,
+ "MIMEtype has a container subtype");
+ assert_regexp_match(recorder.mimeType, /^[a-z]+\/[a-z]+; codecs=[^,]+$/,
+ "MIMEtype has one codec");
+}, "MediaRecorder sets a MIMEType after start() for video");
+
+test(t => {
+ const recorder = new MediaRecorder(createAudioVideoStream(t));
+ recorder.start();
+ assert_not_equals(recorder.mimeType, "",
+ "MediaRecorder has a MIMEtype after start() for audio/video");
+ assert_regexp_match(recorder.mimeType, /^video\//,
+ "MIMEtype has an expected media type");
+ assert_regexp_match(recorder.mimeType, /^[a-z]+\/[a-z]+/,
+ "MIMEtype has a container subtype");
+ assert_regexp_match(recorder.mimeType, /^[a-z]+\/[a-z]+; codecs=[^,]+,[^,]+$/,
+ "MIMEtype has two codecs");
+}, "MediaRecorder sets a MIMEType after start() for audio/video");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-pause-resume.html b/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-pause-resume.html
index 39a88836645..33dfd8560c0 100644
--- a/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-pause-resume.html
+++ b/tests/wpt/web-platform-tests/mediacapture-record/MediaRecorder-pause-resume.html
@@ -11,8 +11,10 @@
</canvas>
<script>
function createVideoStream() {
- let canvas = document.getElementById("canvas");
- canvas.getContext('2d');
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+ ctx.fillStyle = 'green';
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
return canvas.captureStream();
}
@@ -32,6 +34,7 @@
recorder.start();
assert_equals(recorder.state, "recording", "MediaRecorder has been started successfully");
+ await new Promise(r => recorder.onstart = r);
recorder.pause();
assert_equals(recorder.state, "paused", "MediaRecorder should be paused immediately following pause()");
diff --git a/tests/wpt/web-platform-tests/mediacapture-record/idlharness.window.js b/tests/wpt/web-platform-tests/mediacapture-record/idlharness.window.js
index 86f5a158822..2e304b0a0e6 100644
--- a/tests/wpt/web-platform-tests/mediacapture-record/idlharness.window.js
+++ b/tests/wpt/web-platform-tests/mediacapture-record/idlharness.window.js
@@ -7,7 +7,7 @@
idl_test(
['mediastream-recording'],
- ['mediacapture-streams', 'FileAPI', 'html', 'dom'],
+ ['mediacapture-streams', 'FileAPI', 'html', 'dom', 'WebIDL'],
idl_array => {
// Ignored errors will be surfaced in idlharness.js's test_object below.
let recorder, blob, error;
@@ -31,7 +31,9 @@ idl_test(
idl_array.add_objects({ BlobEvent: [blob] });
try {
- error = new MediaRecorderErrorEvent("type", {});
+ error = new MediaRecorderErrorEvent("type", {
+ error: new DOMException,
+ });
} catch(e) {}
idl_array.add_objects({ MediaRecorderErrorEvent: [error] });
}
diff --git a/tests/wpt/web-platform-tests/resources/chromium/webxr-test.js b/tests/wpt/web-platform-tests/resources/chromium/webxr-test.js
index df91abf6d7f..94031657b4b 100644
--- a/tests/wpt/web-platform-tests/resources/chromium/webxr-test.js
+++ b/tests/wpt/web-platform-tests/resources/chromium/webxr-test.js
@@ -89,7 +89,7 @@ class MockVRService {
this.runtimes_ = [];
this.interceptor_ =
- new MojoInterfaceInterceptor(device.mojom.VRService.name);
+ new MojoInterfaceInterceptor(device.mojom.VRService.name, "context", true);
this.interceptor_.oninterfacerequest = e =>
this.bindingSet_.addBinding(this, e.handle);
this.interceptor_.start();
@@ -187,6 +187,15 @@ class MockVRService {
// Implements XRFrameDataProvider and XRPresentationProvider. Maintains a mock
// for XRPresentationProvider.
class MockRuntime {
+ // Mapping from string feature names to the corresponding mojo types.
+ // This is exposed as a member for extensibility.
+ static featureToMojoMap = {
+ "viewer": device.mojom.XRSessionFeature.REF_SPACE_VIEWER,
+ "local": device.mojom.XRSessionFeature.REF_SPACE_LOCAL,
+ "local-floor": device.mojom.XRSessionFeature.REF_SPACE_LOCAL_FLOOR,
+ "bounded-floor": device.mojom.XRSessionFeature.REF_SPACE_BOUNDED_FLOOR,
+ "unbounded": device.mojom.XRSessionFeature.REF_SPACE_UNBOUNDED };
+
constructor(fakeDeviceInit, service) {
this.sessionClient_ = new device.mojom.XRSessionClientPtr();
this.presentation_provider_ = new MockXRPresentationProvider();
@@ -456,19 +465,10 @@ class MockRuntime {
setFeatures(supportedFeatures) {
function convertFeatureToMojom(feature) {
- switch (feature) {
- case "viewer":
- return device.mojom.XRSessionFeature.REF_SPACE_VIEWER;
- case "local":
- return device.mojom.XRSessionFeature.REF_SPACE_LOCAL;
- case "local-floor":
- return device.mojom.XRSessionFeature.REF_SPACE_LOCAL_FLOOR;
- case "bounded-floor":
- return device.mojom.XRSessionFeature.REF_SPACE_BOUNDED_FLOOR;
- case "unbounded":
- return device.mojom.XRSessionFeature.REF_SPACE_UNBOUNDED;
- default:
- return device.mojom.XRSessionFeature.INVALID;
+ if (feature in MockRuntime.featureToMojoMap) {
+ return MockRuntime.featureToMojoMap[feature];
+ } else {
+ return device.mojom.XRSessionFeature.INVALID;
}
}
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-add-async.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-add-async.https.html
new file mode 100644
index 00000000000..ac13e4f4167
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-add-async.https.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>Service Worker: Fetch event added asynchronously doesn't throw</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<script>
+'use strict';
+
+service_worker_test(
+ 'resources/fetch-event-add-async-worker.js');
+</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/global-serviceworker.https.any.js b/tests/wpt/web-platform-tests/service-workers/service-worker/global-serviceworker.https.any.js
index 489b37f83e1..2335f635b2e 100644
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/global-serviceworker.https.any.js
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/global-serviceworker.https.any.js
@@ -17,7 +17,7 @@ async_test((t) => {
assert_true('serviceWorker' in self, 'self.serviceWorker exists');
serviceWorker.postMessage({ messageTest: true });
- // The rest of the rest runs once we receive the above message.
+ // The rest of the test runs once this receives the above message.
addEventListener('message', t.step_func((event) => {
// Ignore unrelated messages.
if (!event.data.messageTest) return;
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-add-async-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-add-async-worker.js
new file mode 100644
index 00000000000..a5a44a57c99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-add-async-worker.js
@@ -0,0 +1,6 @@
+importScripts('/resources/testharness.js');
+
+promise_test(async () => {
+ await new Promise(handler => { step_timeout(handler, 0); });
+ self.addEventListener('fetch', () => {});
+}, 'fetch event added asynchronously does not throw');
diff --git a/tests/wpt/web-platform-tests/tools/ci/run_tc.py b/tests/wpt/web-platform-tests/tools/ci/run_tc.py
index b2826bf075e..3201ff3a9d3 100755
--- a/tests/wpt/web-platform-tests/tools/ci/run_tc.py
+++ b/tests/wpt/web-platform-tests/tools/ci/run_tc.py
@@ -145,6 +145,28 @@ def install_chrome(channel):
run(["sudo", "apt-get", "-qqy", "update"])
run(["sudo", "gdebi", "-qn", "/tmp/%s" % deb_archive])
+def install_webkitgtk_from_apt_repository(channel):
+ # Configure webkitgtk.org/debian repository for $channel and pin it with maximum priority
+ run(["sudo", "apt-key", "adv", "--fetch-keys", "https://webkitgtk.org/debian/apt.key"])
+ with open("/tmp/webkitgtk.list", "w") as f:
+ f.write("deb [arch=amd64] https://webkitgtk.org/debian buster-wpt-webkit-updates %s\n" % channel)
+ run(["sudo", "mv", "/tmp/webkitgtk.list", "/etc/apt/sources.list.d/"])
+ with open("/tmp/99webkitgtk", "w") as f:
+ f.write("Package: *\nPin: origin webkitgtk.org\nPin-Priority: 1999\n")
+ run(["sudo", "mv", "/tmp/99webkitgtk", "/etc/apt/preferences.d/"])
+ # Install webkit2gtk from the webkitgtk.org/debian repository for $channel
+ run(["sudo", "apt-get", "-qqy", "update"])
+ run(["sudo", "apt-get", "-qqy", "upgrade"])
+ run(["sudo", "apt-get", "-qqy", "-t", "buster-wpt-webkit-updates", "install", "webkit2gtk-driver"])
+
+
+def install_webkitgtk(channel):
+ if channel in ("experimental", "dev", "nightly"):
+ raise NotImplementedError("Still can't install from release channel: %s" % channel)
+ elif channel in ("beta", "stable"):
+ install_webkitgtk_from_apt_repository(channel)
+ else:
+ raise ValueError("Unrecognized release channel: %s" % channel)
def start_xvfb():
start(["sudo", "Xvfb", os.environ["DISPLAY"], "-screen", "0",
@@ -217,6 +239,9 @@ def setup_environment(args):
if "chrome" in args.browser:
assert args.channel is not None
install_chrome(args.channel)
+ elif "webkitgtk_minibrowser" in args.browser:
+ assert args.channel is not None
+ install_webkitgtk(args.channel)
if args.xvfb:
start_xvfb()
diff --git a/tests/wpt/web-platform-tests/tools/docker/Dockerfile.webkitgtk b/tests/wpt/web-platform-tests/tools/docker/Dockerfile.webkitgtk
index 8d792b36a47..58080def60f 100644
--- a/tests/wpt/web-platform-tests/tools/docker/Dockerfile.webkitgtk
+++ b/tests/wpt/web-platform-tests/tools/docker/Dockerfile.webkitgtk
@@ -7,9 +7,13 @@ FROM debian:10
ENV DEBIAN_FRONTEND=noninteractive \
DEBCONF_NONINTERACTIVE_SEEN=true
-# Install general requirements not in the base image
+
+# Update and upgrade.
RUN apt-get -qqy update \
- && apt-get -qqy install \
+ && apt-get -qqy upgrade
+
+# Install general requirements not in the base image
+RUN apt-get -qqy install \
bzip2 \
ca-certificates \
dbus-x11 \
@@ -29,19 +33,10 @@ RUN apt-get -qqy update \
xvfb \
git-core
-# Configure buster-wpt-webkit-updates repository
-RUN apt-key adv --fetch-keys https://webkitgtk.org/debian/apt.key
-RUN printf 'deb [arch=amd64] https://webkitgtk.org/debian buster-wpt-webkit-updates main' \
- > /etc/apt/sources.list.d/webkitgtk.list
-RUN printf 'Package: *\nPin: origin webkitgtk.org\nPin-Priority: 1999' \
- > /etc/apt/preferences.d/99webkitgtk
-
-# Update and upgrade
-RUN apt-get update \
- && apt-get -y upgrade
-# Install webkit packages from https://webkitgtk.org/debian
-RUN apt-get install -y -t buster-wpt-webkit-updates webkit2gtk-driver
+# To speed up testers, cache in the image most of WebKitGTK dependencies
+# but don't install them (that will be done at test time)
+RUN apt-get install -qqy --download-only webkit2gtk-driver
# Set the timezone
ENV TZ "UTC"
diff --git a/tests/wpt/web-platform-tests/tools/docker/README.md b/tests/wpt/web-platform-tests/tools/docker/README.md
index c444e4a957f..6bcc47c7744 100644
--- a/tests/wpt/web-platform-tests/tools/docker/README.md
+++ b/tests/wpt/web-platform-tests/tools/docker/README.md
@@ -15,5 +15,3 @@ To update the image used for WebKitGTK:
docker build -f Dockerfile.webkitgtk -t <tag> .
docker push <tag>
```
-
-(This image is not yet used in .taskcluster.yml.)
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/base.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/base.py
index 08b5880a1b7..d17229da468 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/base.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/base.py
@@ -36,6 +36,20 @@ def cmd_arg(name, value=None):
return rv
+def maybe_add_args(required_args, current_args):
+ for required_arg in required_args:
+ # If the arg is in the form of "variable=value", only add it if
+ # no arg with another value for "variable" is already there.
+ if "=" in required_arg:
+ required_arg_prefix = "%s=" % required_arg.split("=")[0]
+ if not any(item.startswith(required_arg_prefix) for item in current_args):
+ current_args.append(required_arg)
+ else:
+ if required_arg not in current_args:
+ current_args.append(required_arg)
+ return current_args
+
+
def get_free_port():
"""Get a random unbound port"""
while True:
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/epiphany.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/epiphany.py
index 599ec9f3110..37e2f21421a 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/epiphany.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/epiphany.py
@@ -1,4 +1,4 @@
-from .base import get_timeout_multiplier # noqa: F401
+from .base import get_timeout_multiplier, maybe_add_args # noqa: F401
from .webkit import WebKitBrowser
from ..executors import executor_kwargs as base_executor_kwargs
from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401
@@ -24,9 +24,12 @@ def check_args(**kwargs):
def browser_kwargs(test_type, run_info_data, config, **kwargs):
+ # Workaround for https://gitlab.gnome.org/GNOME/libsoup/issues/172
+ webdriver_required_args = ["--host=127.0.0.1"]
+ webdriver_args = maybe_add_args(webdriver_required_args, kwargs.get("webdriver_args"))
return {"binary": kwargs["binary"],
"webdriver_binary": kwargs["webdriver_binary"],
- "webdriver_args": kwargs.get("webdriver_args")}
+ "webdriver_args": webdriver_args}
def capabilities(server_config, **kwargs):
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py
index 290fcff5ab2..1763ff44b4e 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py
@@ -181,7 +181,7 @@ def run_info_browser_version(binary):
def update_properties():
- return (["os", "debug", "webrender", "e10s", "sw-e10s", "processor"],
+ return (["os", "debug", "webrender", "fisson", "e10s", "sw-e10s", "processor"],
{"os": ["version"], "processor": ["bits"]})
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py
index 65f78125ad7..3c4947335bf 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py
@@ -1,4 +1,4 @@
-from .base import get_timeout_multiplier # noqa: F401
+from .base import get_timeout_multiplier, maybe_add_args # noqa: F401
from .webkit import WebKitBrowser
from ..executors import executor_kwargs as base_executor_kwargs
from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401
@@ -24,16 +24,25 @@ def check_args(**kwargs):
def browser_kwargs(test_type, run_info_data, config, **kwargs):
+ # Workaround for https://gitlab.gnome.org/GNOME/libsoup/issues/172
+ webdriver_required_args = ["--host=127.0.0.1"]
+ webdriver_args = maybe_add_args(webdriver_required_args, kwargs.get("webdriver_args"))
return {"binary": kwargs["binary"],
"webdriver_binary": kwargs["webdriver_binary"],
- "webdriver_args": kwargs.get("webdriver_args")}
+ "webdriver_args": webdriver_args}
def capabilities(server_config, **kwargs):
+ browser_required_args = ["--automation",
+ "--javascript-can-open-windows-automatically=true",
+ "--enable-xss-auditor=false",
+ "--enable-media-capabilities=true",
+ "--enable-encrypted-media=true",
+ "--enable-media-stream=true",
+ "--enable-mock-capture-devices=true",
+ "--enable-webaudio=true"]
args = kwargs.get("binary_args", [])
- if "--automation" not in args:
- args.append("--automation")
-
+ args = maybe_add_args(browser_required_args, args)
return {
"browserName": "MiniBrowser",
"webkitgtk:browserOptions": {
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/processing-model/cycle-witout-delay.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/processing-model/cycle-witout-delay.html
new file mode 100644
index 00000000000..ed26ad2ced2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/processing-model/cycle-witout-delay.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="a">
+ <head>
+ <title>Cycles without DelayNode in audio node graph</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <script>
+ const t = async_test(
+ "Test that cycles that don't contain a DelayNode are muted"
+ );
+ t.step(function() {
+ var off = new OfflineAudioContext(1, 512, 48000);
+ var osc = new OscillatorNode(off);
+ var fb = new GainNode(off);
+ // zero delay feedback loop
+ osc.connect(fb).connect(fb).connect(off.destination);
+ osc.start(0);
+ off.startRendering().then((b) => {
+ var samples = b.getChannelData(0);
+ var silent = true;
+ for (var i = 0; i < samples.length; i++) {
+ if (samples[i] != 0.0) {
+ silent = false;
+ break;
+ }
+ }
+ assert_true(silent);
+ t.done();
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/processing-model/delay-time-clamping.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/processing-model/delay-time-clamping.html
new file mode 100644
index 00000000000..3f8ed24429a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/processing-model/delay-time-clamping.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html class="a">
+ <head>
+ <title>Delay time clamping in cycles</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <script>
+ const t = async_test(
+ "Test that a DelayNode allows a feedback loop of a single rendering quantum"
+ );
+ t.step(function() {
+ var off = new OfflineAudioContext(1, 512, 48000);
+ var b = off.createBuffer(1, 1, 48000);
+ b.getChannelData(0)[0] = 1;
+ var impulse = new AudioBufferSourceNode(off, {buffer: b});
+ impulse.start(0);
+ // This delayTime of 64 samples MUST be clamped to 128 samples when
+ // in a cycle.
+ var delay = new DelayNode(off, {delayTime: 64/48000});
+ var fb = new GainNode(off);
+ impulse.connect(fb).connect(delay).connect(fb).connect(off.destination);
+ off.startRendering().then((b) => {
+ var samples = b.getChannelData(0);
+ for (var i = 0; i < samples.length; i++) {
+ if ((i % 128) != 0) {
+ assert_equals(samples[i], 0.0, "Non-silent audio found in between delayed impulses");
+ } else {
+ assert_equals(samples[i], 1.0, "Silent audio found instead of a delayed impulse");
+ }
+ }
+ t.done();
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/processing-model/feedback-delay-time.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/processing-model/feedback-delay-time.html
new file mode 100644
index 00000000000..50c8e455b90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/processing-model/feedback-delay-time.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html class="a">
+ <head>
+ <title>Feedback cycle with delay in audio node graph</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <script>
+ const t = async_test(
+ "Test that a DelayNode allows a feedback loop of a single rendering quantum"
+ );
+ t.step(function() {
+ var off = new OfflineAudioContext(1, 512, 48000);
+ var b = off.createBuffer(1, 1, 48000);
+ b.getChannelData(0)[0] = 1;
+ var impulse = new AudioBufferSourceNode(off, {buffer: b});
+ impulse.start(0);
+ var delay = new DelayNode(off, {delayTime: 128/48000});
+ var fb = new GainNode(off);
+ impulse.connect(fb).connect(delay).connect(fb).connect(off.destination);
+ off.startRendering().then((b) => {
+ var samples = b.getChannelData(0);
+ for (var i = 0; i < samples.length; i++) {
+ if ((i % 128) != 0) {
+ assert_equals(samples[i], 0.0, "Non-silent audio found in between delayed impulses");
+ } else {
+ assert_equals(samples[i], 1.0, "Silent audio found instead of a delayed impulse");
+ }
+ }
+ t.done();
+ });
+ });
+ </script>
+ </body>
+</html>