diff options
Diffstat (limited to 'testing/web-platform/tests/credential-management/support/otpcredential-helper.js')
-rw-r--r-- | testing/web-platform/tests/credential-management/support/otpcredential-helper.js | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/testing/web-platform/tests/credential-management/support/otpcredential-helper.js b/testing/web-platform/tests/credential-management/support/otpcredential-helper.js new file mode 100644 index 0000000000..e07e9f5be3 --- /dev/null +++ b/testing/web-platform/tests/credential-management/support/otpcredential-helper.js @@ -0,0 +1,114 @@ +// These tests rely on the User Agent providing an implementation of +// MockWebOTPService. +// +// In Chromium-based browsers this implementation is provided by a polyfill +// in order to reduce the amount of test-only code shipped to users. To enable +// these tests the browser must be run with these options: +// // --enable-blink-features=MojoJS,MojoJSTest + +import {isChromiumBased} from '/resources/test-only-api.m.js'; + +/** + * This enumeration is used by WebOTP WPTs to control mock backend behavior. + * See MockWebOTPService below. + */ +export const Status = { + SUCCESS: 0, + UNHANDLED_REQUEST: 1, + CANCELLED: 2, + ABORTED: 3, +}; + +/** + * A interface which must be implemented by browsers to support WebOTP WPTs. + */ +export class MockWebOTPService { + /** + * Accepts a function to be invoked in response to the next OTP request + * received by the mock. The (optionally async) function, when executed, must + * return an object with a `status` field holding one of the `Status` values + * defined above, and -- if successful -- an `otp` field containing a + * simulated OTP string. + * + * Tests will call this method directly to inject specific response behavior + * into the browser-specific mock implementation. + */ + async handleNextOTPRequest(responseFunc) {} +} + +/** + * Returns a Promise resolving to a browser-specific MockWebOTPService subclass + * instance if one is available. + */ +async function createBrowserSpecificMockImpl() { + if (isChromiumBased) { + return await createChromiumMockImpl(); + } + throw new Error('Unsupported browser.'); +} + +const asyncMock = createBrowserSpecificMockImpl(); + +export function expectOTPRequest() { + return { + async andReturn(callback) { + const mock = await asyncMock; + mock.handleNextOTPRequest(callback); + } + } +} + +/** + * Instantiates a Chromium-specific subclass of MockWebOTPService. + */ +async function createChromiumMockImpl() { + const {SmsStatus, WebOTPService, WebOTPServiceReceiver} = await import( + '/gen/third_party/blink/public/mojom/sms/webotp_service.mojom.m.js'); + const MockWebOTPServiceChromium = class extends MockWebOTPService { + constructor() { + super(); + this.mojoReceiver_ = new WebOTPServiceReceiver(this); + this.interceptor_ = + new MojoInterfaceInterceptor(WebOTPService.$interfaceName); + this.interceptor_.oninterfacerequest = (e) => { + this.mojoReceiver_.$.bindHandle(e.handle); + }; + this.interceptor_.start(); + this.requestHandlers_ = []; + Object.freeze(this); + } + + handleNextOTPRequest(responseFunc) { + this.requestHandlers_.push(responseFunc); + } + + async receive() { + if (this.requestHandlers_.length == 0) { + throw new Error('Mock received unexpected OTP request.'); + } + + const responseFunc = this.requestHandlers_.shift(); + const response = await responseFunc(); + switch (response.status) { + case Status.SUCCESS: + if (typeof response.otp != 'string') { + throw new Error('Mock success results require an OTP string.'); + } + return {status: SmsStatus.kSuccess, otp: response.otp}; + case Status.UNHANDLED_REQUEST: + return {status: SmsStatus.kUnhandledRequest}; + case Status.CANCELLED: + return {status: SmsStatus.kCancelled}; + case Status.ABORTED: + return {status: SmsStatus.kAborted}; + default: + throw new Error( + `Mock result contains unknown status: ${response.status}`); + } + } + + async abort() {} + }; + return new MockWebOTPServiceChromium(); +} + |