diff --git a/.eslintrc.yaml b/.eslintrc.yaml index b889a5e7f..f520fd9f9 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -35,13 +35,7 @@ rules: "@typescript-eslint/no-extra-semi": off eqeqeq: error import/order: - [ - error, - { - alphabetize: { order: "asc" }, - groups: [["builtin", "external", "internal"], "parent", "sibling"], - }, - ] + [error, { alphabetize: { order: "asc" }, groups: [["builtin", "external", "internal"], "parent", "sibling"] }] no-async-promise-executor: off # This isn't a real module, just types, which apparently doesn't resolve. import/no-unresolved: [error, { ignore: ["express-serve-static-core"] }] diff --git a/test/e2e/globalSetup.test.ts b/test/e2e/globalSetup.test.ts index cfbe512ba..ee4b64433 100644 --- a/test/e2e/globalSetup.test.ts +++ b/test/e2e/globalSetup.test.ts @@ -6,12 +6,10 @@ import { CODE_SERVER_ADDRESS, STORAGE } from "../utils/constants" describe("globalSetup", () => { beforeEach(async () => { // Create a new context with the saved storage state + // so we don't have to logged in const storageState = JSON.parse(STORAGE) || {} - console.log("what is storage ", storageState) await jestPlaywright.resetContext({ storageState }) - await page.goto(CODE_SERVER_ADDRESS) - // code-server takes a second to load - await page.waitForTimeout(1000) + await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) it("should keep us logged in if we don't reset the browser", async () => { diff --git a/test/e2e/login.test.ts b/test/e2e/login.test.ts index 1caf40b01..29a232351 100644 --- a/test/e2e/login.test.ts +++ b/test/e2e/login.test.ts @@ -3,8 +3,8 @@ import { CODE_SERVER_ADDRESS, PASSWORD } from "../utils/constants" describe("login", () => { beforeEach(async () => { - await jestPlaywright.resetContext() - await page.goto(CODE_SERVER_ADDRESS) + await jestPlaywright.resetBrowser() + await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) it("should be able to login", async () => { @@ -12,9 +12,7 @@ describe("login", () => { await page.fill(".password", PASSWORD) // Click the submit button and login await page.click(".submit") - // For some reason, it wasn't waiting for the click and navigation before checking - // so adding a timeout ensures that we allow the editor time to load - await page.waitForTimeout(1000) + await page.waitForLoadState("networkidle") // See the editor const codeServerEditor = await page.isVisible(".monaco-workbench") expect(codeServerEditor).toBeTruthy() diff --git a/test/e2e/loginPage.test.ts b/test/e2e/loginPage.test.ts index ef85f8fc4..eee4ae3a2 100644 --- a/test/e2e/loginPage.test.ts +++ b/test/e2e/loginPage.test.ts @@ -5,7 +5,7 @@ import { CODE_SERVER_ADDRESS } from "../utils/constants" describe("login page", () => { beforeEach(async () => { await jestPlaywright.resetContext() - await page.goto(CODE_SERVER_ADDRESS) + await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) it("should see the login page", async () => { diff --git a/test/e2e/logout.test.ts b/test/e2e/logout.test.ts index c717a5f75..da364fe76 100644 --- a/test/e2e/logout.test.ts +++ b/test/e2e/logout.test.ts @@ -3,17 +3,16 @@ import { CODE_SERVER_ADDRESS, PASSWORD } from "../utils/constants" describe("logout", () => { beforeEach(async () => { - await jestPlaywright.resetContext() + await jestPlaywright.resetBrowser() + await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) it("should be able login and logout", async () => { - await page.goto(CODE_SERVER_ADDRESS) // Type in password await page.fill(".password", PASSWORD) // Click the submit button and login await page.click(".submit") - // Allow time to navigate - await page.waitForTimeout(1000) + await page.waitForLoadState("networkidle") // See the editor const codeServerEditor = await page.isVisible(".monaco-workbench") expect(codeServerEditor).toBeTruthy() @@ -28,8 +27,8 @@ describe("logout", () => { await page.hover(logoutButton) await page.click(logoutButton) - // it takes a couple seconds to navigate - await page.waitForTimeout(2000) + // it takes a couple seconds for url to change + await page.waitForLoadState("networkidle") const currentUrl = page.url() expect(currentUrl).toBe(`${CODE_SERVER_ADDRESS}/login`) }) diff --git a/test/e2e/openHelpAbout.test.ts b/test/e2e/openHelpAbout.test.ts index c8830bfe6..fd63766d3 100644 --- a/test/e2e/openHelpAbout.test.ts +++ b/test/e2e/openHelpAbout.test.ts @@ -1,51 +1,16 @@ /// -import { Cookie } from "playwright" -import { hash } from "../../src/node/util" -import { CODE_SERVER_ADDRESS, PASSWORD, STORAGE } from "../utils/constants" -import { createCookieIfDoesntExist } from "../utils/helpers" +import { CODE_SERVER_ADDRESS, STORAGE } from "../utils/constants" describe("Open Help > About", () => { beforeEach(async () => { // Create a new context with the saved storage state + // so we don't have to logged in const storageState = JSON.parse(STORAGE) || {} - - const cookieToStore = { - sameSite: "Lax" as const, - name: "key", - value: hash(PASSWORD), - domain: "localhost", - path: "/", - expires: -1, - httpOnly: false, - secure: false, - } - - // For some odd reason, the login method used in globalSetup.ts doesn't always work - // I don't know if it's on playwright clearing our cookies by accident - // or if it's our cookies disappearing. - // This means we need an additional check to make sure we're logged in. - // We do this by manually adding the cookie to the browser environment - // if it's not there at the time the test starts - const cookies: Cookie[] = storageState.cookies || [] - // If the cookie exists in cookies then - // this will return the cookies with no changes - // otherwise if it doesn't exist, it will create it - // hence the name maybeUpdatedCookies - // - // TODO(@jsjoeio) - // The playwright storage thing sometimes works and sometimes doesn't. We should investigate this further - // at some point. - // See discussion: https://github.com/cdr/code-server/pull/2648#discussion_r575434946 - - const maybeUpdatedCookies = createCookieIfDoesntExist(cookies, cookieToStore) - await jestPlaywright.resetBrowser({ storageState: { cookies: maybeUpdatedCookies } }) + await jestPlaywright.resetContext({ storageState }) + await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "networkidle" }) }) it("should see a 'Help' then 'About' button in the Application Menu that opens a dialog", async () => { - // waitUntil: "domcontentloaded" - // In case the page takes a long time to load - await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "domcontentloaded" }) - // Make sure the editor actually loaded expect(await page.isVisible("div.monaco-workbench")) diff --git a/test/utils/globalSetup.ts b/test/utils/globalSetup.ts index 498d21a3a..44adfaa80 100644 --- a/test/utils/globalSetup.ts +++ b/test/utils/globalSetup.ts @@ -2,37 +2,39 @@ // so that it authenticates us into code-server // ensuring that we're logged in before we run any tests import { chromium } from "playwright" -import { CODE_SERVER_ADDRESS, PASSWORD } from "./constants" +import { PASSWORD } from "./constants" +import { hash } from "../../src/node/util" import * as wtfnode from "./wtfnode" +const cookieToStore = { + sameSite: "Lax" as const, + name: "key", + value: hash(PASSWORD), + domain: "localhost", + path: "/", + expires: -1, + httpOnly: false, + secure: false, +} + module.exports = async () => { console.log("\n🚨 Running Global Setup for Jest End-to-End Tests") console.log(" Please hang tight...") const browser = await chromium.launch() - const context = await browser.newContext() - const page = await context.newPage() + const page = await browser.newPage() + const storage = await page.context().storageState() if (process.env.WTF_NODE) { wtfnode.setup() } - await page.goto(CODE_SERVER_ADDRESS, { waitUntil: "domcontentloaded" }) - // Type in password - await page.fill(".password", PASSWORD) - // Click the submit button and login - await page.click(".submit") - // After logging in, we store a cookie in localStorage - // we need to wait a bit to make sure that happens - // before we grab the storage and save it - await page.waitForTimeout(1000) + storage.cookies = [cookieToStore] // Save storage state and store as an env variable // More info: https://playwright.dev/docs/auth?_highlight=authe#reuse-authentication-state - const storage = await context.storageState() process.env.STORAGE = JSON.stringify(storage) - await page.close() await browser.close() - await context.close() + console.log("✅ Global Setup for Jest End-to-End Tests is now complete.") }