Skip to content

Commit daf050c

Browse files
authored
[FedCM] Add testdriver support for FedCM (#40006)
1 parent b4e14ac commit daf050c

File tree

6 files changed

+357
-1
lines changed

6 files changed

+357
-1
lines changed

docs/writing-tests/testdriver.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,17 @@ the global scope.
9999
.. js:autofunction:: test_driver.set_spc_transaction_mode
100100
```
101101

102+
### Federated Credential Management ###
103+
```eval_rst
104+
.. js:autofunction:: test_driver.cancel_fedcm_dialog
105+
.. js:autofunction:: test_driver.select_fedcm_account
106+
.. js:autofunction:: test_driver.get_fedcm_account_list
107+
.. js:autofunction:: test_driver.get_fedcm_dialog_title
108+
.. js:autofunction:: test_driver.get_fedcm_dialog_type
109+
.. js:autofunction:: test_driver.set_fedcm_delay_enabled
110+
.. js:autofunction:: test_driver.reset_fedcm_cooldown
111+
```
112+
102113
### Using test_driver in other browsing contexts ###
103114

104115
Testdriver can be used in browsing contexts (i.e. windows or frames)

resources/testdriver.js

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,134 @@
680680
set_spc_transaction_mode: function(mode, context=null) {
681681
return window.test_driver_internal.set_spc_transaction_mode(mode, context);
682682
},
683+
684+
/**
685+
* Cancels the Federated Credential Management dialog
686+
*
687+
* Matches the `Cancel dialog
688+
* <https://fedidcg.github.io/FedCM/#webdriver-canceldialog>`_
689+
* WebDriver command.
690+
*
691+
* @param {WindowProxy} context - Browsing context in which
692+
* to run the call, or null for the current
693+
* browsing context.
694+
*
695+
* @returns {Promise} Fulfilled after the dialog is canceled, or rejected
696+
* in case the WebDriver command errors
697+
*/
698+
cancel_fedcm_dialog: function(context=null) {
699+
return window.test_driver_internal.cancel_fedcm_dialog(context);
700+
},
701+
702+
/**
703+
* Selects an account from the Federated Credential Management dialog
704+
*
705+
* Matches the `Select account
706+
* <https://fedidcg.github.io/FedCM/#webdriver-selectaccount>`_
707+
* WebDriver command.
708+
*
709+
* @param {number} account_index - Index of the account to select.
710+
* @param {WindowProxy} context - Browsing context in which
711+
* to run the call, or null for the current
712+
* browsing context.
713+
*
714+
* @returns {Promise} Fulfilled after the account is selected,
715+
* or rejected in case the WebDriver command errors
716+
*/
717+
select_fedcm_account: function(account_index, context=null) {
718+
return window.test_driver_internal.select_fedcm_account(account_index, context);
719+
},
720+
721+
/**
722+
* Gets the account list from the Federated Credential Management dialog
723+
*
724+
* Matches the `Account list
725+
* <https://fedidcg.github.io/FedCM/#webdriver-accountlist>`_
726+
* WebDriver command.
727+
*
728+
* @param {WindowProxy} context - Browsing context in which
729+
* to run the call, or null for the current
730+
* browsing context.
731+
*
732+
* @returns {Promise} fulfilled after the account list is returned, or
733+
* rejected in case the WebDriver command errors
734+
*/
735+
get_fedcm_account_list: function(context=null) {
736+
return window.test_driver_internal.get_fedcm_account_list(context);
737+
},
738+
739+
/**
740+
* Gets the title of the Federated Credential Management dialog
741+
*
742+
* Matches the `Get title
743+
* <https://fedidcg.github.io/FedCM/#webdriver-gettitle>`_
744+
* WebDriver command.
745+
*
746+
* @param {WindowProxy} context - Browsing context in which
747+
* to run the call, or null for the current
748+
* browsing context.
749+
*
750+
* @returns {Promise} Fulfilled after the title is returned, or rejected
751+
* in case the WebDriver command errors
752+
*/
753+
get_fedcm_dialog_title: function(context=null) {
754+
return window.test_driver_internal.get_fedcm_dialog_title(context);
755+
},
756+
757+
/**
758+
* Gets the type of the Federated Credential Management dialog
759+
*
760+
* Matches the `Get dialog type
761+
* <https://fedidcg.github.io/FedCM/#webdriver-getdialogtype>`_
762+
* WebDriver command.
763+
*
764+
* @param {WindowProxy} context - Browsing context in which
765+
* to run the call, or null for the current
766+
* browsing context.
767+
*
768+
* @returns {Promise} Fulfilled after the dialog type is returned, or
769+
* rejected in case the WebDriver command errors
770+
*/
771+
get_fedcm_dialog_type: function(context=null) {
772+
return window.test_driver_internal.get_fedcm_dialog_type(context);
773+
},
774+
775+
/**
776+
* Sets whether promise rejection delay is enabled for the Federated Credential Management dialog
777+
*
778+
* Matches the `Set delay enabled
779+
* <https://fedidcg.github.io/FedCM/#webdriver-setdelayenabled>`_
780+
* WebDriver command.
781+
*
782+
* @param {boolean} enabled - Whether to delay FedCM promise rejection.
783+
* @param {WindowProxy} context - Browsing context in which
784+
* to run the call, or null for the current
785+
* browsing context.
786+
*
787+
* @returns {Promise} Fulfilled after the delay has been enabled or disabled,
788+
* or rejected in case the WebDriver command errors
789+
*/
790+
set_fedcm_delay_enabled: function(enabled, context=null) {
791+
return window.test_driver_internal.set_fedcm_delay_enabled(enabled, context);
792+
},
793+
794+
/**
795+
* Resets the Federated Credential Management dialog's cooldown
796+
*
797+
* Matches the `Reset cooldown
798+
* <https://fedidcg.github.io/FedCM/#webdriver-resetcooldown>`_
799+
* WebDriver command.
800+
*
801+
* @param {WindowProxy} context - Browsing context in which
802+
* to run the call, or null for the current
803+
* browsing context.
804+
*
805+
* @returns {Promise} Fulfilled after the cooldown has been reset,
806+
* or rejected in case the WebDriver command errors
807+
*/
808+
reset_fedcm_cooldown: function(context=null) {
809+
return window.test_driver_internal.reset_fedcm_cooldown(context);
810+
}
683811
};
684812

685813
window.test_driver_internal = {
@@ -805,5 +933,32 @@
805933
throw new Error("set_spc_transaction_mode() is not implemented by testdriver-vendor.js");
806934
},
807935

936+
async cancel_fedcm_dialog(context=null) {
937+
throw new Error("cancel_fedcm_dialog() is not implemented by testdriver-vendor.js");
938+
},
939+
940+
async select_fedcm_account(account_index, context=null) {
941+
throw new Error("select_fedcm_account() is not implemented by testdriver-vendor.js");
942+
},
943+
944+
async get_fedcm_account_list(context=null) {
945+
throw new Error("get_fedcm_account_list() is not implemented by testdriver-vendor.js");
946+
},
947+
948+
async get_fedcm_dialog_title(context=null) {
949+
throw new Error("get_fedcm_dialog_title() is not implemented by testdriver-vendor.js");
950+
},
951+
952+
async get_fedcm_dialog_type(context=null) {
953+
throw new Error("get_fedcm_dialog_type() is not implemented by testdriver-vendor.js");
954+
},
955+
956+
async set_fedcm_delay_enabled(enabled, context=null) {
957+
throw new Error("set_fedcm_delay_enabled() is not implemented by testdriver-vendor.js");
958+
},
959+
960+
async reset_fedcm_cooldown(context=null) {
961+
throw new Error("reset_fedcm_cooldown() is not implemented by testdriver-vendor.js");
962+
}
808963
};
809964
})();

tools/wptrunner/wptrunner/executors/actions.py

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,85 @@ def __call__(self, payload):
277277
self.logger.debug("Setting SPC transaction mode to %s" % mode)
278278
return self.protocol.spc_transactions.set_spc_transaction_mode(mode)
279279

280+
class CancelFedCMDialogAction:
281+
name = "cancel_fedcm_dialog"
282+
283+
def __init__(self, logger, protocol):
284+
self.logger = logger
285+
self.protocol = protocol
286+
287+
def __call__(self, payload):
288+
self.logger.debug("Canceling FedCM dialog")
289+
return self.protocol.fedcm.cancel_fedcm_dialog()
290+
291+
class SelectFedCMAccountAction:
292+
name = "select_fedcm_account"
293+
294+
def __init__(self, logger, protocol):
295+
self.logger = logger
296+
self.protocol = protocol
297+
298+
def __call__(self, payload):
299+
account_index = payload["account_index"]
300+
self.logger.debug(f"Selecting FedCM account of index: {account_index}")
301+
return self.protocol.fedcm.select_fedcm_account(account_index)
302+
303+
class GetFedCMAccountListAction:
304+
name = "get_fedcm_account_list"
305+
306+
def __init__(self, logger, protocol):
307+
self.logger = logger
308+
self.protocol = protocol
309+
310+
def __call__(self, payload):
311+
self.logger.debug("Getting FedCM account list")
312+
return self.protocol.fedcm.get_fedcm_account_list()
313+
314+
class GetFedCMDialogTitleAction:
315+
name = "get_fedcm_dialog_title"
316+
317+
def __init__(self, logger, protocol):
318+
self.logger = logger
319+
self.protocol = protocol
320+
321+
def __call__(self, payload):
322+
self.logger.debug("Getting FedCM dialog title")
323+
return self.protocol.fedcm.get_fedcm_dialog_title()
324+
325+
class GetFedCMDialogTypeAction:
326+
name = "get_fedcm_dialog_type"
327+
328+
def __init__(self, logger, protocol):
329+
self.logger = logger
330+
self.protocol = protocol
331+
332+
def __call__(self, payload):
333+
self.logger.debug("Getting FedCM dialog type")
334+
return self.protocol.fedcm.get_fedcm_dialog_type()
335+
336+
class SetFedCMDelayEnabledAction:
337+
name = "set_fedcm_delay_enabled"
338+
339+
def __init__(self, logger, protocol):
340+
self.logger = logger
341+
self.protocol = protocol
342+
343+
def __call__(self, payload):
344+
enabled = payload["enabled"]
345+
self.logger.debug("Setting FedCM delay enabled as %s" % enabled)
346+
return self.protocol.fedcm.set_fedcm_delay_enabled(enabled)
347+
348+
class ResetFedCMCooldownAction:
349+
name = "reset_fedcm_cooldown"
350+
351+
def __init__(self, logger, protocol):
352+
self.logger = logger
353+
self.protocol = protocol
354+
355+
def __call__(self, payload):
356+
self.logger.debug("Resetting FedCM cooldown")
357+
return self.protocol.fedcm.reset_fedcm_cooldown()
358+
280359
actions = [ClickAction,
281360
DeleteAllCookiesAction,
282361
GetAllCookiesAction,
@@ -296,4 +375,11 @@ def __call__(self, payload):
296375
RemoveCredentialAction,
297376
RemoveAllCredentialsAction,
298377
SetUserVerifiedAction,
299-
SetSPCTransactionModeAction]
378+
SetSPCTransactionModeAction,
379+
CancelFedCMDialogAction,
380+
SelectFedCMAccountAction,
381+
GetFedCMAccountListAction,
382+
GetFedCMDialogTitleAction,
383+
GetFedCMDialogTypeAction,
384+
SetFedCMDelayEnabledAction,
385+
ResetFedCMCooldownAction]

tools/wptrunner/wptrunner/executors/executorwebdriver.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
WindowProtocolPart,
3333
DebugProtocolPart,
3434
SPCTransactionsProtocolPart,
35+
FedCMProtocolPart,
3536
merge_dicts)
3637

3738
from webdriver.client import Session
@@ -359,6 +360,34 @@ def set_spc_transaction_mode(self, mode):
359360
return self.webdriver.send_session_command("POST", "secure-payment-confirmation/set-mode", body)
360361

361362

363+
class WebDriverFedCMProtocolPart(FedCMProtocolPart):
364+
def setup(self):
365+
self.webdriver = self.parent.webdriver
366+
367+
def cancel_fedcm_dialog(self):
368+
return self.webdriver.send_session_command("POST", "fedcm/canceldialog")
369+
370+
def select_fedcm_account(self, account_index):
371+
body = {"accountIndex": account_index}
372+
return self.webdriver.send_session_command("POST", "fedcm/selectaccount", body)
373+
374+
def get_fedcm_account_list(self):
375+
return self.webdriver.send_session_command("GET", "fedcm/accountlist")
376+
377+
def get_fedcm_dialog_title(self):
378+
return self.webdriver.send_session_command("GET", "fedcm/gettitle")
379+
380+
def get_fedcm_dialog_type(self):
381+
return self.webdriver.send_session_command("GET", "fedcm/getdialogtype")
382+
383+
def set_fedcm_delay_enabled(self, enabled):
384+
body = {"enabled": enabled}
385+
return self.webdriver.send_session_command("POST", "fedcm/setdelayenabled", body)
386+
387+
def reset_fedcm_cooldown(self):
388+
return self.webdriver.send_session_command("POST", "fedcm/resetcooldown")
389+
390+
362391
class WebDriverDebugProtocolPart(DebugProtocolPart):
363392
def load_devtools(self):
364393
raise NotImplementedError()
@@ -379,6 +408,7 @@ class WebDriverProtocol(Protocol):
379408
WebDriverSetPermissionProtocolPart,
380409
WebDriverVirtualAuthenticatorProtocolPart,
381410
WebDriverSPCTransactionsProtocolPart,
411+
WebDriverFedCMProtocolPart,
382412
WebDriverDebugProtocolPart]
383413

384414
def __init__(self, executor, browser, capabilities, **kwargs):

tools/wptrunner/wptrunner/executors/protocol.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,52 @@ def set_spc_transaction_mode(self, mode):
616616
pass
617617

618618

619+
class FedCMProtocolPart(ProtocolPart):
620+
"""Protocol part for Federated Credential Management"""
621+
__metaclass__ = ABCMeta
622+
623+
name = "fedcm"
624+
625+
@abstractmethod
626+
def cancel_fedcm_dialog(self):
627+
"""Cancel the FedCM dialog"""
628+
pass
629+
630+
@abstractmethod
631+
def select_fedcm_account(self, account_index):
632+
"""Select a FedCM account
633+
634+
:param int account_index: The index of the account to select"""
635+
pass
636+
637+
@abstractmethod
638+
def get_fedcm_account_list(self):
639+
"""Get the FedCM account list"""
640+
pass
641+
642+
@abstractmethod
643+
def get_fedcm_dialog_title(self):
644+
"""Get the FedCM dialog title"""
645+
pass
646+
647+
@abstractmethod
648+
def get_fedcm_dialog_type(self):
649+
"""Get the FedCM dialog type"""
650+
pass
651+
652+
@abstractmethod
653+
def set_fedcm_delay_enabled(self, enabled):
654+
"""Sets the FedCM delay as enabled or disabled
655+
656+
:param bool enabled: The delay to set"""
657+
pass
658+
659+
@abstractmethod
660+
def reset_fedcm_cooldown(self):
661+
"""Set the FedCM cooldown"""
662+
pass
663+
664+
619665
class PrintProtocolPart(ProtocolPart):
620666
"""Protocol part for rendering to a PDF."""
621667
__metaclass__ = ABCMeta

0 commit comments

Comments
 (0)