mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
Tests/LibWeb: Import some CSSOM WPT tests
This commit is contained in:
parent
13b7c26e9f
commit
d0646236ca
Notes:
github-actions[bot]
2024-11-13 10:08:08 +00:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/d0646236ca6 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2305
52 changed files with 2005 additions and 0 deletions
|
@ -0,0 +1,12 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
2 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Element getClientRects()
|
||||||
|
Pass Range getClientRects()
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass getBoundingClientRect
|
|
@ -0,0 +1,17 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 6 tests
|
||||||
|
|
||||||
|
3 Pass
|
||||||
|
3 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail calls handleEvent method of event listener
|
||||||
|
Pass looks up handleEvent method on every event dispatch
|
||||||
|
Pass doesn't look up handleEvent method on callable event listeners
|
||||||
|
Pass rethrows errors when getting handleEvent
|
||||||
|
Fail throws if handleEvent is falsy and not callable
|
||||||
|
Fail throws if handleEvent is thruthy and not callable
|
|
@ -0,0 +1,19 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 8 tests
|
||||||
|
|
||||||
|
7 Pass
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass EventListener parameter is optional
|
||||||
|
Fail listeners are called when <iframe> is resized
|
||||||
|
Pass listeners are called correct number of times
|
||||||
|
Pass listeners are called in order they were added
|
||||||
|
Pass listener that was added twice is called only once
|
||||||
|
Pass listeners are called in order their MQLs were created
|
||||||
|
Pass removing listener from one MQL doesn't remove it from all MQLs
|
||||||
|
Pass MediaQueryList::removeListener removes added listener
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail MediaQueryList.changed is correct for all lists in the document even during a change event handler
|
|
@ -0,0 +1,18 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 8 tests
|
||||||
|
|
||||||
|
8 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass dispatchEvent triggers listener added with addListener
|
||||||
|
Pass listener added with addListener and addEventListener is called once
|
||||||
|
Pass listener added with addListener and addEventListener (capture) is called twice
|
||||||
|
Pass removeEventListener removes listener added with addListener
|
||||||
|
Pass removeEventListener (capture) doesn't remove listener added with addListener
|
||||||
|
Pass removeListener removes listener added with addEventListener
|
||||||
|
Pass removeListener doesn't remove listener added with addEventListener (capture)
|
||||||
|
Pass capturing event listener fires before non-capturing listener at target
|
|
@ -0,0 +1,18 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 7 tests
|
||||||
|
|
||||||
|
6 Pass
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail onchange adds listener
|
||||||
|
Pass onchange removes listener
|
||||||
|
Pass listeners for "change" type are called
|
||||||
|
Pass listeners with different type are not called
|
||||||
|
Pass addEventListener "once" option is respected
|
||||||
|
Pass removeEventListener removes listener
|
||||||
|
Pass dispatchEvent works as expected
|
|
@ -0,0 +1,17 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 6 tests
|
||||||
|
|
||||||
|
3 Pass
|
||||||
|
3 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass type can be different from "change"
|
||||||
|
Pass init dictionary default values
|
||||||
|
Pass init dictionary overrides
|
||||||
|
Fail argument of addListener
|
||||||
|
Fail argument of onchange
|
||||||
|
Fail constructor of "change" event
|
|
@ -0,0 +1,12 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
2 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass getBoundingClientRect() should return a DOMRect where height=bottom-top
|
||||||
|
Pass getBoundingClientRect() should return a DOMRect where width=right-left
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass getBoundingClientRect on a newly-created Element not yet inserted into the DOM should return an all-zeroes DOMRect
|
|
@ -0,0 +1,12 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
2 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail {Element,Range}.prototype.getBoundingClientRect on SVG <tspan>, Element
|
||||||
|
Fail {Element,Range}.prototype.getBoundingClientRect on SVG <tspan>, Range
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass CSSOM View - GetClientRects().length is the same regardless source new lines
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass getClientRects on a newly-created Element not yet inserted into the DOM should return an empty DOMRectList
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail CSSOM View - 5 - extensions to the Document interface
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Checking whether dynamic changes to visibility interact correctly with table anonymous boxes
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Checking whether dynamic changes to visibility interact correctly with table anonymous boxes
|
|
@ -0,0 +1,14 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 4 tests
|
||||||
|
|
||||||
|
4 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass simple scroll with style: 'margin' and 'overflow: scroll'
|
||||||
|
Pass simple scroll with style: 'margin' and 'overflow: hidden'
|
||||||
|
Pass simple scroll with style: 'padding' and 'overflow: scroll'
|
||||||
|
Pass simple scroll with style: 'padding' and 'overflow: hidden'
|
|
@ -0,0 +1,18 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 8 tests
|
||||||
|
|
||||||
|
8 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Element scrollTop/Left getter/setter test
|
||||||
|
Pass Element scroll test (two arguments)
|
||||||
|
Pass Element scroll test (one argument)
|
||||||
|
Pass Element scrollTo test (two arguments)
|
||||||
|
Pass Element scrollTo test (one argument)
|
||||||
|
Pass Element scrollBy test (two arguments)
|
||||||
|
Pass Element scrollBy test (one argument)
|
||||||
|
Pass Element scroll maximum test
|
|
@ -0,0 +1,17 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 6 tests
|
||||||
|
|
||||||
|
2 Pass
|
||||||
|
4 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail elementsFromPoint for each corner of a simple div
|
||||||
|
Fail elementsFromPoint for each corner of a div that has a pseudo-element
|
||||||
|
Fail elementsFromPoint for each corner of a div that is between another div and its pseudo-element
|
||||||
|
Fail elementsFromPoint for each corner of a div that has a margin
|
||||||
|
Pass elementsFromPoint for each corner of a div with pointer-events:none
|
||||||
|
Pass elementsFromPoint for each corner of a div with a 3d transform
|
|
@ -0,0 +1,39 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 28 tests
|
||||||
|
|
||||||
|
25 Pass
|
||||||
|
3 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass container: 0
|
||||||
|
Fail container: 1
|
||||||
|
Pass container: 2
|
||||||
|
Pass container: 3
|
||||||
|
Pass container: 4
|
||||||
|
Fail container: 5
|
||||||
|
Pass container: 6
|
||||||
|
Pass container: 7
|
||||||
|
Pass container: 8
|
||||||
|
Pass container: 9
|
||||||
|
Pass container: 10
|
||||||
|
Pass container: 11
|
||||||
|
Pass container: 12
|
||||||
|
Pass container: 13
|
||||||
|
Pass container: 14
|
||||||
|
Pass container: 15
|
||||||
|
Pass container: 16
|
||||||
|
Pass container: 17
|
||||||
|
Pass container: 18
|
||||||
|
Pass container: 19
|
||||||
|
Pass container: 20
|
||||||
|
Pass container: 21
|
||||||
|
Pass container: 22
|
||||||
|
Pass container: 23
|
||||||
|
Pass container: 24
|
||||||
|
Fail container: 25
|
||||||
|
Pass container: 26
|
||||||
|
Pass container: 27
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass resize events are not fired on the initial layout
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass resize events are not fired on the initial layout
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass scrolling an element with no CSS layout box should have no effect
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass CSSOM scrollingElement reflects the propagated scroll to viewport correctly
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass CSSOM scrollingElement reflects the propagated scroll to viewport correctly
|
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>CSSOM View APIs that return a DOMRectList</title>
|
||||||
|
<script src=../../resources/testharness.js></script>
|
||||||
|
<script src=../../resources/testharnessreport.js></script>
|
||||||
|
<div id=x>x</div>
|
||||||
|
<script>
|
||||||
|
setup(() => {
|
||||||
|
window.element = document.getElementById('x');
|
||||||
|
});
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const domRectList = element.getClientRects();
|
||||||
|
assert_class_string(domRectList, 'DOMRectList');
|
||||||
|
assert_class_string(domRectList.item(0), 'DOMRect');
|
||||||
|
}, 'Element getClientRects()');
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const range = new Range();
|
||||||
|
range.selectNodeContents(element);
|
||||||
|
const domRectList = range.getClientRects();
|
||||||
|
assert_class_string(domRectList, 'DOMRectList');
|
||||||
|
assert_class_string(domRectList.item(0), 'DOMRect');
|
||||||
|
}, 'Range getClientRects()');
|
||||||
|
</script>
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>getBoundingClientRect</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-getboundingclientrect">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#foo {
|
||||||
|
margin: 0px 0px 0px 5px;
|
||||||
|
transform: translate(10px, 200px);
|
||||||
|
position: fixed;
|
||||||
|
left: 5px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="foo">
|
||||||
|
FOO
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
test(function () {
|
||||||
|
var foo = document.getElementById("foo").getBoundingClientRect();
|
||||||
|
assert_equals(foo.left, 20);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,118 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="flags" content="dom">
|
||||||
|
<title>CSS Test: CSSOM View MediaQueryList::addListener with handleEvent</title>
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#callbackdef-eventlistener">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="resources/matchMedia.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
setup({ allow_uncaught_exception: true });
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let _this;
|
||||||
|
let _event;
|
||||||
|
const listener = {
|
||||||
|
handleEvent(event) {
|
||||||
|
_this = this;
|
||||||
|
_event = event;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mql.addListener(listener);
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
|
||||||
|
assert_equals(_this, listener);
|
||||||
|
assert_equals(_event.media, mql.media);
|
||||||
|
assert_equals(_event.matches, mql.matches);
|
||||||
|
}, "calls handleEvent method of event listener");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
mql.addListener({
|
||||||
|
get handleEvent() {
|
||||||
|
calls++;
|
||||||
|
return function() {};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
assert_equals(calls, 0);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 1);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 2);
|
||||||
|
}, "looks up handleEvent method on every event dispatch");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
const listener = () => {
|
||||||
|
calls++;
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(listener, "handleEvent", {
|
||||||
|
get: t.unreached_func("handleEvent method should not be looked up on functions"),
|
||||||
|
});
|
||||||
|
mql.addListener(listener);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 1);
|
||||||
|
}, "doesn't look up handleEvent method on callable event listeners");
|
||||||
|
|
||||||
|
const uncaught_error_test = async (t, mql, getHandleEvent) => {
|
||||||
|
const eventWatcher = new EventWatcher(t, window, "error", waitForChangesReported);
|
||||||
|
const errorPromise = eventWatcher.wait_for("error");
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
const listener = {
|
||||||
|
get handleEvent() {
|
||||||
|
calls++;
|
||||||
|
return getHandleEvent();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
mql.addListener(listener);
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
|
||||||
|
const event = await errorPromise;
|
||||||
|
throw event.error;
|
||||||
|
} finally {
|
||||||
|
assert_equals(calls, 1, "handleEvent property was not looked up");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const error = { name: "test" };
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
return promise_rejects_exactly(t, error,
|
||||||
|
uncaught_error_test(t, mql, () => { throw error; }));
|
||||||
|
}, "rethrows errors when getting handleEvent");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
const global = getWindow(mql);
|
||||||
|
return promise_rejects_js(t, global.TypeError,
|
||||||
|
uncaught_error_test(t, mql, () => false));
|
||||||
|
}, "throws if handleEvent is falsy and not callable");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
const global = getWindow(mql);
|
||||||
|
return promise_rejects_js(t, global.TypeError,
|
||||||
|
uncaught_error_test(t, mql, () => "str"));
|
||||||
|
}, "throws if handleEvent is thruthy and not callable");
|
||||||
|
</script>
|
|
@ -0,0 +1,161 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="flags" content="dom">
|
||||||
|
<title>CSS Test: CSSOM View MediaQueryList::{add,remove}Listener</title>
|
||||||
|
<link rel="author" title="Rune Lillesveen" href="mailto:rune@opera.com">
|
||||||
|
<link rel="help" href="https://www.w3.org/TR/cssom-view-1/#the-mediaquerylist-interface">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="resources/matchMedia.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const mql = window.matchMedia("(min-width: 100px)");
|
||||||
|
|
||||||
|
mql.addListener(null);
|
||||||
|
mql.addListener(undefined);
|
||||||
|
|
||||||
|
mql.removeListener(null);
|
||||||
|
mql.removeListener(undefined);
|
||||||
|
}, "EventListener parameter is optional");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const iframe = await createIFrame(t, 200, 100);
|
||||||
|
const heightMQL = iframe.contentWindow.matchMedia("(max-height: 50px)");
|
||||||
|
const widthMQL = iframe.contentWindow.matchMedia("(min-width: 150px)");
|
||||||
|
|
||||||
|
let heightEvent;
|
||||||
|
let widthEvent;
|
||||||
|
|
||||||
|
heightMQL.addListener(event => {
|
||||||
|
heightEvent = event;
|
||||||
|
});
|
||||||
|
widthMQL.addListener(event => {
|
||||||
|
widthEvent = event;
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_false(heightMQL.matches);
|
||||||
|
assert_true(widthMQL.matches);
|
||||||
|
|
||||||
|
iframe.height = "50"; // 200x100 => 200x50
|
||||||
|
await waitForChangesReported();
|
||||||
|
|
||||||
|
assert_equals(heightEvent.media, heightMQL.media);
|
||||||
|
assert_true(heightEvent.matches);
|
||||||
|
assert_true(heightMQL.matches);
|
||||||
|
assert_true(widthMQL.matches);
|
||||||
|
|
||||||
|
iframe.width = "100"; // 200x50 => 100x50
|
||||||
|
await waitForChangesReported();
|
||||||
|
|
||||||
|
assert_equals(widthEvent.media, widthMQL.media);
|
||||||
|
assert_false(widthEvent.matches);
|
||||||
|
assert_false(widthMQL.matches);
|
||||||
|
assert_true(heightMQL.matches);
|
||||||
|
}, "listeners are called when <iframe> is resized");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let eventsCount = 0;
|
||||||
|
mql.addListener(() => {
|
||||||
|
eventsCount++;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let i = 1; i <= 10; i++) {
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(eventsCount, i);
|
||||||
|
}
|
||||||
|
}, "listeners are called correct number of times");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
const calls = [];
|
||||||
|
|
||||||
|
mql.addListener(() => {
|
||||||
|
calls.push("1st");
|
||||||
|
});
|
||||||
|
mql.addListener(() => {
|
||||||
|
calls.push("2nd");
|
||||||
|
});
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
|
||||||
|
assert_array_equals(calls, ["1st", "2nd"]);
|
||||||
|
}, "listeners are called in order they were added");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let called = 0;
|
||||||
|
const listener = () => {
|
||||||
|
called++;
|
||||||
|
};
|
||||||
|
|
||||||
|
mql.addListener(listener);
|
||||||
|
mql.addListener(listener);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
|
||||||
|
assert_equals(called, 1);
|
||||||
|
}, "listener that was added twice is called only once");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const iframe = await createIFrame(t, 100);
|
||||||
|
const media = `(min-width: 200px)`;
|
||||||
|
|
||||||
|
const mql1 = iframe.contentWindow.matchMedia(media);
|
||||||
|
const mql2 = iframe.contentWindow.matchMedia(media);
|
||||||
|
const calls = [];
|
||||||
|
|
||||||
|
mql2.addListener(() => {
|
||||||
|
calls.push("mql2");
|
||||||
|
});
|
||||||
|
|
||||||
|
mql1.addListener(() => {
|
||||||
|
calls.push("mql1");
|
||||||
|
});
|
||||||
|
|
||||||
|
iframe.width = "200"; // 100x100 => 200x100
|
||||||
|
await waitForChangesReported();
|
||||||
|
|
||||||
|
assert_array_equals(calls, ["mql1", "mql2"]);
|
||||||
|
}, "listeners are called in order their MQLs were created");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const iframe = await createIFrame(t, 200);
|
||||||
|
const media = `(max-height: 150px)`;
|
||||||
|
|
||||||
|
const mql1 = iframe.contentWindow.matchMedia(media);
|
||||||
|
const mql2 = iframe.contentWindow.matchMedia(media);
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
const listener = () => {
|
||||||
|
calls++;
|
||||||
|
};
|
||||||
|
|
||||||
|
mql1.addListener(listener);
|
||||||
|
mql2.removeListener(listener);
|
||||||
|
|
||||||
|
iframe.height = "50"; // 200x200 => 200x50
|
||||||
|
await waitForChangesReported();
|
||||||
|
|
||||||
|
assert_equals(calls, 1);
|
||||||
|
}, "removing listener from one MQL doesn't remove it from all MQLs");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
const listener = t.unreached_func("should not be called");
|
||||||
|
|
||||||
|
mql.addListener(listener);
|
||||||
|
mql.removeListener(listener);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
}, "MediaQueryList::removeListener removes added listener");
|
||||||
|
</script>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>MediaQueryList.changed is correct for all lists in the document even during a change event handler</title>
|
||||||
|
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||||
|
<link rel="author" href="https://mozilla.org" title="Mozilla">
|
||||||
|
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1648839">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#evaluate-media-queries-and-report-changes">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="resources/matchMedia.js"></script>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
promise_test(async t => {
|
||||||
|
// Create two identical media queries.
|
||||||
|
let mql = await createMQL(t);
|
||||||
|
let mql2 = getWindow(mql).matchMedia(mql.media);
|
||||||
|
|
||||||
|
let changeEvents = 0;
|
||||||
|
|
||||||
|
let check = t.step_func(function() {
|
||||||
|
changeEvents++;
|
||||||
|
assert_equals(mql.matches, mql2.matches, "Value of .matches should match"); // No pun intended
|
||||||
|
});
|
||||||
|
|
||||||
|
mql.addListener(check);
|
||||||
|
mql2.addListener(check);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
|
||||||
|
assert_equals(changeEvents, 2, "Should've fired the change event in both MediaQueryLists");
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,172 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="flags" content="dom">
|
||||||
|
<title>CSS Test: CSSOM View MediaQueryList extends EventTarget (interop)</title>
|
||||||
|
<link rel="help" href="https://www.w3.org/TR/cssom-view-1/#the-mediaquerylist-interface">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="resources/matchMedia.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const mql = window.matchMedia("all");
|
||||||
|
|
||||||
|
let receivedEvent;
|
||||||
|
mql.addListener(event => {
|
||||||
|
receivedEvent = event;
|
||||||
|
});
|
||||||
|
|
||||||
|
const dispatchedEvent = new Event("change");
|
||||||
|
mql.dispatchEvent(dispatchedEvent);
|
||||||
|
|
||||||
|
assert_equals(receivedEvent, dispatchedEvent);
|
||||||
|
}, "dispatchEvent triggers listener added with addListener");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
const listener = {
|
||||||
|
handleEvent() {
|
||||||
|
calls++;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mql.addListener(listener);
|
||||||
|
mql.addEventListener("change", listener);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 1, "triggerMQLEvent");
|
||||||
|
|
||||||
|
mql.dispatchEvent(new Event("change"));
|
||||||
|
assert_equals(calls, 2, "dispatchEvent");
|
||||||
|
}, "listener added with addListener and addEventListener is called once");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
const listener = () => {
|
||||||
|
calls++;
|
||||||
|
};
|
||||||
|
|
||||||
|
mql.addListener(listener);
|
||||||
|
mql.addEventListener("change", listener, true);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 2, "triggerMQLEvent");
|
||||||
|
|
||||||
|
mql.dispatchEvent(new Event("change"));
|
||||||
|
assert_equals(calls, 4, "dispatchEvent");
|
||||||
|
}, "listener added with addListener and addEventListener (capture) is called twice");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
const listener = {
|
||||||
|
handleEvent() {
|
||||||
|
calls++;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mql.addListener(listener);
|
||||||
|
mql.removeEventListener("change", listener);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 0, "triggerMQLEvent");
|
||||||
|
|
||||||
|
mql.dispatchEvent(new Event("change"));
|
||||||
|
assert_equals(calls, 0, "dispatchEvent");
|
||||||
|
}, "removeEventListener removes listener added with addListener");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
const listener = () => {
|
||||||
|
calls++;
|
||||||
|
};
|
||||||
|
|
||||||
|
mql.addListener(listener);
|
||||||
|
mql.removeEventListener("change", listener, true);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 1, "triggerMQLEvent");
|
||||||
|
|
||||||
|
mql.dispatchEvent(new Event("change"));
|
||||||
|
assert_equals(calls, 2, "dispatchEvent");
|
||||||
|
}, "removeEventListener (capture) doesn't remove listener added with addListener");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
const listener = {
|
||||||
|
handleEvent() {
|
||||||
|
calls++;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mql.addEventListener("change", listener);
|
||||||
|
mql.removeListener(listener);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 0, "triggerMQLEvent");
|
||||||
|
|
||||||
|
mql.dispatchEvent(new Event("change"));
|
||||||
|
assert_equals(calls, 0, "dispatchEvent");
|
||||||
|
}, "removeListener removes listener added with addEventListener");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
const listener = () => {
|
||||||
|
calls++;
|
||||||
|
};
|
||||||
|
|
||||||
|
mql.addEventListener("change", listener, true);
|
||||||
|
mql.removeListener(listener);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 1, "triggerMQLEvent");
|
||||||
|
|
||||||
|
mql.dispatchEvent(new Event("change"));
|
||||||
|
assert_equals(calls, 2, "dispatchEvent");
|
||||||
|
}, "removeListener doesn't remove listener added with addEventListener (capture)");
|
||||||
|
|
||||||
|
// See:
|
||||||
|
// * https://github.com/whatwg/dom/issues/746
|
||||||
|
// * https://bugzilla.mozilla.org/show_bug.cgi?id=1492446
|
||||||
|
// * https://bugs.chromium.org/p/chromium/issues/detail?id=949432
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let calls = [];
|
||||||
|
mql.addListener(() => {
|
||||||
|
calls.push("addListener");
|
||||||
|
});
|
||||||
|
mql.addEventListener("change", {
|
||||||
|
handleEvent() {
|
||||||
|
calls.push("addEventListener");
|
||||||
|
},
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_array_equals(calls, ["addEventListener", "addListener"], "triggerMQLEvent");
|
||||||
|
|
||||||
|
calls = [];
|
||||||
|
mql.dispatchEvent(new Event("change"));
|
||||||
|
assert_array_equals(calls, ["addEventListener", "addListener"], "dispatchEvent");
|
||||||
|
}, "capturing event listener fires before non-capturing listener at target");
|
||||||
|
</script>
|
|
@ -0,0 +1,118 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="flags" content="dom">
|
||||||
|
<title>CSS Test: CSSOM View MediaQueryList extends EventTarget</title>
|
||||||
|
<link rel="help" href="https://www.w3.org/TR/cssom-view-1/#the-mediaquerylist-interface">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="resources/matchMedia.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let _event;
|
||||||
|
mql.onchange = event => {
|
||||||
|
_event = event;
|
||||||
|
};
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(_event.media, mql.media);
|
||||||
|
assert_equals(_event.matches, mql.matches);
|
||||||
|
}, "onchange adds listener");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
mql.onchange = () => {
|
||||||
|
calls++;
|
||||||
|
};
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 1);
|
||||||
|
|
||||||
|
mql.onchange = null;
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 1);
|
||||||
|
}, "onchange removes listener");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
mql.addEventListener("change", {
|
||||||
|
handleEvent() {
|
||||||
|
calls++;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 1);
|
||||||
|
}, 'listeners for "change" type are called');
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
mql.addEventListener("matches", t.unreached_func("should not be called"));
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
}, 'listeners with different type are not called');
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let calls = 0;
|
||||||
|
mql.addEventListener("change", {
|
||||||
|
handleEvent() {
|
||||||
|
calls++;
|
||||||
|
},
|
||||||
|
}, {once: true});
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 1);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
assert_equals(calls, 1);
|
||||||
|
}, 'addEventListener "once" option is respected');
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
const listener = t.unreached_func("should not be called");
|
||||||
|
|
||||||
|
mql.addEventListener("change", listener);
|
||||||
|
mql.removeEventListener("change", listener);
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
}, "removeEventListener removes listener");
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const mql = window.matchMedia("all");
|
||||||
|
|
||||||
|
let receivedEvent;
|
||||||
|
mql.addEventListener("custom", event => {
|
||||||
|
receivedEvent = event;
|
||||||
|
event.preventDefault();
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
const dispatchedEvent = new CustomEvent("custom", {
|
||||||
|
cancelable: true,
|
||||||
|
detail: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultAction = mql.dispatchEvent(dispatchedEvent);
|
||||||
|
|
||||||
|
assert_equals(receivedEvent, dispatchedEvent);
|
||||||
|
assert_false(defaultAction);
|
||||||
|
}, "dispatchEvent works as expected");
|
||||||
|
</script>
|
|
@ -0,0 +1,90 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="flags" content="dom">
|
||||||
|
<title>CSS Test: CSSOM View MediaQueryListEvent</title>
|
||||||
|
<link rel="help" href="https://www.w3.org/TR/cssom-view-1/#mediaquerylistevent">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="resources/matchMedia.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
assert_equals(new MediaQueryListEvent("test").type, "test");
|
||||||
|
}, 'type can be different from "change"');
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const event = new MediaQueryListEvent("change");
|
||||||
|
|
||||||
|
assert_equals(event.media, "");
|
||||||
|
assert_false(event.matches);
|
||||||
|
assert_false(event.bubbles);
|
||||||
|
assert_false(event.cancelable);
|
||||||
|
}, "init dictionary default values");
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const event = new MediaQueryListEvent("change", {
|
||||||
|
media: "test",
|
||||||
|
matches: true,
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_equals(event.media, "test");
|
||||||
|
assert_true(event.matches);
|
||||||
|
assert_true(event.bubbles);
|
||||||
|
assert_true(event.cancelable);
|
||||||
|
}, "init dictionary overrides");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let _event;
|
||||||
|
mql.addListener(event => {
|
||||||
|
_event = event;
|
||||||
|
});
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
|
||||||
|
assert_true(_event instanceof getWindow(mql).MediaQueryListEvent);
|
||||||
|
assert_equals(_event.type, "change");
|
||||||
|
assert_false(_event.bubbles);
|
||||||
|
assert_false(_event.cancelable);
|
||||||
|
}, "argument of addListener");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let _event;
|
||||||
|
mql.onchange = event => {
|
||||||
|
_event = event;
|
||||||
|
};
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
|
||||||
|
assert_true(_event instanceof getWindow(mql).MediaQueryListEvent);
|
||||||
|
assert_equals(_event.type, "change");
|
||||||
|
assert_false(_event.bubbles);
|
||||||
|
assert_false(_event.cancelable);
|
||||||
|
}, "argument of onchange");
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
let _event;
|
||||||
|
mql.addEventListener("change", event => {
|
||||||
|
_event = event;
|
||||||
|
});
|
||||||
|
|
||||||
|
triggerMQLEvent(mql);
|
||||||
|
await waitForChangesReported();
|
||||||
|
|
||||||
|
assert_true(_event instanceof getWindow(mql).MediaQueryListEvent);
|
||||||
|
assert_equals(_event.type, "change");
|
||||||
|
assert_false(_event.bubbles);
|
||||||
|
assert_false(_event.cancelable);
|
||||||
|
}, 'constructor of "change" event');
|
||||||
|
</script>
|
|
@ -0,0 +1,41 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSSOM View - 6.1 - getBoundingClientRect tests</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="author" title="Chris Wu" href="mailto:pwx.frontend@gmail.com">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/cssom-view/#dom-element-getboundingclientrect">
|
||||||
|
<meta name="flags" content="dom">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<style type="text/css">
|
||||||
|
#testItem {
|
||||||
|
width: 279px;
|
||||||
|
height: 188px;
|
||||||
|
margin: 100px 0 0 178px;
|
||||||
|
background-color: purple;
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 188px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="testItem">test item</div>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
var titem = document.getElementById('testItem').getBoundingClientRect();
|
||||||
|
test(
|
||||||
|
function(){
|
||||||
|
assert_equals(titem.bottom - titem.top, titem.height, "height should equal bottom minus top")
|
||||||
|
}, "getBoundingClientRect() should return a DOMRect where height=bottom-top"
|
||||||
|
);
|
||||||
|
test(
|
||||||
|
function(){
|
||||||
|
assert_equals(titem.right - titem.left, titem.width, "width should equal right minus left")
|
||||||
|
}, "getBoundingClientRect() should return a DOMRect where width=right-left"
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Test (CSSOM View): getBoundingClientRect of element outside DOM</title>
|
||||||
|
<link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/cssom-view/#dom-element-getclientrects">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/cssom-view/#dom-element-getboundingclientrect">
|
||||||
|
<meta name="flags" content="dom">
|
||||||
|
<meta name="assert" content="Calling getBoundingClientRect on an element that is outside of the DOM (and therefore does not have an associated layout box) should result in an all-zeroes DOMRect and should definitely not throw an error.">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script>
|
||||||
|
test(
|
||||||
|
function () {
|
||||||
|
var rect = document.createElement('div').getBoundingClientRect();
|
||||||
|
assert_equals(rect.x, 0, "DOMRect's x should be zero");
|
||||||
|
assert_equals(rect.y, 0, "DOMRect's y should be zero");
|
||||||
|
assert_equals(rect.width, 0, "DOMRect's width should be zero");
|
||||||
|
assert_equals(rect.height, 0, "DOMRect's height should be zero");
|
||||||
|
},
|
||||||
|
"getBoundingClientRect on a newly-created Element not yet inserted into the DOM should return an all-zeroes DOMRect"
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>{Element,Range}.prototype.getBoundingClientRect on SVG <tspan></title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../../fonts/ahem.css">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-getboundingclientrect">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-range-getboundingclientrect">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<svg>
|
||||||
|
<text y="180" font-size="100" font-family="Ahem"
|
||||||
|
fill="lightblue">X<tspan fill="blue">XX</tspan></text>
|
||||||
|
</svg>
|
||||||
|
<script>
|
||||||
|
function check(object) {
|
||||||
|
let rect = object.getBoundingClientRect();
|
||||||
|
assert_equals(rect.left, 108, 'left');
|
||||||
|
assert_equals(rect.top, 108, 'top');
|
||||||
|
assert_equals(rect.width, 200, 'width');
|
||||||
|
assert_equals(rect.height, 100, 'height');
|
||||||
|
}
|
||||||
|
async_test(t => {
|
||||||
|
window.addEventListener("load", t.step_func_done(() => {
|
||||||
|
let tspan = document.querySelector('tspan');
|
||||||
|
check(tspan);
|
||||||
|
}));
|
||||||
|
}, document.title + ', Element');
|
||||||
|
async_test(t => {
|
||||||
|
window.addEventListener("load", t.step_func_done(() => {
|
||||||
|
let tspan = document.querySelector('tspan');
|
||||||
|
let range = new Range();
|
||||||
|
range.selectNode(tspan);
|
||||||
|
check(range);
|
||||||
|
}));
|
||||||
|
}, document.title + ', Range');
|
||||||
|
</script>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSSOM View - GetClientRects().length is the same regardless source new lines</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view-1/#dom-element-getclientrects">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<span id="single">
|
||||||
|
test test
|
||||||
|
</span><br/>
|
||||||
|
<span id="multiple">
|
||||||
|
test
|
||||||
|
test
|
||||||
|
</span>
|
||||||
|
<script>
|
||||||
|
test(function () {
|
||||||
|
const count = document.querySelector("#single").getClientRects().length;
|
||||||
|
const count2 = document.querySelector("#multiple").getClientRects().length;
|
||||||
|
assert_equals(count, 1, "count");
|
||||||
|
assert_equals(count2, 1, "count2");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Test (CSSOM View): getClientRects of element outside DOM</title>
|
||||||
|
<link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/cssom-view/#dom-element-getclientrects">
|
||||||
|
<meta name="flags" content="dom">
|
||||||
|
<meta name="assert" content="Calling getClientRects on an element that is outside of the DOM (and therefore does not have an associated layout box) should result in an empty DOMRectList and should definitely not throw an error.">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script>
|
||||||
|
test(
|
||||||
|
function () {
|
||||||
|
var rectList = document.createElement('div').getClientRects();
|
||||||
|
assert_equals(rectList.length, 0, "DOMRectList should be empty");
|
||||||
|
},
|
||||||
|
"getClientRects on a newly-created Element not yet inserted into the DOM should return an empty DOMRectList"
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSSOM View - 5 - extensions to the Document interface</title>
|
||||||
|
<link rel="author" title="Neils Christoffersen" href="mailto:neils.christoffersen@gmail.com">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/cssom-view/#extensions-to-the-document-interface">
|
||||||
|
<meta name="flags" content="dom">
|
||||||
|
<meta name="assert" content="elementFromPoint returns correct element">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<style>
|
||||||
|
#targetDiv {
|
||||||
|
position: absolute;
|
||||||
|
top: 10;
|
||||||
|
left: 10;
|
||||||
|
height: 100px;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="myDiv"></div>
|
||||||
|
<div id="log"></div>
|
||||||
|
<div id="targetDiv">
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
var element = document.elementFromPoint(15, 15);
|
||||||
|
|
||||||
|
test ( function() {
|
||||||
|
assert_equals(element.id, "targetDiv", "elementFromPoint didn't return the correct element");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,40 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Checking whether dynamic changes to visibility interact correctly with
|
||||||
|
table anonymous boxes</title>
|
||||||
|
<script src=../../resources/testharness.js></script>
|
||||||
|
<script src=../../resources/testharnessreport.js></script>
|
||||||
|
<style>
|
||||||
|
#overlay {
|
||||||
|
display: table;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: white;
|
||||||
|
z-index: 999
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper { position: relative; }
|
||||||
|
</style>
|
||||||
|
<div id=log></div>
|
||||||
|
<div id="wrapper">
|
||||||
|
<div id="overlay"><div></div></div>
|
||||||
|
<div id="target">Some text</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var t = document.querySelector("#target");
|
||||||
|
var rect = t.getBoundingClientRect();
|
||||||
|
var hit = document.elementFromPoint(rect.x + rect.width/2,
|
||||||
|
rect.y + rect.height/2);
|
||||||
|
assert_equals(hit, t.previousElementSibling,
|
||||||
|
"Should hit the overlay first.");
|
||||||
|
t.previousElementSibling.style.visibility = "hidden";
|
||||||
|
hit = document.elementFromPoint(rect.x + rect.width/2,
|
||||||
|
rect.y + rect.height/2);
|
||||||
|
assert_equals(hit, t,
|
||||||
|
"Should hit our target now that the overlay is hidden.");
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,48 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Checking whether dynamic changes to visibility interact correctly with
|
||||||
|
table anonymous boxes</title>
|
||||||
|
<script src=../../resources/testharness.js></script>
|
||||||
|
<script src=../../resources/testharnessreport.js></script>
|
||||||
|
<style>
|
||||||
|
#overlay {
|
||||||
|
display: table;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: white;
|
||||||
|
z-index: 999
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper { position: relative; }
|
||||||
|
</style>
|
||||||
|
<div id=log></div>
|
||||||
|
<div id="wrapper">
|
||||||
|
<div id="overlay"><div></div></div>
|
||||||
|
<div id="target">Some text</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
// Make sure we have boxes constructed already.
|
||||||
|
document.body.offsetWidth;
|
||||||
|
var overlay = document.querySelector("#overlay");
|
||||||
|
overlay.insertBefore(document.createElement("div"), overlay.firstChild);
|
||||||
|
overlay.appendChild(document.createElement("div"));
|
||||||
|
// Make sure we have boxes constructed for those inserts/appends
|
||||||
|
document.body.offsetWidth;
|
||||||
|
overlay.firstChild.nextSibling.remove();
|
||||||
|
var t = document.querySelector("#target");
|
||||||
|
var rect = t.getBoundingClientRect();
|
||||||
|
var hit = document.elementFromPoint(rect.x + rect.width/2,
|
||||||
|
rect.y + rect.height/2);
|
||||||
|
assert_equals(hit, t.previousElementSibling,
|
||||||
|
"Should hit the overlay first.");
|
||||||
|
t.previousElementSibling.style.visibility = "hidden";
|
||||||
|
hit = document.elementFromPoint(rect.x + rect.width/2,
|
||||||
|
rect.y + rect.height/2);
|
||||||
|
assert_equals(hit, t,
|
||||||
|
"Should hit our target now that the overlay is hidden.");
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,58 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<title>cssom-view - elementScroll - 002</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-scrolltop">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-scrollleft">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id="scroller1" style="height: 100px; width: 100px; overflow: scroll; background: red;">
|
||||||
|
<div style="background: green; margin-top: 100px; margin-left: 100px; width: 100px; height: 100px;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="scroller2" style="height: 100px; width: 100px; overflow: hidden; background: red;">
|
||||||
|
<div style="background: green; margin-top: 100px; padding-left: 100px; width: 100px; height: 100px;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="scroller3" style="height: 100px; width: 100px; overflow: scroll; background: red;">
|
||||||
|
<div style="background: green; padding-top: 100px; margin-left: 100px; width: 100px; height: 100px;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="scroller4" style="height: 100px; width: 100px; overflow: hidden; background: red;">
|
||||||
|
<div style="background: green; padding-top: 100px; padding-left: 100px; width: 100px; height: 100px;"></div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
test(function () {
|
||||||
|
var scroller1 = document.getElementById("scroller1");
|
||||||
|
|
||||||
|
scroller1.scrollTop = 100;
|
||||||
|
scroller1.scrollLeft = 100;
|
||||||
|
assert_equals(scroller1.scrollTop, 100, "changed scrollTop should be 100");
|
||||||
|
assert_equals(scroller1.scrollLeft, 100, "changed scrollLeft should be 100");
|
||||||
|
|
||||||
|
}, "simple scroll with style: 'margin' and 'overflow: scroll'");
|
||||||
|
test(function () {
|
||||||
|
var scroller2 = document.getElementById("scroller2");
|
||||||
|
|
||||||
|
scroller2.scrollTop = 100;
|
||||||
|
scroller2.scrollLeft = 100;
|
||||||
|
assert_equals(scroller2.scrollTop, 100, "changed scrollTop should be 100");
|
||||||
|
assert_equals(scroller2.scrollLeft, 100, "changed scrollLeft should be 100");
|
||||||
|
|
||||||
|
}, "simple scroll with style: 'margin' and 'overflow: hidden'");
|
||||||
|
test(function () {
|
||||||
|
var scroller3 = document.getElementById("scroller3");
|
||||||
|
|
||||||
|
scroller3.scrollTop = 100;
|
||||||
|
scroller3.scrollLeft = 100;
|
||||||
|
assert_equals(scroller3.scrollTop, 100, "changed scrollTop should be 100");
|
||||||
|
assert_equals(scroller3.scrollLeft, 100, "changed scrollLeft should be 100");
|
||||||
|
|
||||||
|
}, "simple scroll with style: 'padding' and 'overflow: scroll'");
|
||||||
|
test(function () {
|
||||||
|
var scroller4 = document.getElementById("scroller4");
|
||||||
|
|
||||||
|
scroller4.scrollTop = 100;
|
||||||
|
scroller4.scrollLeft = 100;
|
||||||
|
assert_equals(scroller4.scrollTop, 100, "changed scrollTop should be 100");
|
||||||
|
assert_equals(scroller4.scrollLeft, 100, "changed scrollLeft should be 100");
|
||||||
|
|
||||||
|
}, "simple scroll with style: 'padding' and 'overflow: hidden'");
|
||||||
|
</script>
|
|
@ -0,0 +1,173 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>cssom-view - elementScroll</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<style>
|
||||||
|
#section {
|
||||||
|
width: 300px;
|
||||||
|
height: 500px;
|
||||||
|
/*position: absolute;*/
|
||||||
|
top: 16px;
|
||||||
|
left: 16px;
|
||||||
|
border: inset gray 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#scrollable {
|
||||||
|
width: 400px;
|
||||||
|
height: 700px;
|
||||||
|
background: linear-gradient(135deg, red, blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<section id="section">
|
||||||
|
<div id="scrollable"></div>
|
||||||
|
<div id="unrelated"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
setup({explicit_done:true});
|
||||||
|
window.onload = function () {
|
||||||
|
var section = document.getElementById("section");
|
||||||
|
var unrelated = document.getElementById("unrelated");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
assert_equals(section.scrollTop, 0, "initial scrollTop should be 0");
|
||||||
|
assert_equals(section.scrollLeft, 0, "initial scrollLeft should be 0");
|
||||||
|
|
||||||
|
section.scrollTop = 30;
|
||||||
|
section.scrollLeft = 40;
|
||||||
|
|
||||||
|
assert_equals(section.scrollTop, 30, "changed scrollTop should be 40");
|
||||||
|
assert_equals(section.scrollLeft, 40, "changed scrollLeft should be 40");
|
||||||
|
assert_equals(unrelated.scrollTop, 0, "unrelated element should not scroll");
|
||||||
|
assert_equals(unrelated.scrollLeft, 0, "unrelated element should not scroll");
|
||||||
|
}, "Element scrollTop/Left getter/setter test");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
section.scroll(50, 60);
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, 50, "changed scrollLeft should be 50");
|
||||||
|
assert_equals(section.scrollTop, 60, "changed scrollTop should be 60");
|
||||||
|
}, "Element scroll test (two arguments)");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
section.scroll({left: 55, top: 65});
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, 55, "changed scrollLeft should be 55");
|
||||||
|
assert_equals(section.scrollTop, 65, "changed scrollTop should be 65");
|
||||||
|
|
||||||
|
section.scroll({left: 85});
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, 85, "changed scrollLeft should be 85");
|
||||||
|
assert_equals(section.scrollTop, 65, "scrollTop should stay at 65");
|
||||||
|
|
||||||
|
section.scroll({top: 75});
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, 85, "scrollLeft should stay at 85");
|
||||||
|
assert_equals(section.scrollTop, 75, "changed scrollTop should be 75");
|
||||||
|
|
||||||
|
section.scroll({});
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, 85, "scrollLeft should stay at 85");
|
||||||
|
assert_equals(section.scrollTop, 75, "scrollTop should stay at 75");
|
||||||
|
|
||||||
|
section.scroll();
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, 85, "scrollLeft should stay at 85");
|
||||||
|
assert_equals(section.scrollTop, 75, "scrollTop should stay at 75");
|
||||||
|
}, "Element scroll test (one argument)");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
section.scrollTo(80, 70);
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, 80, "changed scrollLeft should be 70");
|
||||||
|
assert_equals(section.scrollTop, 70, "changed scrollTop should be 80");
|
||||||
|
}, "Element scrollTo test (two arguments)");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
section.scrollTo({left: 75, top: 85});
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, 75, "changed scrollLeft should be 75");
|
||||||
|
assert_equals(section.scrollTop, 85, "changed scrollTop should be 85");
|
||||||
|
|
||||||
|
section.scrollTo({left: 65});
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, 65, "changed scrollLeft should be 65");
|
||||||
|
assert_equals(section.scrollTop, 85, "scrollTop should stay at 85");
|
||||||
|
|
||||||
|
section.scrollTo({top: 55});
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, 65, "scrollLeft should stay at 65");
|
||||||
|
assert_equals(section.scrollTop, 55, "changed scrollTop should be 55");
|
||||||
|
|
||||||
|
section.scrollTo({});
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, 65, "scrollLeft should stay at 65");
|
||||||
|
assert_equals(section.scrollTop, 55, "scrollTop should stay at 55");
|
||||||
|
|
||||||
|
section.scrollTo();
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, 65, "scrollLeft should stay at 55");
|
||||||
|
assert_equals(section.scrollTop, 55, "scrollTop should stay at 55");
|
||||||
|
}, "Element scrollTo test (one argument)");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var left = section.scrollLeft;
|
||||||
|
var top = section.scrollTop;
|
||||||
|
|
||||||
|
section.scrollBy(10, 20);
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, left + 10, "increment of scrollLeft should be 10")
|
||||||
|
assert_equals(section.scrollTop, top + 20, "increment of scrollTop should be 20")
|
||||||
|
}, "Element scrollBy test (two arguments)");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var left = section.scrollLeft;
|
||||||
|
var top = section.scrollTop;
|
||||||
|
|
||||||
|
section.scrollBy({left: 5, top: 15});
|
||||||
|
left += 5
|
||||||
|
top += 15
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, left, "increment of scrollLeft should be 5")
|
||||||
|
assert_equals(section.scrollTop, top, "increment of scrollTop should be 15")
|
||||||
|
|
||||||
|
section.scrollBy({left: -15});
|
||||||
|
left -= 15
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, left, "decrement of scrollLeft should be 15")
|
||||||
|
assert_equals(section.scrollTop, top, "scrollTop should not be modified")
|
||||||
|
|
||||||
|
section.scrollBy({top: -5});
|
||||||
|
top -= 5;
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, left, "scrollLeft should not be modified")
|
||||||
|
assert_equals(section.scrollTop, top, "decrement of scrollTop should be 5")
|
||||||
|
|
||||||
|
section.scrollBy({});
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, left, "scrollLeft should not be modified")
|
||||||
|
assert_equals(section.scrollTop, top, "scrollTop should not be modified")
|
||||||
|
|
||||||
|
section.scrollBy();
|
||||||
|
|
||||||
|
assert_equals(section.scrollLeft, left, "scrollLeft should not be modified")
|
||||||
|
assert_equals(section.scrollTop, top, "scrollTop should not be modified")
|
||||||
|
}, "Element scrollBy test (one argument)");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
section.scrollTop = 1000;
|
||||||
|
section.scrollLeft = 1000;
|
||||||
|
|
||||||
|
assert_equals(section.scrollTop, 700 - 500, "changed scrollTop should be 200");
|
||||||
|
assert_equals(section.scrollLeft, 400 - 300, "changed scrollLeft should be 100");
|
||||||
|
|
||||||
|
}, "Element scroll maximum test");
|
||||||
|
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,131 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="resources/elementsFromPoint.js"></script>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
height: 500px;
|
||||||
|
}
|
||||||
|
#simpleDiv {
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
background-color: rgba(0,0,255,0.5);
|
||||||
|
}
|
||||||
|
#divWithPseudo {
|
||||||
|
position: absolute;
|
||||||
|
left: 50px;
|
||||||
|
top: 50px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: rgba(255,0,0,0.5);
|
||||||
|
}
|
||||||
|
#divWithPseudo::before {
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
top: 20px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
content: "::before";
|
||||||
|
background-color: rgba(255,0,0,0.5);
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
#divBetweenPseudo {
|
||||||
|
position: absolute;
|
||||||
|
left: 100px;
|
||||||
|
top: 100px;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: rgba(0,255,0,0.5);
|
||||||
|
}
|
||||||
|
#withMargin {
|
||||||
|
margin-top: -15px;
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
background-color: rgba(0,0,0,0.5);
|
||||||
|
}
|
||||||
|
#inlineSpan {
|
||||||
|
float: right;
|
||||||
|
background-color: yellow;
|
||||||
|
width: 100px;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
#noPointerEvents {
|
||||||
|
position: absolute;
|
||||||
|
left: 50px;
|
||||||
|
top: 50px;
|
||||||
|
width: 100px;
|
||||||
|
height: 300px;
|
||||||
|
background-color: rgba(0,0,0,0.1);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
#threeD {
|
||||||
|
position: absolute;
|
||||||
|
transform: translate3d(-100px, -100px, 10px);
|
||||||
|
left: 140px;
|
||||||
|
top: 140px;
|
||||||
|
width: 200px;
|
||||||
|
height: 50px;
|
||||||
|
background-color: rgba(255,255,255,0.5);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div id="simpleDiv"></div>
|
||||||
|
<div id="divWithPseudo"></div>
|
||||||
|
<div id="divBetweenPseudo"></div>
|
||||||
|
<div id="withMargin"><span id="inlineSpan"></span></div>
|
||||||
|
<div id="noPointerEvents"></div>
|
||||||
|
<div id="threeD"></div>
|
||||||
|
<script>
|
||||||
|
var body = document.body;
|
||||||
|
var html = document.documentElement;
|
||||||
|
test(function() {
|
||||||
|
checkElementsFromPointFourCorners('document', 'simpleDiv',
|
||||||
|
[simpleDiv, body, html],
|
||||||
|
[simpleDiv, body, html],
|
||||||
|
[withMargin, simpleDiv, body, html],
|
||||||
|
[divBetweenPseudo, inlineSpan, withMargin, simpleDiv, body, html]);
|
||||||
|
}, "elementsFromPoint for each corner of a simple div");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
checkElementsFromPointFourCorners('document', 'divWithPseudo',
|
||||||
|
[threeD, divWithPseudo, simpleDiv, body, html],
|
||||||
|
[threeD, divWithPseudo, simpleDiv, body, html],
|
||||||
|
[divWithPseudo, simpleDiv, body, html],
|
||||||
|
[divWithPseudo, divBetweenPseudo, divWithPseudo, simpleDiv, body, html]);
|
||||||
|
}, "elementsFromPoint for each corner of a div that has a pseudo-element");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
checkElementsFromPointFourCorners('document', 'divBetweenPseudo',
|
||||||
|
[divWithPseudo, divBetweenPseudo, divWithPseudo, simpleDiv, body, html],
|
||||||
|
[divBetweenPseudo, simpleDiv, body, html],
|
||||||
|
[divBetweenPseudo, inlineSpan, withMargin, simpleDiv, body, html],
|
||||||
|
[divBetweenPseudo, inlineSpan, withMargin, simpleDiv, body, html]);
|
||||||
|
}, "elementsFromPoint for each corner of a div that is between another div and its pseudo-element");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
checkElementsFromPointFourCorners('document', 'withMargin',
|
||||||
|
[withMargin, simpleDiv, body, html],
|
||||||
|
[divBetweenPseudo, inlineSpan, withMargin, simpleDiv, body, html],
|
||||||
|
[withMargin, body, html],
|
||||||
|
[withMargin, body, html]);
|
||||||
|
}, "elementsFromPoint for each corner of a div that has a margin");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
checkElementsFromPointFourCorners('document', 'noPointerEvents',
|
||||||
|
[threeD, divWithPseudo, simpleDiv, body, html],
|
||||||
|
[threeD, divWithPseudo, simpleDiv, body, html],
|
||||||
|
[withMargin, body, html],
|
||||||
|
[withMargin, body, html]);
|
||||||
|
}, "elementsFromPoint for each corner of a div with pointer-events:none");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
checkElementsFromPointFourCorners('document', 'threeD',
|
||||||
|
[threeD, simpleDiv, body, html],
|
||||||
|
[threeD, body, html],
|
||||||
|
[threeD, simpleDiv, body, html],
|
||||||
|
[threeD, body, html]);
|
||||||
|
}, "elementsFromPoint for each corner of a div with a 3d transform");
|
||||||
|
</script>
|
|
@ -0,0 +1,61 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface">
|
||||||
|
<script src=../../resources/testharness.js></script>
|
||||||
|
<script src=../../resources/testharnessreport.js></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../../fonts/ahem.css" />
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.container {
|
||||||
|
position: relative;
|
||||||
|
font: 20px/1 Ahem;
|
||||||
|
width: 150px;
|
||||||
|
height: 100px;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-width: 3px 6px;
|
||||||
|
border-style: solid;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.target { background: grey; }
|
||||||
|
.hl { writing-mode:horizontal-tb; }
|
||||||
|
.vlr { writing-mode:vertical-lr; }
|
||||||
|
</style>
|
||||||
|
<div id=tests>
|
||||||
|
<div class="container hl">
|
||||||
|
<span class="target">x</span>
|
||||||
|
</div>
|
||||||
|
<div class="container vlr">
|
||||||
|
<span class="target">x</span>
|
||||||
|
</div>
|
||||||
|
<div class="container hl">
|
||||||
|
<div class="target">x</div>
|
||||||
|
</div>
|
||||||
|
<div class="container vlr">
|
||||||
|
<div class="target">x</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
setup({explicit_done: true});
|
||||||
|
onload = () => {
|
||||||
|
// Clone the above tests for the following 'display' types:
|
||||||
|
let display = ['inline-block', 'grid', 'inline-grid', 'flex', 'inline-flex', 'flow-root' ];
|
||||||
|
let tests = document.querySelector('#tests');
|
||||||
|
display.forEach((display) => {
|
||||||
|
let t = tests.cloneNode(true);
|
||||||
|
[...t.children].forEach((child) => {
|
||||||
|
child.setAttribute("style", "display:"+display);
|
||||||
|
});
|
||||||
|
document.body.appendChild(t);
|
||||||
|
});
|
||||||
|
// Check that all of them return an offset relative the padding edge.
|
||||||
|
var i = 0;
|
||||||
|
document.querySelectorAll('.target').forEach((target) => {
|
||||||
|
test(() => {
|
||||||
|
assert_equals(target.offsetLeft, 10, 'offsetLeft');
|
||||||
|
assert_equals(target.offsetTop, 2, 'offsetTop');
|
||||||
|
}, 'container: ' + i);
|
||||||
|
i++;
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#run-the-resize-steps"/>
|
||||||
|
<script src=../../resources/testharness.js></script>
|
||||||
|
<script src=../../resources/testharnessreport.js></script>
|
||||||
|
<script>
|
||||||
|
promise_test(async t => {
|
||||||
|
let gotResizeEvent = false;
|
||||||
|
|
||||||
|
on_event(window, 'resize', () => gotResizeEvent = true);
|
||||||
|
|
||||||
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
||||||
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
||||||
|
|
||||||
|
assert_false(gotResizeEvent, 'resize event should not be fired');
|
||||||
|
}, 'resize events are not fired on the initial layout');
|
||||||
|
</script>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#run-the-resize-steps"/>
|
||||||
|
<script src=../../resources/testharness.js></script>
|
||||||
|
<script src=../../resources/testharnessreport.js></script>
|
||||||
|
<script>
|
||||||
|
promise_test(async t => {
|
||||||
|
let gotResizeEvent = false;
|
||||||
|
|
||||||
|
on_event(window, 'resize', () => gotResizeEvent = true);
|
||||||
|
|
||||||
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
||||||
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
||||||
|
|
||||||
|
assert_false(gotResizeEvent, 'resize event should not be fired');
|
||||||
|
}, 'resize events are not fired on the initial layout');
|
||||||
|
</script>
|
|
@ -0,0 +1,48 @@
|
||||||
|
function nodeToString(node) {
|
||||||
|
var str = '';
|
||||||
|
if (node.nodeType == Node.ELEMENT_NODE) {
|
||||||
|
str += node.nodeName;
|
||||||
|
if (node.id)
|
||||||
|
str += '#' + node.id;
|
||||||
|
else if (node.class)
|
||||||
|
str += '.' + node.class;
|
||||||
|
} else if (node.nodeType == Node.TEXT_NODE) {
|
||||||
|
str += '\'' + node.data + '\'';
|
||||||
|
} else if (node.nodeType == Node.DOCUMENT_NODE) {
|
||||||
|
str += '#document';
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
function nodeListToString(nodes) {
|
||||||
|
var nodeString = '';
|
||||||
|
|
||||||
|
for (var i = 0; i < nodes.length; i++) {
|
||||||
|
var str = nodeToString(nodes[i]);
|
||||||
|
if (!str)
|
||||||
|
continue;
|
||||||
|
nodeString += str;
|
||||||
|
if (i + 1 < nodes.length)
|
||||||
|
nodeString += ', ';
|
||||||
|
}
|
||||||
|
return nodeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertElementsFromPoint(doc, x, y, expected) {
|
||||||
|
var query = doc + '.elementsFromPoint(' + x + ',' + y + ')';
|
||||||
|
var sequence = eval(query);
|
||||||
|
assert_equals(nodeListToString(sequence), nodeListToString(expected), query);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkElementsFromPointFourCorners(doc, element, expectedTopLeft, expectedTopRight, expectedBottomLeft, expectedBottomRight) {
|
||||||
|
var rect = eval(doc + '.getElementById(\'' + element + '\')').getBoundingClientRect();
|
||||||
|
var topLeft = {x: rect.left + 1, y: rect.top + 1};
|
||||||
|
var topRight = {x: rect.right - 1, y: rect.top + 1};
|
||||||
|
var bottomLeft = {x: rect.left + 1, y: rect.bottom - 1};
|
||||||
|
var bottomRight = {x: rect.right - 1, y: rect.bottom - 1};
|
||||||
|
|
||||||
|
assertElementsFromPoint(doc, topLeft.x, topLeft.y, expectedTopLeft);
|
||||||
|
assertElementsFromPoint(doc, topRight.x, topRight.y, expectedTopRight);
|
||||||
|
assertElementsFromPoint(doc, bottomLeft.x, bottomLeft.y, expectedBottomLeft);
|
||||||
|
assertElementsFromPoint(doc, bottomRight.x, bottomRight.y, expectedBottomRight);
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
{
|
||||||
|
// private variables are defined with `const` so they don't leak outside this block statement
|
||||||
|
const IFRAME_DEFAULT_SIZE = "200";
|
||||||
|
const iframes = new WeakMap();
|
||||||
|
|
||||||
|
// helpers are defined with `var` so they are globally accessible
|
||||||
|
var createMQL = async t => {
|
||||||
|
const iframe = await createIFrame(t);
|
||||||
|
const mql = iframe.contentWindow.matchMedia(`(max-width: ${IFRAME_DEFAULT_SIZE}px)`);
|
||||||
|
assert_true(mql.matches, "MQL should match on newly created <iframe>");
|
||||||
|
iframes.set(mql, iframe);
|
||||||
|
return mql;
|
||||||
|
};
|
||||||
|
|
||||||
|
var createIFrame = (t, width = IFRAME_DEFAULT_SIZE, height = width) => {
|
||||||
|
assert_not_equals(document.body, null, "<body> element is missing");
|
||||||
|
|
||||||
|
const iframe = document.createElement("iframe");
|
||||||
|
iframe.srcdoc = "";
|
||||||
|
iframe.width = String(width);
|
||||||
|
iframe.height = String(height);
|
||||||
|
iframe.style.border = "none";
|
||||||
|
|
||||||
|
t.add_cleanup(() => {
|
||||||
|
document.body.removeChild(iframe);
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
|
iframe.addEventListener("load", () => {
|
||||||
|
iframe.contentDocument.body.offsetWidth; // reflow
|
||||||
|
resolve(iframe);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.body.appendChild(iframe);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var triggerMQLEvent = mql => {
|
||||||
|
const iframe = iframes.get(mql);
|
||||||
|
assert_not_equals(iframe, undefined, "Passed MQL instance was not created with createMQL");
|
||||||
|
iframe.width = iframe.width === IFRAME_DEFAULT_SIZE ? "250" : IFRAME_DEFAULT_SIZE;
|
||||||
|
};
|
||||||
|
|
||||||
|
var getWindow = mql => {
|
||||||
|
const iframe = iframes.get(mql);
|
||||||
|
assert_not_equals(iframe, undefined, "Passed MQL instance was not created with createMQL");
|
||||||
|
return iframe.contentWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
var waitForChangesReported = () => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
requestAnimationFrame(resolve);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>cssom-view - Scrolling element with no layout box</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-scroll">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#css-layout-box">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
|
||||||
|
<div style="display: none">
|
||||||
|
<div id="elem"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
test(() => {
|
||||||
|
const elem = document.getElementById('elem');
|
||||||
|
elem.scroll(1, 2);
|
||||||
|
|
||||||
|
assert_equals(elem.scrollTop, 0, "scrollTop should be unchanged");
|
||||||
|
assert_equals(elem.scrollLeft, 0, "scrollLeft should be unchanged");
|
||||||
|
}, "scrolling an element with no CSS layout box should have no effect");
|
||||||
|
</script>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!-- quirks -->
|
||||||
|
<title>CSSOM scrollingElement reflects the propagated scroll to viewport correctly</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||||
|
<link rel="author" title="Mozilla" href="https://mozilla.org">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-overflow/#overflow-propagation">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-document-scrollingelement">
|
||||||
|
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5601">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
overflow: clip;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
assert_equals(document.scrollingElement, null);
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!-- quirks -->
|
||||||
|
<title>CSSOM scrollingElement reflects the propagated scroll to viewport correctly</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||||
|
<link rel="author" title="Mozilla" href="https://mozilla.org">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-overflow/#overflow-propagation">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-document-scrollingelement">
|
||||||
|
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5601">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
overflow: clip;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
assert_equals(document.scrollingElement, document.body);
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
Reference in a new issue