diff --git a/client/__tests__/e2e/cellxgeneActions.js b/client/__tests__/e2e/cellxgeneActions.js index eee4714c..9fda69b1 100644 --- a/client/__tests__/e2e/cellxgeneActions.js +++ b/client/__tests__/e2e/cellxgeneActions.js @@ -13,8 +13,11 @@ import { getTestClass, getTestId, isElementPresent, + goToPage, } from "./puppeteerUtils"; +import { appUrlBase } from "./config"; + export async function drag(testId, start, end, lasso = false) { const layout = await waitByID(testId); const elBox = await layout.boxModel(); @@ -312,4 +315,75 @@ export async function assertCategoryDoesNotExist(categoryName) { await expect(result).toBe(false); } + +export async function login() { + const email = `cellxgene-smoke-test+${process.env.DEPLOYMENT_STAGE}@chanzuckerberg.com`; + const password = "Test1111"; + + await goToPage(appUrlBase); + + await clickOn("auth-button"); + + // (thuang): Auth0 form is unstable and unsafe for input until verified + await waitUntilFormFieldStable('[name="email"]'); + + await expect(page).toFillForm("form", { + email, + password, + }); + + await Promise.all([ + page.waitForNavigation({ waitUntil: "networkidle0" }), + expect(page).toClick('[name="submit"]'), + ]); + + expect(page.url()).toContain(appUrlBase); +} + +export async function logout() { + await clickOnUntil("menu", async () => { + await expect(page).toMatch("Log Out"); + + await Promise.all([ + page.waitForNavigation({ waitUntil: "networkidle0" }), + expect(page).toClick("a", { text: "Log Out" }), + ]); + }); + + await expect(page).toMatch("Log In"); +} + +async function waitUntilFormFieldStable(selector) { + const MAX_RETRY = 10; + const WAIT_FOR_MS = 200; + + const EXPECTED_VALUE = "aaa"; + + let retry = 0; + + while (retry < MAX_RETRY) { + try { + await expect(page).toFill(selector, EXPECTED_VALUE); + + const fieldHandle = await expect(page).toMatchElement(selector); + + const fieldValue = await page.evaluate( + (input) => input.value, + fieldHandle + ); + + expect(fieldValue).toBe(EXPECTED_VALUE); + + break; + } catch (error) { + retry += 1; + + await page.waitFor(WAIT_FOR_MS); + } + } + + if (retry === MAX_RETRY) { + throw Error("clickOnUntil() assertion failed!"); + } +} /* eslint-enable no-await-in-loop -- await in loop is needed to emulate sequential user actions */ diff --git a/client/__tests__/e2e/e2e.test.js b/client/__tests__/e2e/e2e.test.js index 982a076a..05f52314 100644 --- a/client/__tests__/e2e/e2e.test.js +++ b/client/__tests__/e2e/e2e.test.js @@ -31,6 +31,8 @@ import { runDiffExp, selectCategory, subset, + login, + logout, } from "./cellxgeneActions"; const data = datasets[DATASET]; @@ -518,4 +520,18 @@ test("lasso moves after pan", async () => { expect(panCount).toBe(initialCount); }); + +const conditionalDescribe = + process.env.TEST_AUTH_INTEGRATION === "true" ? describe : describe.skip; + +conditionalDescribe("AuthN Integration", () => { + it("logs in", async () => { + await login(); + }); + + it("logs out", async () => { + await login(); + await logout(); + }); +}); /* eslint-enable no-await-in-loop -- await in loop is needed to emulate sequential user actions */ diff --git a/client/__tests__/e2e/puppeteer.setup.js b/client/__tests__/e2e/puppeteer.setup.js index 40453777..6c593b93 100644 --- a/client/__tests__/e2e/puppeteer.setup.js +++ b/client/__tests__/e2e/puppeteer.setup.js @@ -17,7 +17,9 @@ setDefaultOptions({ timeout: 20 * 1000 }); jest.retryTimes(ENV_DEFAULT.RETRY_ATTEMPTS); -(async () => { +beforeEach(async () => { + await jestPuppeteer.resetBrowser(); + const userAgent = await browser.userAgent(); await page.setUserAgent(`${userAgent}bot`); @@ -53,6 +55,4 @@ jest.retryTimes(ENV_DEFAULT.RETRY_ATTEMPTS); } } }); -})().catch((error) => { - console.error("puppeteer.setup.js error", error); });