From a427ea05c351603d0ed3a79dfc05f254883155fb Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Thu, 27 Jul 2023 16:04:28 +0800 Subject: [PATCH] refactor(test): add `expectNavigation()` (#4254) --- .../src/tests/ui/bootstrap.test.ts | 27 ++++++++----------- .../src/tests/ui/user-management.test.ts | 10 +++---- .../src/tests/ui/webhooks.test.ts | 11 +++----- .../integration-tests/src/ui-helpers/index.ts | 7 +++-- packages/integration-tests/src/utils.ts | 13 +++++++++ 5 files changed, 35 insertions(+), 33 deletions(-) diff --git a/packages/integration-tests/src/tests/ui/bootstrap.test.ts b/packages/integration-tests/src/tests/ui/bootstrap.test.ts index fc824489f..340aa9b87 100644 --- a/packages/integration-tests/src/tests/ui/bootstrap.test.ts +++ b/packages/integration-tests/src/tests/ui/bootstrap.test.ts @@ -5,7 +5,7 @@ import { consoleUsername, logtoConsoleUrl as logtoConsoleUrlString, } from '#src/constants.js'; -import { appendPathname } from '#src/utils.js'; +import { appendPathname, expectNavigation } from '#src/utils.js'; /** * NOTE: This test suite assumes test cases will run sequentially (which is Jest default). @@ -17,23 +17,20 @@ describe('smoke testing for console admin account creation and sign-in', () => { const logtoConsoleUrl = new URL(logtoConsoleUrlString); it('can open with app element and navigate to welcome page', async () => { - await page.goto(logtoConsoleUrl.href); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await expectNavigation(page.goto(logtoConsoleUrl.href)); await expect(page).toMatchElement('#app'); expect(page.url()).toBe(new URL('console/welcome', logtoConsoleUrl).href); }); it('can register a new admin account and automatically sign in', async () => { - await expect(page).toClick('button', { text: 'Create account' }); + await expectNavigation(expect(page).toClick('button', { text: 'Create account' })); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); expect(page.url()).toBe(new URL('register', logtoConsoleUrl).href); await expect(page).toFill('input[name=identifier]', consoleUsername); - await expect(page).toClick('button[name=submit]'); + await expectNavigation(expect(page).toClick('button[name=submit]')); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); expect(page.url()).toBe(appendPathname('/register/password', logtoConsoleUrl).href); await expect(page).toFillForm('form', { @@ -41,8 +38,7 @@ describe('smoke testing for console admin account creation and sign-in', () => { confirmPassword: consolePassword, }); - await expect(page).toClick('button[name=submit]'); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await expectNavigation(expect(page).toClick('button[name=submit]')); expect(page.url()).toBe(new URL('console/get-started', logtoConsoleUrl).href); }); @@ -53,10 +49,11 @@ describe('smoke testing for console admin account creation and sign-in', () => { // Try awaiting for 500ms before clicking sign-out button await page.waitForTimeout(500); - await expect(page).toClick( - '.ReactModalPortal div[class$=dropdownContainer] div[class$=dropdownItem]:last-child' + await expectNavigation( + expect(page).toClick( + '.ReactModalPortal div[class$=dropdownContainer] div[class$=dropdownItem]:last-child' + ) ); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); expect(page.url()).toBe(new URL('sign-in', logtoConsoleUrl).href); }); @@ -64,14 +61,12 @@ describe('smoke testing for console admin account creation and sign-in', () => { it('can sign in to admin console again', async () => { const initialHref = appendPath(logtoConsoleUrl, 'console', 'applications').href; // Should be able to redirect back after sign-in - await page.goto(initialHref); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await expectNavigation(page.goto(initialHref)); await expect(page).toFillForm('form', { identifier: consoleUsername, password: consolePassword, }); - await expect(page).toClick('button[name=submit]'); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await expectNavigation(expect(page).toClick('button[name=submit]')); expect(page.url()).toBe(initialHref); diff --git a/packages/integration-tests/src/tests/ui/user-management.test.ts b/packages/integration-tests/src/tests/ui/user-management.test.ts index dd4fbfaf5..ff1b8af2d 100644 --- a/packages/integration-tests/src/tests/ui/user-management.test.ts +++ b/packages/integration-tests/src/tests/ui/user-management.test.ts @@ -2,6 +2,7 @@ import { logtoConsoleUrl as logtoConsoleUrlString } from '#src/constants.js'; import { goToAdminConsole } from '#src/ui-helpers/index.js'; import { appendPathname, + expectNavigation, formatPhoneNumberToInternational, generateEmail, generateName, @@ -19,8 +20,7 @@ describe('user management', () => { }); it('navigates to user management page on clicking sidebar menu', async () => { - await page.goto(appendPathname('/console/users', logtoConsoleUrl).href); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await expectNavigation(page.goto(appendPathname('/console/users', logtoConsoleUrl).href)); await expect(page).toMatchElement( 'div[class$=main] div[class$=headline] div[class$=titleEllipsis]', @@ -73,8 +73,7 @@ describe('user management', () => { }); it('fails to create user if no identifier is provided', async () => { - await page.goto(appendPathname('/console/users', logtoConsoleUrl).href); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await expectNavigation(page.goto(appendPathname('/console/users', logtoConsoleUrl).href)); await expect(page).toClick('div[class$=main] div[class$=headline] > button'); await expect(page).toClick('button[type=submit]'); @@ -84,8 +83,7 @@ describe('user management', () => { }); it('fails to create user if any of the identifiers are existed', async () => { - await page.goto(appendPathname('/console/users', logtoConsoleUrl).href); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await expectNavigation(page.goto(appendPathname('/console/users', logtoConsoleUrl).href)); // Conflicted email await expect(page).toClick('div[class$=main] div[class$=headline] > button'); diff --git a/packages/integration-tests/src/tests/ui/webhooks.test.ts b/packages/integration-tests/src/tests/ui/webhooks.test.ts index 25d79132b..bbec53444 100644 --- a/packages/integration-tests/src/tests/ui/webhooks.test.ts +++ b/packages/integration-tests/src/tests/ui/webhooks.test.ts @@ -1,6 +1,6 @@ import { logtoConsoleUrl as logtoConsoleUrlString } from '#src/constants.js'; import { goToAdminConsole } from '#src/ui-helpers/index.js'; -import { appendPathname } from '#src/utils.js'; +import { appendPathname, expectNavigation } from '#src/utils.js'; await page.setViewport({ width: 1280, height: 720 }); @@ -22,8 +22,7 @@ describe('webhooks', () => { }); it('navigates to webhooks page on clicking sidebar menu', async () => { - await page.goto(appendPathname('/console/webhooks', logtoConsoleUrl).href); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await expectNavigation(page.goto(appendPathname('/console/webhooks', logtoConsoleUrl).href)); await expect(page).toMatchElement( 'div[class$=main] div[class$=headline] div[class$=titleEllipsis]', @@ -52,8 +51,7 @@ describe('webhooks', () => { }); it('fails to create webhook if no event is provided', async () => { - await page.goto(appendPathname('/console/webhooks', logtoConsoleUrl).href); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await expectNavigation(page.goto(appendPathname('/console/webhooks', logtoConsoleUrl).href)); await expect(page).toClick('div[class$=main] div[class$=headline] > button'); await expect(page).toFill('input[name=name]', 'hook_name'); @@ -65,8 +63,7 @@ describe('webhooks', () => { }); it('fails to create webhook if endpoint url is not an HTTPS url', async () => { - await page.goto(appendPathname('/console/webhooks', logtoConsoleUrl).href); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await expectNavigation(page.goto(appendPathname('/console/webhooks', logtoConsoleUrl).href)); await expect(page).toClick('div[class$=main] div[class$=headline] > button'); await expect(page).toClick('span[class$=label]', { text: 'Create new account' }); diff --git a/packages/integration-tests/src/ui-helpers/index.ts b/packages/integration-tests/src/ui-helpers/index.ts index 1a792510b..915da2d90 100644 --- a/packages/integration-tests/src/ui-helpers/index.ts +++ b/packages/integration-tests/src/ui-helpers/index.ts @@ -3,18 +3,17 @@ import { consoleUsername, logtoConsoleUrl as logtoConsoleUrlString, } from '#src/constants.js'; +import { expectNavigation } from '#src/utils.js'; export const goToAdminConsole = async () => { const logtoConsoleUrl = new URL(logtoConsoleUrlString); - await page.goto(logtoConsoleUrl.href); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await expectNavigation(page.goto(logtoConsoleUrl.href)); if (page.url() === new URL('sign-in', logtoConsoleUrl).href) { await expect(page).toFillForm('form', { identifier: consoleUsername, password: consolePassword, }); - await expect(page).toClick('button[name=submit]'); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await expectNavigation(expect(page).toClick('button[name=submit]')); } }; diff --git a/packages/integration-tests/src/utils.ts b/packages/integration-tests/src/utils.ts index 1b8287d37..0d0c649aa 100644 --- a/packages/integration-tests/src/utils.ts +++ b/packages/integration-tests/src/utils.ts @@ -64,3 +64,16 @@ export const getAccessTokenPayload = (accessToken: string): Record new URL(path.join(baseUrl.pathname, pathname), baseUrl); + +/** + * Run an action and simultaneously wait for navigation to complete. This is + * useful for actions that trigger navigation, such as clicking a link or + * submitting a form. + */ +export const expectNavigation = async (action: Promise): Promise => { + const [result] = await Promise.all([ + action, + page.waitForNavigation({ waitUntil: 'networkidle0' }), + ]); + return result; +};