diff --git a/packages/app-runtime/test/lib/MockUIBridge.ts b/packages/app-runtime/test/lib/MockUIBridge.ts index 2f8aa61dd..4b923b914 100644 --- a/packages/app-runtime/test/lib/MockUIBridge.ts +++ b/packages/app-runtime/test/lib/MockUIBridge.ts @@ -16,6 +16,10 @@ export class MockUIBridge implements IUIBridge { public reset(): void { this._passwordToReturn = undefined; this._accountIdToReturn = undefined; + + this._showDeviceOnboardingCalls = []; + this._requestAccountSelectionCalls = []; + this._enterPasswordCalls = []; } public showMessage(_account: LocalAccountDTO, _relationship: IdentityDVO, _message: MessageDVO | MailDVO | RequestMessageDVO): Promise> { @@ -30,8 +34,19 @@ export class MockUIBridge implements IUIBridge { throw new Error("Method not implemented."); } - public showDeviceOnboarding(_deviceOnboardingInfo: DeviceOnboardingInfoDTO): Promise> { - throw new Error("Method not implemented."); + public showDeviceOnboarding(deviceOnboardingInfo: DeviceOnboardingInfoDTO): Promise> { + this._showDeviceOnboardingCalls.push(deviceOnboardingInfo); + + return Promise.resolve(Result.ok(undefined)); + } + + private _showDeviceOnboardingCalls: DeviceOnboardingInfoDTO[] = []; + public showDeviceOnboardingCalled(deviceId: string): boolean { + return this._showDeviceOnboardingCalls.some((x) => x.id === deviceId); + } + + public showDeviceOnboardingNotCalled(): boolean { + return this._showDeviceOnboardingCalls.length === 0; } public showRequest(_account: LocalAccountDTO, _request: LocalRequestDVO): Promise> { @@ -42,7 +57,9 @@ export class MockUIBridge implements IUIBridge { throw new Error("Method not implemented."); } - public requestAccountSelection(possibleAccounts: LocalAccountDTO[], _title?: string, _description?: string): Promise> { + public requestAccountSelection(possibleAccounts: LocalAccountDTO[], title?: string, description?: string): Promise> { + this._requestAccountSelectionCalls.push({ possibleAccounts: possibleAccounts, title: title, description: description }); + if (!this._accountIdToReturn) return Promise.resolve(Result.fail(new ApplicationError("code", "message"))); const foundAccount = possibleAccounts.find((x) => x.id === this._accountIdToReturn); @@ -51,9 +68,29 @@ export class MockUIBridge implements IUIBridge { return Promise.resolve(Result.ok(foundAccount)); } - public enterPassword(_passwordType: "pw" | "pin", _pinLength?: number): Promise> { + private _requestAccountSelectionCalls: { possibleAccounts: LocalAccountDTO[]; title?: string; description?: string }[] = []; + public requestAccountSelectionCalled(possibleAccountsLength: number): boolean { + return this._requestAccountSelectionCalls.some((x) => x.possibleAccounts.length === possibleAccountsLength); + } + + public requestAccountSelectionNotCalled(): boolean { + return this._requestAccountSelectionCalls.length === 0; + } + + public enterPassword(passwordType: "pw" | "pin", pinLength?: number): Promise> { + this._enterPasswordCalls.push({ passwordType: passwordType, pinLength: pinLength }); + if (!this._passwordToReturn) return Promise.resolve(Result.fail(new ApplicationError("code", "message"))); return Promise.resolve(Result.ok(this._passwordToReturn)); } + + private _enterPasswordCalls: { passwordType: "pw" | "pin"; pinLength?: number }[] = []; + public enterPasswordCalled(passwordType: "pw" | "pin", pinLength?: number): boolean { + return this._enterPasswordCalls.some((x) => x.passwordType === passwordType && x.pinLength === pinLength); + } + + public enterPasswordNotCalled(): boolean { + return this._enterPasswordCalls.length === 0; + } } diff --git a/packages/app-runtime/test/runtime/AppStringProcessor.test.ts b/packages/app-runtime/test/runtime/AppStringProcessor.test.ts index 74676920a..1a2951a2f 100644 --- a/packages/app-runtime/test/runtime/AppStringProcessor.test.ts +++ b/packages/app-runtime/test/runtime/AppStringProcessor.test.ts @@ -47,6 +47,9 @@ describe("AppStringProcessor", function () { expect(result.isError).toBeDefined(); expect(result.error.code).toBe("error.appStringProcessor.truncatedReferenceInvalid"); + + expect(mockUiBridge.enterPasswordNotCalled()).toBeTruthy(); + expect(mockUiBridge.requestAccountSelectionNotCalled()).toBeTruthy(); }); test("should properly handle a personalized RelationshipTemplate with the correct Identity available", async function () { @@ -63,6 +66,9 @@ describe("AppStringProcessor", function () { expect(result).toBeSuccessful(); await expect(eventBus).toHavePublished(PeerRelationshipTemplateLoadedEvent); + + expect(mockUiBridge.enterPasswordNotCalled()).toBeTruthy(); + expect(mockUiBridge.requestAccountSelectionNotCalled()).toBeTruthy(); }); test("should properly handle a personalized RelationshipTemplate with the correct Identity not available", async function () { @@ -77,6 +83,9 @@ describe("AppStringProcessor", function () { const result = await runtime2.stringProcessor.processTruncatedReference(templateResult.value.truncatedReference); expect(result).toBeAnError("There is no account matching the given 'forIdentityTruncated'.", "error.appruntime.general.noAccountAvailableForIdentityTruncated"); + + expect(mockUiBridge.enterPasswordNotCalled()).toBeTruthy(); + expect(mockUiBridge.requestAccountSelectionNotCalled()).toBeTruthy(); }); test("should properly handle a password protected RelationshipTemplate", async function () { @@ -94,6 +103,9 @@ describe("AppStringProcessor", function () { expect(result.value).toBeUndefined(); await expect(eventBus).toHavePublished(PeerRelationshipTemplateLoadedEvent); + + expect(mockUiBridge.enterPasswordCalled("pw")).toBeTruthy(); + expect(mockUiBridge.requestAccountSelectionCalled(2)).toBeTruthy(); }); test("should properly handle a pin protected RelationshipTemplate", async function () { @@ -111,6 +123,9 @@ describe("AppStringProcessor", function () { expect(result.value).toBeUndefined(); await expect(eventBus).toHavePublished(PeerRelationshipTemplateLoadedEvent); + + expect(mockUiBridge.enterPasswordCalled("pin", 6)).toBeTruthy(); + expect(mockUiBridge.requestAccountSelectionCalled(2)).toBeTruthy(); }); test("should properly handle a password protected personalized RelationshipTemplate", async function () { @@ -128,6 +143,9 @@ describe("AppStringProcessor", function () { expect(result.value).toBeUndefined(); await expect(eventBus).toHavePublished(PeerRelationshipTemplateLoadedEvent); + + expect(mockUiBridge.enterPasswordCalled("pw")).toBeTruthy(); + expect(mockUiBridge.requestAccountSelectionNotCalled()).toBeTruthy(); }); test("should properly handle a pin protected personalized RelationshipTemplate", async function () { @@ -145,5 +163,36 @@ describe("AppStringProcessor", function () { expect(result.value).toBeUndefined(); await expect(eventBus).toHavePublished(PeerRelationshipTemplateLoadedEvent); + + expect(mockUiBridge.enterPasswordCalled("pin", 6)).toBeTruthy(); + expect(mockUiBridge.requestAccountSelectionNotCalled()).toBeTruthy(); + }); + + describe("onboarding", function () { + let runtime3: AppRuntime; + const runtime3MockUiBridge = new MockUIBridge(); + + beforeAll(async function () { + runtime3 = await TestUtil.createRuntime(undefined, runtime3MockUiBridge, eventBus); + await runtime3.start(); + }); + + afterAll(async () => await runtime3.stop()); + + test("device onboarding with a password protected Token", async function () { + const deviceResult = await runtime1Session.transportServices.devices.createDevice({}); + const tokenResult = await runtime1Session.transportServices.devices.getDeviceOnboardingToken({ + id: deviceResult.value.id, + passwordProtection: { password: "password" } + }); + + mockUiBridge.passwordToReturn = "password"; + + const result = await runtime2.stringProcessor.processTruncatedReference(tokenResult.value.truncatedReference); + expect(result).toBeSuccessful(); + expect(result.value).toBeUndefined(); + + expect(mockUiBridge.showDeviceOnboardingCalled(deviceResult.value.id)).toBeTruthy(); + }); }); });