Bug 1470530 - [wdspec] Allow parametrization of "session" fixture and remove global "new_session" fixture. draft
authorHenrik Skupin <mail@hskupin.info>
Fri, 22 Jun 2018 20:50:23 +0200
changeset 813912 87985a2364b920cb16cc34b3b0e986eae59e62b3
parent 813911 841452f2d674c9e757f8ddc3dc124a33bbc54fca
child 813913 5cbc844b1b9fff6b46e19cf8e3babecf53da02f9
push id115045
push userbmo:hskupin@gmail.com
push dateWed, 04 Jul 2018 04:53:58 +0000
bugs1470530
milestone63.0a1
Bug 1470530 - [wdspec] Allow parametrization of "session" fixture and remove global "new_session" fixture. With this patch the "session" fixture will make use of the new "capabilities" fixture to create WebDriver sessions with custom capabilities. It means the separate "new_session" fixture is no longer needed. Further the "session" fixture will only create a new session when the specified capabilities are different from the requested capabilities of the current session. To make it easier for tests to specify custom capabilities a marker with the same name has been created. It accepts a dict of capabilities as argument, and will then parametrize the current test. MozReview-Commit-ID: 8gQCQTtXs7C
testing/web-platform/meta/MANIFEST.json
testing/web-platform/meta/webdriver/tests/close_window/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/delete_cookie/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/element_send_keys/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/execute_async_script/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/execute_script/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/fullscreen_window/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/get_current_url/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/get_element_property/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/get_element_tag_name/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/get_title/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/get_window_rect/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/is_element_selected/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/minimize_window/user_prompts.py.ini
testing/web-platform/meta/webdriver/tests/set_window_rect/user_prompts.py.ini
testing/web-platform/tests/webdriver/tests/close_window/user_prompts.py
testing/web-platform/tests/webdriver/tests/conftest.py
testing/web-platform/tests/webdriver/tests/delete_cookie/user_prompts.py
testing/web-platform/tests/webdriver/tests/element_send_keys/user_prompts.py
testing/web-platform/tests/webdriver/tests/execute_async_script/user_prompts.py
testing/web-platform/tests/webdriver/tests/execute_script/user_prompts.py
testing/web-platform/tests/webdriver/tests/fullscreen_window/user_prompts.py
testing/web-platform/tests/webdriver/tests/get_current_url/user_prompts.py
testing/web-platform/tests/webdriver/tests/get_element_property/user_prompts.py
testing/web-platform/tests/webdriver/tests/get_element_tag_name/user_prompts.py
testing/web-platform/tests/webdriver/tests/get_title/user_prompts.py
testing/web-platform/tests/webdriver/tests/get_window_rect/user_prompts.py
testing/web-platform/tests/webdriver/tests/is_element_selected/user_prompts.py
testing/web-platform/tests/webdriver/tests/maximize_window/user_prompts.py
testing/web-platform/tests/webdriver/tests/minimize_window/user_prompts.py
testing/web-platform/tests/webdriver/tests/set_window_rect/user_prompts.py
testing/web-platform/tests/webdriver/tests/status/status.py
testing/web-platform/tests/webdriver/tests/support/fixtures.py
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -549727,17 +549727,17 @@
    "cd3f0233cc0eaf9295e602ca25aef87fb68df851",
    "support"
   ],
   "css/mediaqueries/support/min-width-tables-001-iframe.html": [
    "29e7fb34c94e2e8411514d1e71d09aca2ddb642e",
    "support"
   ],
   "css/mediaqueries/test_media_queries.html": [
-   "cff3585932589f611a7101329d3b5b6ca27820aa",
+   "a7d78b13e119f8cd1ffa8812a9af67e59280084d",
    "testharness"
   ],
   "css/mediaqueries/viewport-script-dynamic-ref.html": [
    "7d55c513e2de39c9b362fc864233a3008ca6ced2",
    "support"
   ],
   "css/mediaqueries/viewport-script-dynamic.html": [
    "1c2ba1a9116942599804ed29553e85628afadb04",
@@ -619967,21 +619967,21 @@
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/close_window/close.py": [
    "8c22860607cb0f3d610888c9816bf2384e2c5445",
    "wdspec"
   ],
   "webdriver/tests/close_window/user_prompts.py": [
-   "58390344e980306233cd0daedca99fd4ec855cf8",
+   "ff6cf5341848d15094898cf72a01a1834e142a08",
    "wdspec"
   ],
   "webdriver/tests/conftest.py": [
-   "507edfc726b5e4b78937735e3e6969ecc1c135fe",
+   "6d40ad141aea1a1ec6458c32694ef72ef5314569",
    "support"
   ],
   "webdriver/tests/delete_all_cookies/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/delete_all_cookies/delete.py": [
    "1248b2e14b6b690b996f8bf620a6a1f33514256a",
@@ -619991,17 +619991,17 @@
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/delete_cookie/delete.py": [
    "e9b90bac0e666ce82b3c0006830febcef726d688",
    "wdspec"
   ],
   "webdriver/tests/delete_cookie/user_prompts.py": [
-   "65b753bd80a06c3c20b0330f624a4d395fdb7ab2",
+   "fa44075d31887e0b20495164053cc0e5ef4ebed0",
    "wdspec"
   ],
   "webdriver/tests/delete_session/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/delete_session/delete.py": [
    "1df6e1bfba0577a591bda8e0e27b96a1abcea1fb",
@@ -620075,29 +620075,29 @@
    "e4a50a53a13c1ab76c6c002bbda1c103f8c32ccf",
    "wdspec"
   ],
   "webdriver/tests/element_send_keys/send_keys.py": [
    "83e4292e0e587a641f73d21cb1ddadc420251a10",
    "wdspec"
   ],
   "webdriver/tests/element_send_keys/user_prompts.py": [
-   "a351706452816ea1ca9719c22c47bd2fcd3e3ab8",
+   "d53c4c750c125ef2f8131b08b7a3ab49c6672811",
    "wdspec"
   ],
   "webdriver/tests/execute_async_script/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/execute_async_script/collections.py": [
    "d6c95dfdcbfc3b9cf91cf6f943a17b7cd0fee79d",
    "wdspec"
   ],
   "webdriver/tests/execute_async_script/user_prompts.py": [
-   "d89434bc628d4800f2a5a8554e7cdcbba3b6c1e7",
+   "e4b36de9f869a9911316a211541732720ca408ed",
    "wdspec"
   ],
   "webdriver/tests/execute_script/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/execute_script/collections.py": [
    "0ee4e340b38b6aa59043286755822460e76b2dbd",
@@ -620107,17 +620107,17 @@
    "21bae43b3a6e966b8698b7c439b29a68029adc58",
    "wdspec"
   ],
   "webdriver/tests/execute_script/json_serialize_windowproxy.py": [
    "20db10d82ed2b28a22674fcdc37cac0323d33c95",
    "wdspec"
   ],
   "webdriver/tests/execute_script/user_prompts.py": [
-   "4bd4e9089185505d8add4d5ebe9806498da42999",
+   "7534ddf504d1ba2f31b4d0a86aa7a7e11560bfdc",
    "wdspec"
   ],
   "webdriver/tests/find_element/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/find_element/find.py": [
    "9af0db4de0d09cbf68fa43bb40145cffc7b95635",
@@ -620159,17 +620159,17 @@
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/fullscreen_window/fullscreen.py": [
    "8a6e06b2fbd2ec80326ab1145e6ddfb35c6995b4",
    "wdspec"
   ],
   "webdriver/tests/fullscreen_window/user_prompts.py": [
-   "8d6d68bb6bfa9956db5b33598ae3cf33f7022de4",
+   "3d3c647059d820debf51a8a3a9b8fca9f7104d10",
    "wdspec"
   ],
   "webdriver/tests/get_active_element/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/get_active_element/get.py": [
    "6d48b8577c9edf5f1e39fae461831de742ff9dd8",
@@ -620187,45 +620187,45 @@
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/get_current_url/get.py": [
    "f65054e80f7ddc9a7b8600765929935355b5f447",
    "wdspec"
   ],
   "webdriver/tests/get_current_url/user_prompts.py": [
-   "3241e1d4dbda430b32763006d558fb53d06ffaa1",
+   "8af1c24bc33e4929eb04468993037de43b44ac5c",
    "wdspec"
   ],
   "webdriver/tests/get_element_attribute/get.py": [
    "3fdd451b8aa73729f25325cb0e43ae389a223ee7",
    "wdspec"
   ],
   "webdriver/tests/get_element_property/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/get_element_property/get.py": [
    "2b36e390348a37e2138f480a7f36eb08ef6a2ee5",
    "wdspec"
   ],
   "webdriver/tests/get_element_property/user_prompts.py": [
-   "84a1817bd815bd8c2267862eb3d5f927f2849777",
+   "008b612060309096ad73d06f152817a4c14b7a87",
    "wdspec"
   ],
   "webdriver/tests/get_element_tag_name/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/get_element_tag_name/get.py": [
    "66a0b57c29a006b1200e63239a4ea5f8cb90c1bd",
    "wdspec"
   ],
   "webdriver/tests/get_element_tag_name/user_prompts.py": [
-   "88ee5a130fb8fb55974b431d24163bd7de8b305f",
+   "bd497d5d869593fa6c3533a69e054da523a0ef18",
    "wdspec"
   ],
   "webdriver/tests/get_element_text/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/get_element_text/get.py": [
    "8edcb5068617b13c808ddc336196a7e0e98a8072",
@@ -620251,69 +620251,69 @@
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/get_title/get.py": [
    "69a3e55d2f34dc02285af89d78a75d46e7d1282c",
    "wdspec"
   ],
   "webdriver/tests/get_title/user_prompts.py": [
-   "fd24d562bd7d945de1e5f87c241f4c3717359838",
+   "40e39c1cc6bdeed6100d4e35a5dc58ccbfecb8df",
    "wdspec"
   ],
   "webdriver/tests/get_window_rect/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/get_window_rect/get.py": [
    "8d687026889e601f4c1987996f4e5306b0f627f9",
    "wdspec"
   ],
   "webdriver/tests/get_window_rect/user_prompts.py": [
-   "5fd2bc48547788bd24b3b5fc38a18209d85a6747",
+   "5524bb3b4d2d43394fa716ab44ce844c996a5561",
    "wdspec"
   ],
   "webdriver/tests/interface.html": [
    "f7b2c45ff8b1b5790dd390fbe2ab997766f5d9a8",
    "testharness"
   ],
   "webdriver/tests/is_element_selected/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/is_element_selected/selected.py": [
    "afed5bfc86527410e0fb521f7f75d79bee1fb060",
    "wdspec"
   ],
   "webdriver/tests/is_element_selected/user_prompts.py": [
-   "69d7821499ee460f31ed97f3f839cf6899add8fd",
+   "7b02b1737dc4a1fd7ba9d531a883d98e50f1abcd",
    "wdspec"
   ],
   "webdriver/tests/maximize_window/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/maximize_window/maximize.py": [
    "be54b714b8d6c8f282ee896af4a449ccba4cd060",
    "wdspec"
   ],
   "webdriver/tests/maximize_window/user_prompts.py": [
-   "99afcf2148c524eabee410c5ebb89327467a5e35",
+   "ffacd9938e07ff12edc95edb2e83cbe514a25858",
    "wdspec"
   ],
   "webdriver/tests/minimize_window/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/minimize_window/minimize.py": [
    "8b59610ffcbb4ab41a74f149dc74d415edfaf60f",
    "wdspec"
   ],
   "webdriver/tests/minimize_window/user_prompts.py": [
-   "668c775a0e60b377a5a558a2a38b8887ac2683a0",
+   "11655bf89646491bc21e20587cac8a26426be3da",
    "wdspec"
   ],
   "webdriver/tests/navigate_to/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/navigate_to/navigate.py": [
    "6274392529489518207961ed5e6b6bb3ff081572",
@@ -620395,37 +620395,37 @@
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/set_window_rect/set.py": [
    "04161b59c5b144dd571dca3ef224595f9d4612f2",
    "wdspec"
   ],
   "webdriver/tests/set_window_rect/user_prompts.py": [
-   "4ed66d05835d3ab229cb90928e0ca2a15ba08c8a",
+   "f555a76068004b263f6ed7f0e8410f55b51d2bb5",
    "wdspec"
   ],
   "webdriver/tests/status/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/status/status.py": [
-   "1302349ca7d6a3dcc49e26ca0345023a5c6bbe14",
+   "8a5e17655c8eca835f113533e8a57a233823cd83",
    "wdspec"
   ],
   "webdriver/tests/support/__init__.py": [
    "5a31a3917a5157516c10951a3b3d5ffb43b992d9",
    "support"
   ],
   "webdriver/tests/support/asserts.py": [
    "b7424061b41d9bb1b87f147d5b29786695249d10",
    "support"
   ],
   "webdriver/tests/support/fixtures.py": [
-   "d06b203cf5257d1715ff5ac31f6a291c0efb522e",
+   "0ae7915e0bcc0cc5960fdc2e47161a3a888a924e",
    "support"
   ],
   "webdriver/tests/support/http_request.py": [
    "cb40c781fea2280b98135522def5e6a116d7b946",
    "support"
   ],
   "webdriver/tests/support/inline.py": [
    "48399821b7abca50df824e37c41829d7a4573be1",
--- a/testing/web-platform/meta/webdriver/tests/close_window/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/close_window/user_prompts.py.ini
@@ -1,4 +1,4 @@
 [user_prompts.py]
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
--- a/testing/web-platform/meta/webdriver/tests/delete_cookie/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/delete_cookie/user_prompts.py.ini
@@ -1,4 +1,4 @@
 [user_prompts.py]
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
--- a/testing/web-platform/meta/webdriver/tests/element_send_keys/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/element_send_keys/user_prompts.py.ini
@@ -1,4 +1,4 @@
 [user_prompts.py]
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
--- a/testing/web-platform/meta/webdriver/tests/execute_async_script/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/execute_async_script/user_prompts.py.ini
@@ -1,16 +1,16 @@
 [user_prompts.py]
   disabled:
     if webrender: bug 1425588
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
-  [test_handle_prompt_dismiss]
+  [test_handle_prompt_dismiss[capabilities0\]]
     expected: FAIL
 
-  [test_handle_prompt_ignore]
+  [test_handle_prompt_ignore[capabilities0\]]
     expected: FAIL
 
-  [test_handle_prompt_twice]
+  [test_handle_prompt_twice[capabilities0\]]
     expected: FAIL
     disabled: Bug 1459118
 
--- a/testing/web-platform/meta/webdriver/tests/execute_script/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/execute_script/user_prompts.py.ini
@@ -1,16 +1,16 @@
 [user_prompts.py]
   disabled:
     if webrender: bug 1425588
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
-  [test_handle_prompt_dismiss]
+  [test_handle_prompt_dismiss[capabilities0\]]
     expected: FAIL
 
-  [test_handle_prompt_ignore]
+  [test_handle_prompt_ignore[capabilities0\]]
     expected: FAIL
 
-  [test_handle_prompt_twice]
+  [test_handle_prompt_twice[capabilities0\]]
     expected: FAIL
     disabled: Bug 1459118
 
--- a/testing/web-platform/meta/webdriver/tests/fullscreen_window/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/fullscreen_window/user_prompts.py.ini
@@ -1,4 +1,4 @@
 [user_prompts.py]
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
--- a/testing/web-platform/meta/webdriver/tests/get_current_url/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/get_current_url/user_prompts.py.ini
@@ -1,4 +1,4 @@
 [user_prompts.py]
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
--- a/testing/web-platform/meta/webdriver/tests/get_element_property/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/get_element_property/user_prompts.py.ini
@@ -1,9 +1,9 @@
 [user_prompts.py]
   disabled:
     if webrender: bug 1425588
-  [test_handle_prompt_dismiss]
+  [test_handle_prompt_dismiss[capabilities0\]]
     expected: FAIL
 
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
--- a/testing/web-platform/meta/webdriver/tests/get_element_tag_name/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/get_element_tag_name/user_prompts.py.ini
@@ -1,9 +1,9 @@
 [user_prompts.py]
   disabled:
     if webrender: bug 1425588
-  [test_handle_prompt_dismiss]
+  [test_handle_prompt_dismiss[capabilities0\]]
     expected: FAIL
 
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
--- a/testing/web-platform/meta/webdriver/tests/get_title/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/get_title/user_prompts.py.ini
@@ -1,9 +1,9 @@
 [user_prompts.py]
   disabled:
     if webrender: bug 1425588
-  [test_title_handle_prompt_dismiss]
+  [test_title_handle_prompt_dismiss[capabilities0\]]
     expected: FAIL
 
-  [test_title_handle_prompt_accept]
+  [test_title_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
--- a/testing/web-platform/meta/webdriver/tests/get_window_rect/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/get_window_rect/user_prompts.py.ini
@@ -1,6 +1,6 @@
 [user_prompts.py]
   disabled:
     if not debug and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): wpt-sync Bug 1446953
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
--- a/testing/web-platform/meta/webdriver/tests/is_element_selected/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/is_element_selected/user_prompts.py.ini
@@ -1,7 +1,7 @@
 [user_prompts.py]
-  [test_handle_prompt_dismiss]
+  [test_handle_prompt_dismiss[capabilities0\]]
     expected: FAIL
 
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
--- a/testing/web-platform/meta/webdriver/tests/minimize_window/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/minimize_window/user_prompts.py.ini
@@ -1,6 +1,6 @@
 [user_prompts.py]
   disabled:
     if not debug and not webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): wpt-sync Bug 1449780
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
--- a/testing/web-platform/meta/webdriver/tests/set_window_rect/user_prompts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/set_window_rect/user_prompts.py.ini
@@ -1,4 +1,4 @@
 [user_prompts.py]
-  [test_handle_prompt_accept]
+  [test_handle_prompt_accept[capabilities0\]]
     expected: FAIL
 
--- a/testing/web-platform/tests/webdriver/tests/close_window/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/close_window/user_prompts.py
@@ -1,8 +1,10 @@
+import pytest
+
 from tests.support.asserts import assert_error, assert_dialog_handled
 from tests.support.fixtures import create_dialog, create_window
 from tests.support.inline import inline
 
 
 def close(session):
     return session.transport.send(
         "DELETE", "session/{session_id}/window".format(**vars(session)))
@@ -15,19 +17,18 @@ def test_handle_prompt_dismiss_and_notif
 def test_handle_prompt_accept_and_notify():
     """TODO"""
 
 
 def test_handle_prompt_ignore():
     """TODO"""
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {
-        "alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     original_handle = session.window_handle
 
     session.window_handle = create_window(session)()
     session.url = inline("<title>WD doc title</title>")
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
     response = close(session)
     assert response.status == 200
--- a/testing/web-platform/tests/webdriver/tests/conftest.py
+++ b/testing/web-platform/tests/webdriver/tests/conftest.py
@@ -4,26 +4,37 @@ from tests.support.fixtures import (
     add_browser_capabilites,
     add_event_listeners,
     configuration,
     create_dialog,
     create_frame,
     create_window,
     current_session,
     http,
-    new_session,
     server_config,
     session,
     url)
 
 
+@pytest.fixture
+def capabilities():
+    """Default capabilities to use for a new WebDriver session."""
+    return {}
+
+
+def pytest_generate_tests(metafunc):
+    if "capabilities" in metafunc.fixturenames:
+        marker = metafunc.definition.get_closest_marker(name="capabilities")
+        if marker:
+            metafunc.parametrize("capabilities", marker.args, ids=None)
+
+
 pytest.fixture()(add_browser_capabilites)
 pytest.fixture()(add_event_listeners)
 pytest.fixture(scope="session")(configuration)
 pytest.fixture()(create_dialog)
 pytest.fixture()(create_frame)
 pytest.fixture()(create_window)
 pytest.fixture(scope="function")(current_session)
 pytest.fixture()(http)
-pytest.fixture(scope="function")(new_session)
 pytest.fixture()(server_config)
 pytest.fixture(scope="function")(session)
 pytest.fixture()(url)
--- a/testing/web-platform/tests/webdriver/tests/delete_cookie/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/delete_cookie/user_prompts.py
@@ -1,8 +1,10 @@
+import pytest
+
 from tests.support.asserts import assert_error, assert_dialog_handled
 from tests.support.fixtures import create_dialog
 from tests.support.inline import inline
 
 
 def delete_cookie(session, name):
     return session.transport.send("DELETE", "/session/%s/cookie/%s" % (session.session_id, name))
 
@@ -14,38 +16,18 @@ def test_handle_prompt_dismiss_and_notif
 def test_handle_prompt_accept_and_notify():
     """TODO"""
 
 
 def test_handle_prompt_ignore():
     """TODO"""
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    """
-    2. Handle any user prompts and return its value if it is an error.
-
-    [...]
-
-    In order to handle any user prompts a remote end must take the
-    following steps:
-
-      [...]
-
-      2. Perform the following substeps based on the current session's
-      user prompt handler:
-
-        [...]
-
-        - accept state
-           Accept the current user prompt.
-
-    """
-    _, session = new_session({"capabilities": {
-        "alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     session.url = inline("<title>WD doc title</title>")
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
     response = delete_cookie(session, "foo")
     assert response.status == 200
     assert_dialog_handled(session, "dismiss #1")
 
     create_dialog(session)("confirm", text="dismiss #2", result_var="dismiss2")
@@ -55,36 +37,16 @@ def test_handle_prompt_accept(new_sessio
 
     create_dialog(session)("prompt", text="dismiss #3", result_var="dismiss3")
     response = delete_cookie(session, "foo")
     assert response.status == 200
     assert_dialog_handled(session, "dismiss #3")
 
 
 def test_handle_prompt_missing_value(session, create_dialog):
-    """
-    2. Handle any user prompts and return its value if it is an error.
-
-    [...]
-
-    In order to handle any user prompts a remote end must take the
-    following steps:
-
-      [...]
-
-      2. Perform the following substeps based on the current session's
-      user prompt handler:
-
-        [...]
-
-        - missing value default state
-           1. Dismiss the current user prompt.
-           2. Return error with error code unexpected alert open.
-
-    """
     session.url = inline("<title>WD doc title</title>")
     create_dialog("alert", text="dismiss #1", result_var="dismiss1")
 
     response = delete_cookie(session, "foo")
 
     assert_error(response, "unexpected alert open")
     assert_dialog_handled(session, "dismiss #1")
 
--- a/testing/web-platform/tests/webdriver/tests/element_send_keys/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/element_send_keys/user_prompts.py
@@ -1,8 +1,10 @@
+import pytest
+
 from tests.support.asserts import assert_error, assert_dialog_handled
 from tests.support.fixtures import create_dialog
 from tests.support.inline import inline
 
 
 def element_send_keys(session, element, text):
     return session.transport.send(
         "POST", "/session/{session_id}/element/{element_id}/value".format(
@@ -18,19 +20,18 @@ def test_handle_prompt_dismiss_and_notif
 def test_handle_prompt_accept_and_notify():
     """TODO"""
 
 
 def test_handle_prompt_ignore():
     """TODO"""
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {
-        "alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     session.url = inline("<input>")
     element = session.find.css("input", all=False)
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
     response = element_send_keys(session, element, "foo")
     assert response.status == 200
     assert_dialog_handled(session, "dismiss #1")
 
--- a/testing/web-platform/tests/webdriver/tests/execute_async_script/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/execute_async_script/user_prompts.py
@@ -12,88 +12,80 @@ def execute_async_script(session, script
         args = []
     body = {"script": script, "args": args}
 
     return session.transport.send(
         "POST", "/session/{session_id}/execute/async".format(**vars(session)),
         body)
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
-
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     response = execute_async_script(session, "window.alert('Hello');")
     assert_success(response, None)
 
     session.title
     with pytest.raises(error.NoSuchAlertException):
         session.alert.accept()
 
 
-def test_handle_prompt_dismiss(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss"})}})
-
+@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss"})
+def test_handle_prompt_dismiss(session):
     response = execute_async_script(session, "window.alert('Hello');")
     assert_success(response, None)
 
     session.title
     with pytest.raises(error.NoSuchAlertException):
         session.alert.dismiss()
 
 
-def test_handle_prompt_dismiss_and_notify(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss and notify"})}})
-
+@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss and notify"})
+def test_handle_prompt_dismiss_and_notify(session):
     response = execute_async_script(session, "window.alert('Hello');")
     assert_success(response, None)
 
     with pytest.raises(error.UnexpectedAlertOpenException):
         session.title
     with pytest.raises(error.NoSuchAlertException):
         session.alert.dismiss()
 
 
-def test_handle_prompt_accept_and_notify(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept and notify"})}})
-
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept and notify"})
+def test_handle_prompt_accept_and_notify(session):
     response = execute_async_script(session, "window.alert('Hello');")
     assert_success(response, None)
 
     with pytest.raises(error.UnexpectedAlertOpenException):
         session.title
     with pytest.raises(error.NoSuchAlertException):
         session.alert.accept()
 
 
-def test_handle_prompt_ignore(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "ignore"})}})
-
+@pytest.mark.capabilities({"unhandledPromptBehavior": "ignore"})
+def test_handle_prompt_ignore(session):
     response = execute_async_script(session, "window.alert('Hello');")
     assert_success(response, None)
 
     with pytest.raises(error.UnexpectedAlertOpenException):
         session.title
     session.alert.dismiss()
 
 
-def test_handle_prompt_default(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}})
-
+def test_handle_prompt_default(session):
     response = execute_async_script(session, "window.alert('Hello');")
     assert_success(response, None)
 
     with pytest.raises(error.UnexpectedAlertOpenException):
         session.title
     with pytest.raises(error.NoSuchAlertException):
         session.alert.dismiss()
 
 
-def test_handle_prompt_twice(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
-
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_twice(session):
     response = execute_async_script(session, "window.alert('Hello');window.alert('Bye');")
     assert_success(response, None)
 
     session.alert.dismiss()
     # The first alert has been accepted by the user prompt handler, the second one remains.
     # FIXME: this is how browsers currently work, but the spec should clarify if this is the
     #        expected behavior, see https://github.com/w3c/webdriver/issues/1153.
     assert session.alert.text == "Bye"
--- a/testing/web-platform/tests/webdriver/tests/execute_script/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/execute_script/user_prompts.py
@@ -13,88 +13,80 @@ def execute_script(session, script, args
     body = {"script": script, "args": args}
 
     return session.transport.send(
         "POST", "/session/{session_id}/execute/sync".format(
             session_id=session.session_id),
         body)
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
-
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     response = execute_script(session, "window.alert('Hello');")
     assert_success(response, None)
 
     session.title
     with pytest.raises(error.NoSuchAlertException):
         session.alert.accept()
 
 
-def test_handle_prompt_dismiss(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss"})}})
-
+@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss"})
+def test_handle_prompt_dismiss(session):
     response = execute_script(session, "window.alert('Hello');")
     assert_success(response, None)
 
     session.title
     with pytest.raises(error.NoSuchAlertException):
         session.alert.dismiss()
 
 
-def test_handle_prompt_dismiss_and_notify(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss and notify"})}})
-
+@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss and notify"})
+def test_handle_prompt_dismiss_and_notify(session):
     response = execute_script(session, "window.alert('Hello');")
     assert_success(response, None)
 
     with pytest.raises(error.UnexpectedAlertOpenException):
         session.title
     with pytest.raises(error.NoSuchAlertException):
         session.alert.dismiss()
 
 
-def test_handle_prompt_accept_and_notify(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept and notify"})}})
-
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept and notify"})
+def test_handle_prompt_accept_and_notify(session):
     response = execute_script(session, "window.alert('Hello');")
     assert_success(response, None)
 
     with pytest.raises(error.UnexpectedAlertOpenException):
         session.title
     with pytest.raises(error.NoSuchAlertException):
         session.alert.accept()
 
 
-def test_handle_prompt_ignore(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "ignore"})}})
-
+@pytest.mark.capabilities({"unhandledPromptBehavior": "ignore"})
+def test_handle_prompt_ignore(session):
     response = execute_script(session, "window.alert('Hello');")
     assert_success(response, None)
 
     with pytest.raises(error.UnexpectedAlertOpenException):
         session.title
     session.alert.dismiss()
 
 
-def test_handle_prompt_default(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}})
-
+def test_handle_prompt_default(session):
     response = execute_script(session, "window.alert('Hello');")
     assert_success(response, None)
 
     with pytest.raises(error.UnexpectedAlertOpenException):
         session.title
     with pytest.raises(error.NoSuchAlertException):
         session.alert.dismiss()
 
 
-def test_handle_prompt_twice(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
-
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_twice(session):
     response = execute_script(session, "window.alert('Hello');window.alert('Bye');")
     assert_success(response, None)
 
     session.alert.dismiss()
     # The first alert has been accepted by the user prompt handler, the second one remains.
     # FIXME: this is how browsers currently work, but the spec should clarify if this is the
     #        expected behavior, see https://github.com/w3c/webdriver/issues/1153.
     assert session.alert.text == "Bye"
--- a/testing/web-platform/tests/webdriver/tests/fullscreen_window/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/fullscreen_window/user_prompts.py
@@ -1,8 +1,10 @@
+import pytest
+
 from tests.support.asserts import assert_error, assert_dialog_handled
 from tests.support.fixtures import create_dialog
 from tests.support.inline import inline
 
 
 def read_global(session, name):
     return session.execute_script("return %s;" % name)
 
@@ -18,38 +20,18 @@ def test_handle_prompt_dismiss_and_notif
 def test_handle_prompt_accept_and_notify():
     """TODO"""
 
 
 def test_handle_prompt_ignore():
     """TODO"""
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    """
-    2. Handle any user prompts and return its value if it is an error.
-
-    [...]
-
-    In order to handle any user prompts a remote end must take the
-    following steps:
-
-      [...]
-
-      2. Perform the following substeps based on the current session's
-      user prompt handler:
-
-        [...]
-
-        - accept state
-           Accept the current user prompt.
-
-    """
-    _, session = new_session({"capabilities": {
-        "alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     session.url = inline("<title>WD doc title</title>")
     create_dialog(session)("alert", text="accept #1", result_var="accept1")
 
     fullscreen(session)
 
     assert_dialog_handled(session, "accept #1")
     assert read_global(session, "accept1") is None
 
@@ -65,36 +47,16 @@ def test_handle_prompt_accept(new_sessio
 
     fullscreen(session)
 
     assert_dialog_handled(session, "accept #3")
     assert read_global(session, "accept3") == "" or read_global(session, "accept3") == "undefined"
 
 
 def test_handle_prompt_missing_value(session, create_dialog):
-    """
-    2. Handle any user prompts and return its value if it is an error.
-
-    [...]
-
-    In order to handle any user prompts a remote end must take the
-    following steps:
-
-      [...]
-
-      2. Perform the following substeps based on the current session's
-      user prompt handler:
-
-        [...]
-
-        - missing value default state
-           1. Dismiss the current user prompt.
-           2. Return error with error code unexpected alert open.
-
-    """
     session.url = inline("<title>WD doc title</title>")
     create_dialog("alert", text="dismiss #1", result_var="dismiss1")
 
     response = fullscreen(session)
 
     assert_error(response, "unexpected alert open")
     assert_dialog_handled(session, "dismiss #1")
     assert read_global(session, "dismiss1") is None
--- a/testing/web-platform/tests/webdriver/tests/get_current_url/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/get_current_url/user_prompts.py
@@ -1,8 +1,10 @@
+import pytest
+
 from tests.support.asserts import assert_error, assert_dialog_handled
 from tests.support.fixtures import create_dialog
 from tests.support.inline import inline
 
 
 def read_global(session, name):
     return session.execute_script("return %s;" % name)
 
@@ -18,19 +20,18 @@ def test_handle_prompt_dismiss_and_notif
 def test_handle_prompt_accept_and_notify():
     """TODO"""
 
 
 def test_handle_prompt_ignore():
     """TODO"""
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {
-        "alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     session.url = inline("<title>WD doc title</title>")
     create_dialog(session)("alert", text="accept #1", result_var="accept1")
 
     get_current_url(session)
 
     assert_dialog_handled(session, "accept #1")
     assert read_global(session, "accept1") is None
 
--- a/testing/web-platform/tests/webdriver/tests/get_element_property/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/get_element_property/user_prompts.py
@@ -1,27 +1,27 @@
+import pytest
+
 from tests.support.asserts import assert_error, assert_success, assert_dialog_handled
 from tests.support.fixtures import create_dialog
 from tests.support.inline import inline
 
 
 def read_global(session, name):
     return session.execute_script("return %s;" % name)
 
 
 def get_property(session, element_id, name):
     return session.transport.send(
         "GET", "session/{session_id}/element/{element_id}/property/{name}".format(
             session_id=session.session_id, element_id=element_id, name=name))
 
 
-def test_handle_prompt_dismiss(new_session, add_browser_capabilites):
-    # 13.3 step 2
-    _, session = new_session({"capabilities": {
-        "alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss"})
+def test_handle_prompt_dismiss(session):
     session.url = inline("<input id=foo>")
     element = session.find.css("#foo", all=False)
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
 
     result = get_property(session, element.id, "id")
     assert_success(result, "foo")
     assert_dialog_handled(session, "dismiss #1")
@@ -34,19 +34,18 @@ def test_handle_prompt_dismiss(new_sessi
 
     create_dialog(session)("prompt", text="dismiss #3", result_var="dismiss3")
 
     result = get_property(session, element.id, "id")
     assert_success(result, "foo")
     assert_dialog_handled(session, "dismiss #3")
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {
-        "alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     session.url = inline("<input id=foo>")
     element = session.find.css("#foo", all=False)
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
 
     result = get_property(session, element.id, "id")
     assert_success(result, "foo")
     assert_dialog_handled(session, "dismiss #1")
--- a/testing/web-platform/tests/webdriver/tests/get_element_tag_name/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/get_element_tag_name/user_prompts.py
@@ -1,25 +1,26 @@
+import pytest
+
 from tests.support.asserts import assert_error, assert_success, assert_dialog_handled
 from tests.support.fixtures import create_dialog
 from tests.support.inline import inline
 
 
 def read_global(session, name):
     return session.execute_script("return %s;" % name)
 
 
 def get_tag_name(session, element_id):
     return session.transport.send("GET", "session/{session_id}/element/{element_id}/name".format(
         session_id=session.session_id, element_id=element_id))
 
 
-def test_handle_prompt_dismiss(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {
-        "alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss"})
+def test_handle_prompt_dismiss(session):
     session.url = inline("<input id=foo>")
     element = session.find.css("#foo", all=False)
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
 
     result = get_tag_name(session, element.id)
     assert_success(result, "input")
     assert_dialog_handled(session, "dismiss #1")
@@ -32,19 +33,18 @@ def test_handle_prompt_dismiss(new_sessi
 
     create_dialog(session)("prompt", text="dismiss #3", result_var="dismiss3")
 
     result = get_tag_name(session, element.id)
     assert_success(result, "input")
     assert_dialog_handled(session, "dismiss #3")
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {
-        "alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     session.url = inline("<input id=foo>")
     element = session.find.css("#foo", all=False)
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
 
     result = get_tag_name(session, element.id)
     assert_success(result, "input")
     assert_dialog_handled(session, "dismiss #1")
--- a/testing/web-platform/tests/webdriver/tests/get_title/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/get_title/user_prompts.py
@@ -1,25 +1,26 @@
+import pytest
+
 from tests.support.asserts import assert_error, assert_success, assert_dialog_handled
 from tests.support.fixtures import create_dialog
 from tests.support.inline import inline
 
 
 def read_global(session, name):
     return session.execute_script("return %s;" % name)
 
 
 def get_title(session):
     return session.transport.send(
         "GET", "session/{session_id}/title".format(**vars(session)))
 
 
-def test_title_handle_prompt_dismiss(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {
-        "alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss"})
+def test_title_handle_prompt_dismiss(session):
     session.url = inline("<title>WD doc title</title>")
 
     expected_title = read_global(session, "document.title")
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
 
     result = get_title(session)
     assert_success(result, expected_title)
     assert_dialog_handled(session, "dismiss #1")
@@ -37,19 +38,18 @@ def test_title_handle_prompt_dismiss(new
     create_dialog(session)("prompt", text="dismiss #3", result_var="dismiss3")
 
     result = get_title(session)
     assert_success(result, expected_title)
     assert_dialog_handled(session, "dismiss #3")
     assert read_global(session, "dismiss3") is None
 
 
-def test_title_handle_prompt_accept(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {
-        "alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_title_handle_prompt_accept(session):
     session.url = inline("<title>WD doc title</title>")
     create_dialog(session)("alert", text="accept #1", result_var="accept1")
 
     expected_title = read_global(session, "document.title")
 
     result = get_title(session)
     assert_success(result, expected_title)
     assert_dialog_handled(session, "accept #1")
--- a/testing/web-platform/tests/webdriver/tests/get_window_rect/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/get_window_rect/user_prompts.py
@@ -1,8 +1,10 @@
+import pytest
+
 from tests.support.asserts import assert_error, assert_dialog_handled
 from tests.support.fixtures import create_dialog
 from tests.support.inline import inline
 
 
 alert_doc = inline("<script>window.alert()</script>")
 
 
@@ -18,18 +20,18 @@ def test_handle_prompt_dismiss_and_notif
 def test_handle_prompt_accept_and_notify():
     """TODO"""
 
 
 def test_handle_prompt_ignore():
     """TODO"""
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     session.url = inline("<title>WD doc title</title>")
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
     response = get_window_rect(session)
     assert response.status == 200
     assert_dialog_handled(session, "dismiss #1")
 
     create_dialog(session)("confirm", text="dismiss #2", result_var="dismiss2")
--- a/testing/web-platform/tests/webdriver/tests/is_element_selected/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/is_element_selected/user_prompts.py
@@ -1,23 +1,24 @@
+import pytest
+
 from tests.support.asserts import assert_error, assert_dialog_handled, assert_success
 from tests.support.inline import inline
 from tests.support.fixtures import create_dialog
 
 
 def is_element_selected(session, element_id):
     return session.transport.send(
         "GET", "session/{session_id}/element/{element_id}/selected".format(
             session_id=session.session_id,
             element_id=element_id))
 
 
-def test_handle_prompt_dismiss(new_session, add_browser_capabilites):
-    # 13.1 step 2
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "dismiss"})
+def test_handle_prompt_dismiss(session):
     session.url = inline("<input id=foo>")
     element = session.find.css("#foo", all=False)
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
 
     result = is_element_selected(session, element.id)
     assert_success(result, False)
     assert_dialog_handled(session, "dismiss #1")
@@ -30,19 +31,18 @@ def test_handle_prompt_dismiss(new_sessi
 
     create_dialog(session)("prompt", text="dismiss #3", result_var="dismiss3")
 
     result = is_element_selected(session, element.id)
     assert_success(result, False)
     assert_dialog_handled(session, "dismiss #3")
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    # 13.1 step 2
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     session.url = inline("<input id=foo>")
     element = session.find.css("#foo", all=False)
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
 
     result = is_element_selected(session, element.id)
     assert_success(result, False)
     assert_dialog_handled(session, "dismiss #1")
--- a/testing/web-platform/tests/webdriver/tests/maximize_window/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/maximize_window/user_prompts.py
@@ -1,8 +1,10 @@
+import pytest
+
 from tests.support.asserts import assert_error, assert_dialog_handled
 from tests.support.fixtures import create_dialog
 from tests.support.inline import inline
 
 
 def maximize(session):
     return session.transport.send(
         "POST", "session/{session_id}/window/maximize".format(**vars(session)))
@@ -15,18 +17,18 @@ def test_handle_prompt_dismiss_and_notif
 def test_handle_prompt_accept_and_notify():
     """TODO"""
 
 
 def test_handle_prompt_ignore():
     """TODO"""
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     session.url = inline("<title>WD doc title</title>")
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
     response = maximize(session)
     assert response.status == 200
     assert_dialog_handled(session, "dismiss #1")
 
     create_dialog(session)("confirm", text="dismiss #2", result_var="dismiss2")
--- a/testing/web-platform/tests/webdriver/tests/minimize_window/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/minimize_window/user_prompts.py
@@ -1,8 +1,10 @@
+import pytest
+
 from tests.support.asserts import assert_error, assert_dialog_handled
 from tests.support.fixtures import create_dialog
 from tests.support.inline import inline
 
 
 def minimize(session):
     return session.transport.send(
         "POST", "session/{session_id}/window/minimize".format(**vars(session)))
@@ -15,18 +17,18 @@ def test_handle_prompt_dismiss_and_notif
 def test_handle_prompt_accept_and_notify():
     """TODO"""
 
 
 def test_handle_prompt_ignore():
     """TODO"""
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     session.url = inline("<title>WD doc title</title>")
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
     response = minimize(session)
     assert response.status == 200
     assert_dialog_handled(session, "dismiss #1")
 
     create_dialog(session)("confirm", text="dismiss #2", result_var="dismiss2")
--- a/testing/web-platform/tests/webdriver/tests/set_window_rect/user_prompts.py
+++ b/testing/web-platform/tests/webdriver/tests/set_window_rect/user_prompts.py
@@ -1,24 +1,26 @@
+import pytest
+
 from tests.support.asserts import assert_dialog_handled, assert_error, assert_success
 from tests.support.fixtures import create_dialog
 
 
 def set_window_rect(session, rect):
     return session.transport.send(
         "POST", "session/{session_id}/window/rect".format(**vars(session)),
         rect)
 
 
 def test_handle_prompt_dismiss():
     """TODO"""
 
 
-def test_handle_prompt_accept(new_session, add_browser_capabilites):
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+@pytest.mark.capabilities({"unhandledPromptBehavior": "accept"})
+def test_handle_prompt_accept(session):
     original = session.window.rect
 
     # step 2
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
     result = set_window_rect(session, {"x": original["x"],
                                        "y": original["y"]})
     assert result.status == 200
     assert_dialog_handled(session, "dismiss #1")
--- a/testing/web-platform/tests/webdriver/tests/status/status.py
+++ b/testing/web-platform/tests/webdriver/tests/status/status.py
@@ -21,24 +21,22 @@ def test_get_status_no_session(http):
         #       The remote end's readiness state.
         assert value["ready"] in [True, False]
         # "message"
         #       An implementation-defined string explaining the remote end's
         #       readiness state.
         assert isinstance(value["message"], basestring)
 
 
-def test_status_with_session_running_on_endpoint_node(new_session, add_browser_capabilites):
+def test_status_with_session_running_on_endpoint_node(session):
     # For an endpoint node, the maximum number of active
     # sessions is 1: https://www.w3.org/TR/webdriver/#dfn-maximum-active-sessions
     # A session is open, so we expect `ready` to be False
     # 8.3 step 1.
 
-    _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}})
-
     response = get_status(session)
     value = assert_success(response)
     assert value["ready"] is False
     assert "message" in value
 
     session.end()
 
     # Active session count is 0, meaning that the
--- a/testing/web-platform/tests/webdriver/tests/support/fixtures.py
+++ b/testing/web-platform/tests/webdriver/tests/support/fixtures.py
@@ -1,10 +1,11 @@
 from __future__ import print_function
 
+import copy
 import json
 import os
 import urlparse
 import re
 import sys
 
 import webdriver
 
@@ -14,16 +15,20 @@ from tests.support.wait import wait
 default_host = "http://127.0.0.1"
 default_port = "4444"
 
 default_script_timeout = 30
 default_page_load_timeout = 300
 default_implicit_wait_timeout = 0
 
 
+_current_session = None
+_custom_session = False
+
+
 def ignore_exceptions(f):
     def inner(*args, **kwargs):
         try:
             return f(*args, **kwargs)
         except webdriver.error.WebDriverException as e:
             print("Ignored exception %s" % e, file=sys.stderr)
     inner.__name__ = f.__name__
     return inner
@@ -167,31 +172,42 @@ def configuration():
 
     return {
         "host": host,
         "port": port,
         "capabilities": capabilities
     }
 
 
-_current_session = None
-
-
-def session(configuration, request):
+def session(capabilities, configuration, request):
     """Create and start a session for a test that does not itself test session creation.
 
     By default the session will stay open after each test, but we always try to start a
     new one and assume that if that fails there is already a valid session. This makes it
     possible to recover from some errors that might leave the session in a bad state, but
     does not demand that we start a new session per test."""
     global _current_session
+
+    # Update configuration capabilities with custom ones from the
+    # capabilities fixture, which can be set by tests
+    caps = copy.deepcopy(configuration["capabilities"])
+    caps.update(capabilities)
+    caps = {"alwaysMatch": caps}
+
+    # If there is a session with different capabilities active, end it now
+    if _current_session is not None and (
+            caps != _current_session.requested_capabilities):
+        _current_session.end()
+        _current_session = None
+
     if _current_session is None:
-        _current_session = webdriver.Session(configuration["host"],
-                                             configuration["port"],
-                                             capabilities={"alwaysMatch": configuration["capabilities"]})
+        _current_session = webdriver.Session(
+            configuration["host"],
+            configuration["port"],
+            capabilities=caps)
     try:
         _current_session.start()
     except webdriver.error.SessionNotCreatedException:
         if not _current_session.session_id:
             raise
 
     # finalisers are popped off a stack,
     # making their ordering reverse
@@ -204,46 +220,16 @@ def session(configuration, request):
 
     return _current_session
 
 
 def current_session():
     return _current_session
 
 
-def new_session(configuration, request):
-    """Return a factory function that will attempt to start a session with a given body.
-
-    This is intended for tests that are themselves testing new session creation, and the
-    session created is closed at the end of the test."""
-    def end():
-        global _current_session
-        if _current_session is not None and _current_session.session_id:
-            _current_session.end()
-
-        _current_session = None
-
-    def create_session(body):
-        global _current_session
-        _session = webdriver.Session(configuration["host"],
-                                     configuration["port"],
-                                     capabilities=None)
-        value = _session.send_command("POST", "session", body=body)
-        # Don't set the global session until we are sure this succeeded
-        _current_session = _session
-        _session.session_id = value["sessionId"]
-
-        return value, _current_session
-
-    end()
-    request.addfinalizer(end)
-
-    return create_session
-
-
 def add_browser_capabilites(configuration):
     def update_capabilities(capabilities):
         # Make sure there aren't keys in common.
         assert not set(configuration["capabilities"]).intersection(set(capabilities))
         result = dict(configuration["capabilities"])
         result.update(capabilities)
         return result
     return update_capabilities
@@ -253,16 +239,17 @@ def url(server_config):
     def inner(path, protocol="http", query="", fragment=""):
         port = server_config["ports"][protocol][0]
         host = "%s:%s" % (server_config["browser_host"], port)
         return urlparse.urlunsplit((protocol, host, path, query, fragment))
 
     inner.__name__ = "url"
     return inner
 
+
 def create_dialog(session):
     """Create a dialog (one of "alert", "prompt", or "confirm") and provide a
     function to validate that the dialog has been "handled" (either accepted or
     dismissed) by returning some value."""
 
     def create_dialog(dialog_type, text=None, result_var=None):
         assert dialog_type in ("alert", "confirm", "prompt"), (
                "Invalid dialog type: '%s'" % dialog_type)