From 77c248fa1e2a0e01722aab885f15d1f39d4ae97c Mon Sep 17 00:00:00 2001 From: David Rotermund Date: Mon, 26 May 2025 12:07:06 +0200 Subject: [PATCH] Cleaned the comments and used test.describe to nest the tests --- services/repository/files/pathutils.go | 1 - tests/e2e/repo-files.test.e2e.ts | 202 ++++++++++++------------- 2 files changed, 98 insertions(+), 105 deletions(-) diff --git a/services/repository/files/pathutils.go b/services/repository/files/pathutils.go index b327fbe694..ac095571f7 100644 --- a/services/repository/files/pathutils.go +++ b/services/repository/files/pathutils.go @@ -9,7 +9,6 @@ import ( "strings" ) -// var fileNameComponentSanitizeRegexp = regexp.MustCompile(`(?i)\.\.|[<>:\"/\\|?*\x{0000}-\x{001F}]|^(con|prn|aux|nul|com\d|lpt\d)$`) var fileNameComponentSanitizeRegexp = regexp.MustCompile(`(?i)[<>:\"/\\|?*\x{0000}-\x{001F}]|^(con|prn|aux|nul|com\d|lpt\d)$`) // SanitizePath cleans and validates a file path diff --git a/tests/e2e/repo-files.test.e2e.ts b/tests/e2e/repo-files.test.e2e.ts index c65b628e21..5254f5c114 100644 --- a/tests/e2e/repo-files.test.e2e.ts +++ b/tests/e2e/repo-files.test.e2e.ts @@ -8,138 +8,132 @@ // services/repository/files/upload.go // @watch end -// https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md -// lies. Don't use -// make TAGS="sqlite sqlite_unlock_notify" backend -// use -// make TAGS="sqlite sqlite_unlock_notify" build -// otherwise the test fails. - import {expect} from '@playwright/test'; import {test, dynamic_id, save_visual} from './utils_e2e.ts'; test.use({user: 'user2'}); +test.describe('Drag and Drop upload', () => { + test('normal and special characters', async ({page}) => { + const response = await page.goto(`/user2/file-uploads/_upload/main/`); + expect(response?.status()).toBe(200); // Status OK -test('drag and drop upload normal and special characters', async ({page}) => { - const response = await page.goto(`/user2/file-uploads/_upload/main/`); - expect(response?.status()).toBe(200); // Status OK + const testID = dynamic_id(); + const dropzone = page.getByRole('button', {name: 'Drop files or click here to upload.'}); - const testID = dynamic_id(); - const dropzone = page.getByRole('button', {name: 'Drop files or click here to upload.'}); + // create the virtual files + const dataTransferA = await page.evaluateHandle(() => { + const dt = new DataTransfer(); + // add items in different folders + dt.items.add(new File(['Filecontent (dir1/file1.txt)'], 'dir1/file1.txt', {type: 'text/plain'})); + dt.items.add(new File(["Another file's content(double / nested / file.txt)"], 'double / nested / file.txt', {type: 'text / plain'})); + dt.items.add(new File(['Root file (root_file.txt)'], 'root_file.txt', {type: 'text/plain'})); + dt.items.add(new File(['Umlaut test'], 'special/äüöÄÜÖß.txt', {type: 'text/plain'})); + dt.items.add(new File(['Unicode test'], 'special/Ʉ₦ł₵ØĐɆ.txt', {type: 'text/plain'})); + return dt; + }); + // and drop them to the upload area + await dropzone.dispatchEvent('drop', {dataTransfer: dataTransferA}); - // create the virtual files - const dataTransferA = await page.evaluateHandle(() => { - const dt = new DataTransfer(); - // add items in different folders - dt.items.add(new File(['Filecontent (dir1/file1.txt)'], 'dir1/file1.txt', {type: 'text/plain'})); - dt.items.add(new File(["Another file's content(double / nested / file.txt)"], 'double / nested / file.txt', {type: 'text / plain'})); - dt.items.add(new File(['Root file (root_file.txt)'], 'root_file.txt', {type: 'text/plain'})); - dt.items.add(new File(['Umlaut test'], 'special/äüöÄÜÖß.txt', {type: 'text/plain'})); - dt.items.add(new File(['Unicode test'], 'special/Ʉ₦ł₵ØĐɆ.txt', {type: 'text/plain'})); - return dt; + await page.getByText('new branch').click(); + + await page.getByRole('textbox', {name: 'Name the new branch for this'}).fill(testID); + await page.getByRole('button', {name: 'Propose file change'}).click(); + + // check that nested file structure is preserved + await expect(page.getByRole('link', {name: 'dir1/file1.txt'})).toBeVisible(); + await expect(page.getByRole('link', {name: 'double/nested/file.txt'})).toBeVisible(); + await expect(page.getByRole('link', {name: 'special/äüöÄÜÖß.txt'})).toBeVisible(); + await expect(page.getByRole('link', {name: 'special/Ʉ₦ł₵ØĐɆ.txt'})).toBeVisible(); + // Since this is a file in root, there two links with the same label + // we take the on in #diff-file-tree + await expect(page.locator('#diff-file-boxes').getByRole('link', {name: 'root_file.txt'})).toBeVisible(); }); - // and drop them to the upload area - await dropzone.dispatchEvent('drop', {dataTransfer: dataTransferA}); - await page.getByText('new branch').click(); + test('strange paths and spaces', async ({page}) => { + const response = await page.goto(`/user2/file-uploads/_upload/main/`); + expect(response?.status()).toBe(200); // Status OK - await page.getByRole('textbox', {name: 'Name the new branch for this'}).fill(testID); - await page.getByRole('button', {name: 'Propose file change'}).click(); + const testID = dynamic_id(); + const dropzone = page.getByRole('button', {name: 'Drop files or click here to upload.'}); - // check that nested file structure is preserved - await expect(page.getByRole('link', {name: 'dir1/file1.txt'})).toBeVisible(); - await expect(page.getByRole('link', {name: 'double/nested/file.txt'})).toBeVisible(); - await expect(page.getByRole('link', {name: 'special/äüöÄÜÖß.txt'})).toBeVisible(); - await expect(page.getByRole('link', {name: 'special/Ʉ₦ł₵ØĐɆ.txt'})).toBeVisible(); - // Since this is a file in root, there two links with the same label - // we take the on in #diff-file-tree - await expect(page.locator('#diff-file-boxes').getByRole('link', {name: 'root_file.txt'})).toBeVisible(); -}); + // create the virtual files + const dataTransferA = await page.evaluateHandle(() => { + const dt = new DataTransfer(); + // add items in different folders + dt.items.add(new File(['1'], '..dots.txt', {type: 'text/plain'})); + dt.items.add(new File(['2'], '.dots.vanish.txt', {type: 'text/plain'})); + dt.items.add(new File(['3'], 'special/S P A C E !.txt', {type: 'text/plain'})); + return dt; + }); + // and drop them to the upload area + await dropzone.dispatchEvent('drop', {dataTransfer: dataTransferA}); -test('drag and drop upload strange paths and spaces', async ({page}) => { - const response = await page.goto(`/user2/file-uploads/_upload/main/`); - expect(response?.status()).toBe(200); // Status OK + await page.getByText('new branch').click(); - const testID = dynamic_id(); - const dropzone = page.getByRole('button', {name: 'Drop files or click here to upload.'}); + await page.getByRole('textbox', {name: 'Name the new branch for this'}).fill(testID); + await page.getByRole('button', {name: 'Propose file change'}).click(); - // create the virtual files - const dataTransferA = await page.evaluateHandle(() => { - const dt = new DataTransfer(); - // add items in different folders - dt.items.add(new File(['1'], '..dots.txt', {type: 'text/plain'})); - dt.items.add(new File(['2'], '.dots.vanish.txt', {type: 'text/plain'})); - dt.items.add(new File(['3'], 'special/S P A C E !.txt', {type: 'text/plain'})); - return dt; + // check that nested file structure is preserved + // Since this is a file in root, there two links with the same label + // we take the on in #diff-file-tree + await expect(page.locator('#diff-file-boxes').getByRole('link', {name: '.dots.vanish.txt'})).toBeVisible(); + await expect(page.getByRole('link', {name: 'special/S P A C E !.txt'})).toBeVisible(); + // Since this is a file in root, there two links with the same label + // we take the on in #diff-file-tree + await expect(page.locator('#diff-file-boxes').getByRole('link', {name: '..dots.txt'})).toBeVisible(); }); - // and drop them to the upload area - await dropzone.dispatchEvent('drop', {dataTransfer: dataTransferA}); - await page.getByText('new branch').click(); + test('broken path slash in front', async ({page}) => { + const response = await page.goto(`/user2/file-uploads/_upload/main/`); + expect(response?.status()).toBe(200); // Status OK - await page.getByRole('textbox', {name: 'Name the new branch for this'}).fill(testID); - await page.getByRole('button', {name: 'Propose file change'}).click(); + const testID = dynamic_id(); + const dropzone = page.getByRole('button', {name: 'Drop files or click here to upload.'}); - // check that nested file structure is preserved - // Since this is a file in root, there two links with the same label - // we take the on in #diff-file-tree - await expect(page.locator('#diff-file-boxes').getByRole('link', {name: '.dots.vanish.txt'})).toBeVisible(); - await expect(page.getByRole('link', {name: 'special/S P A C E !.txt'})).toBeVisible(); - // Since this is a file in root, there two links with the same label - // we take the on in #diff-file-tree - await expect(page.locator('#diff-file-boxes').getByRole('link', {name: '..dots.txt'})).toBeVisible(); -}); + // create the virtual files + const dataTransferA = await page.evaluateHandle(() => { + const dt = new DataTransfer(); + // add items in different folders + dt.items.add(new File(['1'], '/special/badfirstslash.txt', {type: 'text/plain'})); + return dt; + }); + // and drop them to the upload area + await dropzone.dispatchEvent('drop', {dataTransfer: dataTransferA}); -test('drag and drop upload broken path slash in front', async ({page}) => { - const response = await page.goto(`/user2/file-uploads/_upload/main/`); - expect(response?.status()).toBe(200); // Status OK + await page.getByText('new branch').click(); - const testID = dynamic_id(); - const dropzone = page.getByRole('button', {name: 'Drop files or click here to upload.'}); + await page.getByRole('textbox', {name: 'Name the new branch for this'}).fill(testID); + await page.getByRole('button', {name: 'Propose file change'}).click(); - // create the virtual files - const dataTransferA = await page.evaluateHandle(() => { - const dt = new DataTransfer(); - // add items in different folders - dt.items.add(new File(['1'], '/special/badfirstslash.txt', {type: 'text/plain'})); - return dt; + await expect(page.getByText('Failed to upload files to')).toBeVisible(); + + await save_visual(page); }); - // and drop them to the upload area - await dropzone.dispatchEvent('drop', {dataTransfer: dataTransferA}); - await page.getByText('new branch').click(); + test('broken path with traversal', async ({page}) => { + const response = await page.goto(`/user2/file-uploads/_upload/main/`); + expect(response?.status()).toBe(200); // Status OK - await page.getByRole('textbox', {name: 'Name the new branch for this'}).fill(testID); - await page.getByRole('button', {name: 'Propose file change'}).click(); + const testID = dynamic_id(); + const dropzone = page.getByRole('button', {name: 'Drop files or click here to upload.'}); - await expect(page.getByText('Failed to upload files to')).toBeVisible(); + // create the virtual files + const dataTransferA = await page.evaluateHandle(() => { + const dt = new DataTransfer(); + // add items in different folders + dt.items.add(new File(['1'], '../baddots.txt', {type: 'text/plain'})); + return dt; + }); + // and drop them to the upload area + await dropzone.dispatchEvent('drop', {dataTransfer: dataTransferA}); - await save_visual(page); -}); + await page.getByText('new branch').click(); -test('drag and drop upload broken path with traversal', async ({page}) => { - const response = await page.goto(`/user2/file-uploads/_upload/main/`); - expect(response?.status()).toBe(200); // Status OK + await page.getByRole('textbox', {name: 'Name the new branch for this'}).fill(testID); + await page.getByRole('button', {name: 'Propose file change'}).click(); - const testID = dynamic_id(); - const dropzone = page.getByRole('button', {name: 'Drop files or click here to upload.'}); + await expect(page.getByText('Failed to upload files to')).toBeVisible(); - // create the virtual files - const dataTransferA = await page.evaluateHandle(() => { - const dt = new DataTransfer(); - // add items in different folders - dt.items.add(new File(['1'], '../baddots.txt', {type: 'text/plain'})); - return dt; + await save_visual(page); }); - // and drop them to the upload area - await dropzone.dispatchEvent('drop', {dataTransfer: dataTransferA}); - - await page.getByText('new branch').click(); - - await page.getByRole('textbox', {name: 'Name the new branch for this'}).fill(testID); - await page.getByRole('button', {name: 'Propose file change'}).click(); - - await expect(page.getByText('Failed to upload files to')).toBeVisible(); - - await save_visual(page); });