test: avoid false positives because of changing files

Massimo Melina committed Apr 16, 2025 at 19:57 UTC 31f74c53e962fefe1e1a3a70064be73626bf6e27
7 files changed +56 -25
e2e/frontend.spec.ts
+6 -21
@@ -6,7 +6,6 @@ const password = 'password'
6
7 const t = Date.UTC(2025, 0, 20, 3, 0, 0, 0) / 1000 // a fixed timestamp, for visual comparison
8 fs.utimesSync('tests', t, t)
9 -fs.utimesSync('tests/config.yaml', t, t)
9
10 // a generic test touch several parts
11 test('around1', async ({ page }) => {
@@ -46,12 +45,12 @@ test('around1', async ({ page }) => {
45 - link "Open"
46 `);
47 await page.getByRole('link', { name: 'Download' }).click(); // this also closes the dialog
49 - await page.getByRole('link', { name: 'config.yaml', exact: true }).click();
48 + await page.getByRole('link', { name: 'alfa.txt', exact: true }).click();
49 await screenshot(page);
50 await page.getByRole('button', { name: 'Close' }).click();
51 await page.getByRole('link', { name: 'cantListPage' }).click();
52 await page.getByRole('button', { name: 'Calculate' }).click();
54 - await page.getByText('KB / 4 files').click();
53 + await page.getByText('KB / 2 files').click();
54 await page.locator('#menu-prop-name').getByText('cantListPage').click();
55 await page.getByRole('link', { name: 'Download' }).click();
56 await page.getByRole('link', { name: 'home' }).click();
@@ -95,7 +94,7 @@ test('search1', async ({ page }) => {
94 await page.getByRole('button', { name: 'Search' }).click();
95 await page.locator('input[name="name"]').fill('a');
96 await page.getByRole('button', { name: 'Continue' }).click();
98 - await page.getByText('files, 12 folders, 40.9 KB').click();
97 + await page.getByText('files, 12 folders, 23 KB').click();
98 await page.getByRole('link', { name: 'cantListPage/ alfa.txt' }).click();
99 await page.getByRole('button', { name: 'Close' }).click();
100 await page.getByRole('button', { name: 'Clear search' }).click();
@@ -123,24 +122,9 @@ test('search1', async ({ page }) => {
122 await page.locator('#option-theme').selectOption('dark');
123 await page.getByRole('button', { name: 'Close' }).click();
124 await page.getByRole('link', { name: 'cantListPageAlt, Folder' }).click();
126 - await page.getByText('files, 29 KB').click();
125 + await expect(page.getByText('alfa.txt')).toBeVisible() // be sure the folder is loaded
126 await page.mouse.click(1, 1); // avoid focus inconsistencies
127 await screenshot(page);
129 - await expect(page.getByRole('list')).toMatchAriaSnapshot(`
130 - - list:
131 - - listitem:
132 - - link "test.ts"
133 - - text: /\\d+\\.\\d+ KB/
134 - - listitem:
135 - - link "config.yaml.bak"
136 - - text: 5.1 KB
137 - - listitem:
138 - - link "config.yaml"
139 - - text: 5.1 KB
140 - - listitem:
141 - - link "alfa.txt"
142 - - text: 6 B
143 - `);
128
129 await page.getByRole('button', { name: 'Zip' }).click();
130 await expect(page.getByRole('dialog')).toMatchAriaSnapshot(`
@@ -153,7 +137,7 @@ test('search1', async ({ page }) => {
137 - button "Don't"
138 - button "Select some files"
139 `);
156 - await page.getByRole('button', { name: 'Don\'t' }).click();
140 + await page.getByRole('button', { name: "Don't" }).click();
141 await page.getByRole('button', { name: 'Zip' }).click();
142 await page.getByRole('button', { name: 'Select some files' }).click();
143 await page.getByText('Use checkboxes to select the').click();
@@ -250,6 +234,7 @@ test('admin1', async ({ page }) => {
234 await page.getByRole('tab', { name: 'Search' }).click();
235 await page.getByRole('tab', { name: 'updates' }).click();
236 await clickMenu('Custom HTML');
237 + await expect(page.getByRole('combobox', { name: 'Section Style' })).toBeVisible(); // wait for data to be loaded
238 await screenshot(page);
239 await page.getByRole('main').click();
240 await clickMenu('Logout');
frontend/src/fileMenu.ts
+2 -2
@@ -1,6 +1,6 @@
1 import {
2 dontBotherWithKeys, formatBytes, getHFS, hfsEvent, hIcon, newDialog, prefix, with_, working,
3 - pathEncode, closeDialog, anyDialogOpen, Falsy, operationSuccessful, randomId, err2msg
3 + pathEncode, closeDialog, anyDialogOpen, Falsy, operationSuccessful, randomId, err2msg, HIDE_IN_TESTS
4 } from './misc'
5 import { createElement as h, Fragment, isValidElement, MouseEvent, ReactNode, useState } from 'react'
6 import { Btn, Bytes, Spinner } from './components'
@@ -75,7 +75,7 @@ export async function openFileMenu(entry: DirEntry, ev: MouseEvent, addToMenu: (
75 const props = [
76 { id: 'name', label: t`Name`, value: entry.name },
77 typeof s === 'number' && { id: 'size', label: t`Size`,
78 - value: h(Fragment, {}, formatBytes(s), h('small', {}, prefix(' (', s > getHFS().kb && s.toLocaleString(), ')')) ) },
78 + value: h(Fragment, {}, formatBytes(s), h('small', { className: HIDE_IN_TESTS }, prefix(' (', s > getHFS().kb && s.toLocaleString(), ')')) ) },
79 entry.m && { id: 'timestamp', label: t`Timestamp`, value: entry.m.toLocaleString() },
80 entry.c && { id: 'creation', label: t`Creation`, value: entry.c.toLocaleString() },
81 folder && {
src/cross-const.ts
+1
@@ -13,6 +13,7 @@ export const UPLOAD_RESUMABLE_HASH = 'upload.hash'
13 export const UPLOAD_REQUEST_STATUS = 'upload.status'
14 export const PREVIOUS_TAG = 'previous'
15 export const ALLOW_SESSION_IP_CHANGE = 'allow_session_ip_change'
16 +export const HIDE_IN_TESTS = 'hideInTests'
17
18 export const HTTP_OK = 200
19 export const HTTP_NO_CONTENT = 204
src/listen.ts
+1 -1
@@ -11,7 +11,7 @@ import open from 'open'
11 import {
12 CFG, debounceAsync, ipForUrl, makeNetMatcher, MINUTE, objSameKeys, onlyTruthy, prefix, runAt, wait, xlate
13 } from './misc'
14 -import { PORT_DISABLED, ADMIN_URI, DEV, IS_WINDOWS } from './const'
14 +import { PORT_DISABLED, ADMIN_URI, IS_WINDOWS } from './const'
15 import findProcess from 'find-process'
16 import { anyAccountCanLoginAdmin } from './adminApis'
17 import _ from 'lodash'
tests/beta.svg new
+43
@@ -0,0 +1,43 @@
1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?><!-- Generator: Gravit.io -->
2 +<svg xmlns="http://www.w3.org/2000/svg"
3 + xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="0 0 512 512" width="512pt" height="512pt">
4 + <defs>
5 + <clipPath id="_clipPath_rgwhRu7KShARwLS20t2iyAGct3fRx9sb">
6 + <rect width="512" height="512"/>
7 + </clipPath>
8 + </defs>
9 + <g clip-path="url(#_clipPath_rgwhRu7KShARwLS20t2iyAGct3fRx9sb)">
10 + <g>
11 + <path d=" M 351.693 234.532 L 163.155 234.532 C 147.879 234.511 135.475 245.132 135.45 258.255 C 135.448 259.323 135.53 260.39 135.695 261.448 C 136.088 264.057 138.869 265.898 141.906 265.56 C 142.646 265.478 143.359 265.269 144.002 264.944 C 146.448 263.721 149.234 263.089 152.065 263.115 L 191.547 263.115 C 198.672 263.132 205.003 267.025 207.318 272.814 L 208.26 275.424 C 212.076 285.128 222.656 291.67 234.578 291.697 L 362.784 291.697 C 365.692 291.699 368.548 292.356 371.068 293.603 C 371.92 294.029 372.888 294.253 373.874 294.251 C 376.936 294.251 379.419 292.118 379.419 289.487 L 379.419 258.351 C 379.419 245.196 367.006 234.532 351.693 234.532 L 351.693 234.532 Z " fill="rgb(255,160,0)"/>
12 + <path d=" M 376.68 285.39 C 372.461 283.278 367.666 282.167 362.783 282.17 L 234.577 282.17 C 227.452 282.153 221.122 278.26 218.807 272.471 L 217.864 269.86 C 214.048 260.157 203.468 253.615 191.546 253.587 L 152.064 253.587 C 147.3 253.548 142.611 254.611 138.489 256.665 C 129.749 260.867 124.335 268.801 124.338 277.406 L 124.338 391.738 C 124.338 404.892 136.751 415.556 152.064 415.556 L 362.783 415.556 C 378.096 415.556 390.509 404.892 390.509 391.738 L 390.509 305.989 C 390.543 297.487 385.264 289.623 376.68 285.39 L 376.68 285.39 Z " fill="rgb(255,193,7)"/>
13 + </g>
14 + <g>
15 + <g>
16 + <path d=" M 440.195 128.939 L 441.681 127.373 C 450.505 118.072 450.119 103.381 440.819 94.557 C 431.52 85.733 416.829 86.119 408.005 95.418 L 406.519 96.984 L 417.29 119.355 L 440.195 128.939 Z " fill="rgb(241,205,101)"/>
17 + </g>
18 + <g>
19 + <path d=" M 406.518 96.985 L 391.824 112.471 L 402.359 135.091 L 425.502 144.424 L 440.195 128.939 C 435.188 123.124 429.855 117.5 424.169 112.105 C 418.484 106.709 412.587 101.679 406.518 96.985 L 406.518 96.985 Z " fill="rgb(235,179,79)"/>
20 + </g>
21 + <g>
22 + <path d=" M 454.721 398.439 C 500.67 310.461 485.053 199.301 409.476 127.59 C 333.899 55.879 222.072 46.116 136.626 96.616 L 288.556 255.029 L 454.721 398.439 Z " fill="rgb(230,230,230)"/>
23 + </g>
24 + <g>
25 + <path d=" M 136.626 96.616 C 130.372 100.313 124.253 104.321 118.307 108.662 L 443.653 417.365 C 447.676 411.199 451.357 404.879 454.721 398.439 L 136.626 96.616 Z " fill="rgb(179,179,179)"/>
26 + </g>
27 + </g>
28 + <g>
29 + <g>
30 + <path d=" M 15.729 425.455 C 15.729 436.59 24.881 445.774 31.63 445.774 L 457.861 445.774 C 464.61 445.774 473.762 437.301 473.762 425.455 C 470.502 419.481 464.61 415.476 457.861 415.476 L 31.63 415.476 C 24.881 415.475 18.988 419.481 15.729 425.455 Z " fill="rgb(230,230,230)"/>
31 + </g>
32 + <g>
33 + <path d=" M 457.861 435.434 L 31.63 435.434 C 24.88 435.434 18.988 431.428 15.729 425.455 C 14.028 428.573 13.031 432.217 13.031 436.128 C 13.031 447.534 21.358 456.781 31.631 456.781 L 457.862 456.781 C 468.134 456.781 476.461 447.534 476.461 436.128 C 476.461 432.216 475.464 428.572 473.763 425.455 C 470.502 431.428 464.61 435.434 457.861 435.434 Z " fill="rgb(204,204,204)"/>
34 + </g>
35 + </g>
36 + <g>
37 + <path d=" M 142.529 185.294 C 139.684 168.647 129.054 161.558 122.975 155.597 C 102.021 135.049 97.817 128.964 93.269 112.592 C 88.093 93.964 89.813 76.757 97.586 69.408 C 102.609 64.658 104.366 65.258 99.779 70.157 C 90.572 79.992 91.516 93.396 102.698 111.584 C 109.782 123.107 111.496 125.579 120.2 136.843 C 135.485 153.38 147.887 169.586 145.473 187.536 L 144.295 195.615 L 142.529 185.294 Z " fill="rgb(230,230,230)"/>
38 + </g>
39 + <g>
40 + <path d=" M 125.367 215.618 C 122.522 198.971 111.892 191.882 105.813 185.92 C 84.859 165.373 80.655 159.287 76.107 142.916 C 70.931 124.288 72.651 107.081 80.423 99.731 C 85.447 94.982 87.203 95.581 82.617 100.481 C 73.409 110.316 74.354 123.72 85.536 141.907 C 92.62 153.431 94.334 155.903 103.038 167.167 C 118.323 183.703 130.724 199.909 128.311 217.86 L 127.132 225.938 L 125.367 215.618 Z " fill="rgb(230,230,230)"/>
41 + </g>
42 + </g>
43 +</svg>
\ No newline at end of file
tests/config.yaml
+2
@@ -4,6 +4,8 @@ allowed_referer: x.com
4 localhost_admin: false
5 vfs:
6 masks:
7 + "**/config.yaml*|test.ts":
8 + can_see: false
9 tests/page/!*.png:
10 mime: text/plain
11 protectFromAbove/child/*.txt:
tests/test.ts
+1 -1
@@ -120,7 +120,7 @@ describe('basics', () => {
120 it('zip.partial.resume', req('/f1/?get=zip', { re:/^C3/, length:zipSize-zipOfs }, { headers: { Range: `bytes=${zipOfs}-` } }) )
121 it('zip.partial.end', req('/f1/f2/?get=zip', { re:/^6/, length:10 }, { headers: { Range: 'bytes=-10' } }) )
122 it('zip.alfa is forbidden', req('/protectFromAbove/child/?get=zip&list=alfa.txt//renamed', { empty: true, length:118 }, { method:'HEAD' }))
123 - it('zip.cantReadPage', req('/cantReadPage/?get=zip', { length: 120 }, { method:'HEAD' }))
123 + it('zip.cantReadPage', req('/cantReadPage/?get=zip', { length: 4800 }, { method:'HEAD' }))
124
125 it('referer', req('/f1/page/gpl.png', 403, {
126 headers: { Referer: 'https://some-website.com/try-to-trick/x.com/' }