diff --git a/e2e/login.spec.ts b/e2e/login.spec.ts index 0daa4e2..056eca7 100644 --- a/e2e/login.spec.ts +++ b/e2e/login.spec.ts @@ -1,3 +1,4 @@ +import test from 'node:test'; import {testWithII} from '../src'; const loginSelector = '#login'; @@ -45,3 +46,19 @@ testWithII.describe('with selector', () => { await iiPage.signInWithIdentity({identity, selector: loginSelector}); }); }); + +testWithII.describe.serial('create identity and manual sign-in', () => { + let createdIdentity: number; + + testWithII('create identity and capture it', async ({page, iiPage}) => { + await page.goto('/'); + createdIdentity = await iiPage.createNewIdentity(); + }); + + testWithII('sign in using identity from list or fallback manually', async ({page, iiPage}) => { + await page.goto('/'); + await iiPage.manuallySignInWithIdentity({identity: createdIdentity}); + await page.locator(logoutSelector).click(); + await iiPage.manuallySignInWithIdentity({identity: createdIdentity}); + }); +}); diff --git a/src/page-objects/InternetIdentityPage.ts b/src/page-objects/InternetIdentityPage.ts index bdf11d9..808dfca 100644 --- a/src/page-objects/InternetIdentityPage.ts +++ b/src/page-objects/InternetIdentityPage.ts @@ -153,4 +153,96 @@ export class InternetIdentityPage { await iiPage.waitForEvent('close'); expect(iiPage.isClosed()).toBe(true); }; + + createNewIdentity = async (params?: { + selector?: string; + captcha?: boolean; + }): Promise => { + const iiPagePromise = this.context.waitForEvent('page'); + + await this.page.locator(params?.selector ?? '[data-tid=login-button]').click(); + + const iiPage = await iiPagePromise; + await expect(iiPage).toHaveTitle('Internet Identity'); + + await iiPage.locator('#registerButton').click(); + await iiPage.locator('[data-action=construct-identity]').click(); + + if (params?.captcha === true) { + await iiPage.locator('input#captchaInput').fill('a', {timeout: 10000}); + await iiPage.locator('#confirmRegisterButton').click(); + } + + const identityText = await iiPage.locator('#userNumber').textContent(); + const createdIdentity = parseInt(identityText!); + expect(createdIdentity).not.toBeNull(); + return createdIdentity; + } + + manuallySignInWithIdentity = async ({ + selector, + identity + }: { + selector?: string; + identity: number; + }): Promise => { + const iiPagePromise = this.context.waitForEvent('page'); + + await this.page.locator(selector ?? '[data-tid=login-button]').click(); + + const iiPage = await iiPagePromise; + await expect(iiPage).toHaveTitle('Internet Identity'); + + const existingIdentityLoginLocator = iiPage.locator(`[data-anchor-id="${identity}"]`); + const firstRunManualLoginLocator = iiPage.locator('#loginButton'); + const moreOptionsLoginLocator = iiPage.locator('[data-role="more-options"]'); + + const waitOptions: { state: 'visible'; timeout: number } = { state: 'visible', timeout: 10000 }; + + type RaceResult = 'existingIdentityLogin' | 'firstRunManualLogin' | 'moreOptionsLogin' | 'none'; + + async function getRaceResult( + locator: { waitFor: (options: any) => Promise }, + successResult: RaceResult + ): Promise { + try { + await locator.waitFor(waitOptions); + return successResult; + } catch { + return 'none'; + } + } + + const identityPromise = getRaceResult(existingIdentityLoginLocator, 'existingIdentityLogin'); + const firstTimePromise = getRaceResult(firstRunManualLoginLocator, 'firstRunManualLogin'); + const fallbackPromise = getRaceResult(moreOptionsLoginLocator, 'moreOptionsLogin'); + + const result: RaceResult = await Promise.race([ + identityPromise, + fallbackPromise, + firstTimePromise, + ]); + + switch(result) { + case 'existingIdentityLogin': + await existingIdentityLoginLocator.first().click({ force: true }); + break; + + case 'firstRunManualLogin': + case 'moreOptionsLogin': { + const locator = + result === 'firstRunManualLogin' ? firstRunManualLoginLocator : moreOptionsLoginLocator; + await locator.click({ force: true }); + await iiPage.fill('input[data-role="anchor-input"]', identity.toString()); + await iiPage.locator('[data-action="continue"]').click(); + break; + } + default: + throw new Error( + 'No locator found for Buttons: existingIdentity, firstRunManualLogin or moreOptionsLogin' + ); + } + await iiPage.waitForEvent('close'); + expect(iiPage.isClosed()).toBe(true); + }; }