Skip to content

Commit 2a515a0

Browse files
committed
Centralize credential handling
My thinking is that this may reduce the cognitive overhead for developers writing new test suites.
1 parent 3f2411a commit 2a515a0

File tree

10 files changed

+42
-62
lines changed

10 files changed

+42
-62
lines changed

test/e2e/baseFixture.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import { CodeServer, CodeServerPage } from "./models/CodeServer"
66
* Wraps `test.describe` to create and manage an instance of code-server. If you
77
* don't use this you will need to create your own code-server instance and pass
88
* it to `test.use`.
9+
*
10+
* If `includeCredentials` is `true` page requests will be authenticated.
911
*/
10-
export const describe = (name: string, fn: (codeServer: CodeServer) => void) => {
12+
export const describe = (name: string, includeCredentials: boolean, fn: (codeServer: CodeServer) => void) => {
1113
test.describe(name, () => {
1214
// This will spawn on demand so nothing is necessary on before.
1315
const codeServer = new CodeServer(name)
@@ -18,8 +20,21 @@ export const describe = (name: string, fn: (codeServer: CodeServer) => void) =>
1820
codeServer.close()
1921
})
2022

21-
// This makes `codeServer` available to the extend call below.
22-
test.use({ codeServer })
23+
const storageState = JSON.parse(process.env.STORAGE || "{}")
24+
25+
// Sanity check to ensure the cookie is set.
26+
const cookies = storageState?.cookies
27+
if (includeCredentials && (!cookies || cookies.length !== 1 || !!cookies[0].key)) {
28+
logger.error("no cookies", field("storage", JSON.stringify(cookies)))
29+
throw new Error("no credentials to include")
30+
}
31+
32+
test.use({
33+
// This makes `codeServer` available to the extend call below.
34+
codeServer,
35+
// This provides a cookie that authenticates with code-server.
36+
storageState: includeCredentials ? storageState : {},
37+
})
2338

2439
fn(codeServer)
2540
})

test/e2e/browser.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, test, expect } from "./baseFixture"
22

33
// This is a "gut-check" test to make sure playwright is working as expected
4-
describe("browser", () => {
4+
describe("browser", false, () => {
55
test("browser should display correct userAgent", async ({ codeServerPage, browserName }) => {
66
const displayNames = {
77
chromium: "Chrome",

test/e2e/codeServer.test.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
1-
import { storageState } from "../utils/constants"
21
import { describe, test, expect } from "./baseFixture"
32

4-
describe("CodeServer", () => {
5-
test.use({
6-
storageState,
7-
})
8-
3+
describe("CodeServer", true, () => {
94
test("should navigate to home page", async ({ codeServerPage }) => {
105
// We navigate codeServer before each test
116
// and we start the test with a storage state

test/e2e/globalSetup.test.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
import { storageState } from "../utils/constants"
21
import { describe, test, expect } from "./baseFixture"
32

43
// This test is to make sure the globalSetup works as expected
54
// meaning globalSetup ran and stored the storageState
6-
describe("globalSetup", () => {
7-
test.use({
8-
storageState,
9-
})
10-
5+
describe("globalSetup", true, () => {
116
test("should keep us logged in using the storageState", async ({ codeServerPage }) => {
127
// Make sure the editor actually loaded
138
expect(await codeServerPage.isEditorVisible()).toBe(true)

test/e2e/login.test.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import { PASSWORD } from "../utils/constants"
22
import { describe, test, expect } from "./baseFixture"
33

4-
describe("login", () => {
5-
// Reset the browser so no cookies are persisted
6-
// by emptying the storageState
7-
test.use({
8-
storageState: {},
9-
})
10-
4+
describe("login", false, () => {
115
test("should see the login page", async ({ codeServerPage }) => {
126
// It should send us to the login page
137
expect(await codeServerPage.page.title()).toBe("code-server login")

test/e2e/logout.test.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import { PASSWORD } from "../utils/constants"
22
import { describe, test, expect } from "./baseFixture"
33

4-
describe("logout", () => {
5-
// Reset the browser so no cookies are persisted
6-
// by emptying the storageState
7-
test.use({
8-
storageState: {},
9-
})
10-
4+
describe("logout", false, () => {
115
test("should be able login and logout", async ({ codeServerPage }) => {
126
// Type in password
137
await codeServerPage.page.fill(".password", PASSWORD)

test/e2e/openHelpAbout.test.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
1-
import { storageState } from "../utils/constants"
21
import { describe, test, expect } from "./baseFixture"
32

4-
describe("Open Help > About", () => {
5-
test.use({
6-
storageState,
7-
})
8-
3+
describe("Open Help > About", true, () => {
94
test("should see a 'Help' then 'About' button in the Application Menu that opens a dialog", async ({
105
codeServerPage,
116
}) => {

test/e2e/terminal.test.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,17 @@ import * as cp from "child_process"
22
import * as fs from "fs"
33
import * as path from "path"
44
import util from "util"
5-
import { storageState } from "../utils/constants"
65
import { tmpdir } from "../utils/helpers"
76
import { describe, expect, test } from "./baseFixture"
87

9-
describe("Integrated Terminal", () => {
8+
describe("Integrated Terminal", true, () => {
109
// Create a new context with the saved storage state
1110
// so we don't have to logged in
1211
const testFileName = "pipe"
1312
const testString = "new string test from e2e test"
1413
let tmpFolderPath = ""
1514
let tmpFile = ""
1615

17-
test.use({
18-
storageState,
19-
})
20-
2116
test.beforeAll(async () => {
2217
tmpFolderPath = await tmpdir("integrated-terminal")
2318
tmpFile = path.join(tmpFolderPath, testFileName)

test/utils/constants.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
export const PASSWORD = "e45432jklfdsab"
2-
export const storageState = JSON.parse(process.env.STORAGE || "{}")
32
export const workspaceDir = "workspaces"

test/utils/globalSetup.ts

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { chromium } from "playwright"
1+
import { Cookie } from "playwright"
22
import { hash } from "../../src/node/util"
33
import { PASSWORD, workspaceDir } from "./constants"
44
import { clean } from "./helpers"
@@ -15,31 +15,29 @@ export default async function () {
1515
// Cleanup workspaces from previous tests.
1616
await clean(workspaceDir)
1717

18-
const cookieToStore = {
19-
sameSite: "Lax" as const,
20-
name: "key",
21-
value: await hash(PASSWORD),
22-
domain: "localhost",
23-
path: "/",
24-
expires: -1,
25-
httpOnly: false,
26-
secure: false,
27-
}
28-
29-
const browser = await chromium.launch()
30-
const page = await browser.newPage()
31-
const storage = await page.context().storageState()
32-
3318
if (process.env.WTF_NODE) {
3419
wtfnode.setup()
3520
}
3621

37-
storage.cookies = [cookieToStore]
22+
// TODO: Replace this with a call to code-server to get the cookie. To avoid
23+
// too much overhead we can do an http POST request and avoid spawning a
24+
// browser for it.
25+
const cookies: Cookie[] = [
26+
{
27+
domain: "localhost",
28+
expires: -1,
29+
httpOnly: false,
30+
name: "key",
31+
path: "/",
32+
sameSite: "Lax",
33+
secure: false,
34+
value: await hash(PASSWORD),
35+
},
36+
]
3837

3938
// Save storage state and store as an env variable
4039
// More info: https://playwright.dev/docs/auth/#reuse-authentication-state
41-
process.env.STORAGE = JSON.stringify(storage)
42-
await browser.close()
40+
process.env.STORAGE = JSON.stringify({ cookies })
4341

4442
console.log("✅ Global Setup for Playwright End-to-End Tests is now complete.")
4543
}

0 commit comments

Comments
 (0)