diff options
Diffstat (limited to 'testing/web-platform/tests/infrastructure/testdriver')
52 files changed, 2218 insertions, 0 deletions
diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/actionsWithKeyPressed.html b/testing/web-platform/tests/infrastructure/testdriver/actions/actionsWithKeyPressed.html new file mode 100644 index 0000000000..3e0795b14a --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/actionsWithKeyPressed.html @@ -0,0 +1,66 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: actions with key pressed</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, div#test2 { + position: fixed; + top: 0; + left: 0; + width: 100px; + height: 100px; + background-color: blue; +} + +div#test2 { + position: fixed; + top: 100px; + left: 0; + width: 100px; + height: 100px; + background-color: green; +} +</style> + +<div id="test1"> +</div> + +<div id="test2"> +</div> + +<script> +let keys = []; + +promise_test(async t => { + let test1 = document.getElementById("test1"); + let test2 = document.getElementById("test2"); + document.getElementById("test1").addEventListener("click", + e => {keys.push(e.getModifierState("Shift"))}); + document.getElementById("test2").addEventListener("click", + e => {keys.push(e.getModifierState("Shift"))}); + + let actions = new test_driver.Actions() + .keyDown("\uE008") + .addTick() + .pointerMove(0, 0, {origin: test1}) + .pointerDown() + .pointerUp() + .pointerMove(0, 0, {origin: test2}) + .pointerDown() + .pointerUp() + .addTick() + .keyUp("\uE008") + .addTick() + .pointerMove(0, 0, {origin: test1}) + .pointerDown() + .pointerUp(); + + await actions.send(); + assert_array_equals(keys, [true, true, false]); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/crossOrigin.sub.html b/testing/web-platform/tests/infrastructure/testdriver/actions/crossOrigin.sub.html new file mode 100644 index 0000000000..38b3610af6 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/crossOrigin.sub.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Actions in cross-origin iframe</title> +<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> + +<iframe src="https://{{host}}:{{ports[https][1]}}/infrastructure/testdriver/actions/crossOriginChild.html"></iframe> + +<script> +setup({single_test: true}); +addEventListener("message", (msg) => { + if (msg.data === "PASS") { + done(); + } else if (msg.data === "FAIL") { + assert_unreached("actions failed") + } +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/crossOriginChild.html b/testing/web-platform/tests/infrastructure/testdriver/actions/crossOriginChild.html new file mode 100644 index 0000000000..48e37e233e --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/crossOriginChild.html @@ -0,0 +1,32 @@ +<!doctype html> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/resources/testdriver-actions.js"></script> + +<input type=text> +<script> +let input = document.getElementsByTagName("input")[0]; +addEventListener("load", async () => { + test_driver.set_test_context(parent); + await new test_driver.Actions() + .pointerMove(0, 0, {origin: input}) + .pointerDown() + .pointerUp() + .send(); + await new test_driver.Actions() + .keyDown("P") + .keyUp("P") + .keyDown("A") + .keyUp("A") + .keyDown("S") + .keyUp("S") + .keyDown("S") + .keyUp("S") + .send(); + if (input.value === "PASS") { + test_driver.message_test("PASS", "*") + } else { + test_driver.message_test("FAIL", "*") + } +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/elementPosition.html b/testing/web-platform/tests/infrastructure/testdriver/actions/elementPosition.html new file mode 100644 index 0000000000..145852e7b5 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/elementPosition.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: element position</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#test { + position: fixed; + left: -100px; + top: -25px; + width: 200px; + height: 75px; + background-color:blue; +} +</style> + +<div id="test"> +</div> + +<script> +let events = []; + +async_test(t => { + let test = document.getElementById("test"); + test.addEventListener("click", e => { + events.push(e.clientX); + events.push(e.clientY) + }); + + let div = document.getElementById("test"); + let actions = new test_driver.Actions() + .pointerMove(0, 0, {origin: test}) + .pointerDown() + .pointerUp() + .send() + .then(t.step_func_done(() => assert_array_equals(events, [50, 25]))) + .catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e))); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/elementTiming.html b/testing/web-platform/tests/infrastructure/testdriver/actions/elementTiming.html new file mode 100644 index 0000000000..33731e9299 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/elementTiming.html @@ -0,0 +1,69 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: element timing</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, div#test2 { + position: fixed; + top: 0; + left: 0; + width: 100px; + height: 100px; + background-color: blue; +} + +div#test2 { + display: none; + left: -100px; + background-color: green; +} +</style> + +<div id="test1"> +</div> + +<div id="test2"> +</div> + +<script> +let events = []; + +promise_test(async t => { + let test1 = document.getElementById("test1"); + let test2 = document.getElementById("test2"); + test1.addEventListener("click", + () => { + test2.style.display = "block"; + test2.style.top = "100px"; + test2.style.left = "0" + }); + test2.addEventListener("click", + e => { + events.push(e.clientX); + events.push(e.clientY); + }); + + const waitCondition = new Promise((resolve, reject)=>{setTimeout(resolve, 5000);}); + const test1ClickWatcher = new EventWatcher(t, test1, ["click"], ()=>waitCondition); + const test2ClickWatcher = new EventWatcher(t, test2, ["click"], ()=>waitCondition); + let waitForClicks = Promise.all([test1ClickWatcher.wait_for(["click"]), test2ClickWatcher.wait_for(["click"])]); + + await new test_driver.Actions() + .pointerMove(0, 0, {origin: test1}) + .pointerDown() + .pointerUp() + .send(); + await new test_driver.Actions() + .pointerMove(0, 0, {origin: test2}) + .pointerDown() + .pointerUp() + .send(); + await waitForClicks; + assert_array_equals(events, [50, 150]) +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/eventOrder.html b/testing/web-platform/tests/infrastructure/testdriver/actions/eventOrder.html new file mode 100644 index 0000000000..1fed285a27 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/eventOrder.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: event order</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> + +<button id="a">Button a</button> +<button id="b">Button b</button> +<input id="text-input"> + +<script> +// Pointer 1 is added before Pointer 2 so it comes first in the list of sources +// Therefore its actions happen first +let events = []; + +promise_test(() => { + Array.prototype.forEach.call(document.getElementsByTagName("button"), + (x) => x.addEventListener("mousedown", () => {events.push(x.id)})); + + let button_a = document.getElementById("a"); + let button_b = document.getElementById("b"); + return new test_driver.Actions() + .addPointer("pointer1") + .addPointer("pointer2") + .pointerMove(0, 0, {origin: button_a, sourceName: "pointer1"}) + .pointerMove(0, 0, {origin: button_b, sourceName: "pointer2"}) + .pointerDown({sourceName: "pointer2"}) + .pointerDown({sourceName: "pointer1"}) + .pointerUp({sourceName: "pointer2"}) + .pointerUp({sourceName: "pointer1"}) + .send() + .then(() => assert_array_equals(events, ["a", "b"])); +}); + +// This test uses a large number of keyboard sources to force race conditions +// in implementations which incorrectly dispatch events. Despite belonging to +// the same "tick," each action's initial event should be dispatched in series. +promise_test(() => { + const input = document.getElementById("text-input"); + const actions = new test_driver.Actions(); + const code_for_a = "a".charCodeAt(0); + const keys = Array.from(Array(26)) + .map((_, index) => ({ + sourceName: "keyboard" + index, + code: String.fromCharCode(code_for_a + index) + })); + + keys.forEach(({sourceName}) => actions.addKeyboard(sourceName)); + keys.forEach(({code, sourceName}) => actions.keyDown(code, {sourceName})); + keys.forEach(({code, sourceName}) => actions.keyUp(code,{sourceName})); + + return test_driver.click(input) + .then(() => actions.send()) + .then(() => { + assert_equals(input.value, "abcdefghijklmnopqrstuvwxyz"); + }); +}, "indivisible actions on the same track dispatch events in series"); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/iframe.html b/testing/web-platform/tests/infrastructure/testdriver/actions/iframe.html new file mode 100644 index 0000000000..6c64d6f49a --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/iframe.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions on a document in an iframe</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/resources/testdriver-actions.js"></script> + +<iframe src="iframeChild.html"></iframe> + +<script> +setup({single_test: true}); +addEventListener("load", async () => { + let input = frames[0].document.getElementsByTagName("input")[0]; + await new test_driver.Actions() + .pointerMove(0, 0, {origin: input}) + .pointerDown() + .pointerUp() + .send(); + await new test_driver.Actions() + .setContext(frames[0]) + .keyDown("P") + .keyUp("P") + .keyDown("A") + .keyUp("A") + .keyDown("S") + .keyUp("S") + .keyDown("S") + .keyUp("S") + .send(); + assert_equals(input.value, "PASS"); + done(); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/iframeChild.html b/testing/web-platform/tests/infrastructure/testdriver/actions/iframeChild.html new file mode 100644 index 0000000000..a46c54a7b7 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/iframeChild.html @@ -0,0 +1,2 @@ +<!doctype html> +<input type=text> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/mouseClickCount.html b/testing/web-platform/tests/infrastructure/testdriver/actions/mouseClickCount.html new file mode 100644 index 0000000000..4f02088c5a --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/mouseClickCount.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: test the mouse click counts at different cases</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#test { + position: fixed; + touch-action: none; + top: 5px; + left: 5px; + width: 100px; + height: 100px; + background-color: blue; +} +</style> + +<div id="test"> +</div> + +<script> +let clickCountList = []; + +async_test(t => { + let test = document.getElementById("test"); + test.addEventListener("click", e => { + clickCountList.push(e.detail); + }); + + let div = document.getElementById("test"); + var actions = new test_driver.Actions(); + actions.pointerMove(0, 0, {origin: test}) + .pointerDown() + .pointerUp() + .pointerDown() + .pointerUp() + .pointerMove(15, 15, {origin: test}) + .pointerDown() + .pointerUp() + .pointerDown() + .pointerUp() + .pointerDown() + .pointerUp() + .send() + .then(t.step_func_done(() => { + let expectedClickCountList = [1, 2, 1, 2, 3]; + assert_array_equals(clickCountList, expectedClickCountList); + })).catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e))); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/multiDevice.html b/testing/web-platform/tests/infrastructure/testdriver/actions/multiDevice.html new file mode 100644 index 0000000000..6bc0fa218d --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/multiDevice.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: multiple devices</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> + +<input type="text" id="text"></input> + +<script> +async_test(t => { + let text_box = document.getElementById("text"); + let actions = new test_driver.Actions() + .pointerMove(0, 0, {origin: text_box}) + .pointerDown() + .pointerUp() + .addTick() + .keyDown("p") + .keyUp("p") + .keyDown("a") + .keyUp("a") + .keyDown("s") + .keyUp("s") + .keyDown("s") + .keyUp("s"); + + actions.send() + .then(() => { + assert_equals(text_box.value, "pass"); + t.done(); + }) + .catch(t.unreached_func("Actions sequence failed")); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPoints.html b/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPoints.html new file mode 100644 index 0000000000..64aa429631 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPoints.html @@ -0,0 +1,68 @@ +<!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> +<script src="touchEvents.js"></script> + +<style> +div#test1{ + position: fixed; + touch-action: none; + top: 0; + left: 0; + width: 100px; + height: 100px; + background-color: blue; +} + +</style> + +<div id="test1"> +</div> + +<script> +promise_test(async t => { + const test1 = document.getElementById("test1"); + + const events = []; + addPointerEventListeners(t, test1, events); + + const 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(0, 10, {origin: test1, sourceName: "touchPointer1"}) + .pointerUp({sourceName: "touchPointer1"}) + .pointerUp({sourceName: "touchPointer2"}); + + await actions.send() + + eventEquals(events[0], {type: "pointerdown", pointerId: 2, clientX: 50, clientY: 50}); + eventEquals(events[1], {type: "pointerdown", pointerId: 3, clientX: 60, clientY: 50}); + // Allow one or two pointermove events + let index = 3; + const moveEvents = [events[2]]; + if (events[3].type === "pointermove") { + index += 1; + moveEvents.push(events[3]); + } + for (const event of moveEvents) { + if (event.pointerId === 2) { + eventEquals(event, {type: "pointermove", clientX: 50, clientY: 60}); + } else { + eventEquals(event, {type: "pointermove", pointerId: 3, clientX: 60, clientY: 50}); + } + } + let remainingEvents = events.slice(index); + assert_equals(remainingEvents.length, 2); + eventEquals(remainingEvents[0], {type: "pointerup", pointerId: 2, clientX: 50, clientY: 60}); + eventEquals(remainingEvents[1], {type: "pointerup", pointerId: 3, clientX: 60, clientY: 50}); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsReleaseFirstPoint.html b/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsReleaseFirstPoint.html new file mode 100644 index 0000000000..41027beb67 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsReleaseFirstPoint.html @@ -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> +<script src="touchEvents.js"></script> + +<style> +div#test1{ + position: fixed; + touch-action: none; + top: 0; + left: 0; + width: 100px; + height: 100px; + background-color: blue; +} + +</style> + +<div id="test1"> +</div> + +<script> +promise_test(async t => { + let test1 = document.getElementById("test1"); + const events = []; + addPointerEventListeners(t, test1, events); + + await 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"}) + .send(); + + const expected = [{type: "pointerdown", pointerId: 2, clientX: 50, clientY: 50}, + {type: "pointerdown", pointerId: 3, clientX: 60, clientY: 50}, + {type: "pointerup", pointerId: 2}, + {type: "pointermove", pointerId: 3, clientX: 60, clientY:60}, + {type: "pointerup", pointerId: 3}]; + + assert_equals(events.length, expected.length, "Expected number of events"); + for (let i=0; i<expected.length; i++) { + eventEquals(events[i], expected[i]); + } +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsReleaseSecondPoint.html b/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsReleaseSecondPoint.html new file mode 100644 index 0000000000..58a2263f5b --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsReleaseSecondPoint.html @@ -0,0 +1,69 @@ +<!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> +<script src="touchEvents.js"></script> + +<style> +div#test1{ + position: fixed; + touch-action: none; + top: 0; + left: 0; + width: 100px; + height: 100px; + background-color: blue; +} + +</style> + +<div id="test1"> +</div> + +<script> +promise_test(async t => { + let test1 = document.getElementById("test1"); + + const events = []; + addPointerEventListeners(t, test1, events); + + await 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"}) + .addTick() + .pointerUp({sourceName: "touchPointer2"}) + .addTick() + .pointerUp({sourceName: "touchPointer1"}) + .send(); + + eventEquals(events[0], {type: "pointerdown", pointerId: 2, clientX: 50, clientY: 50}); + eventEquals(events[1], {type: "pointerdown", pointerId: 3, clientX: 60, clientY: 50}); + // Allow one or two pointermove events + let index = 3; + const moveEvents = [events[2]]; + if (events[3].type === "pointermove") { + index += 1; + moveEvents.push(events[3]); + } + for (const event of moveEvents) { + if (event.pointerId === 2) { + eventEquals(event, {type: "pointermove", clientX: 60, clientY: 60}); + } else { + eventEquals(event, {type: "pointermove", pointerId: 3, clientX: 60, clientY: 50}); + } + } + let remainingEvents = events.slice(index); + assert_equals(remainingEvents.length, 2); + eventEquals(remainingEvents[0], {type: "pointerup", pointerId: 3, clientX: 60, clientY: 50}); + eventEquals(remainingEvents[1], {type: "pointerup", pointerId: 2, clientX: 60, clientY: 60}); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsSimultaneousMove.html b/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsSimultaneousMove.html new file mode 100644 index 0000000000..5be5b44896 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsSimultaneousMove.html @@ -0,0 +1,58 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: two touch points with both moving</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> +<script src="touchEvents.js"></script> + +<style> +div#test1{ + position: fixed; + touch-action: none; + top: 0; + left: 0; + width: 100px; + height: 100px; + background-color: blue; +} + +</style> + +<div id="test1"> +</div> + +<script> +promise_test(async t => { + let test1 = document.getElementById("test1"); + + const events = []; + addPointerEventListeners(t, test1, events); + + await 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(0, 10, {origin: test1, sourceName: "touchPointer1"}) + .pointerMove(10, 10, {origin: test1, sourceName: "touchPointer2"}) + .pointerUp({sourceName: "touchPointer1"}) + .pointerUp({sourceName: "touchPointer2"}) + .send(); + + const expected = [{type: "pointerdown", pointerId: 2, clientX: 50, clientY: 50}, + {type: "pointerdown", pointerId: 3, clientX: 60, clientY: 50}, + {type: "pointermove", pointerId: 2, clientX: 50, clientY: 60}, + {type: "pointermove", pointerId: 3, clientX: 60, clientY: 60}, + {type: "pointerup", pointerId: 2, clientX: 50, clientY: 60}, + {type: "pointerup", pointerId: 3, clientX: 60, clientY: 60}]; + assert_equals(events.length, expected.length); + for (let i=0; i<expected.length; i++) { + eventEquals(events[i], expected[i]); + } +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsTwoTouchStarts.html b/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsTwoTouchStarts.html new file mode 100644 index 0000000000..06f48ebc38 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsTwoTouchStarts.html @@ -0,0 +1,58 @@ +<!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; + touch-action: none; + top: 0; + left: 0; + width: 100px; + height: 100px; + background-color: blue; +} + +</style> + +<div id="test1"> +</div> + +<script> +let event_type = []; +let event_id = []; + +promise_test(async t => { + const test1 = document.getElementById("test1"); + const handleEvent = e => { + event_type.push(e.type); + event_id.push(e.pointerId); + } + test1.addEventListener("pointerdown", handleEvent); + test1.addEventListener("pointerup", handleEvent); + test1.addEventListener("pointermove", handleEvent); + + 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"}) + .pointerMove(0, 5, {origin: test1, sourceName: "touchPointer1"}) + .addTick() + .pointerDown({sourceName: "touchPointer2"}) + .addTick() + .pointerUp({sourceName: "touchPointer1"}) + .pointerUp({sourceName: "touchPointer2"}); + + await actions.send() + + assert_array_equals(event_type, ["pointerdown", "pointermove", "pointerdown", "pointerup", "pointerup"]); + assert_array_equals(event_id, [2, 2, 3, 2, 3]); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsWithPause.html b/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsWithPause.html new file mode 100644 index 0000000000..6b89d74c65 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/multiTouchPointsWithPause.html @@ -0,0 +1,67 @@ +<!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> +<script src="touchEvents.js"></script> + +<style> +div#test1{ + position: fixed; + touch-action: none; + top: 0; + left: 0; + width: 100px; + height: 100px; + background-color: blue; +} + +</style> + +<div id="test1"> +</div> + +<script> + +promise_test(async t => { + const test1 = document.getElementById("test1"); + const events = []; + addPointerEventListeners(t, test1, events); + await 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"}) + .pause(0, "pointer", {sourceName: "touchPointer1"}) + .pointerMove(0, 10, {origin: test1, sourceName: "touchPointer2"}) + .pointerUp({sourceName: "touchPointer1"}) + .pointerUp({sourceName: "touchPointer2"}) + .send(); + + eventEquals(events[0], {type: "pointerdown", pointerId: 2, clientX: 50, clientY: 50}); + eventEquals(events[1], {type: "pointerdown", pointerId: 3, clientX: 60, clientY: 50}); + // Allow one or two pointermove events + let index = 3; + const moveEvents = [events[2]]; + if (events[3].type === "pointermove") { + index += 1; + moveEvents.push(events[3]); + } + for (const event of moveEvents) { + if (event.pointerId === 2) { + eventEquals(event, {type: "pointermove", clientX: 50, clientY: 50}); + } else { + eventEquals(event, {type: "pointermove", pointerId: 3, clientX: 50, clientY: 60}); + } + } + let remainingEvents = events.slice(index); + assert_equals(remainingEvents.length, 2); + eventEquals(remainingEvents[0], {type: "pointerup", pointerId: 2, clientX: 50, clientY: 50}); + eventEquals(remainingEvents[1], {type: "pointerup", pointerId: 3, clientX: 50, clientY: 60}); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/pause.html b/testing/web-platform/tests/infrastructure/testdriver/actions/pause.html new file mode 100644 index 0000000000..ec33c51102 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/pause.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>TestDriver actions: 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> + +<script> +promise_test(() => { + let t0 = performance.now(); + return new test_driver.Actions() + .addTick(1000) + .send() + .then(() => assert_greater_than(performance.now() - t0, 1000)); +}) +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/penPointerEventProperties.html b/testing/web-platform/tests/infrastructure/testdriver/actions/penPointerEventProperties.html new file mode 100644 index 0000000000..ba6c15f022 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/penPointerEventProperties.html @@ -0,0 +1,71 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: pointerevent properties of pen type</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#test { + position: fixed; + touch-action: none; + top: 5px; + left: 5px; + width: 100px; + height: 100px; + background-color: blue; +} +</style> + +<div id="test"> +</div> + +<script> +let pointerDownEvent; +let pointerMoveEvent; +let receivedPointerDown = false; + +async_test(t => { + let test = document.getElementById("test"); + var eventList = ['pointermove', 'pointerdown']; + for (eventType of eventList) { + test.addEventListener(eventType, e => { + if (e.type == 'pointerdown') { + receivedPointerDown = true; + pointerDownEvent = e; + } + if (e.type == 'pointermove' && receivedPointerDown) + pointerMoveEvent = e; + }); + } + + let div = document.getElementById("test"); + let actions = new test_driver.Actions() + .addPointer("penPointer1", "pen") + .pointerMove(0, 0, {origin: test}) + .pointerDown({pressure:0.36, tiltX:-72, tiltY:9, twist:86}) + .pointerMove(15, 0, {origin: test}) + .pointerUp() + .send() + .then(t.step_func_done(() => { + assert_equals(pointerDownEvent.type, "pointerdown"); + assert_equals(pointerDownEvent.pointerType, "pen"); + assert_equals(pointerDownEvent.width, 1); + assert_equals(pointerDownEvent.height, 1); + assert_equals(Math.round(pointerDownEvent.pressure * 100) / 100, 0.36); + assert_equals(pointerDownEvent.tiltX, -72); + assert_equals(pointerDownEvent.tiltY, 9); + assert_equals(pointerDownEvent.twist, 86); + assert_equals(pointerMoveEvent.type, "pointermove"); + assert_equals(pointerMoveEvent.pointerType, "pen"); + assert_equals(pointerMoveEvent.width, 1); + assert_equals(pointerMoveEvent.height, 1); + assert_equals(Math.round(pointerMoveEvent.pressure * 100) / 100, 0.5); + assert_equals(pointerMoveEvent.tiltX, 0); + assert_equals(pointerMoveEvent.tiltY, 0); + assert_equals(pointerMoveEvent.twist, 0); + })).catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e))); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/penPointerEvents.html b/testing/web-platform/tests/infrastructure/testdriver/actions/penPointerEvents.html new file mode 100644 index 0000000000..7141fb5655 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/penPointerEvents.html @@ -0,0 +1,159 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: pointerevent properties of pen type</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> +<script src="/pointerevents/pointerevent_support.js"></script> + +<style> +div#test { + position: fixed; + touch-action: none; + top: 5px; + left: 5px; + width: 100px; + height: 100px; + background-color: blue; +} +</style> + +<div id="test"> +</div> + +<script> +let eventList = []; + +async_test(t => { + let test = document.getElementById("test"); + [ + 'pointerover', 'pointerenter', 'pointermove', 'pointerdown', 'pointerup', + 'pointerout', 'pointerleave' + ].forEach(eventType => { + test.addEventListener(eventType, e => { + eventList.push(e); + }); + }); + + let div = document.getElementById("test"); + let actions = new test_driver.Actions() + .addPointer("penPointer1", "pen") + // Force initial position to be outside the test element + .pointerMove(0, 0) + // Prevent coalescence of move events. + .pointerDown() + .pointerUp() + // Trigger over and enter events. + .pointerMove(10, 10) + // Toggle of pen-contact state between each move to prevent coalescence of + // move events. + .pointerDown() + .pointerMove(0, 0, {origin: test}) + .pointerUp() + .pointerMove(15, 0, {origin: test}) + .pointerDown() + .pointerMove(30, 0, {origin: test}) + .pointerUp() + .pointerMove(0, 0) + .send() + .then(t.step_func_done(() => { + const expectedEvents = [ + { + type: 'pointerover', + button: ButtonChange.NONE, + buttons: ButtonsBitfield.NONE + }, + { + type: 'pointerenter', + button: ButtonChange.NONE, + buttons: ButtonsBitfield.NONE + }, + { type: 'pointermove', + button: ButtonChange.NONE, + buttons: ButtonsBitfield.NONE, + clientX: 10, + clientY: 10 + }, + { + type: 'pointerdown', + button: ButtonChange.PEN_CONTACT, + buttons: ButtonsBitfield.PEN_CONTACT, + clientX: 10, + clientY: 10 + }, + { + type: 'pointermove', + button: ButtonChange.NONE, + buttons: ButtonsBitfield.PEN_CONTACT, + clientX: 55, + clientY: 55 + }, + { + type: 'pointerup', + button: ButtonChange.PEN_CONTACT, + buttons: ButtonsBitfield.NONE, + clientX: 55, + clientY: 55 + }, + { + type: 'pointermove', + button: ButtonChange.NONE, + buttons: ButtonsBitfield.NONE, + clientX: 70, + clientY: 55 + }, + { + type: 'pointerdown', + button: ButtonChange.PEN_CONTACT, + buttons: ButtonsBitfield.PEN_CONTACT, + clientX: 70, + clientY: 55 + }, + { + type: 'pointermove', + button: ButtonChange.NONE, + buttons: ButtonsBitfield.PEN_CONTACT, + clientX: 85, + clientY: 55 + }, + { + type: 'pointerup', + button: ButtonChange.PEN_CONTACT, + buttons: ButtonsBitfield.NONE, + clientX: 85, + clientY: 55 + }, + { + type: 'pointerout', + button: ButtonChange.NONE, + buttons: ButtonsBitfield.NONE, + clientX: 0, + clientY: 0 + }, + { + type: 'pointerleave', + button: ButtonChange.NONE, + buttons: ButtonsBitfield.NONE, + clientX: 0, + clientY: 0 + }, + ]; + + for (let i = 0; i < expectedEvents.length; i++) { + const expectedValue = expectedEvents[i]; + const actualValue = eventList[i]; + assert_true(!!actualValue, `Missing $[i}-th event`); + assert_equals(actualValue.pointerType, 'pen', 'Unexpected pointer type'); + for (key in expectedValue) { + assert_equals(actualValue[key], expectedValue[key], + `Mismatch in event[${i}].${key}`); + } + } + + assert_equals(eventList.length, expectedEvents.length, + 'Unexpected number of events'); + })).catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e))); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/textEditCommands.html b/testing/web-platform/tests/infrastructure/testdriver/actions/textEditCommands.html new file mode 100644 index 0000000000..0bc533ecb0 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/textEditCommands.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: text edit commands</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 { padding:0px; margin: 0px; } +</style> +<body> + <div> + <input type="text" id="text1" value="Hello World" /> + <input type="text" id="text2"> + </div> +</body> +<script> +async_test(t => { + let text1 = document.getElementById("text1"); + let text2 = document.getElementById("text2"); + text1.addEventListener("click", function() { + let text1 = document.getElementById("text1"); + text1.value="new text"; + }); + + const ctrl_key = "\uE009"; + const cmd_key = "\uE03D"; + let edit_command_key = ctrl_key; + if(navigator.platform.includes('Mac')) + edit_command_key = cmd_key; + + let actions = new test_driver.Actions() + .pointerMove(0, 0, {origin: text1}) + .pointerDown() + .pointerUp() + .addTick() + .keyDown(edit_command_key) + .keyDown("a") + .keyUp("a") + .keyDown("x") + .keyUp("x") + .keyUp(edit_command_key) + .addTick() + .pointerMove(0, 0, {origin: text2}) + .pointerDown() + .pointerUp() + .keyDown(edit_command_key) + .keyDown("v") + .keyUp("v") + .keyUp(edit_command_key); + + actions.send() + .then(t.step_func_done(() => { + assert_equals(text1.value, ""); + assert_equals(text2.value, "new text"); + })) + .catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e))); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/touchEvents.js b/testing/web-platform/tests/infrastructure/testdriver/actions/touchEvents.js new file mode 100644 index 0000000000..c1213b6693 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/touchEvents.js @@ -0,0 +1,11 @@ +function eventEquals(e, expected) { + for (const prop of Object.keys(expected)) { + assert_equals(e[prop], expected[prop], `Event ${e.type} pointerId ${e.pointerId} property ${prop}`); + } +} + +function addPointerEventListeners(test, target, events) { + for (const event of ["pointerup", "pointerdown", "pointermove"]) { + target.addEventListener(event, test.step_func(e => events.push(e))); + } +} diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/touchPointerEventProperties.html b/testing/web-platform/tests/infrastructure/testdriver/actions/touchPointerEventProperties.html new file mode 100644 index 0000000000..085889949e --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/touchPointerEventProperties.html @@ -0,0 +1,71 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: pointerevent properties of touch type</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#test { + position: fixed; + touch-action: none; + top: 5px; + left: 5px; + width: 100px; + height: 100px; + background-color: blue; +} +</style> + +<div id="test"> +</div> + +<script> +let pointerDownEvent; +let pointerMoveEvent; +let receivedPointerDown = false; + +async_test(t => { + let test = document.getElementById("test"); + var eventList = ['pointermove', 'pointerdown']; + for (eventType of eventList) { + test.addEventListener(eventType, e => { + if (e.type == 'pointerdown') { + receivedPointerDown = true; + pointerDownEvent = e; + } + if (e.type == 'pointermove' && receivedPointerDown) + pointerMoveEvent = e; + }); + } + + let div = document.getElementById("test"); + let actions = new test_driver.Actions() + .addPointer("touchPointer1", "touch") + .pointerMove(0, 0, {origin: test}) + .pointerDown({width:23, height:31, pressure:0.78}) + .pointerMove(15, 0, {origin: test, width:39, height:35, pressure:0.91}) + .pointerUp() + .send() + .then(t.step_func_done(() => { + assert_equals(pointerDownEvent.type, "pointerdown"); + assert_equals(pointerDownEvent.pointerType, "touch"); + assert_equals(pointerDownEvent.width, 23); + assert_equals(pointerDownEvent.height, 31); + assert_equals(Math.round(pointerDownEvent.pressure * 100) / 100, 0.78); + assert_equals(pointerDownEvent.tiltX, 0); + assert_equals(pointerDownEvent.tiltY, 0); + assert_equals(pointerDownEvent.twist, 0); + assert_equals(pointerMoveEvent.type, "pointermove"); + assert_equals(pointerMoveEvent.pointerType, "touch"); + assert_equals(pointerMoveEvent.width, 39); + assert_equals(pointerMoveEvent.height, 35); + assert_equals(Math.round(pointerMoveEvent.pressure * 100) / 100, 0.91); + assert_equals(pointerMoveEvent.tiltX, 0); + assert_equals(pointerMoveEvent.tiltY, 0); + assert_equals(pointerMoveEvent.twist, 0); + })).catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e))); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/actions/wheelScroll.html b/testing/web-platform/tests/infrastructure/testdriver/actions/wheelScroll.html new file mode 100644 index 0000000000..0447c17ef9 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/actions/wheelScroll.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver actions: wheel scroll</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> +#container { + width: 200px; + height: 200px; + overflow: scroll; +} + +#content { + width: 600px; + height: 1000px; + background-color: blue; +} + +</style> + +<div id="container"> + <div id="content"></div> +</div> + +<script> +let event_type = []; +let event_id = []; + +promise_test(async t => { + let container = document.getElementById("container"); + container.addEventListener("wheel", + e => {event_type.push(e.type);}); + + let actions = new test_driver.Actions() + .scroll(0, 0, 0, 50, {origin: container}); + + await actions.send() + assert_array_equals(event_type, ["wheel"]); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/bless.html b/testing/web-platform/tests/infrastructure/testdriver/bless.html new file mode 100644 index 0000000000..12257df01b --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/bless.html @@ -0,0 +1,114 @@ +<!DOCTYPE html> +<head> + <meta charset="utf-8"> + <title>TestDriver bless method</title> + <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> +promise_test(() => { + return test_driver.bless('empty', () => {}); +}, 'functions in the absence of a `body` element'); + </script> +</head> +<body> +<script> +// At the time of this writing, the only standard requirement for user +// activation concerns the interaction between iframe elements and their parent +// browsing contexts [1]. Because testdriver.js currently cannot operate within +// an iframe, the standard requirement cannot be used to verify the correctness +// of the `bless` method. Instead, rely on the optional behavior of early exit +// and rejecting in `video.play()` if the media is not "allowed to play". [2] +// Browsers which don't implement this will pass this test spuriously. +// +// [1] https://html.spec.whatwg.org/multipage/origin.html#attr-iframe-sandbox-allow-top-navigation-by-user-activation +// [2] https://html.spec.whatwg.org/multipage/media.html#allowed-to-play +promise_test(t => { + const video = document.createElement('video'); + document.body.appendChild(video); + t.add_cleanup(() => video.remove()); + return test_driver.bless('start video playback', () => { + // `paused` changes before `play()` returns when "allowed to play", so the + // promise, if any, is ignored. + assert_true(video.paused); + const playPromise = video.play(); + assert_false(video.paused); + if (playPromise) { + playPromise.catch(() => {}); + } + }); +}, 'user activation'); + +promise_test(() => { + return test_driver.bless('demonstrates return value without action') + .then((value) => { + assert_equals(value, null); + }); +}, 'no action function provided'); + +promise_test(() => { + const expectedValue = {}; + + return test_driver.bless('demonstrate a synchronous return value', () => { + return expectedValue; + }).then((actualValue) => { + assert_equals( + actualValue, + expectedValue, + 'the promise should be fulfilled with the returned value' + ); + }); + +}, 'synchronous return value'); + +promise_test(() => { + const expectedError = new Error(); + + return test_driver.bless('demonstrates a synchronous error', () => { + throw expectedError; + }) + .then(() => { + assert_unreached('the promise should be rejected'); + }, (actualError) => { + assert_equals( + actualError, + expectedError, + 'the promise should be rejected with the thrown value' + ); + }); +}, 'synchronous error'); + +promise_test(() => { + const expectedValue = {}; + + return test_driver.bless('demonstrate an asynchronous return value', () => { + return Promise.resolve(expectedValue); + }).then((actualValue) => { + assert_equals( + actualValue, + expectedValue, + 'the promise should be fulfilled with the fulfillment value' + ); + }); + +}, 'asynchronous return value'); + +promise_test(() => { + const expectedError = new Error(); + + return test_driver.bless('demonstrates an asynchronous error', () => { + return Promise.reject(expectedError); + }) + .then(() => { + assert_unreached('the promise should be rejected'); + }, (actualError) => { + assert_equals( + actualError, + expectedError, + 'the promise should be rejected with the rejected value' + ); + }); +}, 'asynchronous error'); +</script> +</body> diff --git a/testing/web-platform/tests/infrastructure/testdriver/click-multiple.html b/testing/web-platform/tests/infrastructure/testdriver/click-multiple.html new file mode 100644 index 0000000000..ed834c5571 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/click-multiple.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver multiple consecutive clicks</title> +<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> + +<button type="button" id="button1">Button 1</button> +<button type="button" id="button2">Button 2</button> +<button type="button" id="button3">Button 3</button> + +<script> +buttons = [ + document.getElementById("button1"), + document.getElementById("button2"), + document.getElementById("button3"), +]; + +promise_test(async t => { + clicked = [false, false, false]; + for (let i = 0; i < buttons.length; i++) { + buttons[i].addEventListener("click", () => { + clicked[i] = true; + }); + } + + await Promise.all([ + test_driver.click(buttons[0]), + test_driver.click(buttons[1]), + test_driver.click(buttons[2]), + ]); + + assert_true(clicked[0]); + assert_true(clicked[1]); + assert_true(clicked[2]); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/click.html b/testing/web-platform/tests/infrastructure/testdriver/click.html new file mode 100644 index 0000000000..37721ad9ef --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/click.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver click method</title> +<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> + +<button type="button" id="button">Button</button> + +<script> +async_test(t => { + let button = document.getElementById("button"); + test_driver + .click(button) + .then(() => t.done()) + .catch(t.unreached_func("click failed")); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/click_child.html b/testing/web-platform/tests/infrastructure/testdriver/click_child.html new file mode 100644 index 0000000000..5899841c4c --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/click_child.html @@ -0,0 +1,7 @@ +<!doctype html> +<button id="button">Button</button> +<div id="log">FAIL</div> +<script> +document.getElementById("button").addEventListener("click", () => + document.getElementById("log").textContent = "PASS"); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/click_child_crossorigin.html b/testing/web-platform/tests/infrastructure/testdriver/click_child_crossorigin.html new file mode 100644 index 0000000000..6a8c6840a2 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/click_child_crossorigin.html @@ -0,0 +1,18 @@ +<!doctype html> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<button id="button">Button</button> +<div id="log">FAIL</div> +<script> +let button = document.getElementById("button"); +button.addEventListener("click", () => + document.getElementById("log").textContent = "PASS"); + +addEventListener("load", () => { + test_driver.set_test_context(parent.opener); + test_driver.click(button) + .then(() => test_driver.message_test("PASS", "*")) + .catch(() => test_driver.message_test("FAIL", "*")); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/click_child_testdriver.html b/testing/web-platform/tests/infrastructure/testdriver/click_child_testdriver.html new file mode 100644 index 0000000000..2c26a963f4 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/click_child_testdriver.html @@ -0,0 +1,18 @@ +<!doctype html> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<button id="button">Button</button> +<div id="log">FAIL</div> +<script> +let button = document.getElementById("button"); +button.addEventListener("click", () => + document.getElementById("log").textContent = "PASS"); + +addEventListener("load", () => { + test_driver.set_test_context(parent); + test_driver.click(button) + .then(() => test_driver.message_test("PASS", "*")) + .catch(() => test_driver.message_test("FAIL", "*")); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/click_iframe.html b/testing/web-platform/tests/infrastructure/testdriver/click_iframe.html new file mode 100644 index 0000000000..167a91afcf --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/click_iframe.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver click on a document in an iframe</title> +<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> + +<iframe src="click_child.html"></iframe> + +<script> +setup({single_test: true}); +addEventListener("load", () => { + let child = frames[0]; + let button = child.document.getElementById("button"); + test_driver + .click(button) + .then(() => { + assert_equals(child.document.getElementById("log").textContent, "PASS"); + done(); + }) + .catch(() => assert_unreached("click failed")); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/click_iframe_crossorigin.sub.html b/testing/web-platform/tests/infrastructure/testdriver/click_iframe_crossorigin.sub.html new file mode 100644 index 0000000000..df2b4477ca --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/click_iframe_crossorigin.sub.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver click on a document in an iframe</title> +<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> +setup({single_test: true}); +addEventListener("message", (msg) => { + if (msg.data === "PASS") { + done(); + } else if (msg.data === "FAIL") { + assert_unreached("click failed") + } +}); +</script> + +<!-- Make sure we add the event listener before loading the iframe, to avoid +potentially missing messages from the child. --> +<iframe src="https://{{host}}:{{ports[https][1]}}/infrastructure/testdriver/click_child_testdriver.html"></iframe> + diff --git a/testing/web-platform/tests/infrastructure/testdriver/click_nested.html b/testing/web-platform/tests/infrastructure/testdriver/click_nested.html new file mode 100644 index 0000000000..378b9e8c0f --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/click_nested.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver click method with multiple windows and nested iframe</title> +<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> + +<iframe src="about:blank"></iframe> + +<script> +setup({single_test: true}); + +window.open("about:blank") +var child = window.open("click_outer_child.html") +window.open("about:blank") + +addEventListener("load",() => { + child.addEventListener("load", () => { + let doc = child.frames[2].document; + let button = doc.getElementById("button"); + test_driver + .click(button) + .then(() => { + assert_equals(doc.getElementById("log").textContent, "PASS"); + done(); + }) + .catch(() => assert_unreached("click failed")); + }); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/click_nested_crossorigin.sub.html b/testing/web-platform/tests/infrastructure/testdriver/click_nested_crossorigin.sub.html new file mode 100644 index 0000000000..af90951df1 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/click_nested_crossorigin.sub.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver click method with multiple windows and nested iframe</title> +<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> + +<iframe src="about:blank"></iframe> + +<script> +setup({single_test: true}); + +window.open("about:blank") +var child = window.open("https://{{host}}:{{ports[https][0]}}/infrastructure/testdriver/click_outer_child.sub.html") +window.open("about:blank") + +addEventListener("message", (msg) => { + if (msg.data === "PASS") { + done(); + } else if (msg.data === "FAIL") { + assert_unreached("click failed") + } +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/click_outer_child.html b/testing/web-platform/tests/infrastructure/testdriver/click_outer_child.html new file mode 100644 index 0000000000..ae4944635f --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/click_outer_child.html @@ -0,0 +1,4 @@ +<!doctype html> +<iframe src="about:blank"></iframe> +<iframe src="about:blank"></iframe> +<iframe src="click_child.html"></iframe> diff --git a/testing/web-platform/tests/infrastructure/testdriver/click_outer_child.sub.html b/testing/web-platform/tests/infrastructure/testdriver/click_outer_child.sub.html new file mode 100644 index 0000000000..8e72223f91 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/click_outer_child.sub.html @@ -0,0 +1,4 @@ +<!doctype html> +<iframe src="about:blank"></iframe> +<iframe src="about:blank"></iframe> +<iframe src="https://{{host}}:{{ports[https][1]}}/infrastructure/testdriver/click_child_crossorigin.html"></iframe> diff --git a/testing/web-platform/tests/infrastructure/testdriver/click_window.html b/testing/web-platform/tests/infrastructure/testdriver/click_window.html new file mode 100644 index 0000000000..614a92478e --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/click_window.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver click method in window</title> +<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> +setup({single_test: true}); +addEventListener("load", () => { + let child = window.open("click_child.html"); + child.addEventListener("load", () => { + let button = child.document.getElementById("button"); + test_driver + .click(button) + .then(() => { + assert_equals(child.document.getElementById("log").textContent, "PASS"); + done(); + }) + .catch(() => assert_unreached("click failed")); + }); +}) +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/delete_all_cookies.html b/testing/web-platform/tests/infrastructure/testdriver/delete_all_cookies.html new file mode 100644 index 0000000000..8d7b82ab04 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/delete_all_cookies.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver delete_all_cookies method</title> +<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> +promise_test(async t => { + document.cookie = "test1=1"; + document.cookie = "test2=2; path=/"; + document.cookie = "test3=3; path=/cookies/resources"; + + return test_driver.delete_all_cookies().then(() => { + assert_true(document.cookie === ""); + }); +}, "DOM-set cookies get deleted"); + +promise_test(async t => { + const cookies = ["test1=1", "test2=2; path=/", "test3=3; path=/cookies/resources", "test4=4; HttpOnly"]; + for (const cookie of cookies) { + const encoded = encodeURIComponent(JSON.stringify(cookie)); + await fetch(`/cookies/resources/cookie.py?set=${encoded}`) + } + + return test_driver.delete_all_cookies().then(() => { + assert_true(document.cookie === ""); + }); +}, "HTTP-set cookies get deleted"); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/file_upload.py b/testing/web-platform/tests/infrastructure/testdriver/file_upload.py new file mode 100644 index 0000000000..9c4dd75438 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/file_upload.py @@ -0,0 +1,2 @@ +def main(request, response): + return b"PASS" if request.POST[b"file_input"].file.read() == b"File to upload\n" else b"FAIL" diff --git a/testing/web-platform/tests/infrastructure/testdriver/file_upload.sub.html b/testing/web-platform/tests/infrastructure/testdriver/file_upload.sub.html new file mode 100644 index 0000000000..0490e89c42 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/file_upload.sub.html @@ -0,0 +1,26 @@ +<!doctype html> +<meta charset=utf8> +<title>File upload using testdriver</title> +<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> +<form id="form"> + <input id="file_input" name="file_input" type="file"> +</form> +<script> +promise_test(() => { + let form = document.getElementById("form"); + let input = document.getElementById("file_input"); + return test_driver + .send_keys(input, String.raw`{{fs_path(file_upload_data.txt)}}`) + .then(() => + fetch("file_upload.py", + {method: "POST", + body: new FormData(form)})) + .then(response => response.text()) + .then(data => { + assert_equals(data, "PASS"); + }); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/file_upload_data.txt b/testing/web-platform/tests/infrastructure/testdriver/file_upload_data.txt new file mode 100644 index 0000000000..097d2a3a3f --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/file_upload_data.txt @@ -0,0 +1 @@ +File to upload diff --git a/testing/web-platform/tests/infrastructure/testdriver/generate_test_report.html b/testing/web-platform/tests/infrastructure/testdriver/generate_test_report.html new file mode 100644 index 0000000000..168c9e9956 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/generate_test_report.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver generate_test_report method</title> +<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> +async_test(t => { + test_driver + .generate_test_report("Test message.") + .then(() => t.done()) + .catch(t.unreached_func("generate_test_report failed")); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/get_all_cookies.sub.html b/testing/web-platform/tests/infrastructure/testdriver/get_all_cookies.sub.html new file mode 100644 index 0000000000..84f93af0a3 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/get_all_cookies.sub.html @@ -0,0 +1,95 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver get_all_cookies method in HTTP</title> +<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> +promise_test(async t => { + t.add_cleanup(test_driver.delete_all_cookies); + const kTenDaysFromNow = new Date(Date.now() + 10 * 24 * 60 * 60 * 1000); + document.cookie = "test0=0"; + document.cookie = `test1=1; Expires=${kTenDaysFromNow.toUTCString()}`; + document.cookie = "test2=2; Path=/"; + // document.cookie = "test3=3; HttpOnly"; This is set in the headers file. + document.cookie = "test4=4; Secure"; + document.cookie = "test5=5; SameSite=Strict"; + document.cookie = "test6=6; SameSite=None; Secure"; + document.cookie = "test7=7; SameSite=Lax"; + const cookies = await test_driver.get_all_cookies(); + assert_equals(cookies.length, 6); + let cookieMap = new Map(); + for (const cookie of cookies) { + cookieMap.set(cookie["name"], cookie); + } + + // test0 + assert_equals(cookieMap.get("test0")["name"], "test0"); + assert_equals(cookieMap.get("test0")["value"], "0"); + assert_equals(cookieMap.get("test0")["path"], "/infrastructure/testdriver"); + assert_equals(cookieMap.get("test0")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test0")["secure"], false); + assert_equals(cookieMap.get("test0")["httpOnly"], false); + assert_equals(cookieMap.get("test0")["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); + + // test1 [Expires in 10 days] + assert_equals(cookieMap.get("test1")["name"], "test1"); + assert_equals(cookieMap.get("test1")["value"], "1"); + assert_equals(cookieMap.get("test1")["path"], "/infrastructure/testdriver"); + assert_equals(cookieMap.get("test1")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test1")["secure"], false); + assert_equals(cookieMap.get("test1")["httpOnly"], false); + assert_equals(cookieMap.get("test1")["expiry"], Math.floor(kTenDaysFromNow.getTime()/1000)); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); + + // test2 [Path /] + assert_equals(cookieMap.get("test2")["name"], "test2"); + assert_equals(cookieMap.get("test2")["value"], "2"); + assert_equals(cookieMap.get("test2")["path"], "/"); + assert_equals(cookieMap.get("test2")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test2")["secure"], false); + assert_equals(cookieMap.get("test2")["httpOnly"], false); + assert_equals(cookieMap.get("test2")["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); + + // test3 [HttpOnly] + assert_equals(cookieMap.get("test3")["name"], "test3"); + assert_equals(cookieMap.get("test3")["value"], "3"); + assert_equals(cookieMap.get("test3")["path"], "/infrastructure/testdriver"); + assert_equals(cookieMap.get("test3")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test3")["secure"], false); + assert_equals(cookieMap.get("test3")["httpOnly"], true); + assert_equals(cookieMap.get("test3")["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); + + // test4 [Secure] Omitted + + // test5 [SameSite Strict] + assert_equals(cookieMap.get("test5")["name"], "test5"); + assert_equals(cookieMap.get("test5")["value"], "5"); + assert_equals(cookieMap.get("test5")["path"], "/infrastructure/testdriver"); + assert_equals(cookieMap.get("test5")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test5")["secure"], false); + assert_equals(cookieMap.get("test5")["httpOnly"], false); + assert_equals(cookieMap.get("test5")["expiry"], undefined); + assert_equals(cookieMap.get("test5")["sameSite"], "Strict"); + + // test6 [SameSite None] Omitted + + // test7 [SameSite Lax] + assert_equals(cookieMap.get("test7")["name"], "test7"); + assert_equals(cookieMap.get("test7")["value"], "7"); + assert_equals(cookieMap.get("test7")["path"], "/infrastructure/testdriver"); + assert_equals(cookieMap.get("test7")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test7")["secure"], false); + assert_equals(cookieMap.get("test7")["httpOnly"], false); + assert_equals(cookieMap.get("test7")["expiry"], undefined); + assert_equals(cookieMap.get("test7")["sameSite"], "Lax"); +}, "Get all HTTP cookies"); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/get_all_cookies.sub.html.headers b/testing/web-platform/tests/infrastructure/testdriver/get_all_cookies.sub.html.headers new file mode 100644 index 0000000000..3dc39a5673 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/get_all_cookies.sub.html.headers @@ -0,0 +1 @@ +Set-Cookie: test3=3; HttpOnly diff --git a/testing/web-platform/tests/infrastructure/testdriver/get_all_cookies.sub.https.html b/testing/web-platform/tests/infrastructure/testdriver/get_all_cookies.sub.https.html new file mode 100644 index 0000000000..e94167133b --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/get_all_cookies.sub.https.html @@ -0,0 +1,112 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver get_all_cookies method in HTTPS</title> +<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> +promise_test(async t => { + t.add_cleanup(test_driver.delete_all_cookies); + const kTenDaysFromNow = new Date(Date.now() + 10 * 24 * 60 * 60 * 1000); + document.cookie = "test0=0"; + document.cookie = `test1=1; Expires=${kTenDaysFromNow.toUTCString()}`; + document.cookie = "test2=2; Path=/"; + // document.cookie = "test3=3; HttpOnly"; This is set in the headers file. + document.cookie = "test4=4; Secure"; + document.cookie = "test5=5; SameSite=Strict"; + document.cookie = "test6=6; SameSite=None; Secure"; + document.cookie = "test7=7; SameSite=Lax"; + const cookies = await test_driver.get_all_cookies(); + assert_equals(cookies.length, 8); + let cookieMap = new Map(); + for (const cookie of cookies) { + cookieMap.set(cookie["name"], cookie); + } + + // test0 + assert_equals(cookieMap.get("test0")["name"], "test0"); + assert_equals(cookieMap.get("test0")["value"], "0"); + assert_equals(cookieMap.get("test0")["path"], "/infrastructure/testdriver"); + assert_equals(cookieMap.get("test0")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test0")["secure"], false); + assert_equals(cookieMap.get("test0")["httpOnly"], false); + assert_equals(cookieMap.get("test0")["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); + + // test1 [Expires in 10 days] + assert_equals(cookieMap.get("test1")["name"], "test1"); + assert_equals(cookieMap.get("test1")["value"], "1"); + assert_equals(cookieMap.get("test1")["path"], "/infrastructure/testdriver"); + assert_equals(cookieMap.get("test1")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test1")["secure"], false); + assert_equals(cookieMap.get("test1")["httpOnly"], false); + assert_equals(cookieMap.get("test1")["expiry"], Math.floor(kTenDaysFromNow.getTime()/1000)); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); + + // test2 [Path /] + assert_equals(cookieMap.get("test2")["name"], "test2"); + assert_equals(cookieMap.get("test2")["value"], "2"); + assert_equals(cookieMap.get("test2")["path"], "/"); + assert_equals(cookieMap.get("test2")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test2")["secure"], false); + assert_equals(cookieMap.get("test2")["httpOnly"], false); + assert_equals(cookieMap.get("test2")["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); + + // test3 [HttpOnly] + assert_equals(cookieMap.get("test3")["name"], "test3"); + assert_equals(cookieMap.get("test3")["value"], "3"); + assert_equals(cookieMap.get("test3")["path"], "/infrastructure/testdriver"); + assert_equals(cookieMap.get("test3")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test3")["secure"], false); + assert_equals(cookieMap.get("test3")["httpOnly"], true); + assert_equals(cookieMap.get("test3")["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); + + // test4 [Secure] + assert_equals(cookieMap.get("test4")["name"], "test4"); + assert_equals(cookieMap.get("test4")["value"], "4"); + assert_equals(cookieMap.get("test4")["path"], "/infrastructure/testdriver"); + assert_equals(cookieMap.get("test4")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test4")["secure"], true); + assert_equals(cookieMap.get("test4")["httpOnly"], false); + assert_equals(cookieMap.get("test4")["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookieMap.get("test0")["sameSite"], "Lax"); + + // test5 [SameSite Strict] + assert_equals(cookieMap.get("test5")["name"], "test5"); + assert_equals(cookieMap.get("test5")["value"], "5"); + assert_equals(cookieMap.get("test5")["path"], "/infrastructure/testdriver"); + assert_equals(cookieMap.get("test5")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test5")["secure"], false); + assert_equals(cookieMap.get("test5")["httpOnly"], false); + assert_equals(cookieMap.get("test5")["expiry"], undefined); + assert_equals(cookieMap.get("test5")["sameSite"], "Strict"); + + // test6 [SameSite None] + assert_equals(cookieMap.get("test6")["name"], "test6"); + assert_equals(cookieMap.get("test6")["value"], "6"); + assert_equals(cookieMap.get("test6")["path"], "/infrastructure/testdriver"); + assert_equals(cookieMap.get("test6")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test6")["secure"], true); + assert_equals(cookieMap.get("test6")["httpOnly"], false); + assert_equals(cookieMap.get("test6")["expiry"], undefined); + assert_equals(cookieMap.get("test6")["sameSite"], "None"); + + // test7 [SameSite Lax] + assert_equals(cookieMap.get("test7")["name"], "test7"); + assert_equals(cookieMap.get("test7")["value"], "7"); + assert_equals(cookieMap.get("test7")["path"], "/infrastructure/testdriver"); + assert_equals(cookieMap.get("test7")["domain"], "{{host}}"); + assert_equals(cookieMap.get("test7")["secure"], false); + assert_equals(cookieMap.get("test7")["httpOnly"], false); + assert_equals(cookieMap.get("test7")["expiry"], undefined); + assert_equals(cookieMap.get("test7")["sameSite"], "Lax"); +}, "Get all HTTPS cookies"); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/get_all_cookies.sub.https.html.headers b/testing/web-platform/tests/infrastructure/testdriver/get_all_cookies.sub.https.html.headers new file mode 100644 index 0000000000..3dc39a5673 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/get_all_cookies.sub.https.html.headers @@ -0,0 +1 @@ +Set-Cookie: test3=3; HttpOnly diff --git a/testing/web-platform/tests/infrastructure/testdriver/get_named_cookie.sub.html b/testing/web-platform/tests/infrastructure/testdriver/get_named_cookie.sub.html new file mode 100644 index 0000000000..28950e2536 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/get_named_cookie.sub.html @@ -0,0 +1,105 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver get_named_cookie method HTTP</title> +<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> +promise_test(async t => { + t.add_cleanup(test_driver.delete_all_cookies); + const kTenDaysFromNow = new Date(Date.now() + 10 * 24 * 60 * 60 * 1000); + document.cookie = "test0=0"; + document.cookie = `test1=1; Expires=${kTenDaysFromNow.toUTCString()}`; + document.cookie = "test2=2; Path=/"; + // document.cookie = "test3=3; HttpOnly"; This is set in the headers file. + document.cookie = "test4=4; Secure"; + document.cookie = "test5=5; SameSite=Strict"; + document.cookie = "test6=6; SameSite=None; Secure"; + document.cookie = "test7=7; SameSite=Lax"; + + // test0 + let cookie = await test_driver.get_named_cookie("test0"); + assert_equals(cookie["name"], "test0"); + assert_equals(cookie["value"], "0"); + assert_equals(cookie["path"], "/infrastructure/testdriver"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], false); + assert_equals(cookie["httpOnly"], false); + assert_equals(cookie["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); + + // test1 [Expires in 10 days] + cookie = await test_driver.get_named_cookie("test1"); + assert_equals(cookie["name"], "test1"); + assert_equals(cookie["value"], "1"); + assert_equals(cookie["path"], "/infrastructure/testdriver"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], false); + assert_equals(cookie["httpOnly"], false); + assert_equals(cookie["expiry"], Math.floor(kTenDaysFromNow.getTime()/1000)); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); + + // test2 [Path /] + cookie = await test_driver.get_named_cookie("test2"); + assert_equals(cookie["name"], "test2"); + assert_equals(cookie["value"], "2"); + assert_equals(cookie["path"], "/"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], false); + assert_equals(cookie["httpOnly"], false); + assert_equals(cookie["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); + + // test3 [HttpOnly] + cookie = await test_driver.get_named_cookie("test3"); + assert_equals(cookie["name"], "test3"); + assert_equals(cookie["value"], "3"); + assert_equals(cookie["path"], "/infrastructure/testdriver"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], false); + assert_equals(cookie["httpOnly"], true); + assert_equals(cookie["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); + + // test4 [Secure] Omitted + try { + await test_driver.get_named_cookie("test4"); + } catch(e) { + assert_equals(e.message, "no such cookie"); + } + + // test5 [SameSite Strict] + cookie = await test_driver.get_named_cookie("test5"); + assert_equals(cookie["name"], "test5"); + assert_equals(cookie["value"], "5"); + assert_equals(cookie["path"], "/infrastructure/testdriver"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], false); + assert_equals(cookie["httpOnly"], false); + assert_equals(cookie["expiry"], undefined); + assert_equals(cookie["sameSite"], "Strict"); + + // test6 [SameSite None] Omitted + try { + await test_driver.get_named_cookie("test6"); + } catch(e) { + assert_equals(e.message, "no such cookie"); + } + + // test7 [SameSite Strict] + cookie = await test_driver.get_named_cookie("test7"); + assert_equals(cookie["name"], "test7"); + assert_equals(cookie["value"], "7"); + assert_equals(cookie["path"], "/infrastructure/testdriver"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], false); + assert_equals(cookie["httpOnly"], false); + assert_equals(cookie["expiry"], undefined); + assert_equals(cookie["sameSite"], "Lax"); +}, "Get Named HTTP cookie"); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/get_named_cookie.sub.html.headers b/testing/web-platform/tests/infrastructure/testdriver/get_named_cookie.sub.html.headers new file mode 100644 index 0000000000..3dc39a5673 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/get_named_cookie.sub.html.headers @@ -0,0 +1 @@ +Set-Cookie: test3=3; HttpOnly diff --git a/testing/web-platform/tests/infrastructure/testdriver/get_named_cookie.sub.https.html b/testing/web-platform/tests/infrastructure/testdriver/get_named_cookie.sub.https.html new file mode 100644 index 0000000000..8e8f443381 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/get_named_cookie.sub.https.html @@ -0,0 +1,114 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver get_named_cookie method HTTPS</title> +<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> +promise_test(async t => { + t.add_cleanup(test_driver.delete_all_cookies); + const kTenDaysFromNow = new Date(Date.now() + 10 * 24 * 60 * 60 * 1000); + document.cookie = "test0=0"; + document.cookie = `test1=1; Expires=${kTenDaysFromNow.toUTCString()}`; + document.cookie = "test2=2; Path=/"; + // document.cookie = "test3=3; HttpOnly"; This is set in the headers file. + document.cookie = "test4=4; Secure"; + document.cookie = "test5=5; SameSite=Strict"; + document.cookie = "test6=6; SameSite=None; Secure"; + document.cookie = "test7=7; SameSite=Lax"; + + // test0 + let cookie = await test_driver.get_named_cookie("test0"); + assert_equals(cookie["name"], "test0"); + assert_equals(cookie["value"], "0"); + assert_equals(cookie["path"], "/infrastructure/testdriver"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], false); + assert_equals(cookie["httpOnly"], false); + assert_equals(cookie["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); + + // test1 [Expires in 10 days] + cookie = await test_driver.get_named_cookie("test1"); + assert_equals(cookie["name"], "test1"); + assert_equals(cookie["value"], "1"); + assert_equals(cookie["path"], "/infrastructure/testdriver"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], false); + assert_equals(cookie["httpOnly"], false); + assert_equals(cookie["expiry"], Math.floor(kTenDaysFromNow.getTime()/1000)); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); + + // test2 [Path /] + cookie = await test_driver.get_named_cookie("test2"); + assert_equals(cookie["name"], "test2"); + assert_equals(cookie["value"], "2"); + assert_equals(cookie["path"], "/"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], false); + assert_equals(cookie["httpOnly"], false); + assert_equals(cookie["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); + + // test3 [HttpOnly] + cookie = await test_driver.get_named_cookie("test3"); + assert_equals(cookie["name"], "test3"); + assert_equals(cookie["value"], "3"); + assert_equals(cookie["path"], "/infrastructure/testdriver"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], false); + assert_equals(cookie["httpOnly"], true); + assert_equals(cookie["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); + + // test4 [Secure] + cookie = await test_driver.get_named_cookie("test4"); + assert_equals(cookie["name"], "test4"); + assert_equals(cookie["value"], "4"); + assert_equals(cookie["path"], "/infrastructure/testdriver"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], true); + assert_equals(cookie["httpOnly"], false); + assert_equals(cookie["expiry"], undefined); + // The 'default lax' behavior varies by browser. + // assert_equals(cookie["sameSite"], "Lax"); + + // test5 [SameSite Strict] + cookie = await test_driver.get_named_cookie("test5"); + assert_equals(cookie["name"], "test5"); + assert_equals(cookie["value"], "5"); + assert_equals(cookie["path"], "/infrastructure/testdriver"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], false); + assert_equals(cookie["httpOnly"], false); + assert_equals(cookie["expiry"], undefined); + assert_equals(cookie["sameSite"], "Strict"); + + // test6 [SameSite None] + cookie = await test_driver.get_named_cookie("test6"); + assert_equals(cookie["name"], "test6"); + assert_equals(cookie["value"], "6"); + assert_equals(cookie["path"], "/infrastructure/testdriver"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], true); + assert_equals(cookie["httpOnly"], false); + assert_equals(cookie["expiry"], undefined); + assert_equals(cookie["sameSite"], "None"); + + // test7 [SameSite Strict] + cookie = await test_driver.get_named_cookie("test7"); + assert_equals(cookie["name"], "test7"); + assert_equals(cookie["value"], "7"); + assert_equals(cookie["path"], "/infrastructure/testdriver"); + assert_equals(cookie["domain"], "{{host}}"); + assert_equals(cookie["secure"], false); + assert_equals(cookie["httpOnly"], false); + assert_equals(cookie["expiry"], undefined); + assert_equals(cookie["sameSite"], "Lax"); +}, "Get Named HTTPS cookie"); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/get_named_cookie.sub.https.html.headers b/testing/web-platform/tests/infrastructure/testdriver/get_named_cookie.sub.https.html.headers new file mode 100644 index 0000000000..3dc39a5673 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/get_named_cookie.sub.https.html.headers @@ -0,0 +1 @@ +Set-Cookie: test3=3; HttpOnly diff --git a/testing/web-platform/tests/infrastructure/testdriver/send_keys.html b/testing/web-platform/tests/infrastructure/testdriver/send_keys.html new file mode 100644 index 0000000000..71ca4405f4 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/send_keys.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver send keys method</title> +<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> + +<input type="text" id="text">Text Input</button> + +<script> +async_test(t => { + let input_text = "Hello, wpt!"; + let text_box = document.getElementById("text"); + test_driver + .send_keys(text_box, input_text) + .then(() => { + assert_equals(text_box.value, input_text); + t.done(); + }) + .catch(t.unreached_func("send keys failed")); +}); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/set_permission.https.html b/testing/web-platform/tests/infrastructure/testdriver/set_permission.https.html new file mode 100644 index 0000000000..7bc42a8538 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/set_permission.https.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<title>TestDriver set_permission method</title> +<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> + const descriptor = { name: "geolocation" }; + + promise_test(async (t) => { + await test_driver.set_permission(descriptor, "granted"); + permission = await navigator.permissions.query(descriptor); + assert_equals(permission.state, "granted"); + }, "Grant Permission"); + + promise_test(async (t) => { + await test_driver.set_permission(descriptor, "denied"); + permission = await navigator.permissions.query(descriptor); + assert_equals(permission.state, "denied"); + }, "Deny Permission"); +</script> diff --git a/testing/web-platform/tests/infrastructure/testdriver/virtual_authenticator.html b/testing/web-platform/tests/infrastructure/testdriver/virtual_authenticator.html new file mode 100644 index 0000000000..04c14719d4 --- /dev/null +++ b/testing/web-platform/tests/infrastructure/testdriver/virtual_authenticator.html @@ -0,0 +1,88 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>TestDriver virtual authenticator methods</title> +<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> +"use strict"; + +// Encodes |data| into a base64url string. There is no '=' padding, and the +// characters '-' and '_' must be used instead of '+' and '/', respectively. +function base64urlEncode(data) { + let result = btoa(data); + return result.replaceAll("=", "").replaceAll("+", "-").replaceAll("/", "_"); +} + +// The example attestation private key from the U2F spec at +// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html#registration-example +// PKCS.8 encoded without encryption, as a base64url string. +const private_key = + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; +let credential_id = base64urlEncode("cred-1"); +let credential = { + credentialId: credential_id, + rpId: window.location.hostname, + privateKey: private_key, + signCount: 0, + isResidentCredential: false, +}; + +let authenticator_id = null; + +promise_test(async t => { + authenticator_id = await test_driver.add_virtual_authenticator({ + protocol: "ctap1/u2f", + transport: "usb", + }); +}, "Can create an authenticator"); + +promise_test(async t => { + return test_driver.add_credential(authenticator_id, credential); +}, "Can add a credential"); + +promise_test(async t => { + let credentials = await test_driver.get_credentials(authenticator_id); + assert_equals(credentials.length, 1); + // The U2F REGISTER operation stores the hash of the rpId, so the rpId + // itself may not be available on the returned credential. + assert_equals(credentials[0].credentialId, credential.credentialId); + assert_equals(credentials[0].privateKey, credential.privateKey); + assert_equals(credentials[0].signCount, credential.signCount); + assert_equals(credentials[0].isResidentCredential, + credential.isResidentCredential); +}, "Can get the credentials"); + +promise_test(async t => { + await test_driver.remove_credential(authenticator_id, credential_id); + let credentials = await test_driver.get_credentials(authenticator_id); + assert_equals(credentials.length, 0); +}, "Can remove a credential"); + +promise_test(async t => { + let credential1 = credential; + let credential2 = + Object.assign({}, credential, {credentialId: base64urlEncode("cred-2")}); + await test_driver.add_credential(authenticator_id, credential1); + await test_driver.add_credential(authenticator_id, credential2); + + let credentials = await test_driver.get_credentials(authenticator_id); + assert_equals(credentials.length, 2); + + await test_driver.remove_all_credentials(authenticator_id); + credentials = await test_driver.get_credentials(authenticator_id); + assert_equals(credentials.length, 0); +}, "Can remove all credentials"); + +promise_test(async t => { + await test_driver.set_user_verified(authenticator_id, {isUserVerified: true}); + await test_driver.set_user_verified(authenticator_id, {isUserVerified: false}); +}, "Can set user verified"); + +promise_test(async t => { + await test_driver.remove_virtual_authenticator(authenticator_id); +}, "Can remove a virtual authenticator"); +</script> |