summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorOtto <otto@codeberg.org>2024-12-29 14:22:48 +0100
committerOtto <otto@codeberg.org>2024-12-29 14:22:48 +0100
commit6d61ae5cbe3209a25428ff959806569e2e7c0897 (patch)
treebea83e7a47d5df72e5db5d94b4f8cfb753f2a38e /tests
parentMerge pull request 'feat: When comparing in repos, mention that pull request ... (diff)
parenttests(e2e): Test new repo dialog and behaviour (diff)
downloadforgejo-6d61ae5cbe3209a25428ff959806569e2e7c0897.tar.xz
forgejo-6d61ae5cbe3209a25428ff959806569e2e7c0897.zip
Merge pull request 'Rework new repo dialog' (#6386) from fnetx/new-repo-form into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6386 Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/e2e/repo-new.test.e2e.ts134
-rw-r--r--tests/e2e/shared/forms.ts3
-rw-r--r--tests/e2e/utils_e2e.ts15
-rw-r--r--tests/integration/repo_generate_test.go2
4 files changed, 153 insertions, 1 deletions
diff --git a/tests/e2e/repo-new.test.e2e.ts b/tests/e2e/repo-new.test.e2e.ts
new file mode 100644
index 0000000000..c9cc29ad56
--- /dev/null
+++ b/tests/e2e/repo-new.test.e2e.ts
@@ -0,0 +1,134 @@
+// @watch start
+// templates/repo/create**.tmpl
+// web_src/css/{form,repo}.css
+// @watch end
+
+import {expect} from '@playwright/test';
+import {test, dynamic_id, save_visual, login_user, login} from './utils_e2e.ts';
+import {validate_form} from './shared/forms.ts';
+
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
+
+test('New repo: invalid', async ({browser}, workerInfo) => {
+ const page = await login({browser}, workerInfo);
+ const response = await page.goto('/repo/create');
+ expect(response?.status()).toBe(200);
+ // check that relevant form content is hidden or available
+ await expect(page.getByRole('group', {name: 'Use a template You can select'}).getByRole('combobox')).toBeVisible();
+ await expect(page.getByText('.gitignore Select .gitignore')).toBeHidden();
+ await expect(page.getByText('Labels Select a label set')).toBeHidden();
+ await validate_form({page}, 'fieldset');
+ await save_visual(page);
+
+ await page.getByLabel('Repository name').fill('*invalid');
+ await page.getByRole('button', {name: 'Create repository'}).click();
+ await expect(page.getByText('Repository name should contain only alphanumeric')).toBeVisible();
+ await save_visual(page);
+});
+
+test('New repo: initialize', async ({browser}, workerInfo) => {
+ const page = await login({browser}, workerInfo);
+ const response = await page.goto('/repo/create');
+ expect(response?.status()).toBe(200);
+ // check that relevant form content is hidden or available
+ await expect(page.getByRole('group', {name: 'Use a template You can select'}).getByRole('combobox')).toBeVisible();
+ await expect(page.getByText('.gitignore Select .gitignore')).toBeHidden();
+ // fill initialization section
+ await page.getByText('Start the Git history with').click();
+ await page.getByText('Select .gitignore templates').click();
+ await page.getByLabel('.gitignore Select .gitignore').fill('Go');
+ await page.getByRole('option', {name: 'Go', exact: true}).click();
+ await page.keyboard.press('Escape');
+ await page.getByLabel('License Select a license file').click();
+ await page.getByRole('option', {name: 'MIT', exact: true}).click();
+ await page.keyboard.press('Escape');
+ // add advanced settings
+ await page.getByText('Click to expand').click();
+ await page.getByPlaceholder('master').fill('main');
+ await page.getByLabel('Make repository a template').check();
+
+ await validate_form({page}, 'fieldset');
+ await save_visual(page);
+ const reponame = dynamic_id();
+ await page.getByLabel('Repository name').fill(reponame);
+ await page.getByRole('button', {name: 'Create repository'}).click();
+ await expect(page.getByRole('link', {name: '.gitignore'})).toBeVisible();
+ await expect(page.getByRole('link', {name: 'LICENSE', exact: true})).toBeVisible();
+ if (!workerInfo.project.name.includes('Mobile')) {
+ await expect(page.getByText('Template', {exact: true})).toBeVisible();
+ }
+ await save_visual(page);
+});
+
+test('New repo: initialize later', async ({browser}, workerInfo) => {
+ const page = await login({browser}, workerInfo);
+ const response = await page.goto('/repo/create');
+ expect(response?.status()).toBe(200);
+
+ const reponame = dynamic_id();
+ await page.getByLabel('Repository name').fill(reponame);
+ await page.getByPlaceholder('Enter short description').fill(`Description for repo ${reponame}`);
+ await page.getByText('Click to expand').click();
+ await page.getByPlaceholder('master').fill('devbranch');
+ await validate_form({page}, 'fieldset');
+ await page.getByRole('button', {name: 'Create repository'}).click();
+ expect(page.url()).toBe(`http://localhost:3003/user2/${reponame}`);
+ await expect(page.getByRole('link', {name: 'New file'})).toBeVisible();
+ await expect(page.getByRole('heading', {name: 'Creating a new repository on'})).toBeVisible();
+ await save_visual(page);
+
+ // add a README
+ await page.getByRole('link', {name: 'New file'}).click();
+ // wait for loading spinner to disappear
+ // Otherwise, filling the filename might not populate the tree_path form field or preview tab
+ // The editor has race conditions, likely related to https://codeberg.org/forgejo/forgejo/issues/3371
+ await expect(page.locator('.is-loading')).toBeHidden();
+ await page.locator('.view-lines').click();
+ await page.keyboard.type('# Heading\n\nHello Forgejo!');
+ await page.getByPlaceholder('Name your fileā€¦').fill('README.md');
+ await expect(page.getByText('Preview')).toBeVisible();
+ await page.getByPlaceholder('Add "<filename>"').fill('My first commit message');
+ await page.getByRole('button', {name: 'Commit changes'}).click();
+ expect(page.url()).toBe(`http://localhost:3003/user2/${reponame}/src/branch/devbranch/README.md`);
+ await expect(page.getByRole('link', {name: 'My first commit message'})).toBeVisible();
+ await expect(page.getByText('Hello Forgejo!')).toBeVisible();
+ await save_visual(page);
+});
+
+test('New repo: from template', async ({browser}, workerInfo) => {
+ test.skip(['Mobile Safari', 'webkit'].includes(workerInfo.project.name), 'WebKit browsers seem to have CORS issues with localhost here.');
+ const page = await login({browser}, workerInfo);
+ const response = await page.goto('/repo/create');
+ expect(response?.status()).toBe(200);
+
+ const reponame = dynamic_id();
+ await page.getByRole('group', {name: 'Use a template You can select'}).getByRole('combobox').click();
+ await page.getByRole('option', {name: 'user27/template1'}).click();
+ await page.getByText('Git content (Default branch)').click();
+ await save_visual(page);
+ await page.getByLabel('Repository name').fill(reponame);
+ await page.getByRole('button', {name: 'Create repository'}).click();
+ await expect(page.getByRole('link', {name: `${reponame}.log`})).toBeVisible();
+ await save_visual(page);
+});
+
+test('New repo: label set', async ({browser}, workerInfo) => {
+ const page = await login({browser}, workerInfo);
+ await page.goto('/repo/create');
+
+ const reponame = dynamic_id();
+ await page.getByText('Click to expand').click();
+ await page.getByLabel('Labels Select a label set').click();
+ await page.getByRole('option', {name: 'Advanced (Kind/Bug, Kind/'}).click();
+ // close dropdown via unrelated click
+ await page.getByText('You can select an existing').click();
+ await save_visual(page);
+ await page.getByLabel('Repository name').fill(reponame);
+ await page.getByRole('button', {name: 'Create repository'}).click();
+ await page.goto(`/user2/${reponame}/issues`);
+ await page.getByRole('link', {name: 'Labels'}).click();
+ await expect(page.getByText('Kind/Bug Something is not')).toBeVisible();
+ await save_visual(page);
+});
diff --git a/tests/e2e/shared/forms.ts b/tests/e2e/shared/forms.ts
index 99ad5a0a6d..fc608489b0 100644
--- a/tests/e2e/shared/forms.ts
+++ b/tests/e2e/shared/forms.ts
@@ -7,6 +7,9 @@ export async function validate_form({page}: {page: Page}, scope: 'form' | 'field
'span[data-tooltip-content',
// exclude weird non-semantic HTML disabled content
'.disabled',
+ // legacy dropdowns don't use semantic HTML yet,
+ // avoid using these where possible
+ '.ui.dropdown',
];
await accessibilityCheck({page}, [scope], excludedElements, []);
diff --git a/tests/e2e/utils_e2e.ts b/tests/e2e/utils_e2e.ts
index 09189e6826..31fc999fb0 100644
--- a/tests/e2e/utils_e2e.ts
+++ b/tests/e2e/utils_e2e.ts
@@ -81,6 +81,14 @@ export async function save_visual(page: Page) {
await page.locator('.flex-item-body > relative-time').filter({hasText: /now|minute/}).evaluateAll((nodes) => {
for (const node of nodes) node.outerHTML = 'relative time in repo';
});
+ // dynamically generated UUIDs
+ await page.getByText('dyn-id-').evaluateAll((nodes) => {
+ for (const node of nodes) node.innerHTML = node.innerHTML.replaceAll(/dyn-id-[a-f0-9-]+/g, 'dynamic-id');
+ });
+ // repeat above, work around https://github.com/microsoft/playwright/issues/34152
+ await page.getByText('dyn-id-').evaluateAll((nodes) => {
+ for (const node of nodes) node.innerHTML = node.innerHTML.replaceAll(/dyn-id-[a-f0-9-]+/g, 'dynamic-id');
+ });
await page.locator('relative-time').evaluateAll((nodes) => {
for (const node of nodes) node.outerHTML = 'time element';
});
@@ -97,6 +105,8 @@ export async function save_visual(page: Page) {
page.locator('#repo_migrating'),
// update order of recently created repos is not fully deterministic
page.locator('.flex-item-main').filter({hasText: 'relative time in repo'}),
+ // dynamic IDs in fixed-size inputs
+ page.locator('input[value*="dyn-id-"]'),
],
});
}
@@ -122,3 +132,8 @@ export async function create_temp_user(browser: Browser, workerInfo: TestInfo, r
return {context: await login_user(browser, workerInfo, username), username};
}
+
+// returns a random string with a pattern that can be filtered for screenshots automatically
+export function dynamic_id() {
+ return `dyn-id-${globalThis.crypto.randomUUID()}`;
+}
diff --git a/tests/integration/repo_generate_test.go b/tests/integration/repo_generate_test.go
index 4bd9f32119..bcee0df417 100644
--- a/tests/integration/repo_generate_test.go
+++ b/tests/integration/repo_generate_test.go
@@ -43,7 +43,7 @@ func assertRepoCreateForm(t *testing.T, htmlDoc *HTMLDoc, owner *user_model.User
// the template menu is loaded client-side, so don't assert the option exists
assert.Equal(t, templateID, htmlDoc.GetInputValueByName("repo_template"), "Unexpected repo_template selection")
- for _, name := range []string{"issue_labels", "gitignores", "license", "readme", "object_format_name"} {
+ for _, name := range []string{"issue_labels", "gitignores", "license", "object_format_name"} {
htmlDoc.AssertDropdownHasOptions(t, name)
}
}