main
ts 64 lines 2.52 KB
Raw
1 import { Page, test } from '@playwright/test'
2 import fs from 'fs'
3 import { readFileSync } from 'node:fs'
4 import { resolve } from 'node:path'
5 import yaml from 'yaml'
6 import { ADMIN_URI } from '../src/cross-const'
7
8 export const username = 'rejetto'
9 export const password = 'password'
10 // keep e2e URL aligned with the same config file used by tests/test.ts and server-for-test
11 export const TEST_PORT = Number(yaml.parse(readFileSync(resolve(process.cwd(), 'tests/config.yaml'), 'utf8')).port)
12 export const FRONTEND_URL = `http://[::1]:${TEST_PORT}/`
13 export const ADMIN_URL = new URL(ADMIN_URI, FRONTEND_URL).href
14 export const uploadName = 'uploaded'
15
16 const t = Date.UTC(2025, 0, 20, 3, 0, 0, 0) / 1000 // a fixed timestamp, for visual comparison
17
18 test.beforeAll(clearUploads)
19
20 // dump page DOM on failure to help diagnose flaky tests
21 test.afterEach(async ({ page }, testInfo) => {
22 if (testInfo.status === 'failed')
23 await testInfo.attach('dom', { body: await page.content(), contentType: 'text/html' })
24 })
25
26 export function clearUploads() {
27 fs.unlink('tests/' + uploadName, () => {});
28 resetTimestamp()
29 }
30
31 export function resetTimestamp() {
32 fs.utimesSync('tests', t, t);
33 fs.utimesSync('tests/alfa.txt', t, t);
34 }
35
36 export function forwardConsole(page: Page) {
37 page.on('console', msg => console.log(msg.type(), msg.text()));
38 }
39
40 export async function clickAdminMenu(page: Page, sectionName: string | RegExp) {
41 const isPhone = (page as any).isPhone ??= await page.evaluate(() => window.matchMedia('(max-width: 600px)').matches)
42 if (isPhone) {
43 // On phones, admin navigation links are rendered inside a drawer that must be opened first.
44 await page.getByRole('button', { name: 'menu' }).nth(0).click()
45 }
46 await page.getByRole('link', { name: sectionName }).click()
47 // The admin page content updates asynchronously after route changes; this avoids transient flakiness across tests.
48 await page.waitForTimeout(100)
49 }
50
51 // only for admin-panel
52 export function clickIconBtn(title: string | RegExp, page: Page) {
53 return page.getByLabel(title).getByRole('button').click()
54 }
55
56 export async function loginAdmin(page: Page) {
57 await page.goto(ADMIN_URL)
58 await page.getByRole('textbox', { name: 'Username' }).fill(username)
59 await page.getByRole('textbox', { name: 'Password' }).fill(password)
60 await page.getByRole('textbox', { name: 'Password' }).press('Enter')
61 const isPhone = await page.evaluate(() => window.matchMedia("(max-width: 600px)").matches)
62 ;(page as any).isPhone = isPhone
63 return isPhone
64 }