mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Update web-platform-tests to revision 548818eee08f7a6e31b9706b352b5d44b2f6d024
This commit is contained in:
parent
82fd8d1daf
commit
5e74467d68
112 changed files with 1704 additions and 536 deletions
|
@ -7,7 +7,7 @@
|
|||
expected: FAIL
|
||||
|
||||
[Opening a blob URL in a new window immediately before revoking it works.]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
[Opening a blob URL in a noopener about:blank window immediately before revoking it works.]
|
||||
expected: FAIL
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,2 +1,2 @@
|
|||
[no-transition-from-ua-to-blocking-stylesheet.html]
|
||||
expected: TIMEOUT
|
||||
expected: FAIL
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
[MediaQueryList-extends-EventTarget.html]
|
||||
expected: TIMEOUT
|
||||
[removeEventListener removes listener]
|
||||
expected: NOTRUN
|
||||
|
||||
[addEventListener "once" option is respected]
|
||||
expected: TIMEOUT
|
||||
|
|
@ -84,3 +84,45 @@
|
|||
[Inserting a custom element into a detached shadow tree that belongs to an HTML document fetched by XHR must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the <template>'s content of a custom element from the owner document into the document of the template elements must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the <template>'s content of a custom element from the owner document into an HTML document fetched by XHR must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the <template>'s content of a custom element from the owner document into the document of an iframe must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the shadow host's shadow of a custom element from the owner document into a cloned document must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the shadow host's shadow of a custom element from the owner document into an HTML document fetched by XHR must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the shadow host's shadow of a custom element from the owner document into a document created by createHTMLDocument must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the <template>'s content of a custom element from the owner document into a new document must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the shadow host's shadow of a custom element from the owner document into an HTML document created by createDocument must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the <template>'s content of a custom element from the owner document into a cloned document must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the <template>'s content of a custom element from the owner document into a document created by createHTMLDocument must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the shadow host's shadow of a custom element from the owner document into the document of the template elements must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the shadow host's shadow of a custom element from the owner document into the document of an iframe must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the shadow host's shadow of a custom element from the owner document into a new document must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
[Moving the <template>'s content of a custom element from the owner document into an HTML document created by createDocument must enqueue and invoke adoptedCallback]
|
||||
expected: FAIL
|
||||
|
||||
|
|
16
tests/wpt/metadata/dom/nodes/adoption.window.js.ini
Normal file
16
tests/wpt/metadata/dom/nodes/adoption.window.js.ini
Normal file
|
@ -0,0 +1,16 @@
|
|||
[adoption.window.html]
|
||||
[appendChild() and DocumentFragment]
|
||||
expected: FAIL
|
||||
|
||||
[appendChild() and ShadowRoot]
|
||||
expected: FAIL
|
||||
|
||||
[adoptNode() and ShadowRoot]
|
||||
expected: FAIL
|
||||
|
||||
[adoptNode() and DocumentFragment with host]
|
||||
expected: FAIL
|
||||
|
||||
[appendChild() and DocumentFragment with host]
|
||||
expected: FAIL
|
||||
|
|
@ -38,6 +38,9 @@
|
|||
[Redirect 307 with HEAD]
|
||||
expected: FAIL
|
||||
|
||||
[Redirect 303 with TESTING]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[redirect-method.any.html]
|
||||
[Redirect 301 with GET]
|
||||
|
@ -79,3 +82,6 @@
|
|||
[Redirect 307 with HEAD]
|
||||
expected: FAIL
|
||||
|
||||
[Redirect 303 with TESTING]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -309,3 +309,24 @@
|
|||
[<iframe>: separate response Content-Type: */* text/html]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: */* text/html]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html;" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html */*]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/html;" \\" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: separate response Content-Type: text/plain */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -11,3 +11,6 @@
|
|||
[X-Content-Type-Options%3A%20nosniff%0C]
|
||||
expected: FAIL
|
||||
|
||||
[X-Content-Type-Options%3A%20'NosniFF']
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
expected: TIMEOUT
|
||||
|
||||
[Embedded credentials matching the top-level are treated as network errors for cross-origin URLs.]
|
||||
expected: TIMEOUT
|
||||
expected: FAIL
|
||||
|
||||
[Embedded credentials matching the top-level are not treated as network errors for same-origin URLs.]
|
||||
expected: TIMEOUT
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[traverse_the_history_1.html]
|
||||
[Multiple history traversals from the same task]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[traverse_the_history_5.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[document-domain-nested-navigate.window.html]
|
||||
[Navigated frame to about:blank and document.domain]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
[supported-elements.html]
|
||||
expected: TIMEOUT
|
||||
[Contenteditable element should support autofocus]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -9,7 +10,7 @@
|
|||
expected: FAIL
|
||||
|
||||
[Area element should support autofocus]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
[Host element with delegatesFocus should support autofocus]
|
||||
expected: FAIL
|
||||
|
|
|
@ -2,3 +2,6 @@
|
|||
[Mutating the style element: mutating a Comment node]
|
||||
expected: FAIL
|
||||
|
||||
[Mutating the style element: inserting an empty DocumentFragment node]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
[iframe_sandbox_popups_escaping-3.html]
|
||||
type: testharness
|
||||
expected: TIMEOUT
|
||||
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
|
||||
expected: TIMEOUT
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -90,3 +90,12 @@
|
|||
[[INPUT in NUMBER status\] The value attribute is empty string]
|
||||
expected: FAIL
|
||||
|
||||
[[INPUT in NUMBER status\] Step mismatch when step is a very small floating number and value is not its integral multiple]
|
||||
expected: FAIL
|
||||
|
||||
[[INPUT in NUMBER status\] No step mismatch when step is a floating number in exponent format and value is its integral multiple]
|
||||
expected: FAIL
|
||||
|
||||
[[INPUT in NUMBER status\] No step mismatch when step is a floating number and value is its integral multiple]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
expected: FAIL
|
||||
|
||||
[Check that rel=noopener with target=_top does a normal load]
|
||||
expected: TIMEOUT
|
||||
expected: FAIL
|
||||
|
||||
[Check that targeting of rel=noopener with a given name reuses an existing window with that name]
|
||||
expected: NOTRUN
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
[crossorigin-sandwich-TAO.sub.html]
|
||||
expected: ERROR
|
||||
[There should be one entry.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
[018.html]
|
||||
expected: TIMEOUT
|
||||
[origin of the script that invoked the method, javascript:]
|
||||
expected: TIMEOUT
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
[017.html]
|
||||
expected: TIMEOUT
|
||||
[origin of the script that invoked the method, about:blank]
|
||||
expected: TIMEOUT
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[018.html]
|
||||
expected: TIMEOUT
|
||||
[origin of the script that invoked the method, javascript:]
|
||||
expected: TIMEOUT
|
||||
|
|
@ -362,7 +362,6 @@ jobs:
|
|||
- template: tools/ci/azure/pip_install.yml
|
||||
parameters:
|
||||
packages: virtualenv
|
||||
- template: tools/ci/azure/install_fonts.yml
|
||||
- template: tools/ci/azure/install_certs.yml
|
||||
- template: tools/ci/azure/install_safari.yml
|
||||
- template: tools/ci/azure/update_hosts.yml
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<title>setTransform with DOMMatrix behaves correctly</title>
|
||||
<html class="reftest-wait">
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
|
||||
<link rel="match" href="setTransform-ref.html">
|
||||
<style>
|
||||
.container {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
#foo {
|
||||
background: paint(foo);
|
||||
}
|
||||
</style>
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<script src="/common/worklet-reftest.js"></script>
|
||||
<body>
|
||||
<div id="foo" class="container"></div>
|
||||
|
||||
<script id="code" type="text/worklet">
|
||||
registerPaint('foo', class {
|
||||
paint(ctx, geom) {
|
||||
ctx.fillStyle = 'green';
|
||||
let m = ctx.getTransform();
|
||||
m.a = 2;
|
||||
m.d = 2;
|
||||
ctx.setTransform(m);
|
||||
ctx.fillRect(0, 0, 50, 50);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<title>setTransform with DOMMatrix behaves correctly</title>
|
||||
<html class="reftest-wait">
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
|
||||
<link rel="match" href="setTransform-ref.html">
|
||||
<style>
|
||||
.container {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
#foo {
|
||||
background: paint(foo);
|
||||
}
|
||||
</style>
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<script src="/common/worklet-reftest.js"></script>
|
||||
<body>
|
||||
<div id="foo" class="container"></div>
|
||||
|
||||
<script id="code" type="text/worklet">
|
||||
registerPaint('foo', class {
|
||||
paint(ctx, geom) {
|
||||
ctx.fillStyle = 'green';
|
||||
ctx.setTransform({a: 2, d: 2});
|
||||
ctx.fillRect(0, 0, 50, 50);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<title>setTransform with NaN should be ignored</title>
|
||||
<html class="reftest-wait">
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
|
||||
<link rel="match" href="setTransform-ref.html">
|
||||
<style>
|
||||
.container {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
#foo {
|
||||
background: paint(foo);
|
||||
}
|
||||
</style>
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<script src="/common/worklet-reftest.js"></script>
|
||||
<body>
|
||||
<div id="foo" class="container"></div>
|
||||
|
||||
<script id="code" type="text/worklet">
|
||||
registerPaint('foo', class {
|
||||
paint(ctx, geom) {
|
||||
ctx.fillStyle = 'green';
|
||||
// Set to a NaN should be ignored.
|
||||
ctx.setTransform({a: NaN, d:2});
|
||||
ctx.fillRect(0, 0, 100, 100);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<title>setTransform with Infinity should be ignored</title>
|
||||
<html class="reftest-wait">
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
|
||||
<link rel="match" href="setTransform-ref.html">
|
||||
<style>
|
||||
.container {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
#foo {
|
||||
background: paint(foo);
|
||||
}
|
||||
</style>
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<script src="/common/worklet-reftest.js"></script>
|
||||
<body>
|
||||
<div id="foo" class="container"></div>
|
||||
|
||||
<script id="code" type="text/worklet">
|
||||
registerPaint('foo', class {
|
||||
paint(ctx, geom) {
|
||||
ctx.fillStyle = 'green';
|
||||
// Set to Infinity should be ignored.
|
||||
ctx.setTransform({a: Infinity, d:2});
|
||||
ctx.fillRect(0, 0, 100, 100);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<canvas id ="canvas" width="200" height="200"></canvas>
|
||||
<script>
|
||||
var ctx = document.getElementById('canvas').getContext('2d');
|
||||
ctx.fillStyle = 'green';
|
||||
let m = ctx.getTransform();
|
||||
m.a = 2;
|
||||
m.d = 2;
|
||||
ctx.setTransform(m);
|
||||
ctx.fillRect(0, 0, 50, 50);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/1432">
|
||||
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
|
||||
<style>
|
||||
#containing-block {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: red;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#containing-block > div {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#inner-flex {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
inline-size: 50px;
|
||||
block-size: 10px;
|
||||
}
|
||||
</style>
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="containing-block" style="flex-direction: row;">
|
||||
<div id="inner-flex" style="margin: 10px; height: 100px;">
|
||||
<div style="position: absolute; top: 0; height: 100px; background: green;">
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 100px; background: green;"></div>
|
||||
</div>
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/1432">
|
||||
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
|
||||
<style>
|
||||
#containing-block {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: red;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#containing-block > div {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#inner-flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
inline-size: 50px;
|
||||
block-size: 10px;
|
||||
}
|
||||
</style>
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id="containing-block" style="flex-direction: column;">
|
||||
<div id="inner-flex" style="margin: 10px; width: 100px;">
|
||||
<div style="position: absolute; left: 0; width: 100px; background: green; writing-mode: vertical-rl;">
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 100px; background: green;"></div>
|
||||
</div>
|
|
@ -2,6 +2,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<title>CSS Reftest Reference</title>
|
||||
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com" />
|
||||
<link rel="mismatch" href="marker-font-variant-numeric-normal-ref.html">
|
||||
<style>
|
||||
@font-face {
|
||||
/* This font looks different with 'font-variant-numeric: tabular-nums' */
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com" />
|
||||
<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#marker-pseudo">
|
||||
<link rel="match" href="marker-font-variant-numeric-default-ref.html">
|
||||
<link rel="mismatch" href="marker-font-variant-numeric-normal-ref.html">
|
||||
<meta name="assert" content="Checks that the markers have the same width thanks to 'font-variant-numeric: tabular-nums', and thus the black boxes are perfectly aligned">
|
||||
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
|
||||
<style>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<title>CSS Reftest Reference</title>
|
||||
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com" />
|
||||
<link rel="mismatch" href="marker-font-variant-numeric-default-ref.html">
|
||||
<style>
|
||||
@font-face {
|
||||
/* This font looks different with 'font-variant-numeric: tabular-nums' */
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com" />
|
||||
<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#marker-pseudo">
|
||||
<link rel="match" href="marker-font-variant-numeric-normal-ref.html">
|
||||
<link rel="mismatch" href="marker-font-variant-numeric-default-ref.html">
|
||||
<meta name="assert" content="Checks that the marker default 'font-variant-numeric: tabular-nums' can be overridden with 'font-variant-numeric: normal'">
|
||||
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
|
||||
<style>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<title>CSS Reftest Reference</title>
|
||||
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com" />
|
||||
<link rel="mismatch" href="marker-unicode-bidi-normal-ref.html">
|
||||
<style>
|
||||
ol {
|
||||
float: left;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com" />
|
||||
<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#marker-pseudo">
|
||||
<link rel="match" href="marker-unicode-bidi-default-ref.html">
|
||||
<link rel="mismatch" href="marker-unicode-bidi-normal-ref.html">
|
||||
<meta name="assert" content="Checks that the markers are isolated from the list items by the bidi algorithm">
|
||||
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
|
||||
<style>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<title>CSS Reftest Reference</title>
|
||||
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com" />
|
||||
<link rel="mismatch" href="marker-unicode-bidi-default-ref.html">
|
||||
<style>
|
||||
ol {
|
||||
float: left;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com" />
|
||||
<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#marker-pseudo">
|
||||
<link rel="match" href="marker-unicode-bidi-normal-ref.html">
|
||||
<link rel="mismatch" href="marker-unicode-bidi-default-ref.html">
|
||||
<meta name="assert" content="Checks that the marker default 'unicode-bidi: isolate' can be overridden with 'unicode-bidi: normal'">
|
||||
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
|
||||
<style>
|
||||
|
|
|
@ -9,6 +9,7 @@ div {
|
|||
font-size: 10px;
|
||||
font-family: Ahem;
|
||||
width: 5.1ch;
|
||||
border: 1px solid blue;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
|
@ -18,4 +19,7 @@ div {
|
|||
<div>1234­xx</div>
|
||||
<div>12345­xx</div>
|
||||
<div>123456­xx</div>
|
||||
|
||||
<div style="width: 10ch"><span>ren­for­cer</span>99999</div>
|
||||
<div><span>00­1</span>222</div>
|
||||
</body>
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
div {
|
||||
font-size: 10px;
|
||||
font-family: Ahem;
|
||||
width: 5.1ch;
|
||||
border: 1px solid blue;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
|
@ -13,4 +15,7 @@ div {
|
|||
<div>1234-<br>xx</div>
|
||||
<div>12345-<br>xx</div>
|
||||
<div>123456-<br>xx</div>
|
||||
|
||||
<div style="width: 10ch">renfor-<br>cer99999</div>
|
||||
<div>00-<br>1222</div>
|
||||
</body>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<meta charset=utf-8>
|
||||
<title>CSS Typed OM IDL</title>
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#idl-index">
|
||||
<meta name="timeout" content="long">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/WebIDLParser.js"></script>
|
||||
|
|
|
@ -51,7 +51,9 @@ var getWindow = mql => {
|
|||
|
||||
var waitForChangesReported = () => {
|
||||
return new Promise(resolve => {
|
||||
step_timeout(resolve, 75);
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(resolve);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<title>CSS Motion Path: offset-anchor with transform-box: fill-box on the svg g element</title>
|
||||
<link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-anchor-property">
|
||||
<link rel="match" href="offset-anchor-transform-box-fill-box-ref.html">
|
||||
<meta name="assert" content="Tests offset-anchor together with a fill-box transform-box on the <g> element">
|
||||
<style>
|
||||
#target {
|
||||
transform-box: fill-box;
|
||||
offset-anchor: 25% 25%;
|
||||
offset-path: path("M75,-25v100");
|
||||
offset-distance: 50%;
|
||||
}
|
||||
</style>
|
||||
<svg width="400" height="400">
|
||||
<rect width="100" height="100" fill="red"/>
|
||||
<g id='target'>
|
||||
<rect x="150" y="100" width="100" height="100" fill="green"/>
|
||||
</g>
|
||||
</svg>
|
|
@ -117,6 +117,38 @@ document_types().forEach(function (entry) {
|
|||
});
|
||||
}, 'Moving the shadow host of a custom element from the owner document into ' + documentName + ' must enqueue and invoke adoptedCallback');
|
||||
|
||||
promise_test(function () {
|
||||
return getDocument().then(function (doc) {
|
||||
const instance = document.createElement('my-custom-element');
|
||||
const host = document.createElement('div');
|
||||
const shadowRoot = host.attachShadow({mode: 'closed'});
|
||||
shadowRoot.appendChild(instance);
|
||||
document.body.appendChild(host);
|
||||
|
||||
calls = [];
|
||||
doc.documentElement.appendChild(shadowRoot);
|
||||
assert_array_equals(calls, ['disconnected', 'adopted', document, doc, 'connected']);
|
||||
});
|
||||
}, 'Moving the shadow host\'s shadow of a custom element from the owner document into ' + documentName + ' must enqueue and invoke adoptedCallback');
|
||||
|
||||
promise_test(function () {
|
||||
return getDocument().then(function (doc) {
|
||||
const instance = document.createElement('my-custom-element');
|
||||
const template = document.createElement('template');
|
||||
const templateContent = template.content;
|
||||
templateContent.appendChild(instance);
|
||||
document.body.appendChild(template);
|
||||
|
||||
calls = [];
|
||||
doc.documentElement.appendChild(templateContent);
|
||||
if (doc === templateContent.ownerDocument) {
|
||||
assert_array_equals(calls, ['connected']);
|
||||
} else {
|
||||
assert_array_equals(calls, ['adopted', templateContent.ownerDocument, doc, 'connected']);
|
||||
}
|
||||
});
|
||||
}, 'Moving the <template>\'s content of a custom element from the owner document into ' + documentName + ' must enqueue and invoke adoptedCallback');
|
||||
|
||||
promise_test(function () {
|
||||
return getDocument().then(function (doc) {
|
||||
var instance = document.createElement('my-custom-element');
|
||||
|
|
|
@ -29,8 +29,8 @@ Test authors are encouraged to use the builder API to generate the sequence of a
|
|||
API can be accessed via the `new test_driver.Actions()` object, and actions are defined in [testdriver-actions.js](https://github.com/web-platform-tests/wpt/blob/master/resources/testdriver-actions.js)
|
||||
|
||||
The `actions.send()` function causes the sequence of actions to be sent to the browser. It is based on the [WebDriver API](https://w3c.github.io/webdriver/#actions).
|
||||
The action can be a keyboard action, a pointer action or a pause. It returns a `Promise` that
|
||||
resolves after the actions have been sent or rejects if an error was thrown.
|
||||
The action can be a keyboard action, a pointer action or a pause. It returns a promise that
|
||||
resolves after the actions have been sent, or rejects if an error was thrown.
|
||||
|
||||
|
||||
Example:
|
||||
|
@ -49,7 +49,7 @@ let actions = new test_driver.Actions()
|
|||
actions.send();
|
||||
```
|
||||
|
||||
Calling into `send()` is going to dispatch the action sequence (via `test_driver.action_sequence`) and also returns a `Promise` which should be handled however is appropriate in the test. The other functions in the `Actions()` object are going to modify the state of the object by adding a new action in the sequence and return the same object. So the functions can be easily chained as shown in the example above. Here is a list of helper functions in the `Actions` class:
|
||||
Calling into `send()` is going to dispatch the action sequence (via `test_driver.action_sequence`) and also returns a promise which should be handled however is appropriate in the test. The other functions in the `Actions()` object are going to modify the state of the object by adding a new action in the sequence and returning the same object. So the functions can be easily chained, as shown in the example above. Here is a list of helper functions in the `Actions` class:
|
||||
|
||||
```
|
||||
pointerDown: Create a pointerDown event for the current default pointer source
|
||||
|
@ -68,19 +68,19 @@ addKeyboard: Add a new key input source with the given name
|
|||
### bless
|
||||
|
||||
Usage: `test_driver.bless(intent, action)`
|
||||
* `intent`: a string describing the motivation for this invocation
|
||||
* `action`: an optional function
|
||||
* _intent_: a string describing the motivation for this invocation
|
||||
* _action_: an optional function
|
||||
|
||||
This function simulates [activation][activation], allowing tests to
|
||||
perform privileged operations that require user interaction. For
|
||||
example, sandboxed iframes with the
|
||||
example, sandboxed iframes with
|
||||
`allow-top-navigation-by-user-activation` may only navigate their
|
||||
parent's browsing context under these circumstances. The `intent`
|
||||
parent's browsing context under these circumstances. The _intent_
|
||||
string is presented to human operators when the test is not run in
|
||||
automation.
|
||||
|
||||
This method returns a promise which is resolved with the result of
|
||||
invoking the `action` function. If no such function is provided, the
|
||||
invoking the _action_ function. If no such function is provided, the
|
||||
promise is resolved with the value `undefined`.
|
||||
|
||||
Example:
|
||||
|
@ -96,11 +96,11 @@ test_driver.bless('initiate media playback', function () {
|
|||
### click
|
||||
|
||||
Usage: `test_driver.click(element)`
|
||||
* `element`: a DOM Element object
|
||||
* _element_: a DOM Element object
|
||||
|
||||
This function causes a click to occur on the target element (an
|
||||
`Element` object), potentially scrolling the document to make it
|
||||
possible to click it. It returns a `Promise` that resolves after the
|
||||
possible to click it. It returns a promise that resolves after the
|
||||
click has occurred or rejects if the element cannot be clicked (for
|
||||
example, it is obscured by an element on top of it).
|
||||
|
||||
|
@ -111,16 +111,16 @@ being called and the promise settling.
|
|||
### send_keys
|
||||
|
||||
Usage: `test_driver.send_keys(element, keys)`
|
||||
* `element`: a DOM Element object
|
||||
* `keys`: string to send to the element
|
||||
* _element_: a DOM Element object
|
||||
* _keys_: string to send to the element
|
||||
|
||||
This function causes the string `keys` to be send to the target
|
||||
This function causes the string _keys_ to be sent to the target
|
||||
element (an `Element` object), potentially scrolling the document to
|
||||
make it possible to send keys. It returns a `Promise` that resolves
|
||||
after the keys have been send or rejects if the keys cannot be sent
|
||||
make it possible to send keys. It returns a promise that resolves
|
||||
after the keys have been sent, or rejects if the keys cannot be sent
|
||||
to the element.
|
||||
|
||||
Note that if the element that's keys need to be send to does not have
|
||||
Note that if the element that the keys need to be sent to does not have
|
||||
a unique ID, the document must not have any DOM mutations made
|
||||
between the function being called and the promise settling.
|
||||
|
||||
|
@ -128,3 +128,27 @@ To send special keys, one must send the respective key's codepoint. Since this u
|
|||
For example, to send the tab key you would send "\uE004".
|
||||
|
||||
[activation]: https://html.spec.whatwg.org/multipage/interaction.html#activation
|
||||
|
||||
### set_permission
|
||||
|
||||
Usage: `test_driver.set_permission(descriptor, state, one_realm)`
|
||||
* _descriptor_: a
|
||||
[PermissionDescriptor](https://w3c.github.io/permissions/#dictdef-permissiondescriptor)
|
||||
or derived object
|
||||
* _state_: a
|
||||
[PermissionState](https://w3c.github.io/permissions/#enumdef-permissionstate)
|
||||
value
|
||||
* _one_realm_: a boolean that indicates whether the permission settings
|
||||
apply to only one realm
|
||||
|
||||
This function causes permission requests and queries for the status of a
|
||||
certain permission type (e.g. "push", or "background-fetch") to always
|
||||
return _state_. It returns a promise that resolves after the permission has
|
||||
been set to be overridden with _state_.
|
||||
|
||||
Example:
|
||||
|
||||
``` js
|
||||
await test_driver.set_permission({ name: "background-fetch" }, "denied");
|
||||
await test_driver.set_permission({ name: "push", userVisibleOnly: true }, "granted", true);
|
||||
```
|
||||
|
|
58
tests/wpt/web-platform-tests/dom/nodes/adoption.window.js
Normal file
58
tests/wpt/web-platform-tests/dom/nodes/adoption.window.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
// Testing DocumentFragment with host separately as it has a different node document by design
|
||||
test(() => {
|
||||
const df = document.createElement("template").content;
|
||||
const child = df.appendChild(new Text('hi'));
|
||||
assert_not_equals(df.ownerDocument, document);
|
||||
const nodeDocument = df.ownerDocument;
|
||||
document.body.appendChild(df);
|
||||
assert_equals(df.childNodes.length, 0);
|
||||
assert_equals(child.ownerDocument, document);
|
||||
assert_equals(df.ownerDocument, nodeDocument);
|
||||
}, `appendChild() and DocumentFragment with host`);
|
||||
|
||||
test(() => {
|
||||
const df = document.createElement("template").content;
|
||||
const child = df.appendChild(new Text('hi'));
|
||||
const nodeDocument = df.ownerDocument;
|
||||
document.adoptNode(df);
|
||||
assert_equals(df.childNodes.length, 1);
|
||||
assert_equals(child.ownerDocument, nodeDocument);
|
||||
assert_equals(df.ownerDocument, nodeDocument);
|
||||
}, `adoptNode() and DocumentFragment with host`);
|
||||
|
||||
[
|
||||
{
|
||||
"name": "DocumentFragment",
|
||||
"creator": doc => doc.createDocumentFragment()
|
||||
},
|
||||
{
|
||||
"name": "ShadowRoot",
|
||||
"creator": doc => doc.createElementNS("http://www.w3.org/1999/xhtml", "div").attachShadow({mode: "closed"})
|
||||
}
|
||||
].forEach(dfTest => {
|
||||
test(() => {
|
||||
const doc = new Document();
|
||||
const df = dfTest.creator(doc);
|
||||
const child = df.appendChild(new Text('hi'));
|
||||
assert_equals(df.ownerDocument, doc);
|
||||
|
||||
document.body.appendChild(df);
|
||||
assert_equals(df.childNodes.length, 0);
|
||||
assert_equals(child.ownerDocument, document);
|
||||
assert_equals(df.ownerDocument, doc);
|
||||
}, `appendChild() and ${dfTest.name}`);
|
||||
|
||||
test(() => {
|
||||
const doc = new Document();
|
||||
const df = dfTest.creator(doc);
|
||||
const child = df.appendChild(new Text('hi'));
|
||||
if (dfTest.name === "ShadowRoot") {
|
||||
assert_throws("HierarchyRequestError", () => document.adoptNode(df));
|
||||
} else {
|
||||
document.adoptNode(df);
|
||||
assert_equals(df.childNodes.length, 1);
|
||||
assert_equals(child.ownerDocument, document);
|
||||
assert_equals(df.ownerDocument, document);
|
||||
}
|
||||
}, `adoptNode() and ${dfTest.name}`);
|
||||
});
|
|
@ -7,28 +7,70 @@
|
|||
// |opts.expectedBodyAsString|: the expected response body as a string. The
|
||||
// server is expected to echo the request body. The default is the empty string
|
||||
// if the request after redirection isn't POST; otherwise it's |opts.body|.
|
||||
// |opts.expectedRequestContentType|: the expected Content-Type of redirected
|
||||
// request.
|
||||
function redirectMethod(desc, redirectUrl, redirectLocation, redirectStatus, method, expectedMethod, opts) {
|
||||
var url = redirectUrl;
|
||||
var urlParameters = "?redirect_status=" + redirectStatus;
|
||||
let url = redirectUrl;
|
||||
let urlParameters = "?redirect_status=" + redirectStatus;
|
||||
urlParameters += "&location=" + encodeURIComponent(redirectLocation);
|
||||
|
||||
var requestInit = {"method": method, "redirect": "follow"};
|
||||
let requestHeaders = {
|
||||
"Content-Encoding": "Identity",
|
||||
"Content-Language": "en-US",
|
||||
"Content-Location": "foo",
|
||||
};
|
||||
let requestInit = {"method": method, "redirect": "follow", "headers" : requestHeaders};
|
||||
opts = opts || {};
|
||||
if (opts.body)
|
||||
if (opts.body) {
|
||||
requestInit.body = opts.body;
|
||||
}
|
||||
|
||||
promise_test(function(test) {
|
||||
return fetch(url + urlParameters, requestInit).then(function(resp) {
|
||||
let expectedRequestContentType = "NO";
|
||||
if (opts.expectedRequestContentType) {
|
||||
expectedRequestContentType = opts.expectedRequestContentType;
|
||||
}
|
||||
|
||||
assert_equals(resp.status, 200, "Response's status is 200");
|
||||
assert_equals(resp.type, "basic", "Response's type basic");
|
||||
assert_equals(resp.headers.get("x-request-method"), expectedMethod, "Request method after redirection is " + expectedMethod);
|
||||
assert_equals(
|
||||
resp.headers.get("x-request-method"),
|
||||
expectedMethod,
|
||||
"Request method after redirection is " + expectedMethod);
|
||||
let hasRequestBodyHeader = true;
|
||||
if (opts.expectedStripRequestBodyHeader) {
|
||||
hasRequestBodyHeader = !opts.expectedStripRequestBodyHeader;
|
||||
}
|
||||
assert_equals(
|
||||
resp.headers.get("x-request-content-type"),
|
||||
expectedRequestContentType,
|
||||
"Request Content-Type after redirection is " + expectedRequestContentType);
|
||||
[
|
||||
"Content-Encoding",
|
||||
"Content-Language",
|
||||
"Content-Location"
|
||||
].forEach(header => {
|
||||
let xHeader = "x-request-" + header.toLowerCase();
|
||||
let expectedValue = hasRequestBodyHeader ? requestHeaders[header] : "NO";
|
||||
assert_equals(
|
||||
resp.headers.get(xHeader),
|
||||
expectedValue,
|
||||
"Request " + header + " after redirection is " + expectedValue);
|
||||
});
|
||||
assert_true(resp.redirected);
|
||||
return resp.text().then(function(text) {
|
||||
let expectedBody = "";
|
||||
if (expectedMethod == "POST")
|
||||
if (expectedMethod == "POST") {
|
||||
expectedBody = opts.expectedBodyAsString || requestInit.body;
|
||||
}
|
||||
let expectedContentLength = expectedBody ? expectedBody.length.toString() : "NO";
|
||||
assert_equals(text, expectedBody, "request body");
|
||||
});
|
||||
assert_equals(
|
||||
resp.headers.get("x-request-content-length"),
|
||||
expectedContentLength,
|
||||
"Request Content-Length after redirection is " + expectedContentLength);
|
||||
});
|
||||
});
|
||||
}, desc);
|
||||
}
|
||||
|
@ -49,19 +91,20 @@ const blobBody = new Blob(["it's me the blob!", " ", "and more blob!"]);
|
|||
const blobBodyAsString = "it's me the blob! and more blob!";
|
||||
|
||||
redirectMethod("Redirect 301 with GET", redirUrl, locationUrl, 301, "GET", "GET");
|
||||
redirectMethod("Redirect 301 with POST", redirUrl, locationUrl, 301, "POST", "GET", { body: stringBody });
|
||||
redirectMethod("Redirect 301 with POST", redirUrl, locationUrl, 301, "POST", "GET", { body: stringBody, expectedStripRequestBodyHeader: true });
|
||||
redirectMethod("Redirect 301 with HEAD", redirUrl, locationUrl, 301, "HEAD", "HEAD");
|
||||
|
||||
redirectMethod("Redirect 302 with GET", redirUrl, locationUrl, 302, "GET", "GET");
|
||||
redirectMethod("Redirect 302 with POST", redirUrl, locationUrl, 302, "POST", "GET", { body: stringBody });
|
||||
redirectMethod("Redirect 302 with POST", redirUrl, locationUrl, 302, "POST", "GET", { body: stringBody, expectedStripRequestBodyHeader: true });
|
||||
redirectMethod("Redirect 302 with HEAD", redirUrl, locationUrl, 302, "HEAD", "HEAD");
|
||||
|
||||
redirectMethod("Redirect 303 with GET", redirUrl, locationUrl, 303, "GET", "GET");
|
||||
redirectMethod("Redirect 303 with POST", redirUrl, locationUrl, 303, "POST", "GET", { body: stringBody });
|
||||
redirectMethod("Redirect 303 with POST", redirUrl, locationUrl, 303, "POST", "GET", { body: stringBody, expectedStripRequestBodyHeader: true });
|
||||
redirectMethod("Redirect 303 with HEAD", redirUrl, locationUrl, 303, "HEAD", "HEAD");
|
||||
redirectMethod("Redirect 303 with TESTING", redirUrl, locationUrl, 303, "TESTING", "GET", { expectedStripRequestBodyHeader: true });
|
||||
|
||||
redirectMethod("Redirect 307 with GET", redirUrl, locationUrl, 307, "GET", "GET");
|
||||
redirectMethod("Redirect 307 with POST (string body)", redirUrl, locationUrl, 307, "POST", "POST", { body: stringBody });
|
||||
redirectMethod("Redirect 307 with POST (string body)", redirUrl, locationUrl, 307, "POST", "POST", { body: stringBody , expectedRequestContentType: "text/plain;charset=UTF-8"});
|
||||
redirectMethod("Redirect 307 with POST (blob body)", redirUrl, locationUrl, 307, "POST", "POST", { body: blobBody, expectedBodyAsString: blobBodyAsString });
|
||||
redirectMethod("Redirect 307 with HEAD", redirUrl, locationUrl, 307, "HEAD", "HEAD");
|
||||
|
||||
|
|
|
@ -8,4 +8,9 @@ def main(request, response):
|
|||
headers.append(("Access-Control-Expose-Headers", "x-request-method"))
|
||||
|
||||
headers.append(("x-request-method", request.method))
|
||||
headers.append(("x-request-content-type", request.headers.get("Content-Type", "NO")))
|
||||
headers.append(("x-request-content-length", request.headers.get("Content-Length", "NO")))
|
||||
headers.append(("x-request-content-encoding", request.headers.get("Content-Encoding", "NO")))
|
||||
headers.append(("x-request-content-language", request.headers.get("Content-Language", "NO")))
|
||||
headers.append(("x-request-content-location", request.headers.get("Content-Location", "NO")))
|
||||
return headers, request.body
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
async_test(t => {
|
||||
// Setting document.domain makes this document cross-origin with that of the frame. However,
|
||||
// about:blank will end up reusing the origin of this document, at which point the frame's
|
||||
// document is no longer cross-origin.
|
||||
const frame = document.body.appendChild(document.createElement('iframe'));
|
||||
document.domain = document.domain;
|
||||
frame.src = "/common/blank.html";
|
||||
frame.onload = t.step_func(() => {
|
||||
assert_throws("SecurityError", () => window[0].document);
|
||||
frame.src = "about:blank";
|
||||
frame.onload = t.step_func_done(() => {
|
||||
// Ensure we can access the child browsing context after navigation to non-initial about:blank
|
||||
assert_equals(window[0].document, frame.contentDocument);
|
||||
});
|
||||
});
|
||||
}, "Navigated frame to about:blank and document.domain");
|
|
@ -0,0 +1,10 @@
|
|||
test(() => {
|
||||
// As the initial:about frame document reuses the origin of this document, setting document.domain
|
||||
// from the frame, resulting in a origin mutation, has no effect on these documents being able to
|
||||
// reach each other, as they share the same "physical" origin.
|
||||
document.body.appendChild(document.createElement('iframe'));
|
||||
const script = document.createElement("script");
|
||||
script.text = "document.domain = document.domain";
|
||||
window[0].document.body.appendChild(script);
|
||||
assert_equals(window[0].document.body.localName, "body");
|
||||
}, "Initial about:blank frame and document.domain in the frame");
|
|
@ -0,0 +1,9 @@
|
|||
test(() => {
|
||||
// As the initial:about frame document reuses the origin of this document, setting document.domain
|
||||
// from this document, resulting in a origin mutation, has no effect on these documents being able
|
||||
// to reach each other, as they share the same "physical" origin.
|
||||
document.body.appendChild(document.createElement('iframe'));
|
||||
document.domain = document.domain;
|
||||
// Ensure we can still access the child browsing context
|
||||
assert_equals(window[0].document.body.localName, "body");
|
||||
}, "Initial about:blank frame and document.domain");
|
|
@ -11,6 +11,7 @@
|
|||
</style>
|
||||
<img src="/images/green.png">
|
||||
<img src="/images/green.png" width=100 height=125>
|
||||
<img src="" width=100 height=125>
|
||||
<script>
|
||||
let t = async_test("Image width and height attributes are used to infer aspect-ratio");
|
||||
function assert_ratio(img, expected) {
|
||||
|
@ -46,7 +47,8 @@ t.step(function() {
|
|||
|
||||
onload = t.step_func_done(function() {
|
||||
let images = document.querySelectorAll("img");
|
||||
assert_ratio(images[2], 1.266); // 1.266 is the original aspect ratio of blue.png
|
||||
assert_ratio(images[3], 1.266); // 1.266 is the original aspect ratio of blue.png
|
||||
assert_equals(getComputedStyle(images[2]).height, "0px"); // aspect-ratio doesn't override intrinsic size of images that don't have any src.
|
||||
assert_ratio(images[1], 2.0); // 2.0 is the original aspect ratio of green.png
|
||||
assert_ratio(images[0], 2.0); // Loaded image's aspect ratio, at least by default, overrides width / height ratio.
|
||||
});
|
||||
|
|
|
@ -37,3 +37,12 @@ test(t => {
|
|||
comment.remove();
|
||||
assert_not_equals(sheet, style.sheet);
|
||||
}, "Mutating the style element: removing a Comment node");
|
||||
|
||||
test(t => {
|
||||
const style = document.body.appendChild(document.createElement("style"));
|
||||
const sheet = style.sheet;
|
||||
t.add_cleanup(() => style.remove());
|
||||
assert_not_equals(sheet, null);
|
||||
style.appendChild(new DocumentFragment());
|
||||
assert_equals(sheet, style.sheet);
|
||||
}, "Mutating the style element: inserting an empty DocumentFragment node");
|
||||
|
|
|
@ -69,7 +69,10 @@
|
|||
{conditions: {step: "", value: "-.8"}, expected: true, name: "[target] The step attribute is not set and the value attribute is a floating number"},
|
||||
{conditions: {step: 2 * 1 * 1, value: ""}, expected: false, name: "[target] The value attribute is empty string"},
|
||||
{conditions: {step: 2 * 1 * 1, value: "2"}, expected: false, name: "[target] The value must match the step"},
|
||||
{conditions: {step: 2 * 1 * 1, value: "3"}, expected: true, name: "[target] The value must mismatch the step"}
|
||||
{conditions: {step: 2 * 1 * 1, value: "3"}, expected: true, name: "[target] The value must mismatch the step"},
|
||||
{conditions: {step: 0.003, value: "3.6"}, expected: false, name: "[target] No step mismatch when step is a floating number and value is its integral multiple"},
|
||||
{conditions: {step: 1e-12, value: "-12345678.9"}, expected: false, name: "[target] No step mismatch when step is a floating number in exponent format and value is its integral multiple"},
|
||||
{conditions: {step: 3e-15, value: "17"}, expected: true, name: "[target] Step mismatch when step is a very small floating number and value is not its integral multiple"},
|
||||
]
|
||||
}
|
||||
];
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
var validator = {
|
||||
|
||||
test_tooLong: function(ctl, data) {
|
||||
var self = this;
|
||||
test(function () {
|
||||
self.pre_check(ctl, "tooLong");
|
||||
test(function() {
|
||||
self.pre_check(ctl, 'tooLong');
|
||||
self.set_conditions(ctl, data.conditions);
|
||||
if (data.dirty)
|
||||
self.set_dirty(ctl);
|
||||
|
||||
if (data.expected)
|
||||
assert_true(ctl.validity.tooLong, "The validity.tooLong should be true.");
|
||||
else
|
||||
assert_false(ctl.validity.tooLong, "The validity.tooLong should be false.");
|
||||
self.iterate_over(ctl, data).forEach(function(val) {
|
||||
const {ctl, data, condStr} = val;
|
||||
if (data.dirty)
|
||||
self.set_dirty(ctl);
|
||||
if (data.expected)
|
||||
assert_true(
|
||||
ctl.validity.tooLong,
|
||||
'The validity.tooLong should be true' + condStr);
|
||||
else
|
||||
assert_false(
|
||||
ctl.validity.tooLong,
|
||||
'The validity.tooLong should be false' + condStr);
|
||||
});
|
||||
}, data.name);
|
||||
},
|
||||
|
||||
|
@ -19,13 +26,19 @@ var validator = {
|
|||
test(function () {
|
||||
self.pre_check(ctl, "tooShort");
|
||||
self.set_conditions(ctl, data.conditions);
|
||||
if (data.dirty)
|
||||
self.set_dirty(ctl);
|
||||
|
||||
if (data.expected)
|
||||
assert_true(ctl.validity.tooShort, "The validity.tooShort should be true.");
|
||||
else
|
||||
assert_false(ctl.validity.tooShort, "The validity.tooShort should be false.");
|
||||
self.iterate_over(ctl, data).forEach(function(val) {
|
||||
const {ctl, data, condStr} = val;
|
||||
if (data.dirty)
|
||||
self.set_dirty(ctl);
|
||||
if (data.expected)
|
||||
assert_true(
|
||||
ctl.validity.tooShort,
|
||||
'The validity.tooShort should be true' + condStr);
|
||||
else
|
||||
assert_false(
|
||||
ctl.validity.tooShort,
|
||||
'The validity.tooShort should be false' + condStr);
|
||||
});
|
||||
}, data.name);
|
||||
},
|
||||
|
||||
|
@ -34,11 +47,17 @@ var validator = {
|
|||
test(function () {
|
||||
self.pre_check(ctl, "patternMismatch");
|
||||
self.set_conditions(ctl, data.conditions);
|
||||
|
||||
if (data.expected)
|
||||
assert_true(ctl.validity.patternMismatch, "The validity.patternMismatch should be true.");
|
||||
else
|
||||
assert_false(ctl.validity.patternMismatch, "The validity.patternMismatch should be false.");
|
||||
self.iterate_over(ctl, data).forEach(function(val) {
|
||||
const {ctl, data, condStr} = val;
|
||||
if (data.expected)
|
||||
assert_true(
|
||||
ctl.validity.patternMismatch,
|
||||
'The validity.patternMismatch should be true' + condStr);
|
||||
else
|
||||
assert_false(
|
||||
ctl.validity.patternMismatch,
|
||||
'The validity.patternMismatch should be false' + condStr);
|
||||
});
|
||||
}, data.name);
|
||||
},
|
||||
|
||||
|
@ -47,10 +66,17 @@ var validator = {
|
|||
test(function () {
|
||||
self.pre_check(ctl, "valueMissing");
|
||||
self.set_conditions(ctl, data.conditions);
|
||||
if (data.expected)
|
||||
assert_true(ctl.validity.valueMissing, "The validity.valueMissing should be true.");
|
||||
else
|
||||
assert_false(ctl.validity.valueMissing, "The validity.valueMissing should be false.");
|
||||
self.iterate_over(ctl, data).forEach(function(val) {
|
||||
const {ctl, data, condStr} = val;
|
||||
if (data.expected)
|
||||
assert_true(
|
||||
ctl.validity.valueMissing,
|
||||
'The validity.valueMissing should be true' + condStr);
|
||||
else
|
||||
assert_false(
|
||||
ctl.validity.valueMissing,
|
||||
'The validity.valueMissing should be false' + condStr);
|
||||
});
|
||||
}, data.name);
|
||||
},
|
||||
|
||||
|
@ -59,11 +85,17 @@ var validator = {
|
|||
test(function () {
|
||||
self.pre_check(ctl, "typeMismatch");
|
||||
self.set_conditions(ctl, data.conditions);
|
||||
|
||||
if (data.expected)
|
||||
assert_true(ctl.validity.typeMismatch, "The validity.typeMismatch should be true.");
|
||||
else
|
||||
assert_false(ctl.validity.typeMismatch, "The validity.typeMismatch should be false.");
|
||||
self.iterate_over(ctl, data).forEach(function(val) {
|
||||
const {ctl, data, condStr} = val;
|
||||
if (data.expected)
|
||||
assert_true(
|
||||
ctl.validity.typeMismatch,
|
||||
'The validity.typeMismatch should be true' + condStr);
|
||||
else
|
||||
assert_false(
|
||||
ctl.validity.typeMismatch,
|
||||
'The validity.typeMismatch should be false' + condStr);
|
||||
});
|
||||
}, data.name);
|
||||
},
|
||||
|
||||
|
@ -72,11 +104,17 @@ var validator = {
|
|||
test(function () {
|
||||
self.pre_check(ctl, "rangeOverflow");
|
||||
self.set_conditions(ctl, data.conditions);
|
||||
|
||||
if (data.expected)
|
||||
assert_true(ctl.validity.rangeOverflow, "The validity.rangeOverflow should be true.");
|
||||
else
|
||||
assert_false(ctl.validity.rangeOverflow, "The validity.rangeOverflow should be false.");
|
||||
self.iterate_over(ctl, data).forEach(function(val) {
|
||||
const {ctl, data, condStr} = val;
|
||||
if (data.expected)
|
||||
assert_true(
|
||||
ctl.validity.rangeOverflow,
|
||||
'The validity.rangeOverflow should be true' + condStr);
|
||||
else
|
||||
assert_false(
|
||||
ctl.validity.rangeOverflow,
|
||||
'The validity.rangeOverflow should be false' + condStr);
|
||||
});
|
||||
}, data.name);
|
||||
},
|
||||
|
||||
|
@ -85,10 +123,17 @@ var validator = {
|
|||
test(function () {
|
||||
self.pre_check(ctl, "rangeUnderflow");
|
||||
self.set_conditions(ctl, data.conditions);
|
||||
if (data.expected)
|
||||
assert_true(ctl.validity.rangeUnderflow, "The validity.rangeUnderflow should be true.");
|
||||
else
|
||||
assert_false(ctl.validity.rangeUnderflow, "The validity.rangeUnderflow should be false.");
|
||||
self.iterate_over(ctl, data).forEach(function(val) {
|
||||
const {ctl, data, condStr} = val;
|
||||
if (data.expected)
|
||||
assert_true(
|
||||
ctl.validity.rangeUnderflow,
|
||||
'The validity.rangeUnderflow should be true' + condStr);
|
||||
else
|
||||
assert_false(
|
||||
ctl.validity.rangeUnderflow,
|
||||
'The validity.rangeUnderflow should be false' + condStr);
|
||||
});
|
||||
}, data.name);
|
||||
},
|
||||
|
||||
|
@ -97,11 +142,17 @@ var validator = {
|
|||
test(function () {
|
||||
self.pre_check(ctl, "stepMismatch");
|
||||
self.set_conditions(ctl, data.conditions);
|
||||
|
||||
if (data.expected)
|
||||
assert_true(ctl.validity.stepMismatch, "The validity.stepMismatch should be true.");
|
||||
else
|
||||
assert_false(ctl.validity.stepMismatch, "The validity.stepMismatch should be false.");
|
||||
self.iterate_over(ctl, data).forEach(function(val) {
|
||||
const {ctl, data, condStr} = val;
|
||||
if (data.expected)
|
||||
assert_true(
|
||||
ctl.validity.stepMismatch,
|
||||
'The validity.stepMismatch should be true' + condStr);
|
||||
else
|
||||
assert_false(
|
||||
ctl.validity.stepMismatch,
|
||||
'The validity.stepMismatch should be false' + condStr);
|
||||
});
|
||||
}, data.name);
|
||||
},
|
||||
|
||||
|
@ -110,11 +161,17 @@ var validator = {
|
|||
test(function () {
|
||||
self.pre_check(ctl, "badInput");
|
||||
self.set_conditions(ctl, data.conditions);
|
||||
|
||||
if (data.expected)
|
||||
assert_true(ctl.validity.badInput, "The validity.badInput should be true.");
|
||||
else
|
||||
assert_false(ctl.validity.badInput, "The validity.badInput should be false.");
|
||||
self.iterate_over(ctl, data).forEach(function(val) {
|
||||
const {ctl, data, condStr} = val;
|
||||
if (data.expected)
|
||||
assert_true(
|
||||
ctl.validity.badInput,
|
||||
'The validity.badInput should be true' + condStr);
|
||||
else
|
||||
assert_false(
|
||||
ctl.validity.badInput,
|
||||
'The validity.badInput should be false' + condStr);
|
||||
});
|
||||
}, data.name);
|
||||
},
|
||||
|
||||
|
@ -123,29 +180,45 @@ var validator = {
|
|||
test(function () {
|
||||
self.pre_check(ctl, "customError");
|
||||
ctl.setCustomValidity(data.conditions.message);
|
||||
|
||||
if (data.expected) {
|
||||
assert_true(ctl.validity.customError, "The validity.customError attribute should be true.");
|
||||
assert_equals(ctl.validationMessage, data.conditions.message,
|
||||
"The validationMessage attribute should be '" + data.conditions.message + "'.");
|
||||
} else {
|
||||
assert_false(ctl.validity.customError, "The validity.customError attribute should be false.");
|
||||
assert_equals(ctl.validationMessage, "", "The validationMessage attribute must be empty.");
|
||||
}
|
||||
self.iterate_over(ctl, data).forEach(function(val) {
|
||||
const {ctl, data, condStr} = val;
|
||||
if (data.expected) {
|
||||
assert_true(
|
||||
ctl.validity.customError,
|
||||
'The validity.customError attribute should be true' + condStr);
|
||||
assert_equals(
|
||||
ctl.validationMessage, data.conditions.message,
|
||||
'The validationMessage attribute should be \'' +
|
||||
data.conditions.message + '\'' + condStr);
|
||||
} else {
|
||||
assert_false(
|
||||
ctl.validity.customError,
|
||||
'The validity.customError attribute should be false' + condStr);
|
||||
assert_equals(
|
||||
ctl.validationMessage, '',
|
||||
'The validationMessage attribute must be empty' + condStr);
|
||||
}
|
||||
});
|
||||
}, data.name);
|
||||
},
|
||||
|
||||
test_isValid: function (ctl, data) {
|
||||
test_isValid: function(ctl, data) {
|
||||
var self = this;
|
||||
test(function () {
|
||||
self.set_conditions(ctl, data.conditions);
|
||||
if (data.dirty)
|
||||
self.set_dirty(ctl);
|
||||
|
||||
if (data.expected)
|
||||
assert_true(ctl.validity.valid, "The validity.valid should be true.");
|
||||
else
|
||||
assert_false(ctl.validity.valid, "The validity.valid should be false.");
|
||||
self.iterate_over(ctl, data).forEach(function(val) {
|
||||
const {ctl, data, condStr} = val;
|
||||
if (data.dirty)
|
||||
self.set_dirty(ctl);
|
||||
if (data.expected)
|
||||
assert_true(
|
||||
ctl.validity.valid,
|
||||
'The validity.valid should be true' + condStr);
|
||||
else
|
||||
assert_false(
|
||||
ctl.validity.valid,
|
||||
'The validity.valid should be false' + condStr);
|
||||
});
|
||||
}, data.name);
|
||||
},
|
||||
|
||||
|
@ -166,7 +239,7 @@ var validator = {
|
|||
}, data.name);
|
||||
},
|
||||
|
||||
test_checkValidity: function (ctl, data) {
|
||||
test_checkValidity: function(ctl, data) {
|
||||
var self = this;
|
||||
test(function () {
|
||||
var eventFired = false;
|
||||
|
@ -210,7 +283,7 @@ var validator = {
|
|||
}, data.name + " (in a form)");
|
||||
},
|
||||
|
||||
test_reportValidity: function (ctl, data) {
|
||||
test_reportValidity: function(ctl, data) {
|
||||
var self = this;
|
||||
test(function () {
|
||||
var eventFired = false;
|
||||
|
@ -255,13 +328,13 @@ var validator = {
|
|||
}, data.name + " (in a form)");
|
||||
},
|
||||
|
||||
test_support_type: function (ctl, typ, testName) {
|
||||
test_support_type: function(ctl, typ, testName) {
|
||||
test(function () {
|
||||
assert_equals(ctl.type, typ, "The " + typ + " type should be supported.");
|
||||
}, testName);
|
||||
},
|
||||
|
||||
set_conditions: function (ctl, obj) {
|
||||
set_conditions: function(ctl, obj) {
|
||||
[
|
||||
"checked",
|
||||
"disabled",
|
||||
|
@ -322,7 +395,28 @@ var validator = {
|
|||
}
|
||||
},
|
||||
|
||||
run_test: function (testee, method) {
|
||||
iterate_over: function(ctl, data) {
|
||||
// Iterate over normal, disabled, readonly, and both.
|
||||
var ctlDisabled = ctl.cloneNode(true);
|
||||
ctlDisabled.disabled = true;
|
||||
var ctlReadonly = ctl.cloneNode(true);
|
||||
ctlReadonly.readonly = true;
|
||||
var ctlBoth = ctl.cloneNode(true);
|
||||
ctlBoth.disabled = true;
|
||||
ctlBoth.readonly = true;
|
||||
return [
|
||||
{ctl: ctl, data: data, condStr: '.'},
|
||||
{ctl: ctlDisabled, data: data, condStr: ', when control is disabled.'},
|
||||
{ctl: ctlReadonly, data: data, condStr: ', when control is readonly.'},
|
||||
{
|
||||
ctl: ctlBoth,
|
||||
data: data,
|
||||
condStr: ', when control is disabled & readonly.'
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
run_test: function(testee, method) {
|
||||
var testMethod = "test_" + method;
|
||||
if (typeof this[testMethod] !== "function") {
|
||||
return false;
|
||||
|
@ -363,7 +457,7 @@ var validator = {
|
|||
prefix = "[" + testee[i].tag + "] ";
|
||||
|
||||
if (testElements[i].tag === "select") {
|
||||
ele.add(new Option("test1", ""));
|
||||
ele.add(new Option('test1', '')); // Placeholder
|
||||
ele.add(new Option("test2", 1));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
<meta name="author" title="Takayoshi Kochi" href="mailto:kochi@chromium.org">
|
||||
<meta name="assert" title="host-including inclusive ancestor should be checked for template content">
|
||||
<link rel="help" href="https://dom.spec.whatwg.org/#concept-tree-host-including-inclusive-ancestor">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id=log></div>
|
||||
<div id="parent">
|
||||
<template id="tmpl"><span>Happy Templating!</span></template>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
test(() => {
|
||||
var parent = document.getElementById('parent');
|
||||
|
@ -53,12 +45,11 @@ test(() => {
|
|||
assert_not_equals(new_doc, tmpl_doc);
|
||||
|
||||
// Try moving tmpl.content to new_doc and check the results.
|
||||
var new_node = new_doc.adoptNode(tmpl.content);
|
||||
assert_equals(new_node.ownerDocument, new_doc);
|
||||
const tmplContentNodeDocument = tmpl.content.ownerDocument;
|
||||
const tmplContentAdoptResult = new_doc.adoptNode(tmpl.content);
|
||||
assert_equals(tmpl.content, tmplContentAdoptResult);
|
||||
assert_equals(tmpl.ownerDocument, document);
|
||||
assert_equals(tmpl.content.ownerDocument, new_doc);
|
||||
assert_not_equals(tmpl.content.ownerDocument, tmpl_doc);
|
||||
assert_not_equals(tmpl.content.ownerDocument, document);
|
||||
assert_equals(tmpl.content.ownerDocument, tmplContentNodeDocument);
|
||||
|
||||
// Hierarchy checks at various combinations.
|
||||
assert_throws('HierarchyRequestError', () => {
|
||||
|
@ -79,7 +70,7 @@ test(() => {
|
|||
assert_equals(tmpl.content.firstChild, span,
|
||||
'<span> should be kept until it is removed, even after ' +
|
||||
'adopted to another document.');
|
||||
new_doc.body.appendChild(new_node);
|
||||
new_doc.body.appendChild(tmpl.content);
|
||||
assert_equals(tmpl.content.firstChild, null,
|
||||
'<span> should be removed from template content.');
|
||||
assert_equals(tmpl_content_reference, tmpl.content,
|
||||
|
@ -88,4 +79,3 @@ test(() => {
|
|||
}, 'Template content should throw exception when its ancestor in ' +
|
||||
'a different document but connected via host is being append.');
|
||||
</script>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
[multiTouchPointsReleaseFirstPoint.html]
|
||||
expected:
|
||||
if product == "firefox" or product == "safari": ERROR
|
||||
[TestDriver actions: two touch points with one moving one pause]
|
||||
expected:
|
||||
if product == "chrome": FAIL
|
|
@ -0,0 +1,6 @@
|
|||
[multiTouchPointsReleaseSecondPoint.html]
|
||||
expected:
|
||||
if product == "firefox" or product == "safari": ERROR
|
||||
[TestDriver actions: two touch points with one moving one pause]
|
||||
expected:
|
||||
if product == "chrome": FAIL
|
|
@ -1,4 +1,4 @@
|
|||
[generate_test_report.html]
|
||||
expected:
|
||||
if product == "firefox": ERROR
|
||||
if product == "safari" or product == "epiphany" or product == "webkit": ERROR
|
||||
[TestDriver generate_test_report method]
|
||||
expected:
|
||||
if product == "firefox" or product == "safari" or product == "epiphany" or product == "webkit": FAIL
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
[set_permission.https.html]
|
||||
expected:
|
||||
if product != "chrome": ERROR
|
||||
[Grant Permission for one realm]
|
||||
expected:
|
||||
if product != "chrome": FAIL
|
||||
|
||||
[Deny Permission, omit one realm]
|
||||
expected:
|
||||
if product != "chrome": FAIL
|
||||
|
|
|
@ -1,3 +1,28 @@
|
|||
[virtual_authenticator.html]
|
||||
expected:
|
||||
if product == "firefox" or product == "safari" or product == "epiphany" or product == "webkit": ERROR
|
||||
[Can create an authenticator]
|
||||
expected:
|
||||
if product == "firefox" or product == "safari" or product == "epiphany" or product == "webkit": FAIL
|
||||
|
||||
[Can add a credential]
|
||||
expected:
|
||||
if product == "firefox" or product == "safari" or product == "epiphany" or product == "webkit": FAIL
|
||||
|
||||
[Can get the credentials]
|
||||
expected:
|
||||
if product == "firefox" or product == "safari" or product == "epiphany" or product == "webkit": FAIL
|
||||
|
||||
[Can remove a credential]
|
||||
expected:
|
||||
if product == "firefox" or product == "safari" or product == "epiphany" or product == "webkit": FAIL
|
||||
|
||||
[Can remove all credentials]
|
||||
expected:
|
||||
if product == "firefox" or product == "safari" or product == "epiphany" or product == "webkit": FAIL
|
||||
|
||||
[Can set user verified]
|
||||
expected:
|
||||
if product == "firefox" or product == "safari" or product == "epiphany" or product == "webkit": FAIL
|
||||
|
||||
[Can remove a virtual authenticator]
|
||||
expected:
|
||||
if product == "firefox" or product == "safari" or product == "epiphany" or product == "webkit": FAIL
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>TestDriver actions: two touch points with one moving one pause</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-actions.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
|
||||
<style>
|
||||
div#test1{
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: blue;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div id="test1">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let event_type = [];
|
||||
let event_id = [];
|
||||
|
||||
async_test(t => {
|
||||
let test1 = document.getElementById("test1");
|
||||
document.getElementById("test1").addEventListener("pointerdown",
|
||||
e => {event_type.push(e.type); event_id.push(e.pointerId);});
|
||||
document.getElementById("test1").addEventListener("pointerup",
|
||||
e => {event_type.push(e.type); event_id.push(e.pointerId);});
|
||||
document.getElementById("test1").addEventListener("pointermove",
|
||||
e => {event_type.push(e.type); event_id.push(e.pointerId);});
|
||||
|
||||
let actions = new test_driver.Actions()
|
||||
.addPointer("touchPointer1", "touch")
|
||||
.addPointer("touchPointer2", "touch")
|
||||
.pointerMove(0, 0, {origin: test1, sourceName: "touchPointer1"})
|
||||
.pointerMove(10, 0, {origin: test1, sourceName: "touchPointer2"})
|
||||
.pointerDown({sourceName: "touchPointer1"})
|
||||
.pointerDown({sourceName: "touchPointer2"})
|
||||
.pointerUp({sourceName: "touchPointer1"})
|
||||
.pointerMove(10, 10, {origin: test1, sourceName: "touchPointer2"})
|
||||
.pointerUp({sourceName: "touchPointer2"});
|
||||
|
||||
actions.send()
|
||||
.then(t.step_func_done(() => {
|
||||
assert_array_equals(event_type, ["pointerdown", "pointerdown", "pointerup", "pointermove", "pointerup"]);
|
||||
assert_array_equals(event_id, [2, 3, 2, 3, 3]);
|
||||
}))
|
||||
.catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e)));
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>TestDriver actions: two touch points with one moving one pause</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-actions.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
|
||||
<style>
|
||||
div#test1{
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: blue;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div id="test1">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let event_type = [];
|
||||
let event_id = [];
|
||||
|
||||
async_test(t => {
|
||||
let test1 = document.getElementById("test1");
|
||||
document.getElementById("test1").addEventListener("pointerdown",
|
||||
e => {event_type.push(e.type); event_id.push(e.pointerId);});
|
||||
document.getElementById("test1").addEventListener("pointerup",
|
||||
e => {event_type.push(e.type); event_id.push(e.pointerId);});
|
||||
document.getElementById("test1").addEventListener("pointermove",
|
||||
e => {event_type.push(e.type); event_id.push(e.pointerId);});
|
||||
|
||||
let actions = new test_driver.Actions()
|
||||
.addPointer("touchPointer1", "touch")
|
||||
.addPointer("touchPointer2", "touch")
|
||||
.pointerMove(0, 0, {origin: test1, sourceName: "touchPointer1"})
|
||||
.pointerMove(10, 0, {origin: test1, sourceName: "touchPointer2"})
|
||||
.pointerDown({sourceName: "touchPointer1"})
|
||||
.pointerDown({sourceName: "touchPointer2"})
|
||||
.pointerMove(10, 10, {origin: test1, sourceName: "touchPointer1"})
|
||||
.pointerUp({sourceName: "touchPointer2"})
|
||||
.pointerUp({sourceName: "touchPointer1"});
|
||||
|
||||
actions.send()
|
||||
.then(t.step_func_done(() => {
|
||||
assert_array_equals(event_type, ["pointerdown", "pointerdown", "pointermove", "pointerup", "pointerup"]);
|
||||
assert_array_equals(event_id, [2, 3, 2, 3, 2]);
|
||||
}))
|
||||
.catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e)));
|
||||
});
|
||||
</script>
|
|
@ -24,7 +24,7 @@ let credential = {
|
|||
isResidentCredential: false,
|
||||
};
|
||||
|
||||
let authenticator_id;
|
||||
let authenticator_id = null;
|
||||
|
||||
promise_test(async t => {
|
||||
authenticator_id = await test_driver.add_virtual_authenticator({
|
||||
|
|
|
@ -19,6 +19,12 @@ interface CookieStore : EventTarget {
|
|||
Promise<void> delete(USVString name);
|
||||
Promise<void> delete(CookieStoreDeleteOptions options);
|
||||
|
||||
[Exposed=ServiceWorker]
|
||||
Promise<void> subscribeToChanges(sequence<CookieStoreGetOptions> subscriptions);
|
||||
|
||||
[Exposed=ServiceWorker]
|
||||
Promise<sequence<CookieStoreGetOptions>> getChangeSubscriptions();
|
||||
|
||||
[Exposed=Window]
|
||||
attribute EventHandler onchange;
|
||||
};
|
||||
|
@ -71,7 +77,8 @@ dictionary CookieListItem {
|
|||
|
||||
typedef sequence<CookieListItem> CookieList;
|
||||
|
||||
[Exposed=Window, SecureContext]
|
||||
[Exposed=Window,
|
||||
SecureContext]
|
||||
interface CookieChangeEvent : Event {
|
||||
constructor(DOMString type, optional CookieChangeEventInit eventInitDict = {});
|
||||
readonly attribute CookieList changed;
|
||||
|
@ -83,8 +90,8 @@ dictionary CookieChangeEventInit : EventInit {
|
|||
CookieList deleted;
|
||||
};
|
||||
|
||||
[Exposed=ServiceWorker]
|
||||
interface ExtendableCookieChangeEvent : ExtendableEvent {
|
||||
[Exposed=ServiceWorker
|
||||
] interface ExtendableCookieChangeEvent : ExtendableEvent {
|
||||
constructor(DOMString type, optional ExtendableCookieChangeEventInit eventInitDict = {});
|
||||
readonly attribute CookieList changed;
|
||||
readonly attribute CookieList deleted;
|
||||
|
@ -95,13 +102,6 @@ dictionary ExtendableCookieChangeEventInit : ExtendableEventInit {
|
|||
CookieList deleted;
|
||||
};
|
||||
|
||||
[Exposed=(ServiceWorker,Window), SecureContext]
|
||||
interface CookieStoreManager {
|
||||
Promise<void> subscribe(sequence<CookieStoreGetOptions> subscriptions);
|
||||
Promise<sequence<CookieStoreGetOptions>> getSubscriptions();
|
||||
Promise<void> unsubscribe(sequence<CookieStoreGetOptions> subscriptions);
|
||||
};
|
||||
|
||||
[SecureContext]
|
||||
partial interface Window {
|
||||
[Replaceable, SameObject] readonly attribute CookieStore cookieStore;
|
||||
|
@ -109,10 +109,6 @@ partial interface Window {
|
|||
|
||||
partial interface ServiceWorkerGlobalScope {
|
||||
[Replaceable, SameObject] readonly attribute CookieStore cookieStore;
|
||||
|
||||
attribute EventHandler oncookiechange;
|
||||
};
|
||||
|
||||
[Exposed=(ServiceWorker,Window), SecureContext]
|
||||
partial interface ServiceWorkerRegistration {
|
||||
readonly attribute CookieStoreManager cookies;
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// (https://github.com/tidoust/reffy-reports)
|
||||
// Source: Feature Policy (https://w3c.github.io/webappsec-feature-policy/)
|
||||
|
||||
[Exposed=Window]
|
||||
interface FeaturePolicy {
|
||||
boolean allowsFeature(DOMString feature, optional DOMString origin);
|
||||
sequence<DOMString> features();
|
||||
|
@ -17,6 +18,7 @@ partial interface Document {
|
|||
partial interface HTMLIFrameElement {
|
||||
[SameObject] readonly attribute FeaturePolicy featurePolicy;
|
||||
};
|
||||
|
||||
[Exposed=Window]
|
||||
interface FeaturePolicyViolationReportBody : ReportBody {
|
||||
readonly attribute DOMString featureId;
|
||||
|
|
|
@ -8,7 +8,6 @@ dictionary RTCConfiguration {
|
|||
RTCIceTransportPolicy iceTransportPolicy;
|
||||
RTCBundlePolicy bundlePolicy;
|
||||
RTCRtcpMuxPolicy rtcpMuxPolicy;
|
||||
DOMString peerIdentity;
|
||||
sequence<RTCCertificate> certificates;
|
||||
[EnforceRange] octet iceCandidatePoolSize = 0;
|
||||
};
|
||||
|
@ -296,11 +295,9 @@ dictionary RTCRtpParameters {
|
|||
dictionary RTCRtpSendParameters : RTCRtpParameters {
|
||||
required DOMString transactionId;
|
||||
required sequence<RTCRtpEncodingParameters> encodings;
|
||||
RTCDegradationPreference degradationPreference = "balanced";
|
||||
};
|
||||
|
||||
dictionary RTCRtpReceiveParameters : RTCRtpParameters {
|
||||
required sequence<RTCRtpDecodingParameters> encodings;
|
||||
};
|
||||
|
||||
dictionary RTCRtpCodingParameters {
|
||||
|
@ -315,12 +312,6 @@ dictionary RTCRtpEncodingParameters : RTCRtpCodingParameters {
|
|||
double scaleResolutionDownBy;
|
||||
};
|
||||
|
||||
enum RTCDegradationPreference {
|
||||
"maintain-framerate",
|
||||
"maintain-resolution",
|
||||
"balanced"
|
||||
};
|
||||
|
||||
dictionary RTCRtcpParameters {
|
||||
DOMString cname;
|
||||
boolean reducedSize;
|
||||
|
@ -615,14 +606,6 @@ enum RTCErrorDetailType {
|
|||
"data-channel-failure",
|
||||
"dtls-failure",
|
||||
"fingerprint-failure",
|
||||
"idp-bad-script-failure",
|
||||
"idp-execution-failure",
|
||||
"idp-load-failure",
|
||||
"idp-need-login",
|
||||
"idp-timeout",
|
||||
"idp-tls-failure",
|
||||
"idp-token-expired",
|
||||
"idp-token-invalid",
|
||||
"sctp-failure",
|
||||
"sdp-syntax-error",
|
||||
"hardware-encoder-not-available",
|
||||
|
|
|
@ -193,7 +193,7 @@ interface XRWebGLLayer {
|
|||
readonly attribute boolean antialias;
|
||||
readonly attribute boolean ignoreDepthValues;
|
||||
|
||||
[SameObject] readonly attribute WebGLFramebuffer framebuffer;
|
||||
[SameObject] readonly attribute WebGLFramebuffer? framebuffer;
|
||||
readonly attribute unsigned long framebufferWidth;
|
||||
readonly attribute unsigned long framebufferHeight;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<link rel="help" href="https://github.com/scott-little/lazyload">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="common.js"></script>
|
||||
</head>
|
||||
|
||||
<!--
|
||||
|
@ -24,12 +25,16 @@ Marked as tentative until https://github.com/whatwg/html/pull/3752 is landed.
|
|||
|
||||
window.addEventListener("load", t.step_func(function() {
|
||||
assert_true(has_in_viewport_loaded, "The in_viewport element should have loaded before window.load().");
|
||||
assert_true(document.getElementById("in_viewport").complete);
|
||||
assert_false(has_window_loaded, "The window.load() event should only fire once.");
|
||||
has_window_loaded = true;
|
||||
document.getElementById("below_viewport").scrollIntoView();
|
||||
}));
|
||||
|
||||
const below_viewport_img_onload = t.step_func_done(function() {
|
||||
assert_true(is_image_fully_loaded(
|
||||
document.getElementById("below_viewport"),
|
||||
document.getElementById("in_viewport")));
|
||||
assert_true(has_window_loaded, "The window.load() event should have fired before below_viewport loaded.");
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -8,7 +8,7 @@ async_test(t => {
|
|||
return;
|
||||
assert_equals(entry.entryType, 'longtask');
|
||||
assert_equals(entry.name, 'self');
|
||||
assert_greater_than(longtask.duration, 50);
|
||||
assert_greater_than(entry.duration, 50);
|
||||
longtaskObserved = true;
|
||||
});
|
||||
assert_true(longtaskObserved, 'Did not observe buffered longtask.');
|
||||
|
|
|
@ -70,49 +70,6 @@
|
|||
test.done();
|
||||
});
|
||||
}, "Test HTMLVideoElement.getVideoPlaybackQuality() with MediaSource API");
|
||||
|
||||
|
||||
mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
|
||||
{
|
||||
var previousQuality = mediaElement.getVideoPlaybackQuality();
|
||||
var timeUpdateCount = 0;
|
||||
var startTime = 0;
|
||||
mediaElement.addEventListener("timeupdate", test.step_func(function (e)
|
||||
{
|
||||
var videoElement = e.target;
|
||||
var newQuality = videoElement.getVideoPlaybackQuality();
|
||||
var now = window.performance.now();
|
||||
|
||||
assert_greater_than_equal(newQuality.totalFrameDelay, 0, "totalFrameDelay >= 0");
|
||||
assert_greater_than_equal(newQuality.totalFrameDelay, previousQuality.totalFrameDelay,
|
||||
"totalFrameDelay increases monotonically");
|
||||
assert_less_than(newQuality.totalFrameDelay, (now - startTime) / 1000,
|
||||
"totalFrameDelay does not exceed the time elapsed since playback started");
|
||||
|
||||
previousQuality = newQuality;
|
||||
timeUpdateCount++;
|
||||
}));
|
||||
|
||||
mediaElement.addEventListener('error', test.unreached_func("Unexpected event 'error'"));
|
||||
|
||||
sourceBuffer.appendBuffer(mediaData);
|
||||
test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_false(sourceBuffer.updating, "updating");
|
||||
mediaSource.endOfStream();
|
||||
assert_less_than(mediaSource.duration, 10, "duration");
|
||||
startTime = window.performance.now();
|
||||
mediaElement.play().catch(test.unreached_func("Unexpected promise rejection"));
|
||||
test.expectEvent(mediaElement, 'ended', 'mediaElement');
|
||||
});
|
||||
|
||||
test.waitForExpectedEvents(function()
|
||||
{
|
||||
assert_greater_than(timeUpdateCount, 2, "timeUpdateCount");
|
||||
test.done();
|
||||
});
|
||||
}, "Test the totalFrameDelay attribute of HTMLVideoElement.getVideoPlaybackQuality() with MediaSource API");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -19,24 +19,24 @@
|
|||
assertInitialHistoryState();
|
||||
await runTestInPortal(portalSrc, 'testIFrameSrcInPortal');
|
||||
assertInitialHistoryState();
|
||||
}, 'Setting iframe src navigates independently in a portal');
|
||||
}, 'Setting iframe src navigates independently with replacement in a portal');
|
||||
|
||||
promise_test(async () => {
|
||||
assertInitialHistoryState();
|
||||
await runTestInPortal(portalSrc, 'testCrossSiteIFrameSrcInPortal');
|
||||
assertInitialHistoryState();
|
||||
}, 'Setting cross site iframe src navigates independently in a portal');
|
||||
}, 'Setting cross site iframe src navigates independently with replacement in a portal');
|
||||
|
||||
promise_test(async () => {
|
||||
assertInitialHistoryState();
|
||||
await runTestInPortal(portalSrc, 'testIFrameNavInPortal');
|
||||
assertInitialHistoryState();
|
||||
}, 'iframe navigates itself independently in a portal');
|
||||
}, 'iframe navigates itself independently with replacement in a portal');
|
||||
|
||||
promise_test(async () => {
|
||||
assertInitialHistoryState();
|
||||
await runTestInPortal(portalSrc, 'testCrossSiteIFrameNavInPortal');
|
||||
assertInitialHistoryState();
|
||||
}, 'Cross site iframe navigates itself independently in a portal');
|
||||
}, 'Cross site iframe navigates itself independently with replacement in a portal');
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
assertInitialHistoryState();
|
||||
await runTestInPortal(portalSrc, 'testHistoryPushStateInPortal');
|
||||
assertInitialHistoryState();
|
||||
}, 'history.pushState navigates independently in a portal');
|
||||
}, 'history.pushState navigates independently with replacement in a portal');
|
||||
|
||||
promise_test(async () => {
|
||||
assertInitialHistoryState();
|
||||
|
@ -31,7 +31,7 @@
|
|||
assertInitialHistoryState();
|
||||
await runTestInPortal(portalSrc, 'testLocationAssignInPortal');
|
||||
assertInitialHistoryState();
|
||||
}, 'location.assign navigates independently in a portal');
|
||||
}, 'location.assign navigates independently with replacement in a portal');
|
||||
|
||||
promise_test(async () => {
|
||||
assertInitialHistoryState();
|
||||
|
@ -43,12 +43,12 @@
|
|||
assertInitialHistoryState();
|
||||
await runTestInPortal(portalSrc, 'testSetLocationHrefInPortal');
|
||||
assertInitialHistoryState();
|
||||
}, 'Setting location.href navigates independently in a portal');
|
||||
}, 'Setting location.href navigates independently with replacement in a portal');
|
||||
|
||||
promise_test(async () => {
|
||||
assertInitialHistoryState();
|
||||
await runTestInPortal(portalSrc, 'testSyntheticAnchorClickInPortal');
|
||||
assertInitialHistoryState();
|
||||
}, 'Synthetic anchor click navigates independently in a portal');
|
||||
}, 'Synthetic anchor click navigates independently with replacement in a portal');
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -37,10 +37,10 @@
|
|||
frameHistoryLength =
|
||||
await messageFrameAndAwaitResponse(iframe, 'reportHistoryLength');
|
||||
assert(
|
||||
history.length == 2, 'History length changed when iframe src set');
|
||||
history.length == 1, 'History length unchanged when iframe src set');
|
||||
assert(
|
||||
frameHistoryLength == 2,
|
||||
'History length in iframe changed when iframe src set');
|
||||
frameHistoryLength == 1,
|
||||
'History length in iframe unchanged when iframe src set');
|
||||
}
|
||||
|
||||
function testIFrameSrcInPortal() {
|
||||
|
@ -66,10 +66,10 @@
|
|||
let frameHistoryLength =
|
||||
await messageFrameAndAwaitResponse(iframe, 'reportHistoryLength');
|
||||
assert(
|
||||
history.length == 2, 'History length changed when iframe navigates');
|
||||
history.length == 1, 'History length unchanged when iframe navigates');
|
||||
assert(
|
||||
frameHistoryLength == 2,
|
||||
'History length in iframe changed when iframe navigates');
|
||||
frameHistoryLength == 1,
|
||||
'History length in iframe unchanged when iframe navigates');
|
||||
}
|
||||
|
||||
function testIFrameNavInPortal() {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
history.pushState('teststate', null, null);
|
||||
|
||||
assert(history.length == 2, 'History length changed');
|
||||
assert(history.length == 1, 'History length unchanged');
|
||||
assert(history.state == 'teststate', 'Update state');
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
|||
let initialLocation = location.href;
|
||||
location.assign('#test');
|
||||
|
||||
assert(history.length == 2, 'History length changed');
|
||||
assert(history.length == 1, 'History length unchanged');
|
||||
assert(location.href != initialLocation, 'Update location');
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@
|
|||
let initialLocation = location.href;
|
||||
location.href = '#test';
|
||||
|
||||
assert(history.length == 2, 'History length changed');
|
||||
assert(history.length == 1, 'History length unchanged');
|
||||
assert(location.href != initialLocation, 'Update location');
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@
|
|||
|
||||
anchor.click();
|
||||
|
||||
assert(history.length == 2, 'History length changed');
|
||||
assert(history.length == 1, 'History length unchanged');
|
||||
assert(location.href != initialLocation, 'Update location');
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
Content-Type: text/css;charset=utf-8
|
||||
Cache-Control: max-age=3600
|
|
@ -0,0 +1,4 @@
|
|||
spec: https://wicg.github.io/ScrollToTextFragment/
|
||||
suggested_reviewers:
|
||||
- nburris
|
||||
- bokan
|
|
@ -0,0 +1,78 @@
|
|||
<!doctype html>
|
||||
<title>Navigating to a text fragment directive</title>
|
||||
<meta charset=utf-8>
|
||||
<link rel="help" href="https://wicg.github.io/ScrollToTextFragment/">
|
||||
<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="/common/utils.js"></script>
|
||||
<script src="stash.js"></script>
|
||||
<script>
|
||||
// Test security restriction for user activation
|
||||
for (let user_activation of [true, false]) {
|
||||
promise_test(t => new Promise((resolve, reject) => {
|
||||
let key = token();
|
||||
|
||||
if (user_activation) {
|
||||
test_driver.bless('Open a URL with a text fragment directive', () => {
|
||||
window.open(`scroll-to-text-fragment-target.html?key=${key}#:~:text=test`, '_blank', 'noopener');
|
||||
});
|
||||
} else {
|
||||
window.open(`scroll-to-text-fragment-target.html?key=${key}#:~:text=test`, '_blank', 'noopener');
|
||||
}
|
||||
|
||||
fetchResults(key, resolve, reject);
|
||||
}).then(data => {
|
||||
assert_equals(data.href.indexOf(':~:'), -1, 'Expected fragment directive to be stripped from the URL.');
|
||||
|
||||
if (user_activation) {
|
||||
assert_equals(data.scrollPosition, 'text', 'Expected window.open() with a user activation to scroll to text.');
|
||||
} else {
|
||||
assert_equals(data.scrollPosition, 'top', 'Expected window.open() with no user activation to not activate text fragment directive.');
|
||||
}
|
||||
}), `Test that a text fragment directive requires a user activation (user_activation=${user_activation}).`);
|
||||
}
|
||||
|
||||
// Test security restriction for no window opener
|
||||
for (let noopener of [true, false]) {
|
||||
promise_test(t => new Promise((resolve, reject) => {
|
||||
let key = token();
|
||||
|
||||
test_driver.bless('Open a URL with a text fragment directive', () => {
|
||||
if (noopener) {
|
||||
window.open(`scroll-to-text-fragment-target.html?key=${key}#:~:text=test`, '_blank', 'noopener');
|
||||
} else {
|
||||
window.open(`scroll-to-text-fragment-target.html?key=${key}#:~:text=test`, '_blank');
|
||||
}
|
||||
});
|
||||
|
||||
fetchResults(key, resolve, reject);
|
||||
}).then(data => {
|
||||
assert_equals(data.href.indexOf(':~:'), -1, 'Expected fragment directive to be stripped from the URL.');
|
||||
|
||||
if (noopener) {
|
||||
assert_equals(data.scrollPosition, 'text', 'Expected window.open() with noopener to scroll to text.');
|
||||
} else {
|
||||
assert_equals(data.scrollPosition, 'top', 'Expected window.open() with opener to not activate text fragment directive.');
|
||||
}
|
||||
}), `Test that a text fragment directive is not activated when there is a window opener (noopener=${noopener}).`);
|
||||
}
|
||||
|
||||
// Test security restriction for no activation in an iframe
|
||||
promise_test(t => new Promise((resolve, reject) => {
|
||||
let key = token();
|
||||
|
||||
let frame = document.createElement('iframe');
|
||||
document.body.appendChild(frame);
|
||||
|
||||
test_driver.bless('Navigate the iframe with a text fragment directive', () => {
|
||||
frame.src = `scroll-to-text-fragment-target.html?key=${key}#:~:text=test`;
|
||||
});
|
||||
|
||||
fetchResults(key, resolve, reject);
|
||||
}).then(data => {
|
||||
assert_equals(data.href.indexOf(':~:'), -1, 'Expected fragment directive to be stripped from the URL.');
|
||||
assert_equals(data.scrollPosition, 'top', 'Expected iframe navigation to not activate text fragment directive.');
|
||||
}), 'Test that a text fragment directive is not activated within an iframe.');
|
||||
</script>
|
|
@ -1,5 +1,6 @@
|
|||
<!doctype html>
|
||||
<title>Navigating to a text fragment anchor</title>
|
||||
<script src="stash.js"></script>
|
||||
<script>
|
||||
function isInView(element) {
|
||||
let rect = element.getBoundingClientRect();
|
||||
|
@ -8,8 +9,6 @@ function isInView(element) {
|
|||
}
|
||||
|
||||
function checkScroll() {
|
||||
let bc = new BroadcastChannel('scroll-to-text-fragment');
|
||||
|
||||
let position = 'unknown';
|
||||
if (window.scrollY == 0)
|
||||
position = 'top';
|
||||
|
@ -30,9 +29,10 @@ function checkScroll() {
|
|||
else if (isInView(document.getElementById('horizontal-scroll')) && window.scrollX > 0)
|
||||
position = 'horizontal-scroll';
|
||||
|
||||
bc.postMessage({ scrollPosition: position, href: window.location.href });
|
||||
bc.close();
|
||||
window.close();
|
||||
let results = { scrollPosition: position, href: window.location.href };
|
||||
|
||||
let key = (new URL(document.location)).searchParams.get("key");
|
||||
stashResults(key, results);
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
|
|
|
@ -7,6 +7,16 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/common/utils.js"></script>
|
||||
<script src="stash.js"></script>
|
||||
<!--
|
||||
This test suite performs scroll to text navigations to
|
||||
scroll-to-text-fragment-target.html and then checks the results, which are
|
||||
communicated back from the target page via the WPT Stash server (see stash.py).
|
||||
This structure is necessary because scroll to text security restrictions
|
||||
specifically restrict the navigator from being able to observe the result of
|
||||
the navigation, e.g. the target page cannot have a window opener.
|
||||
-->
|
||||
<script>
|
||||
let test_cases = [
|
||||
// Test non-text fragment directives
|
||||
|
@ -217,82 +227,18 @@ let test_cases = [
|
|||
];
|
||||
|
||||
for (const test_case of test_cases) {
|
||||
promise_test(t => new Promise(resolve => {
|
||||
let channel = new BroadcastChannel('scroll-to-text-fragment');
|
||||
channel.addEventListener("message", e => {
|
||||
resolve(e.data);
|
||||
}, {once: true});
|
||||
promise_test(t => new Promise((resolve, reject) => {
|
||||
let key = token();
|
||||
|
||||
test_driver.bless('Open a URL with a text fragment directive', () => {
|
||||
window.open('scroll-to-text-fragment-target.html' + test_case.fragment, '_blank', 'noopener');
|
||||
window.open(`scroll-to-text-fragment-target.html?key=${key}${test_case.fragment}`, '_blank', 'noopener');
|
||||
});
|
||||
|
||||
fetchResults(key, resolve, reject);
|
||||
}).then(data => {
|
||||
assert_equals(data.href.indexOf(':~:'), -1, 'Expected fragment directive to be stripped from the URL.');
|
||||
assert_equals(data.scrollPosition, test_case.expect_position,
|
||||
`Expected ${test_case.fragment} (${test_case.description}) to scroll to ${test_case.expect_position}.`);
|
||||
}), `Test navigation with fragment: ${test_case.description}.`);
|
||||
}
|
||||
|
||||
promise_test(t => new Promise(resolve => {
|
||||
let channel = new BroadcastChannel('scroll-to-text-fragment');
|
||||
channel.addEventListener("message", e => {
|
||||
assert_equals(e.data.href.indexOf(':~:'), -1, 'Expected fragment directive to be stripped from the URL.');
|
||||
|
||||
// The first navigation has no user activation.
|
||||
assert_equals(e.data.scrollPosition, 'top', 'Expected window.open() with no user activation to not activate text fragment directive.');
|
||||
|
||||
// Now ensure that a navigation with a user activation does activate the text fragment directive.
|
||||
test_driver.bless('Open a URL with a text fragment directive', () => {
|
||||
window.open('scroll-to-text-fragment-target.html#:~:text=test', '_blank', 'noopener');
|
||||
});
|
||||
channel.addEventListener("message", e => {
|
||||
resolve(e.data.scrollPosition);
|
||||
}, {once: true});
|
||||
}, {once: true});
|
||||
|
||||
window.open('scroll-to-text-fragment-target.html#:~:text=test', '_blank', 'noopener');
|
||||
}).then(scrollPosition => {
|
||||
assert_equals(scrollPosition, 'text', 'Expected window.open() with a user activation to scroll to text.');
|
||||
}), 'Test that a text fragment directive is not activated without a user activation');
|
||||
|
||||
promise_test(t => new Promise(resolve => {
|
||||
let channel = new BroadcastChannel('scroll-to-text-fragment');
|
||||
channel.addEventListener("message", e => {
|
||||
assert_equals(e.data.href.indexOf(':~:'), -1, 'Expected fragment directive to be stripped from the URL.');
|
||||
|
||||
// The first navigation has an opener.
|
||||
assert_equals(e.data.scrollPosition, 'top', 'Expected window.open() with opener to not activate text fragment directive.');
|
||||
|
||||
// Now ensure that a navigation with noopener does activate the text fragment directive.
|
||||
test_driver.bless('Open a URL with a text fragment directive', () => {
|
||||
window.open('scroll-to-text-fragment-target.html#:~:text=test', '_blank', 'noopener');
|
||||
});
|
||||
channel.addEventListener("message", e => {
|
||||
resolve(e.data.scrollPosition);
|
||||
}, {once: true});
|
||||
}, {once: true});
|
||||
|
||||
test_driver.bless('Open a URL with a text fragment directive', () => {
|
||||
window.open('scroll-to-text-fragment-target.html#:~:text=test', '_blank');
|
||||
});
|
||||
}).then(scrollPosition => {
|
||||
assert_equals(scrollPosition, 'text', 'Expected window.open() with noopener to scroll to text.');
|
||||
}), 'Test that a text fragment directive is not activated when there is a window opener.');
|
||||
|
||||
promise_test(t => new Promise(resolve => {
|
||||
let channel = new BroadcastChannel('scroll-to-text-fragment');
|
||||
channel.addEventListener("message", e => {
|
||||
resolve(e.data);
|
||||
}, {once: true});
|
||||
|
||||
let frame = document.createElement('iframe');
|
||||
document.body.appendChild(frame);
|
||||
|
||||
test_driver.bless('Navigate the iframe with a text fragment directive', () => {
|
||||
frame.src = 'scroll-to-text-fragment-target.html#:~:text=test';
|
||||
});
|
||||
}).then(data => {
|
||||
assert_equals(data.href.indexOf(':~:'), -1, 'Expected fragment directive to be stripped from the URL.');
|
||||
assert_equals(data.scrollPosition, 'top', 'Expected iframe navigation to not activate text fragment directive.');
|
||||
}), 'Test that a text fragment directive is not activated within an iframe.');
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// Put test results into Stash
|
||||
function stashResults(key, results) {
|
||||
fetch(`/scroll-to-text-fragment/stash.py?key=${key}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(results)
|
||||
});
|
||||
}
|
||||
|
||||
// Fetch test results from the Stash
|
||||
function fetchResults(key, resolve, reject) {
|
||||
fetch(`/scroll-to-text-fragment/stash.py?key=${key}`).then(response => {
|
||||
return response.text();
|
||||
}).then(text => {
|
||||
if (text) {
|
||||
try {
|
||||
const results = JSON.parse(text);
|
||||
resolve(results);
|
||||
} catch(e) {
|
||||
reject();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import time
|
||||
|
||||
def main(request, response):
|
||||
key = request.GET.first("key")
|
||||
|
||||
if request.method == "POST":
|
||||
# Received result data from target page
|
||||
request.server.stash.put(key, request.body, '/scroll-to-text-fragment/')
|
||||
return "ok"
|
||||
else:
|
||||
# Request for result data from test page
|
||||
value = request.server.stash.take(key, '/scroll-to-text-fragment/')
|
||||
# Poll until data is stashed
|
||||
while value is None:
|
||||
time.sleep(.1)
|
||||
value = request.server.stash.take(key, '/scroll-to-text-fragment/')
|
||||
return value
|
|
@ -188,3 +188,13 @@ for (const preventCancel of [true, false]) {
|
|||
|
||||
}, `an undefined rejection from write should cause pipeTo() to reject when preventCancel is ${preventCancel}`);
|
||||
}
|
||||
|
||||
promise_test(t => {
|
||||
const rs = new ReadableStream();
|
||||
const ws = new WritableStream();
|
||||
return promise_rejects(t, new TypeError(), rs.pipeTo(ws, {
|
||||
get preventAbort() {
|
||||
ws.getWriter();
|
||||
}
|
||||
}), 'pipeTo should reject');
|
||||
}, 'pipeTo() should reject if an option getter grabs a writer');
|
||||
|
|
|
@ -253,3 +253,14 @@ promise_test(() => {
|
|||
assert_array_equals(writable.events, [], 'writable should not be aborted');
|
||||
});
|
||||
}, 'preventAbort should work');
|
||||
|
||||
test(() => {
|
||||
const rs = new ReadableStream();
|
||||
const readable = new ReadableStream();
|
||||
const writable = new WritableStream();
|
||||
assert_throws(new TypeError(), () => rs.pipeThrough({readable, writable}, {
|
||||
get preventAbort() {
|
||||
writable.getWriter();
|
||||
}
|
||||
}), 'pipeThrough should throw');
|
||||
}, 'pipeThrough() should throw if an option getter grabs a writer');
|
||||
|
|
|
@ -11,7 +11,6 @@ steps:
|
|||
- template: pip_install.yml
|
||||
parameters:
|
||||
packages: virtualenv
|
||||
- template: install_fonts.yml
|
||||
- template: install_certs.yml
|
||||
- template: install_safari.yml
|
||||
- template: update_hosts.yml
|
||||
|
|
|
@ -9,7 +9,8 @@ import subprocess
|
|||
import sys
|
||||
|
||||
browser_specific_args = {
|
||||
"firefox": ["--install-browser"]
|
||||
"firefox": ["--install-browser"],
|
||||
"servo": ["--install-browser", "--processes=12"]
|
||||
}
|
||||
|
||||
|
||||
|
@ -67,6 +68,10 @@ def main(product, commit_range, wpt_args):
|
|||
]
|
||||
wpt_args += browser_specific_args.get(product, [])
|
||||
|
||||
# Hack to run servo with one process only for wdspec
|
||||
if product == "servo" and "--test-type=wdspec" in wpt_args:
|
||||
wpt_args = [item for item in wpt_args if not item.startswith("--processes")]
|
||||
|
||||
command = ["python", "./wpt", "run"] + wpt_args + [product]
|
||||
|
||||
logger.info("Executing command: %s" % " ".join(command))
|
||||
|
|
|
@ -4,7 +4,7 @@ components:
|
|||
workerType: ci
|
||||
schedulerId: taskcluster-github
|
||||
deadline: "24 hours"
|
||||
image: harjgam/web-platform-tests:0.33
|
||||
image: harjgam/web-platform-tests:0.34
|
||||
maxRunTime: 7200
|
||||
artifacts:
|
||||
public/results:
|
||||
|
|
|
@ -15,8 +15,11 @@ RUN apt-get -qqy update \
|
|||
fluxbox \
|
||||
gdebi \
|
||||
git \
|
||||
gstreamer1.0-plugins-bad \
|
||||
libosmesa6-dev \
|
||||
libvirt-daemon-system \
|
||||
libvirt-clients \
|
||||
libunwind8 \
|
||||
locales \
|
||||
openjdk-8-jre-headless \
|
||||
pulseaudio \
|
||||
|
|
|
@ -484,10 +484,6 @@ def check_parsed(repo_root, path, f):
|
|||
if len(testharnessreport_nodes) > 1:
|
||||
errors.append(rules.MultipleTestharnessReport.error(path))
|
||||
|
||||
testharnesscss_nodes = source_file.root.findall(".//{http://www.w3.org/1999/xhtml}link[@href='/resources/testharness.css']")
|
||||
if testharnesscss_nodes:
|
||||
errors.append(rules.PresentTestharnessCSS.error(path))
|
||||
|
||||
for element in source_file.variant_nodes:
|
||||
if "content" not in element.attrib:
|
||||
errors.append(rules.VariantMissing.error(path))
|
||||
|
|
|
@ -199,11 +199,6 @@ class MultipleTestharnessReport(Rule):
|
|||
description = "More than one `<script src='/resources/testharnessreport.js'>`"
|
||||
|
||||
|
||||
class PresentTestharnessCSS(Rule):
|
||||
name = "PRESENT-TESTHARNESSCSS"
|
||||
description = "Explicit link to testharness.css present"
|
||||
|
||||
|
||||
class VariantMissing(Rule):
|
||||
name = "VARIANT-MISSING"
|
||||
description = collapse("""
|
||||
|
|
|
@ -410,29 +410,6 @@ def test_missing_testdriver_vendor():
|
|||
]
|
||||
|
||||
|
||||
def test_present_testharnesscss():
|
||||
code = b"""
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css"/>
|
||||
</html>
|
||||
"""
|
||||
error_map = check_with_files(code)
|
||||
|
||||
for (filename, (errors, kind)) in error_map.items():
|
||||
check_errors(errors)
|
||||
|
||||
if kind in ["web-lax", "web-strict"]:
|
||||
assert errors == [
|
||||
("PRESENT-TESTHARNESSCSS", "Explicit link to testharness.css present", filename, None),
|
||||
]
|
||||
elif kind == "python":
|
||||
assert errors == [
|
||||
("PARSE-FAILED", "Unable to parse file", filename, 2),
|
||||
]
|
||||
|
||||
|
||||
def test_testharness_path():
|
||||
code = b"""\
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
|
|
@ -46,6 +46,7 @@ def executor_kwargs(test_type, server_config, cache_manager, run_info_data,
|
|||
rv["pause_after_test"] = kwargs["pause_after_test"]
|
||||
if test_type == "wdspec":
|
||||
rv["capabilities"] = {}
|
||||
rv["webdriver_binary"] = kwargs["binary"]
|
||||
return rv
|
||||
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ class TimedRunner(object):
|
|||
executor = threading.Thread(target=self.run_func)
|
||||
executor.start()
|
||||
|
||||
# Add twice the timeout multiplier since the called function is expected to
|
||||
# Add twice the extra timeout since the called function is expected to
|
||||
# wait at least self.timeout + self.extra_timeout and this gives some leeway
|
||||
timeout = self.timeout + 2 * self.extra_timeout if self.timeout else None
|
||||
finished = self.result_flag.wait(timeout)
|
||||
|
@ -654,6 +654,8 @@ class CallbackHandler(object):
|
|||
WebDriver. Things that are more different to WebDriver may need to create a
|
||||
fully custom implementation."""
|
||||
|
||||
unimplemented_exc = (NotImplementedError,)
|
||||
|
||||
def __init__(self, logger, protocol, test_window):
|
||||
self.protocol = protocol
|
||||
self.test_window = test_window
|
||||
|
@ -700,6 +702,9 @@ class CallbackHandler(object):
|
|||
raise ValueError("Unknown action %s" % action)
|
||||
try:
|
||||
result = action_handler(payload)
|
||||
except self.unimplemented_exc:
|
||||
self.logger.warning("Action %s not implemented" % action)
|
||||
self._send_message("complete", "error", "Action %s not implemented" % action)
|
||||
except Exception:
|
||||
self.logger.warning("Action %s failed" % action)
|
||||
self.logger.warning(traceback.format_exc())
|
||||
|
|
|
@ -31,7 +31,10 @@ from .protocol import (ActionSequenceProtocolPart,
|
|||
ClickProtocolPart,
|
||||
SendKeysProtocolPart,
|
||||
TestDriverProtocolPart,
|
||||
CoverageProtocolPart)
|
||||
CoverageProtocolPart,
|
||||
GenerateTestReportProtocolPart,
|
||||
VirtualAuthenticatorProtocolPart,
|
||||
SetPermissionProtocolPart)
|
||||
from ..testrunner import Stop
|
||||
from ..webdriver_server import GeckoDriverServer
|
||||
|
||||
|
@ -481,6 +484,44 @@ class MarionetteCoverageProtocolPart(CoverageProtocolPart):
|
|||
# This usually happens if the process crashed
|
||||
pass
|
||||
|
||||
class MarionetteGenerateTestReportProtocolPart(GenerateTestReportProtocolPart):
|
||||
def setup(self):
|
||||
self.marionette = self.parent.marionette
|
||||
|
||||
def generate_test_report(self, config):
|
||||
raise NotImplementedError("generate_test_report not yet implemented")
|
||||
|
||||
class MarionetteVirtualAuthenticatorProtocolPart(VirtualAuthenticatorProtocolPart):
|
||||
def setup(self):
|
||||
self.marionette = self.parent.marionette
|
||||
|
||||
def add_virtual_authenticator(self, config):
|
||||
raise NotImplementedError("add_virtual_authenticator not yet implemented")
|
||||
|
||||
def remove_virtual_authenticator(self, authenticator_id):
|
||||
raise NotImplementedError("remove_virtual_authenticator not yet implemented")
|
||||
|
||||
def add_credential(self, authenticator_id, credential):
|
||||
raise NotImplementedError("add_credential not yet implemented")
|
||||
|
||||
def get_credentials(self, authenticator_id):
|
||||
raise NotImplementedError("get_credentials not yet implemented")
|
||||
|
||||
def remove_credential(self, authenticator_id, credential_id):
|
||||
raise NotImplementedError("remove_credential not yet implemented")
|
||||
|
||||
def remove_all_credentials(self, authenticator_id):
|
||||
raise NotImplementedError("remove_all_credentials not yet implemented")
|
||||
|
||||
def set_user_verified(self, authenticator_id, uv):
|
||||
raise NotImplementedError("set_user_verified not yet implemented")
|
||||
|
||||
class MarionetteSetPermissionProtocolPart(SetPermissionProtocolPart):
|
||||
def setup(self):
|
||||
self.marionette = self.parent.marionette
|
||||
|
||||
def set_permission(self, name, state, one_realm):
|
||||
raise NotImplementedError("set_permission not yet implemented")
|
||||
|
||||
class MarionetteProtocol(Protocol):
|
||||
implements = [MarionetteBaseProtocolPart,
|
||||
|
@ -493,7 +534,10 @@ class MarionetteProtocol(Protocol):
|
|||
MarionetteActionSequenceProtocolPart,
|
||||
MarionetteTestDriverProtocolPart,
|
||||
MarionetteAssertsProtocolPart,
|
||||
MarionetteCoverageProtocolPart]
|
||||
MarionetteCoverageProtocolPart,
|
||||
MarionetteGenerateTestReportProtocolPart,
|
||||
MarionetteVirtualAuthenticatorProtocolPart,
|
||||
MarionetteSetPermissionProtocolPart]
|
||||
|
||||
def __init__(self, executor, browser, capabilities=None, timeout_multiplier=1, e10s=True, ccov=False):
|
||||
do_delayed_imports()
|
||||
|
|
|
@ -31,6 +31,10 @@ import webdriver as client
|
|||
here = os.path.join(os.path.split(__file__)[0])
|
||||
|
||||
|
||||
class WebDriverCallbackHandler(CallbackHandler):
|
||||
unimplemented_exc = (NotImplementedError, client.UnknownCommandException)
|
||||
|
||||
|
||||
class WebDriverBaseProtocolPart(BaseProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
@ -376,7 +380,7 @@ class WebDriverTestharnessExecutor(TestharnessExecutor):
|
|||
parent_window,
|
||||
timeout=5*self.timeout_multiplier)
|
||||
self.protocol.base.set_window(test_window)
|
||||
handler = CallbackHandler(self.logger, protocol, test_window)
|
||||
handler = WebDriverCallbackHandler(self.logger, protocol, test_window)
|
||||
protocol.webdriver.url = url
|
||||
|
||||
if not self.supports_eager_pageload:
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
result = JSON.parse(data.message).result
|
||||
pending_resolve(result);
|
||||
} else {
|
||||
pending_reject();
|
||||
pending_reject(`${data.status}: ${data.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue