Skip to content

Commit baf168f

Browse files
committed
test: e2e tests (playwright, 3 roles)
1 parent aff5562 commit baf168f

33 files changed

Lines changed: 3205 additions & 0 deletions

playwright.config.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { defineConfig } from '@playwright/test'
2+
3+
export default defineConfig({
4+
testDir: './tests/e2e',
5+
fullyParallel: false,
6+
workers: 1,
7+
retries: 0,
8+
reporter: [['list'], ['html', { open: 'never' }]],
9+
timeout: 30_000,
10+
11+
globalSetup: './tests/global-setup.ts',
12+
globalTeardown: './tests/global-teardown.ts',
13+
14+
use: {
15+
baseURL: 'http://localhost:3000',
16+
storageState: 'tests/.auth/admin.json',
17+
viewport: { width: 1920, height: 1080 },
18+
trace: 'on-first-retry',
19+
},
20+
21+
webServer: {
22+
command: 'pnpm dev',
23+
port: 3000,
24+
reuseExistingServer: true,
25+
timeout: 60_000,
26+
},
27+
})

tests/.auth/admin.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"cookies": [
3+
{
4+
"name": "NEXT_LOCALE",
5+
"value": "en",
6+
"domain": "localhost",
7+
"path": "/",
8+
"expires": -1,
9+
"httpOnly": false,
10+
"secure": false,
11+
"sameSite": "Lax"
12+
},
13+
{
14+
"name": "next-auth.csrf-token",
15+
"value": "15c0242d3788914e347e0b3ee3e41402fde64cab40b0bd64bf7d4c7c623feb39%7C9c8cee96d44663b2c85c387b5d3239f5d997146e8431b63de8a671db578fdc49",
16+
"domain": "localhost",
17+
"path": "/",
18+
"expires": -1,
19+
"httpOnly": true,
20+
"secure": false,
21+
"sameSite": "Lax"
22+
},
23+
{
24+
"name": "next-auth.callback-url",
25+
"value": "http%3A%2F%2Flocalhost%3A3000%2Fen%2Fauth%2Fsignin",
26+
"domain": "localhost",
27+
"path": "/",
28+
"expires": -1,
29+
"httpOnly": true,
30+
"secure": false,
31+
"sameSite": "Lax"
32+
},
33+
{
34+
"name": "next-auth.session-token",
35+
"value": "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..jpUtdaTA5vCmySdb.qx1BNVjLcBYfw_47dOvMwNJooYZrokf40GtTr0AFOR0RjwYt5tZo1Zuof5sya8doHS3CJqSFgRpi4IKZFdIkv-Q1T77ncE1Ex3h1M9_MkuNdeBMrBFSBStDgLOruAL5vDkChN74Ww_jT-HlcUYCPypnsVc5WBkh6ipdnjQwEDM2iIYQ4mu-ggnojIoHURTSMCTJlVVj-rXUqxh8LkDA3eyxlrnBORFhn3-fKeGkMUoRFlpphuaiB9NZVcHFWDZ6XqQKKgOmbNvPvyYDtuaGlan3Y0pjftm2kuGVSvWK8owEkIiMXYhJ-9WQOfauhYcfwisXjYBgHhdGcTWwyVyHFv-aRNiLZWCDAnwHifgMVG7Or_mBTBRkz4OMW87FK_q-6.03wckCOmQM1uDYlrc6Zthw",
36+
"domain": "localhost",
37+
"path": "/",
38+
"expires": 1775996965.808128,
39+
"httpOnly": true,
40+
"secure": false,
41+
"sameSite": "Lax"
42+
}
43+
],
44+
"origins": []
45+
}

tests/.auth/agent.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"cookies": [
3+
{
4+
"name": "NEXT_LOCALE",
5+
"value": "en",
6+
"domain": "localhost",
7+
"path": "/",
8+
"expires": -1,
9+
"httpOnly": false,
10+
"secure": false,
11+
"sameSite": "Lax"
12+
},
13+
{
14+
"name": "next-auth.csrf-token",
15+
"value": "bc0aaab533c8e6bc8274fc00a3a6403e16ffda3710d2f9352afe7ca4f9e804d9%7Ca6d20fef1be2759f43cb1c22ff9f49000b9bb6583b756ed20ce6c7a20e0293e7",
16+
"domain": "localhost",
17+
"path": "/",
18+
"expires": -1,
19+
"httpOnly": true,
20+
"secure": false,
21+
"sameSite": "Lax"
22+
},
23+
{
24+
"name": "next-auth.callback-url",
25+
"value": "http%3A%2F%2Flocalhost%3A3000%2Fen%2Fauth%2Fsignin",
26+
"domain": "localhost",
27+
"path": "/",
28+
"expires": -1,
29+
"httpOnly": true,
30+
"secure": false,
31+
"sameSite": "Lax"
32+
},
33+
{
34+
"name": "next-auth.session-token",
35+
"value": "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..dUT5P7MSmyyFFYbP.veF2DP2-onsa6uEOTD_F4pDuauQ5qWmZ39xLQ3N5Lzmp0Xzsh4Jcm5ijsZYnxoAVAKppFH5Vp7POp9u260-inIp6Z58yXGMk0U_LdEi4OcJdDXA3TVC18HAQonkjtZP-fxS8rhh-gruMHqBrB2VDFWjugs4EOiGmxGDC_-nRQT8AUdIm4229pPezEHMI0Ov7CnGcIVbRMDr6CIThHidNGIY2q-yJB2q2OnO_BiXwvXrb3fpw5WmB2l2Ag-ayL3uLZHs4PYqNwlnU0WYtPqFRL__nGOQJ45_nJveCJyy7DO4LwU0s87JgrqmSquGhqlJaJ9-uEJuMQx1k98UFebfWXXmYS-mCdUaLe2MHNR8WIrWdgZ01-i3jX_bZ0_5rqPQBaKI.5n7Qu304CJnkJDTE4wf-XQ",
36+
"domain": "localhost",
37+
"path": "/",
38+
"expires": 1775996967.264855,
39+
"httpOnly": true,
40+
"secure": false,
41+
"sameSite": "Lax"
42+
}
43+
],
44+
"origins": []
45+
}

tests/.auth/agent2.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"cookies": [
3+
{
4+
"name": "NEXT_LOCALE",
5+
"value": "en",
6+
"domain": "localhost",
7+
"path": "/",
8+
"expires": -1,
9+
"httpOnly": false,
10+
"secure": false,
11+
"sameSite": "Lax"
12+
},
13+
{
14+
"name": "next-auth.csrf-token",
15+
"value": "078e708529e70cac57a0bbe1eba4337db655d1941b69275338d7d55dab7e50a6%7Ca09d32ac6fa800e206fb46bfe252bc870c65451890f6ee06f17b1b2ae2a14dd4",
16+
"domain": "localhost",
17+
"path": "/",
18+
"expires": -1,
19+
"httpOnly": true,
20+
"secure": false,
21+
"sameSite": "Lax"
22+
},
23+
{
24+
"name": "next-auth.callback-url",
25+
"value": "http%3A%2F%2Flocalhost%3A3000%2Fen%2Fauth%2Fsignin",
26+
"domain": "localhost",
27+
"path": "/",
28+
"expires": -1,
29+
"httpOnly": true,
30+
"secure": false,
31+
"sameSite": "Lax"
32+
},
33+
{
34+
"name": "next-auth.session-token",
35+
"value": "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..t51F3qFNpopleZKX.JRix1qi9PLpuHzFEvjQ5E-E_d7TS-IT45HELDSxhJLVfrGDJRETgUr2it6YKA2ajkRTSC57czsr_VaRPUCicxP1arb82TI_c8eSpJWVm1Dq6oWEFJTzVwBXhnF8k7AsLpjOv5HwFfg5-7m5Zi-Thj7bJJb6crRjPZ3oQdUkbzoLNKARVQqaHrXlRrkK9AApxHdOJdFphKuLIgGANbfM38ghaw4cotGQan-CoKKxmAhNgHNtLYZD0vLdw53W0-yYTOnU6bUt7LwGZqSUsREM7baG-J_JseM53z7063OvnpwT7Bj0JaMnsTlC3bcsvaFnQiMmpXh5nc2SN3-4fQIemMVLd6A3ZEA6AJw2uSpI8Bre8WNvQvJRnvwyoBcSaeBZa._ysGS7HfBqIWkYow4tIHOg",
36+
"domain": "localhost",
37+
"path": "/",
38+
"expires": 1775996968.761174,
39+
"httpOnly": true,
40+
"secure": false,
41+
"sameSite": "Lax"
42+
}
43+
],
44+
"origins": []
45+
}

tests/.auth/customer.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"cookies": [
3+
{
4+
"name": "NEXT_LOCALE",
5+
"value": "en",
6+
"domain": "localhost",
7+
"path": "/",
8+
"expires": -1,
9+
"httpOnly": false,
10+
"secure": false,
11+
"sameSite": "Lax"
12+
},
13+
{
14+
"name": "next-auth.csrf-token",
15+
"value": "b1da158f1efff986b7b70840555926c638cf8391b1666e2d5510aba08a3155f6%7C160d000c80a3e145d75d337f27a716ef1f426b44d8e6ca0de82ab6b7015147e8",
16+
"domain": "localhost",
17+
"path": "/",
18+
"expires": -1,
19+
"httpOnly": true,
20+
"secure": false,
21+
"sameSite": "Lax"
22+
},
23+
{
24+
"name": "next-auth.callback-url",
25+
"value": "http%3A%2F%2Flocalhost%3A3000%2Fen%2Fauth%2Fsignin",
26+
"domain": "localhost",
27+
"path": "/",
28+
"expires": -1,
29+
"httpOnly": true,
30+
"secure": false,
31+
"sameSite": "Lax"
32+
},
33+
{
34+
"name": "next-auth.session-token",
35+
"value": "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..tJUEVb0GPzF373cT.6O5XDlN5sBJaYl-DajBgdw-FL6yCEY_oSwvwBlcEWpKRFb_jjM_6aLWS99cjuOnsTG-gpcidp41Z_MqzwG-3rFBhZMgHvNfCfBb15ORF2bP0EEp1A8AAEIADb136c34q2WC7pIDGtoSZlSAXjY_ZbM_S0wTjtlzICMuYsC-iSJLPSkj0gL0v_zQf7aGgDLrWyg058MOgpYnJfa1_Fwp5AzVUwwOYl7_-bnXPEd-W1J5Eu-1wwMGKcOgK3kl-jGTSaqk6sM0CFCQc8crbi305C0O29a7_r0I9L86R55zgOSW07ZpVl3Cm2NEXeRKcleVoXtVcCHrHwspwqznYY0F3OmvofIZ_7AAgjJzi_mnnlFD80K5-wg_wAwgI-dItgR-5dd32-F7GhDAqFn4.PRvdy02_-XFgAzQpK6HdKg",
36+
"domain": "localhost",
37+
"path": "/",
38+
"expires": 1775996970.320178,
39+
"httpOnly": true,
40+
"secure": false,
41+
"sameSite": "Lax"
42+
}
43+
],
44+
"origins": []
45+
}

tests/auth.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/**
2+
* Auth fixtures for Playwright
3+
*
4+
* Usage:
5+
* import { test, expect } from '../auth'
6+
* test('admin can see users page', async ({ adminPage }) => { ... })
7+
* test('customer sees own issues', async ({ customerPage }) => { ... })
8+
*/
9+
import { test as base, type Page, type BrowserContext } from '@playwright/test'
10+
import path from 'path'
11+
12+
type AuthFixtures = {
13+
adminPage: Page
14+
agentPage: Page
15+
agent2Page: Page
16+
customerPage: Page
17+
adminContext: BrowserContext
18+
agentContext: BrowserContext
19+
agent2Context: BrowserContext
20+
customerContext: BrowserContext
21+
}
22+
23+
function authFile(role: string) {
24+
return path.join(__dirname, '.auth', `${role}.json`)
25+
}
26+
27+
export const test = base.extend<AuthFixtures>({
28+
adminContext: async ({ browser }, use) => {
29+
const context = await browser.newContext({
30+
storageState: authFile('admin'),
31+
})
32+
await use(context)
33+
await context.close()
34+
},
35+
adminPage: async ({ adminContext }, use) => {
36+
const page = await adminContext.newPage()
37+
await use(page)
38+
await page.close()
39+
},
40+
41+
agentContext: async ({ browser }, use) => {
42+
const context = await browser.newContext({
43+
storageState: authFile('agent'),
44+
})
45+
await use(context)
46+
await context.close()
47+
},
48+
agentPage: async ({ agentContext }, use) => {
49+
const page = await agentContext.newPage()
50+
await use(page)
51+
await page.close()
52+
},
53+
54+
agent2Context: async ({ browser }, use) => {
55+
const context = await browser.newContext({
56+
storageState: authFile('agent2'),
57+
})
58+
await use(context)
59+
await context.close()
60+
},
61+
agent2Page: async ({ agent2Context }, use) => {
62+
const page = await agent2Context.newPage()
63+
await use(page)
64+
await page.close()
65+
},
66+
67+
customerContext: async ({ browser }, use) => {
68+
const context = await browser.newContext({
69+
storageState: authFile('customer'),
70+
})
71+
await use(context)
72+
await context.close()
73+
},
74+
customerPage: async ({ customerContext }, use) => {
75+
const page = await customerContext.newPage()
76+
await use(page)
77+
await page.close()
78+
},
79+
})
80+
81+
export { expect } from '@playwright/test'

0 commit comments

Comments
 (0)