@samitouri / QOSami-HFS / commits / 69ddf06b

better code: centralized

Massimo Melina committed Apr 21, 2026 at 11:18 UTC 69ddf06bd2b4cfc55b29af82d7d5b495db37ee54
4 files changed +20 -18
e2e/admin-vfs.spec.ts
+8 -8
@@ -1,5 +1,5 @@
1 import { expect, Page, test } from '@playwright/test'
2 -import { clickAdminMenu, URL, username, password, clickIconBtn } from './common'
2 +import { ADMIN_URL, clickAdminMenu, username, password, clickIconBtn } from './common'
3
4 async function selectVfsNode(page: Page, name: string, expectedId: string) {
5 await page.getByRole('treeitem', { name, exact: true }).click()
@@ -23,7 +23,7 @@ async function expandVfsNode(page: Page, nodeId: string) {
23 }
24
25 test('move via cut/paste keeps node visible', async ({ page }) => {
26 - await page.goto(URL + '~/admin/')
26 + await page.goto(ADMIN_URL)
27 await page.getByRole('textbox', { name: 'Username' }).fill(username)
28 await page.getByRole('textbox', { name: 'Password' }).fill(password)
29 await page.getByRole('textbox', { name: 'Password' }).press('Enter')
@@ -61,7 +61,7 @@ test('move via cut/paste keeps node visible', async ({ page }) => {
61 })
62
63 test('move to nested destination expands ancestors', async ({ page }) => {
64 - await page.goto(URL + '~/admin/')
64 + await page.goto(ADMIN_URL)
65 await page.getByRole('textbox', { name: 'Username' }).fill(username)
66 await page.getByRole('textbox', { name: 'Password' }).fill(password)
67 await page.getByRole('textbox', { name: 'Password' }).press('Enter')
@@ -103,7 +103,7 @@ test('move to nested destination expands ancestors', async ({ page }) => {
103 })
104
105 test('move into empty folder keeps node visible', async ({ page }) => {
106 - await page.goto(URL + '~/admin/')
106 + await page.goto(ADMIN_URL)
107 await page.getByRole('textbox', { name: 'Username' }).fill(username)
108 await page.getByRole('textbox', { name: 'Password' }).fill(password)
109 await page.getByRole('textbox', { name: 'Password' }).press('Enter')
@@ -141,7 +141,7 @@ test('move into empty folder keeps node visible', async ({ page }) => {
141 })
142
143 test('delete virtual folder updates tree and marks modified', async ({ page }) => {
144 - await page.goto(URL + '~/admin/')
144 + await page.goto(ADMIN_URL)
145 await page.getByRole('textbox', { name: 'Username' }).fill(username)
146 await page.getByRole('textbox', { name: 'Password' }).fill(password)
147 await page.getByRole('textbox', { name: 'Password' }).press('Enter')
@@ -165,7 +165,7 @@ test('delete virtual folder updates tree and marks modified', async ({ page }) =
165 })
166
167 test('undo toggles with single-level redo behavior', async ({ page }) => {
168 - await page.goto(URL + '~/admin/')
168 + await page.goto(ADMIN_URL)
169 await page.getByRole('textbox', { name: 'Username' }).fill(username)
170 await page.getByRole('textbox', { name: 'Password' }).fill(password)
171 await page.getByRole('textbox', { name: 'Password' }).press('Enter')
@@ -217,7 +217,7 @@ test('undo toggles with single-level redo behavior', async ({ page }) => {
217 })
218
219 test('apply keeps unset permissions nullish in-memory', async ({ page }) => {
220 - await page.goto(URL + '~/admin/')
220 + await page.goto(ADMIN_URL)
221 await page.getByRole('textbox', { name: 'Username' }).fill(username)
222 await page.getByRole('textbox', { name: 'Password' }).fill(password)
223 await page.getByRole('textbox', { name: 'Password' }).press('Enter')
@@ -248,7 +248,7 @@ test('apply keeps unset permissions nullish in-memory', async ({ page }) => {
248 })
249
250 test('apply refreshes inherited permissions for descendants in-memory', async ({ page }) => {
251 - await page.goto(URL + '~/admin/')
251 + await page.goto(ADMIN_URL)
252 await page.getByRole('textbox', { name: 'Username' }).fill(username)
253 await page.getByRole('textbox', { name: 'Password' }).fill(password)
254 await page.getByRole('textbox', { name: 'Password' }).press('Enter')
e2e/common.ts
+4 -2
@@ -3,12 +3,14 @@ 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 const TEST_PORT = Number(yaml.parse(readFileSync(resolve(process.cwd(), 'tests/config.yaml'), 'utf8')).port)
11 -export const URL = `http://[::1]:${TEST_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
@@ -52,7 +54,7 @@ export function clickIconBtn(title: string | RegExp, page: Page) {
54 }
55
56 export async function loginAdmin(page: Page) {
55 - await page.goto(URL + '~/admin/')
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')
e2e/frontend.spec.ts
+5 -5
@@ -2,14 +2,14 @@ import { test, expect, Page } from '@playwright/test'
2 import fs from 'fs'
3 import { wait } from '../src/cross'
4 import {
5 - clickAdminMenu, clickIconBtn, forwardConsole, loginAdmin, password, resetTimestamp, URL, username
5 + clickAdminMenu, clickIconBtn, forwardConsole, loginAdmin, password, resetTimestamp, FRONTEND_URL, username
6 } from './common'
7
8 // a generic test touch several parts
9 test('around1', async ({ page }) => {
10 forwardConsole(page)
11 resetTimestamp()
12 - await page.goto(URL)
12 + await page.goto(FRONTEND_URL)
13 await expect(page).toHaveTitle(/File server/)
14 await screenshot(page)
15 await page.getByRole('button', { name: 'Login' }).click()
@@ -119,7 +119,7 @@ test('around1', async ({ page }) => {
119
120 test('search1', async ({ page }) => {
121 resetTimestamp()
122 - await page.goto(URL)
122 + await page.goto(FRONTEND_URL)
123 await page.getByRole('button', { name: 'Search' }).click()
124 await page.locator('input[name="name"]').fill('a')
125 await page.getByRole('button', { name: 'Continue' }).click()
@@ -175,7 +175,7 @@ test('search1', async ({ page }) => {
175 })
176
177 test('frontend-admin', async ({ page }) => {
178 - await page.goto(URL, { waitUntil: 'networkidle' })
178 + await page.goto(FRONTEND_URL, { waitUntil: 'networkidle' })
179 await page.evaluate(() => document.fonts.ready) // aspetta i font
180 await page.getByRole('button', { name: 'Options' }).click()
181 // no admin button yet,
@@ -336,7 +336,7 @@ test('anew', async ({ page, browserName }) => {
336 })
337
338 test('order field', async ({ page }) => {
339 - await page.goto(URL + 'renameChild/orderTest/')
339 + await page.goto(FRONTEND_URL + 'renameChild/orderTest/')
340 await expect(page.getByText('orderTest')).toBeVisible()
341 await expect(page.locator('.entry-name')).toHaveText(['B', 'A', 'C'])
342 })
e2e/serial.spec.ts
+3 -3
@@ -1,5 +1,5 @@
1 import { expect, test } from '@playwright/test'
2 -import { clearUploads, clickAdminMenu, clickIconBtn, loginAdmin, password, uploadName, URL, username } from './common'
2 +import { ADMIN_URL, clearUploads, clickAdminMenu, clickIconBtn, loginAdmin, password, uploadName, FRONTEND_URL, username } from './common'
3
4 // this test is separated to run serially, as it will modify folder timestamp for a few seconds, during which other tests may fail
5 test.describe.configure({ mode: 'serial' }) // to disconnect the upload consistently, i need only 1 upload at a time
@@ -12,7 +12,7 @@ export const fileToUpload = {
12
13 test('upload1', async ({ page, context, browserName }) => {
14 if (browserName !== 'chromium') return // only chromium has cdpSession
15 - await page.goto(URL);
15 + await page.goto(FRONTEND_URL);
16 await page.getByRole('button', { name: 'Login' }).click();
17 await page.getByRole('textbox', { name: 'Username' }).fill(username);
18 await page.getByRole('textbox', { name: 'Password' }).fill(password);
@@ -26,7 +26,7 @@ test('upload1', async ({ page, context, browserName }) => {
26 const pageAdminPromise = page.waitForEvent('popup');
27 await page.getByRole('button', { name: 'Admin-panel' }).click();
28 const pageAdmin = await pageAdminPromise;
29 - await pageAdmin.goto(URL + '~/admin/#/monitoring'); // cross-device way of changing page
29 + await pageAdmin.goto(ADMIN_URL + '#/monitoring'); // cross-device way of changing page
30 await page.locator('div').filter({ hasText: 'xOptionsAdmin-panelSort by:' }).nth(2).click();
31 await page.getByRole('button', { name: 'Close' }).click();
32 await page.getByRole('button', { name: 'Upload' }).click();