This test passes if it has the same output as the reference. You see the word "before", a small space, and then the word "after".
+beforeafter diff --git a/tests/wpt/web-platform-tests/css/css-contain/reference/contain-size-fieldset-001-ref.html b/tests/wpt/web-platform-tests/css/css-contain/reference/contain-size-fieldset-001-ref.html new file mode 100644 index 00000000000..85f5c73c2ec --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-contain/reference/contain-size-fieldset-001-ref.html @@ -0,0 +1,15 @@ + + +This test passes if it has the same output as the reference. You see the word "before", a small space, and then the word "after".
+beforeafter diff --git a/tests/wpt/web-platform-tests/css/css-grid/alignment/grid-alignment-style-changes-001.html b/tests/wpt/web-platform-tests/css/css-grid/alignment/grid-alignment-style-changes-001.html new file mode 100644 index 00000000000..25ce0619dbf --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-grid/alignment/grid-alignment-style-changes-001.html @@ -0,0 +1,62 @@ + + +flex rows - column-axis baseline - the blue orthogonal item didn't participate in the first iteration+
flex row - column-axis baseline - the blue relative sized item didn't participate in the first iterarion+
flex row - both the blue relative sized and red orthogonal didn't participate in the first iteration+
flex column - row-axis baseline - the blue orthogonal item didn't participate in the first iteration+
flex column - column-axis baseline - the blue relative sized item didn't participate in the first iterarion+
flex columns - both the blue relative sized and red orthogonal didn't participate in the first iteration+
Passes if there are two green squares
+Passes if there are two green squares
+This is a script test because of how ridiculously differently the current +engines render these cases.
+ + + diff --git a/tests/wpt/web-platform-tests/css/css-text/tab-size/tab-min-rendered-width-1-ref.html b/tests/wpt/web-platform-tests/css/css-text/tab-size/tab-min-rendered-width-1-ref.html new file mode 100644 index 00000000000..7623adb59e6 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-text/tab-size/tab-min-rendered-width-1-ref.html @@ -0,0 +1,34 @@ + + + +++
++ + + diff --git a/tests/wpt/web-platform-tests/css/css-text/tab-size/tab-min-rendered-width-1.html b/tests/wpt/web-platform-tests/css/css-text/tab-size/tab-min-rendered-width-1.html new file mode 100644 index 00000000000..6b014260e36 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-text/tab-size/tab-min-rendered-width-1.html @@ -0,0 +1,27 @@ + + + +
++ + + diff --git a/tests/wpt/web-platform-tests/css/css-transitions/transitionevent-interface.html b/tests/wpt/web-platform-tests/css/css-transitions/transitionevent-interface.html new file mode 100644 index 00000000000..cd47469ec74 --- /dev/null +++ b/tests/wpt/web-platform-tests/css/css-transitions/transitionevent-interface.html @@ -0,0 +1,229 @@ + + +
This tests that a image document has positive-value domInteractive.
+ + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/navigation-timing/dom_interactive_media_document.html b/tests/wpt/web-platform-tests/navigation-timing/dom_interactive_media_document.html new file mode 100644 index 00000000000..e4e45725d83 --- /dev/null +++ b/tests/wpt/web-platform-tests/navigation-timing/dom_interactive_media_document.html @@ -0,0 +1,25 @@ + + + + +This tests that a media document has positive-value domInteractive.
+ + + \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/payment-method-id/payment-request-ctor-pmi-handling.https.html b/tests/wpt/web-platform-tests/payment-method-id/payment-request-ctor-pmi-handling.https.html new file mode 100644 index 00000000000..5f888f0389f --- /dev/null +++ b/tests/wpt/web-platform-tests/payment-method-id/payment-request-ctor-pmi-handling.https.html @@ -0,0 +1,149 @@ + + + +Check that child css are loaded with the referrer and referrer policy + from the external stylesheet.
+ + + + + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/child-css/internal-import-stylesheet.html b/tests/wpt/web-platform-tests/referrer-policy/css-integration/child-css/internal-import-stylesheet.html new file mode 100644 index 00000000000..aebf5031484 --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/child-css/internal-import-stylesheet.html @@ -0,0 +1,45 @@ + + + +Check that child css are loaded with the referrer and referrer policy + from the internal stylesheet.
+ + + + + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/child-css/processing-instruction.html b/tests/wpt/web-platform-tests/referrer-policy/css-integration/child-css/processing-instruction.html new file mode 100644 index 00000000000..b6333e2c7b2 --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/child-css/processing-instruction.html @@ -0,0 +1,47 @@ + + + +Check that child css are loaded with the referrer and referrer policy the + external stylesheet(referenced from a ProcessingInstruction).
+ + + + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/css-test-helper.js b/tests/wpt/web-platform-tests/referrer-policy/css-integration/css-test-helper.js new file mode 100644 index 00000000000..f5886dbbcbe --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/css-test-helper.js @@ -0,0 +1,66 @@ +var svg_ns = "http://www.w3.org/2000/svg"; +var url_prefix = location.protocol + "//" + location.hostname + ":" + + location.port + "/referrer-policy/generic/subresource/"; + +var svg_test_properties = [ + 'fill', + 'stroke', + 'filter', + 'clip-path', + 'marker-start', + 'marker-mid', + 'marker-end', + 'mask', + 'mask-image', +]; + +// Schedules async_test's for each of the test properties +// Parameters: +// testProperties: An array of test properties. +// testDescription: A test description +// testFunction: A function call which sets up the expect result and runs +// the actual test +function runSvgTests(testProperties, testDescription, testFunction) { + let runNextTest = function () { + let property = testProperties.shift(); + if (property === undefined) { + return; + } + + let current = { + test: async_test(testDescription + " " + property), + id: token(), + property: property, + }; + + testFunction(current); + + let check_url = url_prefix + "svg.py" + "?id=" + current.id + + "&report-headers"; + current.test.step_timeout( + queryXhr.bind(this, check_url, + function(message) { + current.test.step(function() { + assert_own_property(message, "headers"); + assert_own_property(message, "referrer"); + assert_equals(message.referrer, current.expected); + }); + current.test.done(); + }), + 800); + + }; + + add_result_callback(runNextTest); + runNextTest(); +} + +function createSvg() { + let svg = document.createElementNS(svg_ns, 'svg'); + svg.setAttribute('width', '400'); + svg.setAttribute('height', '400'); + let path = document.createElementNS(svg_ns, 'path'); + path.setAttribute('d', 'M 50,5 95,100 5,100 z'); + svg.appendChild(path); + return svg; +} diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/external-import-stylesheet.html b/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/external-import-stylesheet.html new file mode 100644 index 00000000000..c344c56c5bf --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/external-import-stylesheet.html @@ -0,0 +1,53 @@ + + + +Check that resources from imported stylesheets (loaded from external + stylesheets) are loaded with the referrer and referrer policy from the + external stylesheet.
+ + + + + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/external-stylesheet.html b/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/external-stylesheet.html new file mode 100644 index 00000000000..24e4bb99900 --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/external-stylesheet.html @@ -0,0 +1,47 @@ + + + +Check that resources from external stylesheets are loaded with + the referrer and referrer policy from the external stylesheet.
+ + + + + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/internal-import-stylesheet.html b/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/internal-import-stylesheet.html new file mode 100644 index 00000000000..54e2383423c --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/internal-import-stylesheet.html @@ -0,0 +1,45 @@ + + + +Check that resources from stylesheets (imported from internal + stylesheets) are loaded with the referrer and referrer policy from from the + imported style sheet.
+ + + + + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/internal-stylesheet.html b/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/internal-stylesheet.html new file mode 100644 index 00000000000..b3869bcebdc --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/internal-stylesheet.html @@ -0,0 +1,45 @@ + + + +Check that resources from internal stylesheets are loaded with + the referrer and referrer policy from the document.
+ + + + + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/processing-instruction.html b/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/processing-instruction.html new file mode 100644 index 00000000000..89ee918e24e --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/font-face/processing-instruction.html @@ -0,0 +1,51 @@ + + + +Check that resources from external stylesheets (referenced from a + ProcessingInstruction) are loaded with the referrer and referrer policy + from the external stylesheet.
+ + + + + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/external-import-stylesheet.html b/tests/wpt/web-platform-tests/referrer-policy/css-integration/image/external-import-stylesheet.html similarity index 84% rename from tests/wpt/web-platform-tests/referrer-policy/css-integration/external-import-stylesheet.html rename to tests/wpt/web-platform-tests/referrer-policy/css-integration/image/external-import-stylesheet.html index 7b6ec6431bd..0023af31b17 100644 --- a/tests/wpt/web-platform-tests/referrer-policy/css-integration/external-import-stylesheet.html +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/image/external-import-stylesheet.html @@ -19,10 +19,13 @@ + + + + + + + + + +Check that resources from external stylesheets are loaded with + the referrer and referrer policy from the external stylesheet.
+ + + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/svg/inline-style.html b/tests/wpt/web-platform-tests/referrer-policy/css-integration/svg/inline-style.html new file mode 100644 index 00000000000..1f46acb4a32 --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/svg/inline-style.html @@ -0,0 +1,35 @@ + + + +Check that resources from inline styles are loaded with + the referrer and referrer policy from the document.
+ + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/svg/internal-stylesheet.html b/tests/wpt/web-platform-tests/referrer-policy/css-integration/svg/internal-stylesheet.html new file mode 100644 index 00000000000..08be4effa47 --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/svg/internal-stylesheet.html @@ -0,0 +1,35 @@ + + + +Check that resources from internal styles are loaded with + the referrer and referrer policy from the document.
+ + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/svg/presentation-attribute.html b/tests/wpt/web-platform-tests/referrer-policy/css-integration/svg/presentation-attribute.html new file mode 100644 index 00000000000..edeceb1a785 --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/svg/presentation-attribute.html @@ -0,0 +1,40 @@ + + + +Check that resources from presentation attributes are loaded with + the referrer and referrer policy from the document.
+ + + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/css-integration/svg/processing-instruction.html b/tests/wpt/web-platform-tests/referrer-policy/css-integration/svg/processing-instruction.html new file mode 100644 index 00000000000..ba0e6673a38 --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/css-integration/svg/processing-instruction.html @@ -0,0 +1,38 @@ + + + +Check that resources from external stylesheets (referenced from a + ProcessingInstruction) are loaded with the referrer and referrer policy + from the external stylesheet.
+ + + + + + diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/subresource/font.py b/tests/wpt/web-platform-tests/referrer-policy/generic/subresource/font.py new file mode 100644 index 00000000000..50a5bd2f399 --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/generic/subresource/font.py @@ -0,0 +1,72 @@ +import os, sys, json, base64 +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import subresource + +def generate_payload(request, server_data): + data = ('{"headers": %(headers)s}') % server_data + if "id" in request.GET: + request.server.stash.put(request.GET["id"], data) + # Simple base64 encoded .tff font + return base64.decodestring("AAEAAAANAIAAAwBQRkZUTU6u6MkAAAXcAAAAHE9TLzJWYW" + "QKAAABWAAAAFZjbWFwAA8D7wAAAcAAAAFCY3Z0IAAhAnkA" + "AAMEAAAABGdhc3D//wADAAAF1AAAAAhnbHlmCC6aTwAAAx" + "QAAACMaGVhZO8ooBcAAADcAAAANmhoZWEIkAV9AAABFAAA" + "ACRobXR4EZQAhQAAAbAAAAAQbG9jYQBwAFQAAAMIAAAACm" + "1heHAASQA9AAABOAAAACBuYW1lehAVOgAAA6AAAAIHcG9z" + "dP+uADUAAAWoAAAAKgABAAAAAQAAMhPyuV8PPPUACwPoAA" + "AAAMU4Lm0AAAAAxTgubQAh/5wFeAK8AAAACAACAAAAAAAA" + "AAEAAAK8/5wAWgXcAAAAAAV4AAEAAAAAAAAAAAAAAAAAAA" + "AEAAEAAAAEAAwAAwAAAAAAAgAAAAEAAQAAAEAALgAAAAAA" + "AQXcAfQABQAAAooCvAAAAIwCigK8AAAB4AAxAQIAAAIABg" + "kAAAAAAAAAAAABAAAAAAAAAAAAAAAAUGZFZABAAEEAQQMg" + "/zgAWgK8AGQAAAABAAAAAAAABdwAIQAAAAAF3AAABdwAZA" + "AAAAMAAAADAAAAHAABAAAAAAA8AAMAAQAAABwABAAgAAAA" + "BAAEAAEAAABB//8AAABB////wgABAAAAAAAAAQYAAAEAAA" + "AAAAAAAQIAAAACAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAhAnkAAAAqACoAKgBGAAAAAgAhAA" + "ABKgKaAAMABwAusQEALzyyBwQA7TKxBgXcPLIDAgDtMgCx" + "AwAvPLIFBADtMrIHBgH8PLIBAgDtMjMRIREnMxEjIQEJ6M" + "fHApr9ZiECWAAAAwBk/5wFeAK8AAMABwALAAABNSEVATUh" + "FQE1IRUB9AH0/UQDhPu0BRQB9MjI/tTIyP7UyMgAAAAAAA" + "4ArgABAAAAAAAAACYATgABAAAAAAABAAUAgQABAAAAAAAC" + "AAYAlQABAAAAAAADACEA4AABAAAAAAAEAAUBDgABAAAAAA" + "AFABABNgABAAAAAAAGAAUBUwADAAEECQAAAEwAAAADAAEE" + "CQABAAoAdQADAAEECQACAAwAhwADAAEECQADAEIAnAADAA" + "EECQAEAAoBAgADAAEECQAFACABFAADAAEECQAGAAoBRwBD" + "AG8AcAB5AHIAaQBnAGgAdAAgACgAYwApACAAMgAwADAAOA" + "AgAE0AbwB6AGkAbABsAGEAIABDAG8AcgBwAG8AcgBhAHQA" + "aQBvAG4AAENvcHlyaWdodCAoYykgMjAwOCBNb3ppbGxhIE" + "NvcnBvcmF0aW9uAABNAGEAcgBrAEEAAE1hcmtBAABNAGUA" + "ZABpAHUAbQAATWVkaXVtAABGAG8AbgB0AEYAbwByAGcAZQ" + "AgADIALgAwACAAOgAgAE0AYQByAGsAQQAgADoAIAA1AC0A" + "MQAxAC0AMgAwADAAOAAARm9udEZvcmdlIDIuMCA6IE1hcm" + "tBIDogNS0xMS0yMDA4AABNAGEAcgBrAEEAAE1hcmtBAABW" + "AGUAcgBzAGkAbwBuACAAMAAwADEALgAwADAAMAAgAABWZX" + "JzaW9uIDAwMS4wMDAgAABNAGEAcgBrAEEAAE1hcmtBAAAA" + "AgAAAAAAAP+DADIAAAABAAAAAAAAAAAAAAAAAAAAAAAEAA" + "AAAQACACQAAAAAAAH//wACAAAAAQAAAADEPovuAAAAAMU4" + "Lm0AAAAAxTgubQ=="); + +def generate_report_headers_payload(request, server_data): + stashed_data = request.server.stash.take(request.GET["id"]) + return stashed_data + +def main(request, response): + handler = lambda data: generate_payload(request, data) + content_type = 'application/x-font-truetype' + + if "report-headers" in request.GET: + handler = lambda data: generate_report_headers_payload(request, data) + content_type = 'application/json' + + subresource.respond(request, + response, + payload_generator = handler, + content_type = content_type, + access_control_allow_origin = "*") diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/subresource/stylesheet.py b/tests/wpt/web-platform-tests/referrer-policy/generic/subresource/stylesheet.py index 328db29b957..54378216774 100644 --- a/tests/wpt/web-platform-tests/referrer-policy/generic/subresource/stylesheet.py +++ b/tests/wpt/web-platform-tests/referrer-policy/generic/subresource/stylesheet.py @@ -3,24 +3,66 @@ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import subresource def generate_payload(request, server_data): - return subresource.get_template("stylesheet.css.template") % {"id": request.GET["id"]} + data = ('{"headers": %(headers)s}') % server_data + type = 'image' + if "type" in request.GET: + type = request.GET["type"] + + if "id" in request.GET: + request.server.stash.put(request.GET["id"], data) + + if type == 'image': + return subresource.get_template("image.css.template") % {"id": request.GET["id"]} + + elif type == 'font': + return subresource.get_template("font.css.template") % {"id": request.GET["id"]} + + elif type == 'svg': + return subresource.get_template("svg.css.template") % { + "id": request.GET["id"], + "property": request.GET["property"]} def generate_import_rule(request, server_data): - data = "@import url('%(url)s?id=%(id)s');" % { + type = 'image' + property = None; + if "type" in request.GET: + type = request.GET["type"] + if type == "svg" and "property" in request.GET: + property = request.GET["property"] + if property is None: + return "@import url('%(url)s?id=%(id)s&type=%(type)s');" % { + "id": request.GET["id"], + "url": subresource.create_redirect_url(request, cross_origin = True), + "type": type + } + return "@import url('%(url)s?id=%(id)s&type=%(type)s&property=%(property)s');" % { "id": request.GET["id"], - "url": subresource.create_redirect_url(request, cross_origin = True) + "url": subresource.create_redirect_url(request, cross_origin = True), + "type": type, + "property": property } - return data + +def generate_report_headers_payload(request, server_data): + stashed_data = request.server.stash.take(request.GET["id"]) + return stashed_data def main(request, response): payload_generator = lambda data: generate_payload(request, data) + content_type = "text/css" + referrer_policy = "unsafe-url" if "import-rule" in request.GET: payload_generator = lambda data: generate_import_rule(request, data) + if "report-headers" in request.GET: + payload_generator = lambda data: generate_report_headers_payload(request, data) + content_type = 'application/json' + + if "referrer-policy" in request.GET: + referrer_policy = request.GET["referrer-policy"] + subresource.respond( request, response, payload_generator = payload_generator, - content_type = "text/css", - maybe_additional_headers = { "Referrer-Policy": "unsafe-url" }) - + content_type = content_type, + maybe_additional_headers = { "Referrer-Policy": referrer_policy }) diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/subresource/svg.py b/tests/wpt/web-platform-tests/referrer-policy/generic/subresource/svg.py new file mode 100644 index 00000000000..8618875c79f --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/generic/subresource/svg.py @@ -0,0 +1,36 @@ +import os, sys, json +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +import subresource + +def generate_payload(request, server_data): + data = ('{"headers": %(headers)s}') % server_data + if "id" in request.GET: + with request.server.stash.lock: + request.server.stash.take(request.GET["id"]) + request.server.stash.put(request.GET["id"], data) + return ""; + +def generate_payload_embedded(request, server_data): + return subresource.get_template("svg.embedded.template") % { + "id": request.GET["id"], + "property": request.GET["property"]}; + +def generate_report_headers_payload(request, server_data): + stashed_data = request.server.stash.take(request.GET["id"]) + return stashed_data + +def main(request, response): + handler = lambda data: generate_payload(request, data) + content_type = 'image/svg+xml' + + if "embedded-svg" in request.GET: + handler = lambda data: generate_payload_embedded(request, data) + + if "report-headers" in request.GET: + handler = lambda data: generate_report_headers_payload(request, data) + content_type = 'application/json' + + subresource.respond(request, + response, + payload_generator = handler, + content_type = content_type) diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/template/font.css.template b/tests/wpt/web-platform-tests/referrer-policy/generic/template/font.css.template new file mode 100644 index 00000000000..9b19df3cf1f --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/generic/template/font.css.template @@ -0,0 +1,9 @@ +@font-face { + font-family: 'wpt'; + font-style: normal; + font-weight: normal; + src: url(/referrer-policy/generic/subresource/font.py?id=%(id)s) format('truetype'); +} +body { + font-family: 'wpt'; +} diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/template/stylesheet.css.template b/tests/wpt/web-platform-tests/referrer-policy/generic/template/image.css.template similarity index 100% rename from tests/wpt/web-platform-tests/referrer-policy/generic/template/stylesheet.css.template rename to tests/wpt/web-platform-tests/referrer-policy/generic/template/image.css.template diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/template/svg.css.template b/tests/wpt/web-platform-tests/referrer-policy/generic/template/svg.css.template new file mode 100644 index 00000000000..ffaefed4aa4 --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/generic/template/svg.css.template @@ -0,0 +1,3 @@ +path { + %(property)s: url(/referrer-policy/generic/subresource/svg.py?id=%(id)s#invalidFragment); +} diff --git a/tests/wpt/web-platform-tests/referrer-policy/generic/template/svg.embedded.template b/tests/wpt/web-platform-tests/referrer-policy/generic/template/svg.embedded.template new file mode 100644 index 00000000000..5986c4800a7 --- /dev/null +++ b/tests/wpt/web-platform-tests/referrer-policy/generic/template/svg.embedded.template @@ -0,0 +1,5 @@ + + + diff --git a/tests/wpt/web-platform-tests/resource-timing/resources/TAOResponse.py b/tests/wpt/web-platform-tests/resource-timing/resources/TAOResponse.py index 060f9b0c9a7..fefc75b7b7f 100644 --- a/tests/wpt/web-platform-tests/resource-timing/resources/TAOResponse.py +++ b/tests/wpt/web-platform-tests/resource-timing/resources/TAOResponse.py @@ -17,22 +17,22 @@ def main(request, response): # case-sensitive match for origin, pass response.headers.set('Timing-Allow-Origin', origin) elif tao == 'space': - # space seperated list of origin and wildcard, fail + # space separated list of origin and wildcard, fail response.headers.set('Timing-Allow-Origin', (origin + ' *')) elif tao == 'multi': - # more than one TAO values, seperated by comma, pass + # more than one TAO values, separated by comma, pass response.headers.set('Timing-Allow-Origin', origin) response.headers.append('Timing-Allow-Origin', '*') elif tao == 'multi_wildcard': - # multiple wildcards, seperated by comma, pass + # multiple wildcards, separated by comma, pass response.headers.set('Timing-Allow-Origin', '*') response.headers.append('Timing-Allow-Origin', '*') elif tao == 'match_origin': - # contains a match of origin, seperated by comma, pass + # contains a match of origin, separated by comma, pass response.headers.set('Timing-Allow-Origin', origin) response.headers.append('Timing-Allow-Origin', "fake") elif tao == 'match_wildcard': - # contains a wildcard, seperated by comma, pass + # contains a wildcard, separated by comma, pass response.headers.set('Timing-Allow-Origin', "fake") response.headers.append('Timing-Allow-Origin', '*') elif tao == 'uppercase': diff --git a/tests/wpt/web-platform-tests/resources/test/conftest.py b/tests/wpt/web-platform-tests/resources/test/conftest.py index 5fca1d24c41..dde9e9dc0a7 100644 --- a/tests/wpt/web-platform-tests/resources/test/conftest.py +++ b/tests/wpt/web-platform-tests/resources/test/conftest.py @@ -2,11 +2,12 @@ import io import json import os import ssl -import urllib2 import html5lib import pytest from selenium import webdriver +from six import text_type +from six.moves import urllib from wptserver import WPTServer @@ -63,8 +64,8 @@ class HTMLItem(pytest.Item, pytest.Collector): # Some tests are reliant on the WPT servers substitution functionality, # so tests must be retrieved from the server rather than read from the # file system directly. - handle = urllib2.urlopen(self.url, - context=parent.session.config.ssl_context) + handle = urllib.request.urlopen(self.url, + context=parent.session.config.ssl_context) try: markup = handle.read() finally: @@ -87,7 +88,7 @@ class HTMLItem(pytest.Item, pytest.Collector): continue if element.tag == 'script': if element.attrib.get('id') == 'expected': - self.expected = json.loads(unicode(element.text)) + self.expected = json.loads(text_type(element.text)) src = element.attrib.get('src', '') @@ -186,7 +187,7 @@ class HTMLItem(pytest.Item, pytest.Collector): @staticmethod def _assert_sequence(nums): if nums and len(nums) > 0: - assert nums == range(1, nums[-1] + 1) + assert nums == list(range(1, nums[-1] + 1)) @staticmethod def _scrub_stack(test_obj): diff --git a/tests/wpt/web-platform-tests/resources/test/tests/functional/api-tests-1.html b/tests/wpt/web-platform-tests/resources/test/tests/functional/api-tests-1.html index a9d92b12f81..c65d026edba 100644 --- a/tests/wpt/web-platform-tests/resources/test/tests/functional/api-tests-1.html +++ b/tests/wpt/web-platform-tests/resources/test/tests/functional/api-tests-1.html @@ -147,8 +147,8 @@ var A = function(){this.a = "a"} A.prototype = {b:"b"} var a = new A(); - assert_exists(a, "a"); - assert_not_exists(a, "b"); + assert_own_property(a, "a"); + assert_false(a.hasOwnProperty("b"), "unexpected property found: \"b\""); assert_inherits(a, "b"); } test(testAssertInherits, "test for assert[_not]_exists and insert_inherits") diff --git a/tests/wpt/web-platform-tests/resources/test/tests/functional/log-insertion.html b/tests/wpt/web-platform-tests/resources/test/tests/functional/log-insertion.html new file mode 100644 index 00000000000..3f28266d576 --- /dev/null +++ b/tests/wpt/web-platform-tests/resources/test/tests/functional/log-insertion.html @@ -0,0 +1,33 @@ + +The third test validates a simple values-animation on a path's d attribute made of M, C and Z commands where the values attribute is specified and - specifies three seperate values. + specifies three separate values. The attribute is compatible with the path element's d attribute.
diff --git a/tests/wpt/web-platform-tests/tools/ci/check_stability.py b/tests/wpt/web-platform-tests/tools/ci/check_stability.py index 2b32eb50c0f..a0633110860 100644 --- a/tests/wpt/web-platform-tests/tools/ci/check_stability.py +++ b/tests/wpt/web-platform-tests/tools/ci/check_stability.py @@ -272,6 +272,7 @@ def run(venv, wpt_args, **kwargs): wpt_kwargs["verify_log_full"] = False if wpt_kwargs["repeat"] == 1: wpt_kwargs["repeat"] = 10 + wpt_kwargs["headless"] = False wpt_kwargs = setup_wptrunner(venv, **wpt_kwargs) diff --git a/tests/wpt/web-platform-tests/tools/ci/taskcluster-run.py b/tests/wpt/web-platform-tests/tools/ci/taskcluster-run.py index 45416501e03..5a720baa2e9 100755 --- a/tests/wpt/web-platform-tests/tools/ci/taskcluster-run.py +++ b/tests/wpt/web-platform-tests/tools/ci/taskcluster-run.py @@ -73,7 +73,8 @@ def main(product, commit_range, wpt_args): "-y", "--no-pause", "--no-restart-on-unexpected", - "--install-fonts" + "--install-fonts", + "--no-headless" ] wpt_args += browser_specific_args.get(product, []) diff --git a/tests/wpt/web-platform-tests/tools/manifest/vcs.py b/tests/wpt/web-platform-tests/tools/manifest/vcs.py index 42e9863712f..675eb01714f 100644 --- a/tests/wpt/web-platform-tests/tools/manifest/vcs.py +++ b/tests/wpt/web-platform-tests/tools/manifest/vcs.py @@ -1,5 +1,6 @@ import os import subprocess +import platform from .sourcefile import SourceFile @@ -16,9 +17,12 @@ class Git(object): full_cmd = ["git", cmd] + list(args) try: return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT) - except WindowsError: - full_cmd[0] = "git.bat" - return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT) + except Exception as e: + if platform.uname()[0] == "Windows" and isinstance(e, WindowsError): + full_cmd[0] = "git.bat" + return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT) + else: + raise return git @classmethod diff --git a/tests/wpt/web-platform-tests/tools/wpt/browser.py b/tests/wpt/web-platform-tests/tools/wpt/browser.py index 7b943c2e73c..052ec66a091 100644 --- a/tests/wpt/web-platform-tests/tools/wpt/browser.py +++ b/tests/wpt/web-platform-tests/tools/wpt/browser.py @@ -102,6 +102,11 @@ class Firefox(Browser): "beta": "latest-beta", "nightly": "latest" } + application_name = { + "stable": "Firefox.app", + "beta": "Firefox.app", + "nightly": "Firefox Nightly.app" + } if channel not in branch: raise ValueError("Unrecognised release channel: %s" % channel) @@ -131,10 +136,10 @@ class Firefox(Browser): try: mozinstall.install(filename, dest) except mozinstall.mozinstall.InstallError: - if platform == "mac" and os.path.exists(os.path.join(dest, "Firefox Nightly.app")): + if platform == "mac" and os.path.exists(os.path.join(dest, application_name[channel])): # mozinstall will fail if nightly is already installed in the venv because # mac installation uses shutil.copy_tree - mozinstall.uninstall(os.path.join(dest, "Firefox Nightly.app")) + mozinstall.uninstall(os.path.join(dest, application_name[channel])) mozinstall.install(filename, dest) else: raise @@ -142,7 +147,7 @@ class Firefox(Browser): os.remove(filename) return self.find_binary_path(dest) - def find_binary_path(self, path=None): + def find_binary_path(self,path=None, channel="nightly"): """Looks for the firefox binary in the virtual environment""" platform = { @@ -151,9 +156,15 @@ class Firefox(Browser): "Darwin": "mac" }.get(uname[0]) + application_name = { + "stable": "Firefox.app", + "beta": "Firefox.app", + "nightly": "Firefox Nightly.app" + }.get(channel) + if path is None: #os.getcwd() doesn't include the venv path - path = os.path.join(os.getcwd(), "_venv", "browsers") + path = os.path.join(os.getcwd(), "_venv", "browsers", channel) binary = None @@ -163,7 +174,8 @@ class Firefox(Browser): import mozinstall binary = mozinstall.get_binary(path, "firefox") elif platform == "mac": - binary = find_executable("firefox", os.path.join(path, "Firefox Nightly.app", "Contents", "MacOS")) + binary = find_executable("firefox", os.path.join(path, application_name, + "Contents", "MacOS")) return binary @@ -171,14 +183,15 @@ class Firefox(Browser): if venv_path is None: venv_path = os.path.join(os.getcwd(), "_venv") - path = os.path.join(venv_path, "browsers") - if channel is not None: - path = os.path.join(path, channel) - binary = self.find_binary_path(path) + if channel is None: + channel = "nightly" + + path = os.path.join(venv_path, "browsers", channel) + binary = self.find_binary_path(path, channel) if not binary and uname[0] == "Darwin": - macpaths = ["/Applications/FirefoxNightly.app/Contents/MacOS", - os.path.expanduser("~/Applications/FirefoxNightly.app/Contents/MacOS"), + macpaths = ["/Applications/Firefox Nightly.app/Contents/MacOS", + os.path.expanduser("~/Applications/Firefox Nightly.app/Contents/MacOS"), "/Applications/Firefox Developer Edition.app/Contents/MacOS", os.path.expanduser("~/Applications/Firefox Developer Edition.app/Contents/MacOS"), "/Applications/Firefox.app/Contents/MacOS", diff --git a/tests/wpt/web-platform-tests/tools/wpt/run.py b/tests/wpt/web-platform-tests/tools/wpt/run.py index 7e8827b1069..d08b0f93807 100644 --- a/tests/wpt/web-platform-tests/tools/wpt/run.py +++ b/tests/wpt/web-platform-tests/tools/wpt/run.py @@ -177,6 +177,9 @@ class Firefox(BrowserSetup): def setup_kwargs(self, kwargs): if kwargs["binary"] is None: + if kwargs["browser_channel"] is None: + logger.info("No browser channel specified. Running nightly instead.") + binary = self.browser.find_binary(self.venv.path, kwargs["browser_channel"]) if binary is None: @@ -221,6 +224,10 @@ Consider installing certutil via your OS package manager or directly.""") channel=kwargs["browser_channel"]) kwargs["prefs_root"] = prefs_root + if kwargs["headless"] is None: + kwargs["headless"] = True + logger.info("Running in headless mode, pass --no-headless to disable") + # Allow WebRTC tests to call getUserMedia. kwargs["extra_prefs"].append("media.navigator.streams.fake=true") diff --git a/tests/wpt/web-platform-tests/tools/wpt/tests/test_wpt.py b/tests/wpt/web-platform-tests/tools/wpt/tests/test_wpt.py index d0cb2b85c99..8387dc9613e 100644 --- a/tests/wpt/web-platform-tests/tools/wpt/tests/test_wpt.py +++ b/tests/wpt/web-platform-tests/tools/wpt/tests/test_wpt.py @@ -169,23 +169,25 @@ def test_run_firefox(manifest_dir): if is_port_8000_in_use(): pytest.skip("port 8000 already in use") - os.environ["MOZ_HEADLESS"] = "1" - try: - if sys.platform == "darwin": - fx_path = os.path.join(wpt.localpaths.repo_root, "_venv", "browsers", "nightly", "Firefox Nightly.app") - else: - fx_path = os.path.join(wpt.localpaths.repo_root, "_venv", "browsers", "nightly", "firefox") - if os.path.exists(fx_path): - shutil.rmtree(fx_path) - with pytest.raises(SystemExit) as excinfo: - wpt.main(argv=["run", "--no-pause", "--install-browser", "--yes", - "--metadata", manifest_dir, - "firefox", "/dom/nodes/Element-tagName.html"]) - assert os.path.exists(fx_path) + if sys.platform == "darwin": + fx_path = os.path.join(wpt.localpaths.repo_root, "_venv", "browsers", "nightly", "Firefox Nightly.app") + else: + fx_path = os.path.join(wpt.localpaths.repo_root, "_venv", "browsers", "nightly", "firefox") + if os.path.exists(fx_path): shutil.rmtree(fx_path) - assert excinfo.value.code == 0 - finally: - del os.environ["MOZ_HEADLESS"] + with pytest.raises(SystemExit) as excinfo: + wpt.main(argv=["run", "--no-pause", "--install-browser", "--yes", + # The use of `--binary-args` is intentional: it + # demonstrates that internally-managed command-line + # arguments are properly merged with those specified by + # the user. See + # https://github.com/web-platform-tests/wpt/pull/13154 + "--binary-arg=-headless", + "--metadata", manifest_dir, + "firefox", "/dom/nodes/Element-tagName.html"]) + assert os.path.exists(fx_path) + shutil.rmtree(fx_path) + assert excinfo.value.code == 0 @pytest.mark.slow diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_chrome.txt b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_chrome.txt index 22a07532657..3f86182b7d0 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_chrome.txt +++ b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_chrome.txt @@ -1,2 +1,2 @@ mozprocess == 0.26 -selenium==3.14.0 +selenium==3.14.1 diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_chrome_android.txt b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_chrome_android.txt index 22a07532657..3f86182b7d0 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_chrome_android.txt +++ b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_chrome_android.txt @@ -1,2 +1,2 @@ mozprocess == 0.26 -selenium==3.14.0 +selenium==3.14.1 diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_edge.txt b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_edge.txt index 22a07532657..3f86182b7d0 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_edge.txt +++ b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_edge.txt @@ -1,2 +1,2 @@ mozprocess == 0.26 -selenium==3.14.0 +selenium==3.14.1 diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_firefox.txt b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_firefox.txt index f1e6a8585ca..bfe0d4bc347 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_firefox.txt +++ b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_firefox.txt @@ -1,8 +1,8 @@ -marionette_driver==2.6.0 -mozprofile==1.1.0 +marionette_driver==2.7.0 +mozprofile==2.0.0 mozprocess == 0.26 mozcrash == 1.0 -mozrunner == 7.0.0 +mozrunner==7.0.2 mozleak == 0.1 mozinstall==1.16.0 mozdownload==1.24 diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_ie.txt b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_ie.txt index 22a07532657..3f86182b7d0 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_ie.txt +++ b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_ie.txt @@ -1,2 +1,2 @@ mozprocess == 0.26 -selenium==3.14.0 +selenium==3.14.1 diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_opera.txt b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_opera.txt index 22a07532657..3f86182b7d0 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_opera.txt +++ b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_opera.txt @@ -1,2 +1,2 @@ mozprocess == 0.26 -selenium==3.14.0 +selenium==3.14.1 diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_safari.txt b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_safari.txt index 5a1d26b8b9b..3f86182b7d0 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_safari.txt +++ b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_safari.txt @@ -1,2 +1,2 @@ mozprocess == 0.26 -selenium==3.13.0 +selenium==3.14.1 diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_sauce.txt b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_sauce.txt index 77a74222433..07c525a67fd 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/requirements_sauce.txt +++ b/tests/wpt/web-platform-tests/tools/wptrunner/requirements_sauce.txt @@ -1,3 +1,3 @@ mozprocess == 0.26 -selenium==3.14.0 +selenium==3.14.1 requests==2.19.1 diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/chrome.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/chrome.py index 8b0ba4585a9..d41df8dec0e 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/chrome.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/chrome.py @@ -47,6 +47,11 @@ def executor_kwargs(test_type, server_config, cache_manager, run_info_data, for (kwarg, capability) in [("binary", "binary"), ("binary_args", "args")]: if kwargs[kwarg] is not None: capabilities["goog:chromeOptions"][capability] = kwargs[kwarg] + if kwargs["headless"]: + if "args" not in capabilities["goog:chromeOptions"]: + capabilities["goog:chromeOptions"]["args"] = [] + if "--headless" not in capabilities["goog:chromeOptions"]["args"]: + capabilities["goog:chromeOptions"]["args"].append("--headless") if test_type == "testharness": capabilities["goog:chromeOptions"]["useAutomationExtension"] = False capabilities["goog:chromeOptions"]["excludeSwitches"] = ["enable-automation"] diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/chrome_webdriver.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/chrome_webdriver.py index a63460f4544..2ee8ec41ed6 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/chrome_webdriver.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/chrome_webdriver.py @@ -41,6 +41,12 @@ def executor_kwargs(test_type, server_config, cache_manager, run_info_data, if kwargs[kwarg] is not None: capabilities["goog:chromeOptions"][capability] = kwargs[kwarg] + if kwargs["headless"]: + if "args" not in capabilities["goog:chromeOptions"]: + capabilities["goog:chromeOptions"]["args"] = [] + if "--headless" not in capabilities["goog:chromeOptions"]["args"]: + capabilities["goog:chromeOptions"]["args"].append("--headless") + if test_type == "testharness": capabilities["goog:chromeOptions"]["useAutomationExtension"] = False capabilities["goog:chromeOptions"]["excludeSwitches"] = ["enable-automation"] diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py index 9f7ebfa2ca5..b370b5d7a5e 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py @@ -83,7 +83,8 @@ def browser_kwargs(test_type, run_info_data, config, **kwargs): "asan": run_info_data.get("asan"), "stylo_threads": kwargs["stylo_threads"], "chaos_mode_flags": kwargs["chaos_mode_flags"], - "config": config} + "config": config, + "headless": kwargs["headless"]} def executor_kwargs(test_type, server_config, cache_manager, run_info_data, @@ -106,6 +107,11 @@ def executor_kwargs(test_type, server_config, cache_manager, run_info_data, options["binary"] = kwargs["binary"] if kwargs["binary_args"]: options["args"] = kwargs["binary_args"] + if kwargs["headless"]: + if "args" not in options: + options["args"] = [] + if "--headless" not in options["args"]: + options["args"].append("--headless") options["prefs"] = { "network.dns.localDomains": ",".join(server_config.domains_set) } @@ -155,7 +161,7 @@ class FirefoxBrowser(Browser): symbols_path=None, stackwalk_binary=None, certutil_binary=None, ca_certificate_path=None, e10s=False, stackfix_dir=None, binary_args=None, timeout_multiplier=None, leak_check=False, asan=False, - stylo_threads=1, chaos_mode_flags=None, config=None): + stylo_threads=1, chaos_mode_flags=None, config=None, headless=None): Browser.__init__(self, logger) self.binary = binary self.prefs_root = prefs_root @@ -188,6 +194,7 @@ class FirefoxBrowser(Browser): self.lsan_handler = None self.stylo_threads = stylo_threads self.chaos_mode_flags = chaos_mode_flags + self.headless = headless def settings(self, test): self.lsan_allowed = test.lsan_allowed @@ -216,6 +223,8 @@ class FirefoxBrowser(Browser): env["STYLO_THREADS"] = str(self.stylo_threads) if self.chaos_mode_flags is not None: env["MOZ_CHAOSMODE"] = str(self.chaos_mode_flags) + if self.headless: + env["MOZ_HEADLESS"] = "1" preferences = self.load_prefs() @@ -251,9 +260,11 @@ class FirefoxBrowser(Browser): if self.ca_certificate_path is not None: self.setup_ssl() + args = self.binary_args[:] if self.binary_args else [] + args += [cmd_arg("marionette"), "about:blank"] + debug_args, cmd = browser_command(self.binary, - self.binary_args if self.binary_args else [] + - [cmd_arg("marionette"), "about:blank"], + args, self.debug_info) self.runner = FirefoxRunner(profile=self.profile, diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py index e684bf68076..db388bbca0a 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py @@ -115,8 +115,9 @@ def find_slow_status(test): """Check if a single test almost times out. We are interested in tests that almost time out (i.e. likely to be flaky). - Therefore, timeout statuses are ignored, including (EXTERNAL-)TIMEOUT & - CRASH (tests that time out may be marked as CRASH if crashes are detected). + Therefore, timeout statuses are ignored, including (EXTERNAL-)TIMEOUT. + CRASH & ERROR are also ignored because the they override TIMEOUT; a test + that both crashes and times out is marked as CRASH, so it won't be flaky. Returns: A result status produced by a run that almost times out; None, if no @@ -125,7 +126,7 @@ def find_slow_status(test): if "timeout" not in test: return None threshold = test["timeout"] * FLAKY_THRESHOLD - for status in ['PASS', 'FAIL', 'OK', 'ERROR']: + for status in ['PASS', 'FAIL', 'OK']: if (status in test["longest_duration"] and test["longest_duration"][status] > threshold): return status diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py index 7e386b881d4..353e2ada1eb 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py @@ -210,7 +210,7 @@ class BrowserManager(object): self.command_queue.put((command, args)) def init_timeout(self): - # This is called from a seperate thread, so we send a message to the + # This is called from a separate thread, so we send a message to the # main loop so we get back onto the manager thread self.logger.debug("init_failed called from timer") self.send_message("init_failed") diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/test_stability.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/test_stability.py index 5a051b6c899..c3c89f2f192 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/test_stability.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/tests/test_stability.py @@ -20,6 +20,9 @@ def test_find_slow_status(): assert stability.find_slow_status({ "longest_duration": {"CRASH": 10}, "timeout": 10}) is None + assert stability.find_slow_status({ + "longest_duration": {"ERROR": 10}, + "timeout": 10}) is None assert stability.find_slow_status({ "longest_duration": {"PASS": 1}, "timeout": 10}) is None diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py index d25e561ad19..467903f2773 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py @@ -205,6 +205,10 @@ scheme host and port.""") help="Allow the wptrunner to install fonts on your system") config_group.add_argument("--font-dir", action="store", type=abs_path, dest="font_dir", help="Path to local font installation directory", default=None) + config_group.add_argument("--headless", action="store_true", + help="Run browser in headless mode", default=None) + config_group.add_argument("--no-headless", action="store_false", dest="headless", + help="Don't run browser in headless mode") build_type = parser.add_mutually_exclusive_group() build_type.add_argument("--debug-build", dest="debug", action="store_true", @@ -365,6 +369,7 @@ def set_from_config(kwargs): check_paths(kwargs) + def get_test_paths(config): # Set up test_paths test_paths = OrderedDict() diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py index a6a29724ad7..6bd1db9927c 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py @@ -124,6 +124,8 @@ def get_pause_after_test(test_loader, **kwargs): if kwargs["pause_after_test"] is None: if kwargs["repeat_until_unexpected"]: return False + if kwargs["headless"]: + return False if kwargs["repeat"] == 1 and kwargs["rerun"] == 1 and total_tests == 1: return True return False diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/base.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/base.py index e49c8287c59..741ab0bcb74 100644 --- a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/base.py +++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/base.py @@ -75,7 +75,7 @@ class TestUsingServer(unittest.TestCase): req.add_data(body) if auth is not None: - req.add_header("Authorization", "Basic %s" % base64.b64encode('%s:%s' % auth)) + req.add_header("Authorization", b"Basic %s" % base64.b64encode(("%s:%s" % auth).encode("utf-8"))) return urlopen(req) diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_handlers.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_handlers.py index 15c7cb7e803..759a096b799 100644 --- a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_handlers.py +++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_handlers.py @@ -88,19 +88,16 @@ class TestFileHandler(TestUsingServer): self.request("/document.txt", headers={"Range":"bytes=%i-%i" % (len(expected), len(expected) + 10)}) self.assertEqual(cm.exception.code, 416) - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_sub_config(self): resp = self.request("/sub.sub.txt") expected = b"localhost localhost %i" % self.server.port assert resp.read().rstrip() == expected - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_sub_headers(self): resp = self.request("/sub_headers.sub.txt", headers={"X-Test": "PASS"}) expected = b"PASS" assert resp.read().rstrip() == expected - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_sub_params(self): resp = self.request("/sub_params.sub.txt", query="test=PASS") expected = b"PASS" @@ -108,7 +105,6 @@ class TestFileHandler(TestUsingServer): class TestFunctionHandler(TestUsingServer): - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_string_rv(self): @wptserve.handlers.handler def handler(request, response): @@ -119,7 +115,7 @@ class TestFunctionHandler(TestUsingServer): resp = self.request(route[1]) self.assertEqual(200, resp.getcode()) self.assertEqual("9", resp.info()["Content-Length"]) - self.assertEqual("test data", resp.read()) + self.assertEqual(b"test data", resp.read()) def test_tuple_1_rv(self): @wptserve.handlers.handler @@ -134,7 +130,6 @@ class TestFunctionHandler(TestUsingServer): assert cm.value.code == 500 - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_tuple_2_rv(self): @wptserve.handlers.handler def handler(request, response): @@ -146,9 +141,8 @@ class TestFunctionHandler(TestUsingServer): self.assertEqual(200, resp.getcode()) self.assertEqual("4", resp.info()["Content-Length"]) self.assertEqual("test-value", resp.info()["test-header"]) - self.assertEqual("test", resp.read()) + self.assertEqual(b"test", resp.read()) - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_tuple_3_rv(self): @wptserve.handlers.handler def handler(request, response): @@ -159,9 +153,8 @@ class TestFunctionHandler(TestUsingServer): resp = self.request(route[1]) self.assertEqual(202, resp.getcode()) self.assertEqual("test-value", resp.info()["test-header"]) - self.assertEqual("test data", resp.read()) + self.assertEqual(b"test data", resp.read()) - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_tuple_3_rv_1(self): @wptserve.handlers.handler def handler(request, response): @@ -173,7 +166,7 @@ class TestFunctionHandler(TestUsingServer): self.assertEqual(202, resp.getcode()) self.assertEqual("Some Status", resp.msg) self.assertEqual("test-value", resp.info()["test-header"]) - self.assertEqual("test data", resp.read()) + self.assertEqual(b"test data", resp.read()) def test_tuple_4_rv(self): @wptserve.handlers.handler @@ -263,7 +256,6 @@ class TestPythonHandler(TestUsingServer): self.assertEqual("PASS", resp.info()["X-Test"]) self.assertEqual(b"PASS", resp.read()) - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_import(self): dir_name = os.path.join(doc_root, "subdir") assert dir_name not in sys.path @@ -273,7 +265,7 @@ class TestPythonHandler(TestUsingServer): assert "test_module" not in sys.modules self.assertEqual(200, resp.getcode()) self.assertEqual("text/plain", resp.info()["Content-Type"]) - self.assertEqual("PASS", resp.read()) + self.assertEqual(b"PASS", resp.read()) def test_no_main(self): with pytest.raises(HTTPError) as cm: @@ -314,13 +306,12 @@ class TestDirectoryHandler(TestUsingServer): class TestAsIsHandler(TestUsingServer): - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_as_is(self): resp = self.request("/test.asis") self.assertEqual(202, resp.getcode()) self.assertEqual("Giraffe", resp.msg) self.assertEqual("PASS", resp.info()["X-Test"]) - self.assertEqual("Content", resp.read()) + self.assertEqual(b"Content", resp.read()) #Add a check that the response is actually sane diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py index 83b2c621641..7739af5e26e 100644 --- a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py +++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py @@ -57,40 +57,35 @@ class TestSlice(TestUsingServer): self.assertEqual(resp.read(), expected[:10]) class TestSub(TestUsingServer): - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_sub_config(self): resp = self.request("/sub.txt", query="pipe=sub") - expected = "localhost localhost %i" % self.server.port + expected = b"localhost localhost %i" % self.server.port self.assertEqual(resp.read().rstrip(), expected) @pytest.mark.xfail(sys.platform == "win32", reason="https://github.com/web-platform-tests/wpt/issues/12949") - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_sub_file_hash(self): resp = self.request("/sub_file_hash.sub.txt") - expected = """ + expected = b""" md5: JmI1W8fMHfSfCarYOSxJcw== sha1: nqpWqEw4IW8NjD6R375gtrQvtTo= sha224: RqQ6fMmta6n9TuA/vgTZK2EqmidqnrwBAmQLRQ== sha256: G6Ljg1uPejQxqFmvFOcV/loqnjPTW5GSOePOfM/u0jw= sha384: lkXHChh1BXHN5nT5BYhi1x67E1CyYbPKRKoF2LTm5GivuEFpVVYtvEBHtPr74N9E -sha512: r8eLGRTc7ZznZkFjeVLyo6/FyQdra9qmlYCwKKxm3kfQAswRS9+3HsYk3thLUhcFmmWhK4dXaICz -JwGFonfXwg==""" +sha512: r8eLGRTc7ZznZkFjeVLyo6/FyQdra9qmlYCwKKxm3kfQAswRS9+3HsYk3thLUhcFmmWhK4dXaICzJwGFonfXwg==""" self.assertEqual(resp.read().rstrip(), expected.strip()) def test_sub_file_hash_unrecognized(self): with self.assertRaises(urllib.error.HTTPError): self.request("/sub_file_hash_unrecognized.sub.txt") - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_sub_headers(self): resp = self.request("/sub_headers.txt", query="pipe=sub", headers={"X-Test": "PASS"}) - expected = "PASS" + expected = b"PASS" self.assertEqual(resp.read().rstrip(), expected) @pytest.mark.xfail(sys.platform == "win32", reason="https://github.com/web-platform-tests/wpt/issues/12949") - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_sub_location(self): resp = self.request("/sub_location.sub.txt?query_string") expected = """ @@ -101,30 +96,27 @@ pathname: /sub_location.sub.txt port: {0} query: ?query_string scheme: http -server: http://localhost:{0}""".format(self.server.port) +server: http://localhost:{0}""".format(self.server.port).encode("ascii") self.assertEqual(resp.read().rstrip(), expected.strip()) - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_sub_params(self): resp = self.request("/sub_params.txt", query="test=PASS&pipe=sub") - expected = "PASS" + expected = b"PASS" self.assertEqual(resp.read().rstrip(), expected) - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_sub_url_base(self): resp = self.request("/sub_url_base.sub.txt") - self.assertEqual(resp.read().rstrip(), "Before / After") + self.assertEqual(resp.read().rstrip(), b"Before / After") - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_sub_uuid(self): resp = self.request("/sub_uuid.sub.txt") - self.assertRegexpMatches(resp.read().rstrip(), r"Before [a-f0-9-]+ After") + self.assertRegexpMatches(resp.read().rstrip(), b"Before [a-f0-9-]+ After") - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_sub_var(self): resp = self.request("/sub_var.sub.txt") port = self.server.port - expected = "localhost %s A %s B localhost C" % (port, port) + print(port, type(port)) + expected = b"localhost %d A %d B localhost C" % (port, port) self.assertEqual(resp.read().rstrip(), expected) class TestTrickle(TestUsingServer): @@ -144,12 +136,10 @@ class TestTrickle(TestUsingServer): self.assertEqual(resp.info()["Expires"], "0") class TestPipesWithVariousHandlers(TestUsingServer): - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_with_python_file_handler(self): resp = self.request("/test_string.py", query="pipe=slice(null,2)") - self.assertEqual(resp.read(), "PA") + self.assertEqual(resp.read(), b"PA") - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_with_python_func_handler(self): @wptserve.handlers.handler def handler(request, response): @@ -157,9 +147,8 @@ class TestPipesWithVariousHandlers(TestUsingServer): route = ("GET", "/test/test_pipes_1/", handler) self.server.router.register(*route) resp = self.request(route[1], query="pipe=slice(null,2)") - self.assertEqual(resp.read(), "PA") + self.assertEqual(resp.read(), b"PA") - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_with_python_func_handler_using_response_writer(self): @wptserve.handlers.handler def handler(request, response): @@ -168,9 +157,8 @@ class TestPipesWithVariousHandlers(TestUsingServer): self.server.router.register(*route) resp = self.request(route[1], query="pipe=slice(null,2)") # slice has not been applied to the response, because response.writer was used. - self.assertEqual(resp.read(), "PASS") + self.assertEqual(resp.read(), b"PASS") - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_header_pipe_with_python_func_using_response_writer(self): @wptserve.handlers.handler def handler(request, response): @@ -180,9 +168,8 @@ class TestPipesWithVariousHandlers(TestUsingServer): resp = self.request(route[1], query="pipe=header(X-TEST,FAIL)") # header pipe was ignored, because response.writer was used. self.assertFalse(resp.info().get("X-TEST")) - self.assertEqual(resp.read(), "CONTENT") + self.assertEqual(resp.read(), b"CONTENT") - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_with_json_handler(self): @wptserve.handlers.json_handler def handler(request, response): @@ -190,32 +177,29 @@ class TestPipesWithVariousHandlers(TestUsingServer): route = ("GET", "/test/test_pipes_2/", handler) self.server.router.register(*route) resp = self.request(route[1], query="pipe=slice(null,2)") - self.assertEqual(resp.read(), '"{') + self.assertEqual(resp.read(), b'"{') - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_slice_with_as_is_handler(self): resp = self.request("/test.asis", query="pipe=slice(null,2)") self.assertEqual(202, resp.getcode()) self.assertEqual("Giraffe", resp.msg) self.assertEqual("PASS", resp.info()["X-Test"]) # slice has not been applied to the response, because response.writer was used. - self.assertEqual("Content", resp.read()) + self.assertEqual(b"Content", resp.read()) - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_headers_with_as_is_handler(self): resp = self.request("/test.asis", query="pipe=header(X-TEST,FAIL)") self.assertEqual(202, resp.getcode()) self.assertEqual("Giraffe", resp.msg) # header pipe was ignored. self.assertEqual("PASS", resp.info()["X-TEST"]) - self.assertEqual("Content", resp.read()) + self.assertEqual(b"Content", resp.read()) - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_trickle_with_as_is_handler(self): t0 = time.time() resp = self.request("/test.asis", query="pipe=trickle(1:d2:5:d1:r2)") t1 = time.time() - self.assertTrue('Content' in resp.read()) + self.assertTrue(b'Content' in resp.read()) self.assertGreater(6, t1-t0) if __name__ == '__main__': diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_request.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_request.py index 97d75eb7128..983539260a5 100644 --- a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_request.py +++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_request.py @@ -1,5 +1,3 @@ -import sys - import pytest wptserve = pytest.importorskip("wptserve") @@ -8,7 +6,6 @@ from wptserve.request import InputFile class TestInputFile(TestUsingServer): - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_seek(self): @wptserve.handlers.handler def handler(request, response): @@ -16,28 +13,27 @@ class TestInputFile(TestUsingServer): f = request.raw_input f.seek(5) rv.append(f.read(2)) - rv.append(f.tell()) + rv.append(b"%d" % f.tell()) f.seek(0) rv.append(f.readline()) - rv.append(f.tell()) + rv.append(b"%d" % f.tell()) rv.append(f.read(-1)) - rv.append(f.tell()) + rv.append(b"%d" % f.tell()) f.seek(0) rv.append(f.read()) f.seek(0) rv.extend(f.readlines()) - return " ".join(str(item) for item in rv) + return b" ".join(rv) route = ("POST", "/test/test_seek", handler) self.server.router.register(*route) - resp = self.request(route[1], method="POST", body="12345ab\ncdef") + resp = self.request(route[1], method="POST", body=b"12345ab\ncdef") self.assertEqual(200, resp.getcode()) - self.assertEqual(["ab", "7", "12345ab\n", "8", "cdef", "12", - "12345ab\ncdef", "12345ab\n", "cdef"], - resp.read().split(" ")) + self.assertEqual([b"ab", b"7", b"12345ab\n", b"8", b"cdef", b"12", + b"12345ab\ncdef", b"12345ab\n", b"cdef"], + resp.read().split(b" ")) - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_seek_input_longer_than_buffer(self): @wptserve.handlers.handler def handler(request, response): @@ -45,11 +41,11 @@ class TestInputFile(TestUsingServer): f = request.raw_input f.seek(5) rv.append(f.read(2)) - rv.append(f.tell()) + rv.append(b"%d" % f.tell()) f.seek(0) - rv.append(f.tell()) - rv.append(f.tell()) - return " ".join(str(item) for item in rv) + rv.append(b"%d" % f.tell()) + rv.append(b"%d" % f.tell()) + return b" ".join(rv) route = ("POST", "/test/test_seek", handler) self.server.router.register(*route) @@ -57,10 +53,10 @@ class TestInputFile(TestUsingServer): old_max_buf = InputFile.max_buffer_size InputFile.max_buffer_size = 10 try: - resp = self.request(route[1], method="POST", body="1"*20) + resp = self.request(route[1], method="POST", body=b"1"*20) self.assertEqual(200, resp.getcode()) - self.assertEqual(["11", "7", "0", "0"], - resp.read().split(" ")) + self.assertEqual([b"11", b"7", b"0", b"0"], + resp.read().split(b" ")) finally: InputFile.max_buffer_size = old_max_buf @@ -119,7 +115,6 @@ class TestRequest(TestUsingServer): class TestAuth(TestUsingServer): - @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2") def test_auth(self): @wptserve.handlers.handler def handler(request, response): @@ -129,4 +124,4 @@ class TestAuth(TestUsingServer): self.server.router.register(*route) resp = self.request(route[1], auth=("test", "PASS")) self.assertEqual(200, resp.getcode()) - self.assertEqual(["test", "PASS"], resp.read().split(" ")) + self.assertEqual([b"test", b"PASS"], resp.read().split(b" ")) diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py index ad96f591a3a..33a43e1f06b 100644 --- a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py +++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py @@ -1,5 +1,6 @@ from cgi import escape from collections import deque +import base64 import gzip as gzip_module import hashlib import os @@ -273,8 +274,9 @@ def slice(request, response, start, end=None): (spelled "null" in a query string) to indicate the end of the file. """ - content = resolve_content(response) - response.content = content[start:end] + content = resolve_content(response)[start:end] + response.content = content + response.headers.set("Content-Length", len(content)) return response @@ -392,7 +394,7 @@ class SubFunctions(object): @staticmethod def file_hash(request, algorithm, path): - algorithm = algorithm.decode("ascii") + assert isinstance(algorithm, text_type) if algorithm not in SubFunctions.supported_algorithms: raise ValueError("Unsupported encryption algorithm: '%s'" % algorithm) @@ -400,7 +402,7 @@ class SubFunctions(object): absolute_path = os.path.join(request.doc_root, path) try: - with open(absolute_path) as f: + with open(absolute_path, "rb") as f: hash_obj.update(f.read()) except IOError: # In this context, an unhandled IOError will be interpreted by the @@ -410,7 +412,7 @@ class SubFunctions(object): # the path to the file to be hashed is invalid. raise Exception('Cannot open file for hash computation: "%s"' % absolute_path) - return hash_obj.digest().encode('base64').strip() + return base64.b64encode(hash_obj.digest()).strip() def template(request, content, escape_type="html"): #TODO: There basically isn't any error handling here @@ -425,7 +427,6 @@ def template(request, content, escape_type="html"): tokens = deque(tokens) token_type, field = tokens.popleft() - field = field.decode("ascii") if token_type == "var": variable = field @@ -470,14 +471,14 @@ def template(request, content, escape_type="html"): raise Exception("Undefined template variable %s" % field) while tokens: - ttype, field = tokens.popleft() + ttype, tfield = tokens.popleft() if ttype == "index": - value = value[field] + value = value[tfield] elif ttype == "arguments": - value = value(request, *field) + value = value(request, *tfield) else: raise Exception( - "unexpected token type %s (token '%r'), expected ident or arguments" % (ttype, field) + "unexpected token type %s (token '%r'), expected ident or arguments" % (ttype, tfield) ) assert isinstance(value, (int, (binary_type, text_type))), tokens @@ -485,12 +486,19 @@ def template(request, content, escape_type="html"): if variable is not None: variables[variable] = value + if field == "GET" and not isinstance(value, str): + value = value.decode("utf-8") + escape_func = {"html": lambda x:escape(x, quote=True), "none": lambda x:x}[escape_type] #Should possibly support escaping for other contexts e.g. script #TODO: read the encoding of the response - return escape_func(text_type(value)).encode("utf-8") + if isinstance(value, binary_type): + value = value.decode("utf-8") + elif isinstance(value, int): + value = text_type(value) + return escape_func(value).encode("utf-8") template_regexp = re.compile(br"{{([^}]*)}}") new_content = template_regexp.sub(config_replacement, content) diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/request.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/request.py index cb575ccdba4..233ff151c28 100644 --- a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/request.py +++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/request.py @@ -1,7 +1,7 @@ import base64 import cgi from six.moves.http_cookies import BaseCookie -from six import BytesIO +from six import BytesIO, binary_type, text_type import tempfile from six.moves.urllib.parse import parse_qsl, urlsplit @@ -318,8 +318,8 @@ class Request(object): def cookies(self): if self._cookies is None: parser = BaseCookie() - cookie_headers = self.headers.get("cookie", "") - parser.load(cookie_headers) + cookie_headers = self.headers.get("cookie", u"") + parser.load(cookie_headers.encode("utf-8")) cookies = Cookies() for key, value in parser.iteritems(): cookies[key] = CookieValue(value) @@ -355,6 +355,16 @@ class H2Request(Request): super(H2Request, self).__init__(request_handler) +def maybedecode(s): + if isinstance(s, text_type): + return s + + if isinstance(s, binary_type): + return s.decode("ascii") + + raise TypeError("Unexpected value in RequestHeaders: %r" % s) + + class RequestHeaders(dict): """Dictionary-like API for accessing request headers.""" def __init__(self, items): @@ -369,15 +379,17 @@ class RequestHeaders(dict): for value in values: # getallmatchingheaders returns raw header lines, so # split to get name, value - multiples.append(value.split(':', 1)[1].strip()) - dict.__setitem__(self, key, multiples) + multiples.append(maybedecode(value).split(':', 1)[1].strip()) + headers = multiples else: - dict.__setitem__(self, key, [items[header]]) + headers = [maybedecode(items[header])] + dict.__setitem__(self, maybedecode(key), headers) def __getitem__(self, key): """Get all headers of a certain (case-insensitive) name. If there is more than one, the values are returned comma separated""" + key = maybedecode(key) values = dict.__getitem__(self, key.lower()) if len(values) == 1: return values[0] @@ -403,6 +415,7 @@ class RequestHeaders(dict): def get_list(self, key, default=missing): """Get all the header values for a particular field name as a list""" + key = maybedecode(key) try: return dict.__getitem__(self, key.lower()) except KeyError: @@ -412,6 +425,7 @@ class RequestHeaders(dict): raise def __contains__(self, key): + key = maybedecode(key) return dict.__contains__(self, key.lower()) def iteritems(self): @@ -599,6 +613,7 @@ class Authentication(object): if "authorization" in headers: header = headers.get("authorization") + assert isinstance(header, text_type) auth_type, data = header.split(" ", 1) if auth_type in auth_schemes: self.username, self.password = auth_schemes[auth_type](data) @@ -606,5 +621,6 @@ class Authentication(object): raise HTTPException(400, "Unsupported authentication scheme %s" % auth_type) def decode_basic(self, data): - decoded_data = base64.decodestring(data) - return decoded_data.split(":", 1) + assert isinstance(data, text_type) + decoded_data = base64.decodestring(data.encode("utf-8")) + return decoded_data.decode("utf-8").split(":", 1) diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/response.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/response.py index 44299cc994e..483265bf084 100644 --- a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/response.py +++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/response.py @@ -183,8 +183,10 @@ class Response(object): True, the entire content of the file will be returned as a string facilitating non-streaming operations like template substitution. """ - if isinstance(self.content, (binary_type, text_type)): + if isinstance(self.content, binary_type): yield self.content + elif isinstance(self.content, text_type): + yield self.content.encode("utf-8") elif hasattr(self.content, "read"): if read_file: yield self.content.read() diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/constructor/compile.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/constructor/compile.any.js index 0139a18fda3..bd23a8666e7 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/constructor/compile.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/constructor/compile.any.js @@ -68,6 +68,10 @@ promise_test(() => { return WebAssembly.compile(emptyModuleBinary).then(assert_Module); }, "Result type"); +promise_test(() => { + return WebAssembly.compile(emptyModuleBinary, {}).then(assert_Module); +}, "Stray argument"); + promise_test(() => { const buffer = new WasmModuleBuilder().toBuffer(); assert_equals(buffer[0], 0); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/constructor/validate.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/constructor/validate.any.js index 70bd9f7022a..c8613cbd9b3 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/constructor/validate.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/constructor/validate.any.js @@ -94,3 +94,7 @@ for (const [module, expected] of modules) { } } } + +test(() => { + assert_true(WebAssembly.validate(emptyModuleBinary, {})); +}, "Stray argument"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/global/constructor.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/global/constructor.any.js index 7a45cc4191c..237f99c8b29 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/global/constructor.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/global/constructor.any.js @@ -119,3 +119,9 @@ for (const type of ["i32", "f32", "f64"]) { }, `Explicit value ${name} for type ${type}`); } } + +test(() => { + const argument = { "value": "i32" }; + const global = new WebAssembly.Global(argument, 0, {}); + assert_Global(global, 0); +}, "Stray argument"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/global/value-set.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/global/value-get-set.any.js similarity index 84% rename from tests/wpt/web-platform-tests/wasm/jsapi/global/value-set.any.js rename to tests/wpt/web-platform-tests/wasm/jsapi/global/value-get-set.any.js index b4e6770f10e..6de62d5f583 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/global/value-set.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/global/value-get-set.any.js @@ -92,3 +92,20 @@ test(() => { assert_throws(new TypeError(), () => setter.call(global)); }, "Calling setter without argument"); + +test(() => { + const argument = { "value": "i32", "mutable": true }; + const global = new WebAssembly.Global(argument); + const desc = Object.getOwnPropertyDescriptor(WebAssembly.Global.prototype, "value"); + assert_equals(typeof desc, "object"); + + const getter = desc.get; + assert_equals(typeof getter, "function"); + + const setter = desc.set; + assert_equals(typeof setter, "function"); + + assert_equals(getter.call(global, {}), 0); + assert_equals(setter.call(global, 1, {}), undefined); + assert_equals(global.value, 1); +}, "Stray argument"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/global/valueOf.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/global/valueOf.any.js index 176c5a78469..d4a84b254f7 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/global/valueOf.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/global/valueOf.any.js @@ -20,3 +20,9 @@ test(() => { assert_throws(new TypeError(), () => fn.call(thisValue), `this=${format_value(thisValue)}`); } }, "Branding"); + +test(() => { + const argument = { "value": "i32" }; + const global = new WebAssembly.Global(argument, 0); + assert_equals(global.valueOf({}), 0); +}, "Stray argument"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/instance/exports.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/instance/exports.any.js index 31423918720..cad468660e0 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/instance/exports.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/instance/exports.any.js @@ -33,6 +33,20 @@ test(() => { } }, "Branding"); +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + const instance = new WebAssembly.Instance(module); + const exports = instance.exports; + + const desc = Object.getOwnPropertyDescriptor(WebAssembly.Instance.prototype, "exports"); + assert_equals(typeof desc, "object"); + + const getter = desc.get; + assert_equals(typeof getter, "function"); + + assert_equals(getter.call(instance, {}), exports); +}, "Stray argument"); + test(() => { const module = new WebAssembly.Module(emptyModuleBinary); const instance = new WebAssembly.Instance(module); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/instanceTestFactory.js b/tests/wpt/web-platform-tests/wasm/jsapi/instanceTestFactory.js index 1663ffb3469..24f849e6f94 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/instanceTestFactory.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/instanceTestFactory.js @@ -214,4 +214,16 @@ const instanceTestFactory = [ }; } ], + + [ + "stray argument", + function() { + return { + buffer: emptyModuleBinary, + args: [{}, {}], + exports: {}, + verify: () => {} + }; + } + ], ]; diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/memory/buffer.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/memory/buffer.any.js index b04460b6c5e..4788ffcf84f 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/memory/buffer.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/memory/buffer.any.js @@ -26,6 +26,20 @@ test(() => { } }, "Branding"); +test(() => { + const argument = { "initial": 0 }; + const memory = new WebAssembly.Memory(argument); + const buffer = memory.buffer; + + const desc = Object.getOwnPropertyDescriptor(WebAssembly.Memory.prototype, "buffer"); + assert_equals(typeof desc, "object"); + + const getter = desc.get; + assert_equals(typeof getter, "function"); + + assert_equals(getter.call(memory, {}), buffer); +}, "Stray argument"); + test(() => { const argument = { "initial": 0 }; const memory = new WebAssembly.Memory(argument); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/memory/constructor.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/memory/constructor.any.js index 5caf7cc8bb9..a584a23ecf0 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/memory/constructor.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/memory/constructor.any.js @@ -139,3 +139,9 @@ test(() => { const memory = new WebAssembly.Memory(argument); assert_Memory(memory, { "size": 4 }); }, "Non-zero initial"); + +test(() => { + const argument = { "initial": 0 }; + const memory = new WebAssembly.Memory(argument, {}); + assert_Memory(memory, { "size": 0 }); +}, "Stray argument"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/memory/grow.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/memory/grow.any.js index 95300399f19..1ccfb946756 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/memory/grow.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/memory/grow.any.js @@ -168,3 +168,18 @@ for (const value of outOfRangeValues) { assert_throws(new TypeError(), () => memory.grow(value)); }, `Out-of-range argument: ${format_value(value)}`); } + +test(() => { + const argument = { "initial": 0 }; + const memory = new WebAssembly.Memory(argument); + const oldMemory = memory.buffer; + assert_ArrayBuffer(oldMemory, { "size": 0 }, "Buffer before growing"); + + const result = memory.grow(2, {}); + assert_equals(result, 0); + + const newMemory = memory.buffer; + assert_not_equals(oldMemory, newMemory); + assert_ArrayBuffer(oldMemory, { "detached": true }, "Old buffer after growing"); + assert_ArrayBuffer(newMemory, { "size": 2 }, "New buffer after growing"); +}, "Stray argument"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/module/constructor.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/module/constructor.any.js index 32f183fac87..a467c1a17bb 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/module/constructor.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/module/constructor.any.js @@ -58,3 +58,8 @@ test(() => { const module = new WebAssembly.Module(emptyModuleBinary); assert_true(Object.isExtensible(module)); }, "Extensibility"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary, {}); + assert_equals(Object.getPrototypeOf(module), WebAssembly.Module.prototype); +}, "Stray argument"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/module/customSections.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/module/customSections.any.js index 58ac63b61c9..04c5abed524 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/module/customSections.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/module/customSections.any.js @@ -160,3 +160,8 @@ test(() => { bytes, ]); }, "Custom sections with U+FFFD"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + assert_sections(WebAssembly.Module.customSections(module, "", {}), []); +}, "Stray argument"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/module/exports.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/module/exports.any.js index e63a885a4c3..9d95b652233 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/module/exports.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/module/exports.any.js @@ -128,3 +128,9 @@ test(() => { ]; assert_exports(exports, expected); }, "exports"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + const exports = WebAssembly.Module.exports(module, {}); + assert_exports(exports, []); +}, "Stray argument"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/module/imports.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/module/imports.any.js index 640da591d21..b3bb8598b08 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/module/imports.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/module/imports.any.js @@ -118,3 +118,9 @@ test(() => { ]; assert_imports(imports, expected); }, "imports"); + +test(() => { + const module = new WebAssembly.Module(emptyModuleBinary); + const imports = WebAssembly.Module.imports(module, {}); + assert_imports(imports, []); +}, "Stray argument"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/table/constructor.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/table/constructor.any.js index e924bdb2ba4..99eee19fecd 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/table/constructor.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/table/constructor.any.js @@ -96,6 +96,12 @@ test(() => { assert_Table(table, { "length": 5 }); }, "Basic (non-zero)"); +test(() => { + const argument = { "element": "anyfunc", "initial": 0 }; + const table = new WebAssembly.Table(argument, {}); + assert_Table(table, { "length": 0 }); +}, "Stray argument"); + test(() => { const proxy = new Proxy({}, { has(o, x) { diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/table/get-set.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/table/get-set.any.js index 66c41340c20..f8a0194364f 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/table/get-set.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/table/get-set.any.js @@ -220,3 +220,11 @@ test(() => { assert_equals(called, 1); }, "Order of argument conversion"); +test(() => { + const {fn} = functions; + const argument = { "element": "anyfunc", "initial": 1 }; + const table = new WebAssembly.Table(argument); + + assert_equals(table.get(0, {}), null); + assert_equals(table.set(0, fn, {}), undefined); +}, "Stray argument"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/table/grow.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/table/grow.any.js index d3efb511e4b..4978e3ca23d 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/table/grow.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/table/grow.any.js @@ -84,3 +84,13 @@ for (const value of outOfRangeValues) { assert_throws(new TypeError(), () => table.grow(value)); }, `Out-of-range argument: ${format_value(value)}`); } + +test(() => { + const argument = { "element": "anyfunc", "initial": 5 }; + const table = new WebAssembly.Table(argument); + assert_equal_to_array(table, nulls(5), "before"); + + const result = table.grow(3, {}); + assert_equals(result, 5); + assert_equal_to_array(table, nulls(8), "after"); +}, "Stray argument"); diff --git a/tests/wpt/web-platform-tests/wasm/jsapi/table/length.any.js b/tests/wpt/web-platform-tests/wasm/jsapi/table/length.any.js index a6a9661dbad..b1bfa6cfd1f 100644 --- a/tests/wpt/web-platform-tests/wasm/jsapi/table/length.any.js +++ b/tests/wpt/web-platform-tests/wasm/jsapi/table/length.any.js @@ -26,6 +26,20 @@ test(() => { } }, "Branding"); +test(() => { + const argument = { "element": "anyfunc", "initial": 2 }; + const table = new WebAssembly.Table(argument); + assert_equals(table.length, 2, "Initial length"); + + const desc = Object.getOwnPropertyDescriptor(WebAssembly.Table.prototype, "length"); + assert_equals(typeof desc, "object"); + + const getter = desc.get; + assert_equals(typeof getter, "function"); + + assert_equals(getter.call(table, {}), 2); +}, "Stray argument"); + test(() => { const argument = { "element": "anyfunc", "initial": 2 }; const table = new WebAssembly.Table(argument); diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/special_keys.py b/tests/wpt/web-platform-tests/webdriver/tests/actions/special_keys.py deleted file mode 100644 index 416cbdcf20f..00000000000 --- a/tests/wpt/web-platform-tests/webdriver/tests/actions/special_keys.py +++ /dev/null @@ -1,82 +0,0 @@ -# META: timeout=long - -import pytest -import time -from tests.actions.support.keys import ALL_EVENTS, Keys -from tests.actions.support.refine import filter_dict, get_keys, get_events -from webdriver import error - -@pytest.mark.parametrize("name,expected", ALL_EVENTS.items()) -def test_webdriver_special_key_sends_keydown(session, - key_reporter, - key_chain, - name, - expected): - if name.startswith("F"): - # Prevent default behavior for F1, etc., but only after keydown - # bubbles up to body. (Otherwise activated browser menus/functions - # may interfere with subsequent tests.) - session.execute_script(""" - document.body.addEventListener("keydown", - function(e) { e.preventDefault() }); - """) - if (session.capabilities["browserName"] == 'internet explorer'): - key_reporter.click() - session.execute_script("resetEvents();") - key_chain.key_down(getattr(Keys, name)).perform() - - # only interested in keydown - first_event = get_events(session)[0] - # make a copy so we can throw out irrelevant keys and compare to events - expected = dict(expected) - - del expected["value"] - - # check and remove keys that aren't in expected - assert first_event["type"] == "keydown" - assert first_event["repeat"] == False - first_event = filter_dict(first_event, expected) - if first_event["code"] == None: - del first_event["code"] - del expected["code"] - assert first_event == expected - # only printable characters should be recorded in input field - entered_keys = get_keys(key_reporter) - if len(expected["key"]) == 1: - assert entered_keys == expected["key"] - else: - assert len(entered_keys) == 0 - - -@pytest.mark.parametrize("value", [ - (u"f"), - (u"\u0BA8\u0BBF"), - (u"\u1100\u1161\u11A8"), -]) -def test_multiple_codepoint_keys_behave_correctly(session, - key_reporter, - key_chain, - value): - key_chain \ - .key_down(value) \ - .key_up(value) \ - .perform() - - assert get_keys(key_reporter) == value - - -@pytest.mark.parametrize("value", [ - (u"fa"), - (u"\u0BA8\u0BBFb"), - (u"\u0BA8\u0BBF\u0BA8"), - (u"\u1100\u1161\u11A8c") -]) -def test_invalid_multiple_codepoint_keys_fail(session, - key_reporter, - key_chain, - value): - with pytest.raises(error.InvalidArgumentException): - key_chain \ - .key_down(value) \ - .key_up(value) \ - .perform() \ No newline at end of file diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/__init__.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/__init__.py similarity index 100% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/__init__.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/__init__.py diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/conftest.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/conftest.py similarity index 91% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/conftest.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/conftest.py index 55cecd11782..dffae0b98cd 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/actions/conftest.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/conftest.py @@ -37,4 +37,4 @@ def key_reporter(session, test_actions_page, request): @pytest.fixture def test_actions_page(session, url): - session.url = url("/webdriver/tests/actions/support/test_actions_wdspec.html") + session.url = url("/webdriver/tests/perform_actions/support/test_actions_wdspec.html") diff --git a/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key.py new file mode 100644 index 00000000000..2b3414c5ebf --- /dev/null +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key.py @@ -0,0 +1,25 @@ +import pytest + +from webdriver.error import NoSuchWindowException + +from tests.perform_actions.support.keys import Keys +from tests.perform_actions.support.refine import get_keys + + +def test_null_response_value(session, key_chain): + value = key_chain.key_up("a").perform() + assert value is None + + +def test_no_browsing_context(session, closed_window, key_chain): + with pytest.raises(NoSuchWindowException): + key_chain.key_up("a").perform() + + +def test_backspace_erases_keys(session, key_reporter, key_chain): + key_chain \ + .send_keys("efcd") \ + .send_keys([Keys.BACKSPACE, Keys.BACKSPACE]) \ + .perform() + + assert get_keys(key_reporter) == "ef" diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/key.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key_events.py similarity index 51% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/key.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key_events.py index 50c4ed9132b..462688a55e5 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/actions/key.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key_events.py @@ -1,33 +1,91 @@ +# META: timeout=long + import pytest -from webdriver.error import NoSuchWindowException - -from tests.actions.support.keys import Keys -from tests.actions.support.refine import filter_dict, get_keys, get_events +from tests.perform_actions.support.keys import ALL_EVENTS, Keys +from tests.perform_actions.support.refine import filter_dict, get_events, get_keys -def test_null_response_value(session, key_chain): - value = key_chain.key_up("a").perform() - assert value is None - - value = session.actions.release() - assert value is None - - -def test_no_browsing_context(session, closed_window, key_chain): - with pytest.raises(NoSuchWindowException): - key_chain.key_up("a").perform() - - -def test_lone_keyup_sends_no_events(session, key_reporter, key_chain): +def test_keyup_only_sends_no_events(session, key_reporter, key_chain): key_chain.key_up("a").perform() + assert len(get_keys(key_reporter)) == 0 assert len(get_events(session)) == 0 + session.actions.release() assert len(get_keys(key_reporter)) == 0 assert len(get_events(session)) == 0 +@pytest.mark.parametrize("key, event", [ + (Keys.ALT, "ALT"), + (Keys.CONTROL, "CONTROL"), + (Keys.META, "META"), + (Keys.SHIFT, "SHIFT"), + (Keys.R_ALT, "R_ALT"), + (Keys.R_CONTROL, "R_CONTROL"), + (Keys.R_META, "R_META"), + (Keys.R_SHIFT, "R_SHIFT"), +]) +def test_modifier_key_sends_correct_events(session, key_reporter, key_chain, key, event): + code = ALL_EVENTS[event]["code"] + value = ALL_EVENTS[event]["key"] + + key_chain \ + .key_down(key) \ + .key_up(key) \ + .perform() + all_events = get_events(session) + + expected = [ + {"code": code, "key": value, "type": "keydown"}, + {"code": code, "key": value, "type": "keyup"}, + ] + + events = [filter_dict(e, expected[0]) for e in all_events] + if len(events) > 0 and events[0]["code"] is None: + # Remove 'code' entry if browser doesn't support it + expected = [filter_dict(e, {"key": "", "type": ""}) for e in expected] + events = [filter_dict(e, expected[0]) for e in events] + assert events == expected + + assert len(get_keys(key_reporter)) == 0 + + +@pytest.mark.parametrize("key,event", [ + (Keys.ESCAPE, "ESCAPE"), + (Keys.RIGHT, "RIGHT"), +]) +def test_non_printable_key_sends_events(session, key_reporter, key_chain, key, event): + code = ALL_EVENTS[event]["code"] + value = ALL_EVENTS[event]["key"] + + key_chain \ + .key_down(key) \ + .key_up(key) \ + .perform() + all_events = get_events(session) + + expected = [ + {"code": code, "key": value, "type": "keydown"}, + {"code": code, "key": value, "type": "keypress"}, + {"code": code, "key": value, "type": "keyup"}, + ] + + events = [filter_dict(e, expected[0]) for e in all_events] + if len(events) > 0 and events[0]["code"] is None: + # Remove 'code' entry if browser doesn't support it + expected = [filter_dict(e, {"key": "", "type": ""}) for e in expected] + events = [filter_dict(e, expected[0]) for e in events] + if len(events) == 2: + # most browsers don't send a keypress for non-printable keys + assert events == [expected[0], expected[2]] + else: + assert events == expected + + assert len(get_keys(key_reporter)) == 0 + + @pytest.mark.parametrize("value,code", [ (u"a", "KeyA",), ("a", "KeyA",), @@ -39,133 +97,57 @@ def test_lone_keyup_sends_no_events(session, key_reporter, key_chain): (u"\u2603", ""), (u"\uF6C2", ""), # PUA ]) -def test_single_printable_key_sends_correct_events(session, - key_reporter, - key_chain, - value, - code): +def test_printable_key_sends_correct_events(session, key_reporter, key_chain, value, code): key_chain \ .key_down(value) \ .key_up(value) \ .perform() + all_events = get_events(session) + expected = [ {"code": code, "key": value, "type": "keydown"}, {"code": code, "key": value, "type": "keypress"}, {"code": code, "key": value, "type": "keyup"}, ] - all_events = get_events(session) + events = [filter_dict(e, expected[0]) for e in all_events] - if len(events) > 0 and events[0]["code"] == None: + if len(events) > 0 and events[0]["code"] is None: # Remove 'code' entry if browser doesn't support it expected = [filter_dict(e, {"key": "", "type": ""}) for e in expected] events = [filter_dict(e, expected[0]) for e in events] assert events == expected + assert get_keys(key_reporter) == value -@pytest.mark.parametrize("value", [ - (u"\U0001F604"), - (u"\U0001F60D"), -]) -def test_single_emoji_records_correct_key(session, key_reporter, key_chain, value): - # Not using key_chain.send_keys() because we always want to treat value as - # one character here. `len(value)` varies by platform for non-BMP characters, - # so we don't want to iterate over value. - key_chain \ - .key_down(value) \ - .key_up(value) \ - .perform() - # events sent by major browsers are inconsistent so only check key value - assert get_keys(key_reporter) == value - - -@pytest.mark.parametrize("value,code,key", [ - (u"\uE050", "ShiftRight", "Shift"), - (u"\uE053", "OSRight", "Meta"), - (Keys.CONTROL, "ControlLeft", "Control"), -]) -def test_single_modifier_key_sends_correct_events(session, - key_reporter, - key_chain, - value, - code, - key): - key_chain \ - .key_down(value) \ - .key_up(value) \ - .perform() - all_events = get_events(session) - expected = [ - {"code": code, "key": key, "type": "keydown"}, - {"code": code, "key": key, "type": "keyup"}, - ] - events = [filter_dict(e, expected[0]) for e in all_events] - if len(events) > 0 and events[0]["code"] == None: - # Remove 'code' entry if browser doesn't support it - expected = [filter_dict(e, {"key": "", "type": ""}) for e in expected] - events = [filter_dict(e, expected[0]) for e in events] - assert events == expected - assert len(get_keys(key_reporter)) == 0 - - -@pytest.mark.parametrize("value,code,key", [ - (Keys.ESCAPE, "Escape", "Escape"), - (Keys.RIGHT, "ArrowRight", "ArrowRight"), -]) -def test_single_nonprintable_key_sends_events(session, - key_reporter, - key_chain, - value, - code, - key): - key_chain \ - .key_down(value) \ - .key_up(value) \ - .perform() - expected = [ - {"code": code, "key": key, "type": "keydown"}, - {"code": code, "key": key, "type": "keypress"}, - {"code": code, "key": key, "type": "keyup"}, - ] - all_events = get_events(session) - events = [filter_dict(e, expected[0]) for e in all_events] - if len(events) > 0 and events[0]["code"] == None: - # Remove 'code' entry if browser doesn't support it - expected = [filter_dict(e, {"key": "", "type": ""}) for e in expected] - events = [filter_dict(e, expected[0]) for e in events] - if len(events) == 2: - # most browsers don't send a keypress for non-printable keys - assert events == [expected[0], expected[2]] - else: - assert events == expected - assert len(get_keys(key_reporter)) == 0 - - -def test_sequence_of_keydown_printable_keys_sends_events(session, - key_reporter, - key_chain): +def test_sequence_of_keydown_printable_keys_sends_events(session, key_reporter, key_chain): key_chain \ .key_down("a") \ .key_down("b") \ .perform() + all_events = get_events(session) + expected = [ {"code": "KeyA", "key": "a", "type": "keydown"}, {"code": "KeyA", "key": "a", "type": "keypress"}, {"code": "KeyB", "key": "b", "type": "keydown"}, {"code": "KeyB", "key": "b", "type": "keypress"}, ] - all_events = get_events(session) + events = [filter_dict(e, expected[0]) for e in all_events] - if len(events) > 0 and events[0]["code"] == None: + if len(events) > 0 and events[0]["code"] is None: # Remove 'code' entry if browser doesn't support it expected = [filter_dict(e, {"key": "", "type": ""}) for e in expected] events = [filter_dict(e, expected[0]) for e in events] assert events == expected + assert get_keys(key_reporter) == "ab" -def test_sequence_of_keydown_character_keys(session, key_reporter, key_chain): +def test_sequence_of_keydown_printable_characters_sends_events(session, key_reporter, key_chain): key_chain.send_keys("ef").perform() + all_events = get_events(session) + expected = [ {"code": "KeyE", "key": "e", "type": "keydown"}, {"code": "KeyE", "key": "e", "type": "keypress"}, @@ -174,20 +156,50 @@ def test_sequence_of_keydown_character_keys(session, key_reporter, key_chain): {"code": "KeyF", "key": "f", "type": "keypress"}, {"code": "KeyF", "key": "f", "type": "keyup"}, ] - all_events = get_events(session) + events = [filter_dict(e, expected[0]) for e in all_events] - if len(events) > 0 and events[0]["code"] == None: + if len(events) > 0 and events[0]["code"] is None: # Remove 'code' entry if browser doesn't support it expected = [filter_dict(e, {"key": "", "type": ""}) for e in expected] events = [filter_dict(e, expected[0]) for e in events] assert events == expected + assert get_keys(key_reporter) == "ef" -def test_backspace_erases_keys(session, key_reporter, key_chain): - key_chain \ - .send_keys("efcd") \ - .send_keys([Keys.BACKSPACE, Keys.BACKSPACE]) \ - .perform() - assert get_keys(key_reporter) == "ef" +@pytest.mark.parametrize("name,expected", ALL_EVENTS.items()) +def test_special_key_sends_keydown(session, key_reporter, key_chain, name, expected): + if name.startswith("F"): + # Prevent default behavior for F1, etc., but only after keydown + # bubbles up to body. (Otherwise activated browser menus/functions + # may interfere with subsequent tests.) + session.execute_script(""" + document.body.addEventListener("keydown", + function(e) { e.preventDefault() }); + """) + if (session.capabilities["browserName"] == 'internet explorer'): + key_reporter.click() + session.execute_script("resetEvents();") + key_chain.key_down(getattr(Keys, name)).perform() + # only interested in keydown + first_event = get_events(session)[0] + # make a copy so we can throw out irrelevant keys and compare to events + expected = dict(expected) + + del expected["value"] + + # check and remove keys that aren't in expected + assert first_event["type"] == "keydown" + assert first_event["repeat"] is False + first_event = filter_dict(first_event, expected) + if first_event["code"] is None: + del first_event["code"] + del expected["code"] + assert first_event == expected + # only printable characters should be recorded in input field + entered_keys = get_keys(key_reporter) + if len(expected["key"]) == 1: + assert entered_keys == expected["key"] + else: + assert len(entered_keys) == 0 diff --git a/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key_modifiers.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key_modifiers.py new file mode 100644 index 00000000000..55dc9280c62 --- /dev/null +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key_modifiers.py @@ -0,0 +1,24 @@ +import pytest + +from tests.perform_actions.support.keys import Keys + + +@pytest.mark.parametrize("modifier", [Keys.SHIFT, Keys.R_SHIFT]) +def test_shift_modifier_generates_capital_letters(session, key_reporter, key_chain, modifier): + key_chain \ + .send_keys("b") \ + .key_down(modifier) \ + .key_down("c") \ + .key_up(modifier) \ + .key_up("c") \ + .key_down("d") \ + .key_up("d") \ + .key_down(modifier) \ + .key_down("e") \ + .key_up("e") \ + .key_down("f") \ + .key_up(modifier) \ + .key_up("f") \ + .perform() + + assert key_reporter.property("value") == "bCdEF" diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/key_shortcuts.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key_shortcuts.py similarity index 92% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/key_shortcuts.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key_shortcuts.py index ec062f75224..31b533ac850 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/actions/key_shortcuts.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key_shortcuts.py @@ -1,5 +1,5 @@ -from tests.actions.support.keys import Keys, MODIFIER_KEY -from tests.actions.support.refine import get_keys +from tests.perform_actions.support.keys import Keys, MODIFIER_KEY +from tests.perform_actions.support.refine import get_keys def test_mod_a_and_backspace_deletes_all_text(session, key_reporter, key_chain): diff --git a/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key_special_keys.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key_special_keys.py new file mode 100644 index 00000000000..003bba42941 --- /dev/null +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/key_special_keys.py @@ -0,0 +1,38 @@ +import pytest + +from webdriver import error + +from tests.perform_actions.support.refine import get_keys + + +@pytest.mark.parametrize("value", [ + (u"\U0001F604"), + (u"\U0001F60D"), + (u"\u0BA8\u0BBF"), + (u"\u1100\u1161\u11A8"), +]) +def test_codepoint_keys_behave_correctly(session, key_reporter, key_chain, value): + # Not using key_chain.send_keys() because we always want to treat value as + # one character here. `len(value)` varies by platform for non-BMP characters, + # so we don't want to iterate over value. + key_chain \ + .key_down(value) \ + .key_up(value) \ + .perform() + + # events sent by major browsers are inconsistent so only check key value + assert get_keys(key_reporter) == value + + +@pytest.mark.parametrize("value", [ + (u"fa"), + (u"\u0BA8\u0BBFb"), + (u"\u0BA8\u0BBF\u0BA8"), + (u"\u1100\u1161\u11A8c") +]) +def test_invalid_multiple_codepoint_keys_fail(session, key_reporter, key_chain, value): + with pytest.raises(error.InvalidArgumentException): + key_chain \ + .key_down(value) \ + .key_up(value) \ + .perform() diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/none.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/none.py similarity index 100% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/none.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/none.py diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer.py similarity index 94% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/mouse.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer.py index ca8bffceb71..9a68f322d70 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer.py @@ -2,8 +2,8 @@ import pytest from webdriver.error import NoSuchWindowException -from tests.actions.support.mouse import get_inview_center, get_viewport_rect -from tests.actions.support.refine import get_events, filter_dict +from tests.perform_actions.support.mouse import get_inview_center, get_viewport_rect +from tests.perform_actions.support.refine import filter_dict, get_events from tests.support.asserts import assert_move_to_coordinates from tests.support.inline import inline from tests.support.wait import wait @@ -18,9 +18,6 @@ def test_null_response_value(session, mouse_chain): value = mouse_chain.click().perform() assert value is None - value = session.actions.release() - assert value is None - def test_no_browsing_context(session, closed_window, mouse_chain): with pytest.raises(NoSuchWindowException): @@ -91,7 +88,7 @@ def test_click_element_center(session, test_actions_page, mouse_chain): assert e["target"] == "outer" -def test_click_navigation(session, url, release_actions): +def test_click_navigation(session, url): destination = url("/webdriver/tests/actions/support/test_actions_wdspec.html") start = link_doc(destination) diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/control_click.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_contextmenu.py similarity index 94% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/control_click.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_contextmenu.py index 2ec819b772f..c64c51252a5 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/actions/control_click.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_contextmenu.py @@ -1,7 +1,7 @@ import pytest -from tests.actions.support.refine import filter_dict, get_events -from tests.actions.support.keys import Keys +from tests.perform_actions.support.keys import Keys +from tests.perform_actions.support.refine import filter_dict, get_events @pytest.mark.parametrize("modifier, prop", [ diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse_dblclick.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_dblclick.py similarity index 93% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/mouse_dblclick.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_dblclick.py index fc53a51ab76..8c89cef5f38 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse_dblclick.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_dblclick.py @@ -1,6 +1,6 @@ import pytest -from tests.actions.support.refine import get_events, filter_dict +from tests.perform_actions.support.refine import filter_dict, get_events from tests.support.asserts import assert_move_to_coordinates diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/modifier_click.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_modifier_click.py similarity index 94% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/modifier_click.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_modifier_click.py index fbfd837710b..ba81f6d090b 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/actions/modifier_click.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_modifier_click.py @@ -1,7 +1,7 @@ import pytest -from tests.actions.support.refine import filter_dict, get_events -from tests.actions.support.keys import Keys +from tests.perform_actions.support.keys import Keys +from tests.perform_actions.support.refine import filter_dict, get_events @pytest.mark.parametrize("modifier, prop", [ diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/pointer_origin.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_origin.py similarity index 98% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/pointer_origin.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_origin.py index cad59f0a13b..3ebf14c348c 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/actions/pointer_origin.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_origin.py @@ -2,7 +2,7 @@ import pytest from webdriver import MoveTargetOutOfBoundsException -from tests.actions.support.mouse import get_inview_center, get_viewport_rect +from tests.perform_actions.support.mouse import get_inview_center, get_viewport_rect from tests.support.inline import inline diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse_pause_dblclick.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_pause_dblclick.py similarity index 92% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/mouse_pause_dblclick.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_pause_dblclick.py index ad179673176..85679f3614a 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse_pause_dblclick.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/pointer_pause_dblclick.py @@ -1,5 +1,5 @@ -from tests.actions.support.mouse import get_inview_center, get_viewport_rect -from tests.actions.support.refine import get_events, filter_dict +from tests.perform_actions.support.mouse import get_inview_center, get_viewport_rect +from tests.perform_actions.support.refine import filter_dict, get_events _DBLCLICK_INTERVAL = 640 diff --git a/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/sequence.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/sequence.py new file mode 100644 index 00000000000..3536abeb12b --- /dev/null +++ b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/sequence.py @@ -0,0 +1,9 @@ +# META: timeout=long + +from tests.perform_actions.support.refine import get_events, get_keys + + +def test_perform_no_actions_send_no_events(session, key_reporter, key_chain): + key_chain.perform() + assert len(get_keys(key_reporter)) == 0 + assert len(get_events(session)) == 0 diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/support/__init__.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/support/__init__.py similarity index 100% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/support/__init__.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/support/__init__.py diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/support/keys.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/support/keys.py similarity index 100% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/support/keys.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/support/keys.py diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/support/mouse.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/support/mouse.py similarity index 100% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/support/mouse.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/support/mouse.py diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/support/refine.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/support/refine.py similarity index 100% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/support/refine.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/support/refine.py diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/support/test_actions_wdspec.html b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/support/test_actions_wdspec.html similarity index 100% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/support/test_actions_wdspec.html rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/support/test_actions_wdspec.html diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/validity.py b/tests/wpt/web-platform-tests/webdriver/tests/perform_actions/validity.py similarity index 100% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/validity.py rename to tests/wpt/web-platform-tests/webdriver/tests/perform_actions/validity.py diff --git a/tests/wpt/web-platform-tests/webdriver/tests/release_actions/__init__.py b/tests/wpt/web-platform-tests/webdriver/tests/release_actions/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/wpt/web-platform-tests/webdriver/tests/release_actions/conftest.py b/tests/wpt/web-platform-tests/webdriver/tests/release_actions/conftest.py new file mode 100644 index 00000000000..df86db63067 --- /dev/null +++ b/tests/wpt/web-platform-tests/webdriver/tests/release_actions/conftest.py @@ -0,0 +1,40 @@ +import pytest + + +@pytest.fixture +def key_chain(session): + return session.actions.sequence("key", "keyboard_id") + + +@pytest.fixture +def mouse_chain(session): + return session.actions.sequence( + "pointer", + "pointer_id", + {"pointerType": "mouse"}) + + +@pytest.fixture +def none_chain(session): + return session.actions.sequence("none", "none_id") + + +@pytest.fixture(autouse=True) +def release_actions(session, request): + # release all actions after each test + # equivalent to a teardown_function, but with access to session fixture + request.addfinalizer(session.actions.release) + + +@pytest.fixture +def key_reporter(session, test_actions_page, request): + """Represents focused input element from `test_keys_page` fixture.""" + input_el = session.find.css("#keys", all=False) + input_el.click() + session.execute_script("resetEvents();") + return input_el + + +@pytest.fixture +def test_actions_page(session, url): + session.url = url("/webdriver/tests/release_actions/support/test_actions_wdspec.html") diff --git a/tests/wpt/web-platform-tests/webdriver/tests/release_actions/release.py b/tests/wpt/web-platform-tests/webdriver/tests/release_actions/release.py new file mode 100644 index 00000000000..84719043d1c --- /dev/null +++ b/tests/wpt/web-platform-tests/webdriver/tests/release_actions/release.py @@ -0,0 +1,18 @@ +from tests.support.asserts import assert_error, assert_success + + +def release_actions(session): + return session.transport.send( + "DELETE", + "/session/{session_id}/actions".format(**vars(session)), + ) + + +def test_null_response_value(session): + response = release_actions(session) + assert_success(response, None) + + +def test_no_browsing_context(session, closed_window): + response = release_actions(session) + assert_error(response, "no such window") diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/sequence.py b/tests/wpt/web-platform-tests/webdriver/tests/release_actions/sequence.py similarity index 91% rename from tests/wpt/web-platform-tests/webdriver/tests/actions/sequence.py rename to tests/wpt/web-platform-tests/webdriver/tests/release_actions/sequence.py index b62d00c3e9b..2d816f8094b 100644 --- a/tests/wpt/web-platform-tests/webdriver/tests/actions/sequence.py +++ b/tests/wpt/web-platform-tests/webdriver/tests/release_actions/sequence.py @@ -1,12 +1,6 @@ # META: timeout=long -from tests.actions.support.refine import get_keys, filter_dict, get_events - - -def test_perform_no_actions_send_no_events(session, key_reporter, key_chain): - key_chain.perform() - assert len(get_keys(key_reporter)) == 0 - assert len(get_events(session)) == 0 +from tests.release_actions.support.refine import filter_dict, get_events, get_keys def test_release_no_actions_sends_no_events(session, key_reporter): diff --git a/tests/wpt/web-platform-tests/webdriver/tests/release_actions/support/__init__.py b/tests/wpt/web-platform-tests/webdriver/tests/release_actions/support/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/wpt/web-platform-tests/webdriver/tests/release_actions/support/refine.py b/tests/wpt/web-platform-tests/webdriver/tests/release_actions/support/refine.py new file mode 100644 index 00000000000..3a6d63e04ce --- /dev/null +++ b/tests/wpt/web-platform-tests/webdriver/tests/release_actions/support/refine.py @@ -0,0 +1,33 @@ +def get_events(session): + """Return list of key events recorded in the test_keys_page fixture.""" + events = session.execute_script("return allEvents.events;") or [] + # `key` values in `allEvents` may be escaped (see `escapeSurrogateHalf` in + # test_keys_wdspec.html), so this converts them back into unicode literals. + for e in events: + # example: turn "U+d83d" (6 chars) into u"\ud83d" (1 char) + if "key" in e and e["key"].startswith(u"U+"): + key = e["key"] + hex_suffix = key[key.index("+") + 1:] + e["key"] = unichr(int(hex_suffix, 16)) + return events + + +def get_keys(input_el): + """Get printable characters entered into `input_el`. + + :param input_el: HTML input element. + """ + rv = input_el.property("value") + if rv is None: + return "" + else: + return rv + + +def filter_dict(source, d): + """Filter `source` dict to only contain same keys as `d` dict. + + :param source: dictionary to filter. + :param d: dictionary whose keys determine the filtering. + """ + return {k: source[k] for k in d.keys()} diff --git a/tests/wpt/web-platform-tests/webdriver/tests/release_actions/support/test_actions_wdspec.html b/tests/wpt/web-platform-tests/webdriver/tests/release_actions/support/test_actions_wdspec.html new file mode 100644 index 00000000000..6f844cd255a --- /dev/null +++ b/tests/wpt/web-platform-tests/webdriver/tests/release_actions/support/test_actions_wdspec.html @@ -0,0 +1,197 @@ + + + +
+