{{template "shared/search/input" dict "Value" .Value "Disabled" .Disabled "Placeholder" .Placeholder}}
- {{svg "octicon-triangle-down" 14 "dropdown icon"}}
{{ctx.Locale.Tr (printf "search.%s" .Selected)}}
diff --git a/templates/user/dashboard/feeds.tmpl b/templates/user/dashboard/feeds.tmpl
index 85ae7266d9..bd2a3800a2 100644
--- a/templates/user/dashboard/feeds.tmpl
+++ b/templates/user/dashboard/feeds.tmpl
@@ -103,11 +103,11 @@
{{ctx.Locale.Tr "action.compare_commits" $push.Len}} »
{{end}}
{{else if .GetOpType.InActions "create_issue"}}
-
{{RenderIssueTitle ctx (index .GetIssueInfos 1) (.Repo.ComposeMetas ctx)}}
+
{{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}}
{{else if .GetOpType.InActions "create_pull_request"}}
-
{{RenderIssueTitle ctx (index .GetIssueInfos 1) (.Repo.ComposeMetas ctx)}}
+
{{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}}
{{else if .GetOpType.InActions "comment_issue" "approve_pull_request" "reject_pull_request" "comment_pull"}}
-
{{RenderIssueTitle ctx (.GetIssueTitle ctx) (.Repo.ComposeMetas ctx)}}
+
{{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}}
{{$comment := index .GetIssueInfos 1}}
{{if $comment}}
{{RenderMarkdownToHtml ctx $comment}}
@@ -115,7 +115,7 @@
{{else if .GetOpType.InActions "merge_pull_request"}}
{{index .GetIssueInfos 1}}
{{else if .GetOpType.InActions "close_issue" "reopen_issue" "close_pull_request" "reopen_pull_request"}}
-
{{RenderIssueTitle ctx (.GetIssueTitle ctx) (.Repo.ComposeMetas ctx)}}
+
{{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}}
{{else if .GetOpType.InActions "pull_review_dismissed"}}
{{ctx.Locale.Tr "action.review_dismissed_reason"}}
{{index .GetIssueInfos 2 | RenderEmoji $.Context}}
diff --git a/tests/e2e/README.md b/tests/e2e/README.md
index 35fc5e7d1d..8d8858bfd5 100644
--- a/tests/e2e/README.md
+++ b/tests/e2e/README.md
@@ -250,18 +250,16 @@ test('For anyone', async ({page}) => {
If you need a user account, you can use something like:
~~~js
-import {test} from './utils_e2e.ts';
+import {test, login_user, login} from './utils_e2e.ts';
-// reuse user2 token from scope `shared`
-test.use({user: 'user2', authScope: 'shared'})
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2'); // or another user
+});
-test('For signed users only', async ({page}) => {
-
-})
+test('For signed users only', async ({browser}, workerInfo) => {
+ const page = await login({browser}, workerInfo);
~~~
-users are created in [utils_e2e_test.go](utils_e2e_test.go)
-
### Run tests very selectively
Browser testing can take some time.
diff --git a/tests/e2e/actions.test.e2e.ts b/tests/e2e/actions.test.e2e.ts
index 4e93b89ee0..a66b608080 100644
--- a/tests/e2e/actions.test.e2e.ts
+++ b/tests/e2e/actions.test.e2e.ts
@@ -10,66 +10,76 @@
// @watch end
import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test, login_user, save_visual, load_logged_in_context} from './utils_e2e.ts';
+
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
const workflow_trigger_notification_text = 'This workflow has a workflow_dispatch event trigger.';
-test.describe('Workflow Authenticated user2', () => {
- test.use({user: 'user2'});
- test('workflow dispatch present', async ({page}) => {
- await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
+test('workflow dispatch present', async ({browser}, workerInfo) => {
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ const page = await context.newPage();
- await expect(page.getByText(workflow_trigger_notification_text)).toBeVisible();
+ await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
- const run_workflow_btn = page.locator('#workflow_dispatch_dropdown>button');
- await expect(run_workflow_btn).toBeVisible();
+ await expect(page.getByText(workflow_trigger_notification_text)).toBeVisible();
- const menu = page.locator('#workflow_dispatch_dropdown>.menu');
- await expect(menu).toBeHidden();
- await run_workflow_btn.click();
- await expect(menu).toBeVisible();
- await save_visual(page);
+ const run_workflow_btn = page.locator('#workflow_dispatch_dropdown>button');
+ await expect(run_workflow_btn).toBeVisible();
+
+ const menu = page.locator('#workflow_dispatch_dropdown>.menu');
+ await expect(menu).toBeHidden();
+ await run_workflow_btn.click();
+ await expect(menu).toBeVisible();
+ await save_visual(page);
+});
+
+test('workflow dispatch error: missing inputs', async ({browser}, workerInfo) => {
+ test.skip(workerInfo.project.name === 'Mobile Safari', 'Flaky behaviour on mobile safari; see https://codeberg.org/forgejo/forgejo/pulls/3334#issuecomment-2033383');
+
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ const page = await context.newPage();
+
+ await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
+
+ await page.locator('#workflow_dispatch_dropdown>button').click();
+
+ // Remove the required attribute so we can trigger the error message!
+ await page.evaluate(() => {
+ const elem = document.querySelector('input[name="inputs[string2]"]');
+ elem?.removeAttribute('required');
});
- test('dispatch error: missing inputs', async ({page}, testInfo) => {
- test.skip(testInfo.project.name === 'Mobile Safari', 'Flaky behaviour on mobile safari; see https://codeberg.org/forgejo/forgejo/pulls/3334#issuecomment-2033383');
+ await page.locator('#workflow-dispatch-submit').click();
- await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
+ await expect(page.getByText('Require value for input "String w/o. default".')).toBeVisible();
+ await save_visual(page);
+});
- await page.locator('#workflow_dispatch_dropdown>button').click();
+test('workflow dispatch success', async ({browser}, workerInfo) => {
+ test.skip(workerInfo.project.name === 'Mobile Safari', 'Flaky behaviour on mobile safari; see https://codeberg.org/forgejo/forgejo/pulls/3334#issuecomment-2033383');
- // Remove the required attribute so we can trigger the error message!
- await page.evaluate(() => {
- const elem = document.querySelector('input[name="inputs[string2]"]');
- elem?.removeAttribute('required');
- });
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ const page = await context.newPage();
- await page.locator('#workflow-dispatch-submit').click();
+ await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
- await expect(page.getByText('Require value for input "String w/o. default".')).toBeVisible();
- await save_visual(page);
- });
+ await page.locator('#workflow_dispatch_dropdown>button').click();
- test('dispatch success', async ({page}, testInfo) => {
- test.skip(testInfo.project.name === 'Mobile Safari', 'Flaky behaviour on mobile safari; see https://codeberg.org/forgejo/forgejo/pulls/3334#issuecomment-2033383');
- await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
+ await page.fill('input[name="inputs[string2]"]', 'abc');
+ await save_visual(page);
+ await page.locator('#workflow-dispatch-submit').click();
- await page.locator('#workflow_dispatch_dropdown>button').click();
+ await expect(page.getByText('Workflow run was successfully requested.')).toBeVisible();
- await page.fill('input[name="inputs[string2]"]', 'abc');
- await save_visual(page);
- await page.locator('#workflow-dispatch-submit').click();
-
- await expect(page.getByText('Workflow run was successfully requested.')).toBeVisible();
-
- await expect(page.locator('.run-list>:first-child .run-list-meta', {hasText: 'now'})).toBeVisible();
- await save_visual(page);
- });
+ await expect(page.locator('.run-list>:first-child .run-list-meta', {hasText: 'now'})).toBeVisible();
+ await save_visual(page);
});
test('workflow dispatch box not available for unauthenticated users', async ({page}) => {
await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0');
await expect(page.locator('body')).not.toContainText(workflow_trigger_notification_text);
- await save_visual(page);
});
diff --git a/tests/e2e/clipboard-copy.test.e2e.ts b/tests/e2e/clipboard-copy.test.e2e.ts
index 2ae0e0dfff..70a3425868 100644
--- a/tests/e2e/clipboard-copy.test.e2e.ts
+++ b/tests/e2e/clipboard-copy.test.e2e.ts
@@ -8,7 +8,7 @@
// @watch end
import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test} from './utils_e2e.ts';
test('copy src file path to clipboard', async ({page}, workerInfo) => {
test.skip(['Mobile Safari', 'webkit'].includes(workerInfo.project.name), 'Apple clipboard API addon - starting at just $499!');
@@ -19,7 +19,6 @@ test('copy src file path to clipboard', async ({page}, workerInfo) => {
await page.click('[data-clipboard-text]');
const clipboardText = await page.evaluate(() => navigator.clipboard.readText());
expect(clipboardText).toContain('README.md');
- await save_visual(page);
});
test('copy diff file path to clipboard', async ({page}, workerInfo) => {
@@ -31,6 +30,4 @@ test('copy diff file path to clipboard', async ({page}, workerInfo) => {
await page.click('[data-clipboard-text]');
const clipboardText = await page.evaluate(() => navigator.clipboard.readText());
expect(clipboardText).toContain('README.md');
- await expect(page.getByText('Copied')).toBeVisible();
- await save_visual(page);
});
diff --git a/tests/e2e/dashboard-ci-status.test.e2e.ts b/tests/e2e/dashboard-ci-status.test.e2e.ts
index d35fe299ff..1d23122b44 100644
--- a/tests/e2e/dashboard-ci-status.test.e2e.ts
+++ b/tests/e2e/dashboard-ci-status.test.e2e.ts
@@ -3,26 +3,22 @@
// @watch end
import {expect} from '@playwright/test';
-import {test} from './utils_e2e.ts';
+import {test, login_user, save_visual, load_logged_in_context} from './utils_e2e.ts';
-test.use({user: 'user2'});
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
-test.describe.configure({retries: 2});
-
-test('Correct link and tooltip', async ({page}, testInfo) => {
- if (testInfo.retry) {
- await page.goto('/user2/test_workflows/actions');
- }
-
- const searchResponse = page.waitForResponse((resp) => resp.url().includes('/repo/search?') && resp.status() === 200);
+test('Correct link and tooltip', async ({browser}, workerInfo) => {
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ const page = await context.newPage();
const response = await page.goto('/?repo-search-query=test_workflows');
expect(response?.status()).toBe(200);
- await searchResponse;
-
const repoStatus = page.locator('.dashboard-repos .repo-owner-name-list > li:nth-child(1) > a:nth-child(2)');
+ // wait for network activity to cease (so status was loaded in frontend)
+ await page.waitForLoadState('networkidle'); // eslint-disable-line playwright/no-networkidle
await expect(repoStatus).toHaveAttribute('href', '/user2/test_workflows/actions', {timeout: 10000});
await expect(repoStatus).toHaveAttribute('data-tooltip-content', /^(Error|Failure)$/);
- // ToDo: Ensure stable screenshot of dashboard. Known to be flaky: https://code.forgejo.org/forgejo/visual-browser-testing/commit/206d4cfb7a4af6d8d7043026cdd4d63708798b2a
- // await save_visual(page);
+ await save_visual(page);
});
diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go
index 245bd347b8..b8c89625c0 100644
--- a/tests/e2e/e2e_test.go
+++ b/tests/e2e/e2e_test.go
@@ -89,7 +89,6 @@ func TestE2e(t *testing.T) {
runArgs := []string{"npx", "playwright", "test"}
- _, testVisual := os.LookupEnv("VISUAL_TEST")
// To update snapshot outputs
if _, set := os.LookupEnv("ACCEPT_VISUAL"); set {
runArgs = append(runArgs, "--update-snapshots")
@@ -113,10 +112,6 @@ func TestE2e(t *testing.T) {
onForgejoRun(t, func(*testing.T, *url.URL) {
defer DeclareGitRepos(t)()
thisTest := runArgs
- // when all tests are run, use unique artifacts directories per test to preserve artifacts from other tests
- if testVisual {
- thisTest = append(thisTest, "--output=tests/e2e/test-artifacts/"+testname)
- }
thisTest = append(thisTest, path)
cmd := exec.Command(runArgs[0], thisTest...)
cmd.Env = os.Environ()
@@ -126,7 +121,7 @@ func TestE2e(t *testing.T) {
cmd.Stderr = os.Stderr
err := cmd.Run()
- if err != nil && !testVisual {
+ if err != nil {
log.Fatal("Playwright Failed: %s", err)
}
})
diff --git a/tests/e2e/example.test.e2e.ts b/tests/e2e/example.test.e2e.ts
index 97c5b8684b..b2a679a82d 100644
--- a/tests/e2e/example.test.e2e.ts
+++ b/tests/e2e/example.test.e2e.ts
@@ -5,7 +5,7 @@
// @watch end
import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test} from './utils_e2e.ts';
test('Load Homepage', async ({page}) => {
const response = await page.goto('/');
@@ -26,7 +26,6 @@ test('Register Form', async ({page}, workerInfo) => {
expect(page.url()).toBe(`${workerInfo.project.use.baseURL}/`);
await expect(page.locator('.secondary-nav span>img.ui.avatar')).toBeVisible();
await expect(page.locator('.ui.positive.message.flash-success')).toHaveText('Account was successfully created. Welcome!');
- await save_visual(page);
});
// eslint-disable-next-line playwright/no-skipped-test
diff --git a/tests/e2e/explore.test.e2e.ts b/tests/e2e/explore.test.e2e.ts
index 1bb5af3cc6..44c9b21f58 100644
--- a/tests/e2e/explore.test.e2e.ts
+++ b/tests/e2e/explore.test.e2e.ts
@@ -7,7 +7,7 @@
// @watch end
import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test} from './utils_e2e.ts';
test('Explore view taborder', async ({page}) => {
await page.goto('/explore/repos');
@@ -42,5 +42,4 @@ test('Explore view taborder', async ({page}) => {
}
}
expect(res).toBe(exp);
- await save_visual(page);
});
diff --git a/tests/e2e/git-notes.test.e2e.ts b/tests/e2e/git-notes.test.e2e.ts
index 1e2cbe76fc..8b80a3aa77 100644
--- a/tests/e2e/git-notes.test.e2e.ts
+++ b/tests/e2e/git-notes.test.e2e.ts
@@ -1,16 +1,17 @@
// @ts-check
-import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test, expect} from '@playwright/test';
+import {login_user, save_visual, load_logged_in_context} from './utils_e2e.ts';
-test.use({user: 'user2'});
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
-test('Change git note', async ({page}) => {
+test('Change git note', async ({browser}, workerInfo) => {
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ const page = await context.newPage();
let response = await page.goto('/user2/repo1/commit/65f1bf27bc3bf70f64657658635e66094edbcb4d');
expect(response?.status()).toBe(200);
- // An add button should not be present, because the commit already has a commit note
- await expect(page.locator('#commit-notes-add-button')).toHaveCount(0);
-
await page.locator('#commit-notes-edit-button').click();
let textarea = page.locator('textarea[name="notes"]');
diff --git a/tests/e2e/issue-comment.test.e2e.ts b/tests/e2e/issue-comment.test.e2e.ts
index 1c19f98c48..4fce16764b 100644
--- a/tests/e2e/issue-comment.test.e2e.ts
+++ b/tests/e2e/issue-comment.test.e2e.ts
@@ -5,11 +5,14 @@
// @watch end
import {expect} from '@playwright/test';
-import {test, save_visual} from './utils_e2e.ts';
+import {test, save_visual, login_user, login} from './utils_e2e.ts';
-test.use({user: 'user2'});
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
-test('Menu accessibility', async ({page}) => {
+test('Menu accessibility', async ({browser}, workerInfo) => {
+ const page = await login({browser}, workerInfo);
await page.goto('/user2/repo1/issues/1');
await expect(page.getByLabel('user2 reacted eyes. Remove eyes')).toBeVisible();
await expect(page.getByLabel('reacted laugh. Remove laugh')).toBeVisible();
@@ -21,8 +24,9 @@ test('Menu accessibility', async ({page}) => {
await expect(page.getByLabel('user1, user2 reacted laugh. Remove laugh')).toBeVisible();
});
-test('Hyperlink paste behaviour', async ({page}, workerInfo) => {
+test('Hyperlink paste behaviour', async ({browser}, workerInfo) => {
test.skip(['Mobile Safari', 'Mobile Chrome', 'webkit'].includes(workerInfo.project.name), 'Mobile clients seem to have very weird behaviour with this test, which I cannot confirm with real usage');
+ const page = await login({browser}, workerInfo);
await page.goto('/user2/repo1/issues/new');
await page.locator('textarea').click();
// same URL
@@ -54,7 +58,8 @@ test('Hyperlink paste behaviour', async ({page}, workerInfo) => {
await page.locator('textarea').fill('');
});
-test('Always focus edit tab first on edit', async ({page}) => {
+test('Always focus edit tab first on edit', async ({browser}, workerInfo) => {
+ const page = await login({browser}, workerInfo);
const response = await page.goto('/user2/repo1/issues/1');
expect(response?.status()).toBe(200);
@@ -77,29 +82,9 @@ test('Always focus edit tab first on edit', async ({page}) => {
await save_visual(page);
});
-test('Reset content of comment edit field on cancel', async ({page}) => {
- const response = await page.goto('/user2/repo1/issues/1');
- expect(response?.status()).toBe(200);
-
- const editorTextarea = page.locator('[id="_combo_markdown_editor_1"]');
-
- // Change the content of the edit field
- await page.click('#issue-1 .comment-container .context-menu');
- await page.click('#issue-1 .comment-container .menu>.edit-content');
- await expect(editorTextarea).toHaveValue('content for the first issue');
- await editorTextarea.fill('some random string');
- await expect(editorTextarea).toHaveValue('some random string');
- await page.click('#issue-1 .comment-container .edit .cancel');
-
- // Edit again and assert that the edit field should be reset to the initial content
- await page.click('#issue-1 .comment-container .context-menu');
- await page.click('#issue-1 .comment-container .menu>.edit-content');
- await expect(editorTextarea).toHaveValue('content for the first issue');
- await save_visual(page);
-});
-
-test('Quote reply', async ({page}, workerInfo) => {
+test('Quote reply', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name !== 'firefox', 'Uses Firefox specific selection quirks');
+ const page = await login({browser}, workerInfo);
const response = await page.goto('/user2/repo1/issues/1');
expect(response?.status()).toBe(200);
@@ -172,8 +157,9 @@ test('Quote reply', async ({page}, workerInfo) => {
await editorTextarea.fill('');
});
-test('Pull quote reply', async ({page}, workerInfo) => {
+test('Pull quote reply', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name !== 'firefox', 'Uses Firefox specific selection quirks');
+ const page = await login({browser}, workerInfo);
const response = await page.goto('/user2/commitsonpr/pulls/1/files');
expect(response?.status()).toBe(200);
diff --git a/tests/e2e/issue-sidebar.test.e2e.ts b/tests/e2e/issue-sidebar.test.e2e.ts
index fe2a6cec87..f4d50a13ba 100644
--- a/tests/e2e/issue-sidebar.test.e2e.ts
+++ b/tests/e2e/issue-sidebar.test.e2e.ts
@@ -7,13 +7,14 @@
/* eslint playwright/expect-expect: ["error", { "assertFunctionNames": ["check_wip"] }] */
import {expect, type Page} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test, save_visual, login_user, login} from './utils_e2e.ts';
-test.use({user: 'user2'});
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
test.describe('Pull: Toggle WIP', () => {
const prTitle = 'pull5';
-
async function toggle_wip_to({page}, should: boolean) {
await page.waitForLoadState('domcontentloaded');
if (should) {
@@ -38,7 +39,8 @@ test.describe('Pull: Toggle WIP', () => {
}
}
- test.beforeEach(async ({page}) => {
+ test.beforeEach(async ({browser}, workerInfo) => {
+ const page = await login({browser}, workerInfo);
const response = await page.goto('/user2/repo1/pulls/5');
expect(response?.status()).toBe(200); // Status OK
// ensure original title
@@ -48,8 +50,9 @@ test.describe('Pull: Toggle WIP', () => {
await check_wip({page}, false);
});
- test('simple toggle', async ({page}, workerInfo) => {
+ test('simple toggle', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636');
+ const page = await login({browser}, workerInfo);
await page.goto('/user2/repo1/pulls/5');
// toggle to WIP
await toggle_wip_to({page}, true);
@@ -59,8 +62,9 @@ test.describe('Pull: Toggle WIP', () => {
await check_wip({page}, false);
});
- test('manual edit', async ({page}, workerInfo) => {
+ test('manual edit', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636');
+ const page = await login({browser}, workerInfo);
await page.goto('/user2/repo1/pulls/5');
// manually edit title to another prefix
await page.locator('#issue-title-edit-show').click();
@@ -72,8 +76,9 @@ test.describe('Pull: Toggle WIP', () => {
await check_wip({page}, false);
});
- test('maximum title length', async ({page}, workerInfo) => {
+ test('maximum title length', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636');
+ const page = await login({browser}, workerInfo);
await page.goto('/user2/repo1/pulls/5');
// check maximum title length is handled gracefully
const maxLenStr = prTitle + 'a'.repeat(240);
@@ -91,16 +96,17 @@ test.describe('Pull: Toggle WIP', () => {
});
});
-test('Issue: Labels', async ({page}, workerInfo) => {
+test('Issue: Labels', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636');
- async function submitLabels({page}: { page: Page }) {
+ async function submitLabels({page}: {page: Page}) {
const submitted = page.waitForResponse('/user2/repo1/issues/labels');
await page.locator('textarea').first().click(); // close via unrelated element
await submitted;
await page.waitForLoadState();
}
+ const page = await login({browser}, workerInfo);
// select label list in sidebar only
const labelList = page.locator('.issue-content-right .labels-list a');
const response = await page.goto('/user2/repo1/issues/1');
@@ -138,8 +144,9 @@ test('Issue: Labels', async ({page}, workerInfo) => {
await expect(labelList.filter({hasText: 'label1'})).toBeVisible();
});
-test('Issue: Assignees', async ({page}, workerInfo) => {
+test('Issue: Assignees', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636');
+ const page = await login({browser}, workerInfo);
// select label list in sidebar only
const assigneesList = page.locator('.issue-content-right .assignees.list .selected .item a');
@@ -175,8 +182,9 @@ test('Issue: Assignees', async ({page}, workerInfo) => {
await expect(page.locator('.ui.assignees.list .item.no-select')).toBeHidden();
});
-test('New Issue: Assignees', async ({page}, workerInfo) => {
+test('New Issue: Assignees', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636');
+ const page = await login({browser}, workerInfo);
// select label list in sidebar only
const assigneesList = page.locator('.issue-content-right .assignees.list .selected .item');
@@ -216,8 +224,9 @@ test('New Issue: Assignees', async ({page}, workerInfo) => {
await save_visual(page);
});
-test('Issue: Milestone', async ({page}, workerInfo) => {
+test('Issue: Milestone', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636');
+ const page = await login({browser}, workerInfo);
const response = await page.goto('/user2/repo1/issues/1');
expect(response?.status()).toBe(200);
@@ -239,8 +248,9 @@ test('Issue: Milestone', async ({page}, workerInfo) => {
await expect(page.locator('.timeline-item.event').last()).toContainText('user2 removed this from the milestone1 milestone');
});
-test('New Issue: Milestone', async ({page}, workerInfo) => {
+test('New Issue: Milestone', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636');
+ const page = await login({browser}, workerInfo);
const response = await page.goto('/user2/repo1/issues/new');
expect(response?.status()).toBe(200);
diff --git a/tests/e2e/markdown-editor.test.e2e.ts b/tests/e2e/markdown-editor.test.e2e.ts
index 35e9de2ea6..ca2d6e01b6 100644
--- a/tests/e2e/markdown-editor.test.e2e.ts
+++ b/tests/e2e/markdown-editor.test.e2e.ts
@@ -5,16 +5,21 @@
// @watch end
import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test, save_visual, load_logged_in_context, login_user} from './utils_e2e.ts';
-test.use({user: 'user2'});
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
-test('Markdown image preview behaviour', async ({page}, workerInfo) => {
+test('Markdown image preview behaviour', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Flaky behaviour on mobile safari;');
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+
// Editing the root README.md file for image preview
const editPath = '/user2/repo1/src/branch/master/README.md';
+ const page = await context.newPage();
const response = await page.goto(editPath, {waitUntil: 'domcontentloaded'});
expect(response?.status()).toBe(200);
@@ -38,9 +43,12 @@ test('Markdown image preview behaviour', async ({page}, workerInfo) => {
await save_visual(page);
});
-test('markdown indentation', async ({page}) => {
+test('markdown indentation', async ({browser}, workerInfo) => {
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+
const initText = `* first\n* second\n* third\n* last`;
+ const page = await context.newPage();
const response = await page.goto('/user2/repo1/issues/new');
expect(response?.status()).toBe(200);
@@ -108,9 +116,12 @@ test('markdown indentation', async ({page}) => {
await expect(textarea).toHaveValue(initText);
});
-test('markdown list continuation', async ({page}) => {
- const initText = `* first\n* second`;
+test('markdown list continuation', async ({browser}, workerInfo) => {
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ const initText = `* first\n* second\n* third\n* last`;
+
+ const page = await context.newPage();
const response = await page.goto('/user2/repo1/issues/new');
expect(response?.status()).toBe(200);
@@ -119,20 +130,25 @@ test('markdown list continuation', async ({page}) => {
const indent = page.locator('button[data-md-action="indent"]');
await textarea.fill(initText);
- // Test continuation of ' * ' prefix
- await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.indexOf('rst'), it.value.indexOf('rst')));
- await indent.click();
+ // Test continuation of '* ' prefix
+ await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.indexOf('cond'), it.value.indexOf('cond')));
await textarea.press('End');
await textarea.press('Enter');
+ await textarea.pressSequentially('middle');
+ await expect(textarea).toHaveValue(`* first\n* second\n* middle\n* third\n* last`);
+
+ // Test continuation of ' * ' prefix
+ await indent.click();
+ await textarea.press('Enter');
await textarea.pressSequentially('muddle');
- await expect(textarea).toHaveValue(`${tab}* first\n${tab}* muddle\n* second`);
+ await expect(textarea).toHaveValue(`* first\n* second\n${tab}* middle\n${tab}* muddle\n* third\n* last`);
// Test breaking in the middle of a line
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.lastIndexOf('ddle'), it.value.lastIndexOf('ddle')));
await textarea.pressSequentially('tate');
await textarea.press('Enter');
await textarea.pressSequentially('me');
- await expect(textarea).toHaveValue(`${tab}* first\n${tab}* mutate\n${tab}* meddle\n* second`);
+ await expect(textarea).toHaveValue(`* first\n* second\n${tab}* middle\n${tab}* mutate\n${tab}* meddle\n* third\n* last`);
// Test not triggering when Shift held
await textarea.fill(initText);
@@ -140,36 +156,35 @@ test('markdown list continuation', async ({page}) => {
await textarea.press('Shift+Enter');
await textarea.press('Enter');
await textarea.pressSequentially('...but not least');
- await expect(textarea).toHaveValue(`* first\n* second\n\n...but not least`);
+ await expect(textarea).toHaveValue(`* first\n* second\n* third\n* last\n\n...but not least`);
// Test continuation of ordered list
- await textarea.fill(`1. one`);
+ await textarea.fill(`1. one\n2. two`);
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.length, it.value.length));
await textarea.press('Enter');
- await textarea.pressSequentially(' ');
- await textarea.press('Enter');
await textarea.pressSequentially('three');
- await textarea.press('Enter');
- await textarea.press('Enter');
- await expect(textarea).toHaveValue(`1. one\n2. \n3. three\n\n`);
+ await expect(textarea).toHaveValue(`1. one\n2. two\n3. three`);
// Test continuation of alternative ordered list syntax
- await textarea.fill(`1) one`);
+ await textarea.fill(`1) one\n2) two`);
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.length, it.value.length));
await textarea.press('Enter');
- await textarea.pressSequentially(' ');
- await textarea.press('Enter');
await textarea.pressSequentially('three');
+ await expect(textarea).toHaveValue(`1) one\n2) two\n3) three`);
+
+ // Test continuation of blockquote
+ await textarea.fill(`> knowledge is power`);
+ await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.length, it.value.length));
await textarea.press('Enter');
- await textarea.press('Enter');
- await expect(textarea).toHaveValue(`1) one\n2) \n3) three\n\n`);
+ await textarea.pressSequentially('france is bacon');
+ await expect(textarea).toHaveValue(`> knowledge is power\n> france is bacon`);
// Test continuation of checklists
- await textarea.fill(`- [ ]have a problem\n- [x]create a solution`);
+ await textarea.fill(`- [ ] have a problem\n- [x] create a solution`);
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.length, it.value.length));
await textarea.press('Enter');
await textarea.pressSequentially('write a test');
- await expect(textarea).toHaveValue(`- [ ]have a problem\n- [x]create a solution\n- [ ]write a test`);
+ await expect(textarea).toHaveValue(`- [ ] have a problem\n- [x] create a solution\n- [ ] write a test`);
// Test all conceivable syntax (except ordered lists)
const prefixes = [
@@ -185,6 +200,7 @@ test('markdown list continuation', async ({page}) => {
'> ',
'> > ',
'- [ ] ',
+ '- [ ]', // This does seem to render, so allow.
'* [ ] ',
'+ [ ] ',
];
@@ -192,16 +208,15 @@ test('markdown list continuation', async ({page}) => {
await textarea.fill(`${prefix}one`);
await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.length, it.value.length));
await textarea.press('Enter');
- await textarea.pressSequentially(' ');
- await textarea.press('Enter');
await textarea.pressSequentially('two');
- await textarea.press('Enter');
- await textarea.press('Enter');
- await expect(textarea).toHaveValue(`${prefix}one\n${prefix} \n${prefix}two\n\n`);
+ await expect(textarea).toHaveValue(`${prefix}one\n${prefix}two`);
}
});
-test('markdown insert table', async ({page}) => {
+test('markdown insert table', async ({browser}, workerInfo) => {
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+
+ const page = await context.newPage();
const response = await page.goto('/user2/repo1/issues/new');
expect(response?.status()).toBe(200);
@@ -223,29 +238,3 @@ test('markdown insert table', async ({page}) => {
await expect(textarea).toHaveValue('| Header | Header |\n|---------|---------|\n| Content | Content |\n| Content | Content |\n| Content | Content |\n');
await save_visual(page);
});
-
-test('text expander has higher prio then prefix continuation', async ({page}) => {
- const response = await page.goto('/user2/repo1/issues/new');
- expect(response?.status()).toBe(200);
-
- const textarea = page.locator('textarea[name=content]');
- const initText = `* first`;
- await textarea.fill(initText);
- await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.indexOf('rst'), it.value.indexOf('rst')));
- await textarea.press('End');
-
- // Test emoji completion
- await textarea.press('Enter');
- await textarea.pressSequentially(':smile_c');
- await textarea.press('Enter');
- await expect(textarea).toHaveValue(`* first\n* 😸`);
-
- // Test username completion
- await textarea.press('Enter');
- await textarea.pressSequentially('@user');
- await textarea.press('Enter');
- await expect(textarea).toHaveValue(`* first\n* 😸\n* @user2 `);
-
- await textarea.press('Enter');
- await expect(textarea).toHaveValue(`* first\n* 😸\n* @user2 \n* `);
-});
diff --git a/tests/e2e/markup.test.e2e.ts b/tests/e2e/markup.test.e2e.ts
index 398a0a6300..2726942d57 100644
--- a/tests/e2e/markup.test.e2e.ts
+++ b/tests/e2e/markup.test.e2e.ts
@@ -3,7 +3,7 @@
// @watch end
import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test} from './utils_e2e.ts';
test('markup with #xyz-mode-only', async ({page}) => {
const response = await page.goto('/user2/repo1/issues/1');
@@ -13,5 +13,4 @@ test('markup with #xyz-mode-only', async ({page}) => {
await expect(comment).toBeVisible();
await expect(comment.locator('[src$="#gh-light-mode-only"]')).toBeVisible();
await expect(comment.locator('[src$="#gh-dark-mode-only"]')).toBeHidden();
- await save_visual(page);
});
diff --git a/tests/e2e/org-settings.test.e2e.ts b/tests/e2e/org-settings.test.e2e.ts
index df554e0674..22a8bc0e2d 100644
--- a/tests/e2e/org-settings.test.e2e.ts
+++ b/tests/e2e/org-settings.test.e2e.ts
@@ -5,13 +5,16 @@
// @watch end
import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test, save_visual, login_user, login} from './utils_e2e.ts';
import {validate_form} from './shared/forms.ts';
-test.use({user: 'user2'});
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
-test('org team settings', async ({page}, workerInfo) => {
+test('org team settings', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Cannot get it to work - as usual');
+ const page = await login({browser}, workerInfo);
const response = await page.goto('/org/org3/teams/team1/edit');
expect(response?.status()).toBe(200);
diff --git a/tests/e2e/profile_actions.test.e2e.ts b/tests/e2e/profile_actions.test.e2e.ts
index a66dc43aab..65090e62b2 100644
--- a/tests/e2e/profile_actions.test.e2e.ts
+++ b/tests/e2e/profile_actions.test.e2e.ts
@@ -5,11 +5,13 @@
// @watch end
import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test, save_visual, login_user, load_logged_in_context} from './utils_e2e.ts';
-test.use({user: 'user2'});
+test('Follow actions', async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ const page = await context.newPage();
-test('Follow actions', async ({page}) => {
await page.goto('/user1');
// Check if following and then unfollowing works.
diff --git a/tests/e2e/reaction-selectors.test.e2e.ts b/tests/e2e/reaction-selectors.test.e2e.ts
index 54b7d91869..3ce71b24d7 100644
--- a/tests/e2e/reaction-selectors.test.e2e.ts
+++ b/tests/e2e/reaction-selectors.test.e2e.ts
@@ -4,9 +4,11 @@
// @watch end
import {expect, type Locator} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test, save_visual, login_user, load_logged_in_context} from './utils_e2e.ts';
-test.use({user: 'user2'});
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
const assertReactionCounts = (comment: Locator, counts: unknown) =>
expect(async () => {
@@ -24,7 +26,6 @@ const assertReactionCounts = (comment: Locator, counts: unknown) =>
]),
),
);
- // eslint-disable-next-line playwright/no-standalone-expect
return expect(reactions).toStrictEqual(counts);
}).toPass();
@@ -34,7 +35,10 @@ async function toggleReaction(menu: Locator, reaction: string) {
await menu.locator(`[role=menuitem][data-reaction-content="${reaction}"]`).click();
}
-test('Reaction Selectors', async ({page}) => {
+test('Reaction Selectors', async ({browser}, workerInfo) => {
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ const page = await context.newPage();
+
const response = await page.goto('/user2/repo1/issues/1');
expect(response?.status()).toBe(200);
diff --git a/tests/e2e/release.test.e2e.ts b/tests/e2e/release.test.e2e.ts
index 49c67793e6..fefa446c59 100644
--- a/tests/e2e/release.test.e2e.ts
+++ b/tests/e2e/release.test.e2e.ts
@@ -9,18 +9,24 @@
// @watch end
import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test, login_user, save_visual, load_logged_in_context} from './utils_e2e.ts';
import {validate_form} from './shared/forms.ts';
-test.use({user: 'user2'});
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
test.describe.configure({
timeout: 30000,
});
-test('External Release Attachments', async ({page, isMobile}) => {
+test('External Release Attachments', async ({browser, isMobile}, workerInfo) => {
test.skip(isMobile);
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ /** @type {import('@playwright/test').Page} */
+ const page = await context.newPage();
+
// Click "New Release"
await page.goto('/user2/repo2/releases');
await page.click('.button.small.primary');
diff --git a/tests/e2e/repo-code.test.e2e.ts b/tests/e2e/repo-code.test.e2e.ts
index 11b710c956..264dd3a8e0 100644
--- a/tests/e2e/repo-code.test.e2e.ts
+++ b/tests/e2e/repo-code.test.e2e.ts
@@ -5,9 +5,13 @@
// @watch end
import {expect, type Page} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test, save_visual, login_user, login} from './utils_e2e.ts';
import {accessibilityCheck} from './shared/accessibility.ts';
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
+
async function assertSelectedLines(page: Page, nums: string[]) {
const pageAssertions = async () => {
expect(
@@ -49,7 +53,6 @@ test('Line Range Selection', async ({page}) => {
// out-of-bounds end line
await page.goto(`${filePath}#L1-L100`);
await assertSelectedLines(page, ['1', '2', '3']);
- await save_visual(page);
});
test('Readable diff', async ({page}, workerInfo) => {
@@ -76,26 +79,22 @@ test('Readable diff', async ({page}, workerInfo) => {
await expect(page.getByText(thisDiff.added, {exact: true})).toHaveCSS('background-color', 'rgb(134, 239, 172)');
}
}
+});
+
+test('Username highlighted in commits', async ({browser}, workerInfo) => {
+ const page = await login({browser}, workerInfo);
+ await page.goto('/user2/mentions-highlighted/commits/branch/main');
+ // check first commit
+ await page.getByRole('link', {name: 'A commit message which'}).click();
+ await expect(page.getByRole('link', {name: '@user2'})).toHaveCSS('background-color', /(.*)/);
+ await expect(page.getByRole('link', {name: '@user1'})).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)');
+ await accessibilityCheck({page}, ['.commit-header'], [], []);
+ await save_visual(page);
+ // check second commit
+ await page.goto('/user2/mentions-highlighted/commits/branch/main');
+ await page.locator('tbody').getByRole('link', {name: 'Another commit which mentions'}).click();
+ await expect(page.getByRole('link', {name: '@user2'})).toHaveCSS('background-color', /(.*)/);
+ await expect(page.getByRole('link', {name: '@user1'})).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)');
+ await accessibilityCheck({page}, ['.commit-header'], [], []);
await save_visual(page);
});
-
-test.describe('As authenticated user', () => {
- test.use({user: 'user2'});
-
- test('Username highlighted in commits', async ({page}) => {
- await page.goto('/user2/mentions-highlighted/commits/branch/main');
- // check first commit
- await page.getByRole('link', {name: 'A commit message which'}).click();
- await expect(page.getByRole('link', {name: '@user2'})).toHaveCSS('background-color', /(.*)/);
- await expect(page.getByRole('link', {name: '@user1'})).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)');
- await accessibilityCheck({page}, ['.commit-header'], [], []);
- await save_visual(page);
- // check second commit
- await page.goto('/user2/mentions-highlighted/commits/branch/main');
- await page.locator('tbody').getByRole('link', {name: 'Another commit which mentions'}).click();
- await expect(page.getByRole('link', {name: '@user2'})).toHaveCSS('background-color', /(.*)/);
- await expect(page.getByRole('link', {name: '@user1'})).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)');
- await accessibilityCheck({page}, ['.commit-header'], [], []);
- await save_visual(page);
- });
-});
diff --git a/tests/e2e/repo-commitgraph.test.e2e.ts b/tests/e2e/repo-commitgraph.test.e2e.ts
index e8b85c5997..5f0cad117a 100644
--- a/tests/e2e/repo-commitgraph.test.e2e.ts
+++ b/tests/e2e/repo-commitgraph.test.e2e.ts
@@ -5,30 +5,13 @@
// @watch end
import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test} from './utils_e2e.ts';
test('Commit graph overflow', async ({page}) => {
- const response = await page.goto('/user2/repo1/graph');
- expect(response?.status()).toBe(200);
-
- await page.click('#flow-select-refs-dropdown');
- const input = page.locator('#flow-select-refs-dropdown');
- await input.press('Enter');
- await input.press('Enter');
- await input.press('Enter');
- await input.press('Enter');
- await input.press('Enter');
- await input.press('Enter');
- await input.press('Enter');
- await input.press('Enter');
- await input.press('Enter');
- await input.press('Enter');
-
- await expect(page.locator('#flow-select-refs-dropdown')).toBeInViewport({ratio: 1});
+ await page.goto('/user2/diff-test/graph');
await expect(page.getByRole('button', {name: 'Mono'})).toBeInViewport({ratio: 1});
await expect(page.getByRole('button', {name: 'Color'})).toBeInViewport({ratio: 1});
await expect(page.locator('.selection.search.dropdown')).toBeInViewport({ratio: 1});
- await save_visual(page);
});
test('Switch branch', async ({page}) => {
@@ -45,5 +28,4 @@ test('Switch branch', async ({page}) => {
await expect(page.locator('#loading-indicator')).toBeHidden();
await expect(page.locator('#rel-container')).toBeVisible();
await expect(page.locator('#rev-container')).toBeVisible();
- await save_visual(page);
});
diff --git a/tests/e2e/repo-migrate.test.e2e.ts b/tests/e2e/repo-migrate.test.e2e.ts
index 5e67f89ed1..a0f9ab6c80 100644
--- a/tests/e2e/repo-migrate.test.e2e.ts
+++ b/tests/e2e/repo-migrate.test.e2e.ts
@@ -3,13 +3,15 @@
// @watch end
import {expect} from '@playwright/test';
-import {test, save_visual, test_context} from './utils_e2e.ts';
+import {test, save_visual, login_user, load_logged_in_context} from './utils_e2e.ts';
-test.use({user: 'user2'});
+test.beforeAll(({browser}, workerInfo) => login_user(browser, workerInfo, 'user2'));
-test('Migration Progress Page', async ({page, browser}, workerInfo) => {
+test('Migration Progress Page', async ({page: unauthedPage, browser}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Flaky actionability checks on Mobile Safari');
+ const page = await (await load_logged_in_context(browser, workerInfo, 'user2')).newPage();
+
expect((await page.goto('/user2/invalidrepo'))?.status(), 'repo should not exist yet').toBe(404);
await page.goto('/repo/migrate?service_type=1');
@@ -21,11 +23,10 @@ test('Migration Progress Page', async ({page, browser}, workerInfo) => {
await form.locator('button.primary').click({timeout: 5000});
await expect(page).toHaveURL('user2/invalidrepo');
await save_visual(page);
+ // page screenshot of unauthedPage is checked automatically after the test
- const ctx = await test_context(browser);
- const unauthenticatedPage = await ctx.newPage();
- expect((await unauthenticatedPage.goto('/user2/invalidrepo'))?.status(), 'public migration page should be accessible').toBe(200);
- await expect(unauthenticatedPage.locator('#repo_migrating_progress')).toBeVisible();
+ expect((await unauthedPage.goto('/user2/invalidrepo'))?.status(), 'public migration page should be accessible').toBe(200);
+ await expect(unauthedPage.locator('#repo_migrating_progress')).toBeVisible();
await page.reload();
await expect(page.locator('#repo_migrating_failed')).toBeVisible();
@@ -36,6 +37,4 @@ test('Migration Progress Page', async ({page, browser}, workerInfo) => {
await save_visual(page);
await deleteModal.getByRole('button', {name: 'Delete repository'}).click();
await expect(page).toHaveURL('/');
- // checked last to preserve the order of screenshots from first run
- await save_visual(unauthenticatedPage);
});
diff --git a/tests/e2e/repo-new.test.e2e.ts b/tests/e2e/repo-new.test.e2e.ts
index ad202825a0..c9cc29ad56 100644
--- a/tests/e2e/repo-new.test.e2e.ts
+++ b/tests/e2e/repo-new.test.e2e.ts
@@ -4,12 +4,15 @@
// @watch end
import {expect} from '@playwright/test';
-import {test, dynamic_id, save_visual} from './utils_e2e.ts';
+import {test, dynamic_id, save_visual, login_user, login} from './utils_e2e.ts';
import {validate_form} from './shared/forms.ts';
-test.use({user: 'user2'});
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
-test('New repo: invalid', async ({page}) => {
+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
@@ -25,7 +28,8 @@ test('New repo: invalid', async ({page}) => {
await save_visual(page);
});
-test('New repo: initialize', async ({page}, workerInfo) => {
+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
@@ -58,7 +62,8 @@ test('New repo: initialize', async ({page}, workerInfo) => {
await save_visual(page);
});
-test('New repo: initialize later', async ({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);
@@ -92,8 +97,9 @@ test('New repo: initialize later', async ({page}) => {
await save_visual(page);
});
-test('New repo: from template', async ({page}, workerInfo) => {
+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);
@@ -108,7 +114,8 @@ test('New repo: from template', async ({page}, workerInfo) => {
await save_visual(page);
});
-test('New repo: label set', async ({page}) => {
+test('New repo: label set', async ({browser}, workerInfo) => {
+ const page = await login({browser}, workerInfo);
await page.goto('/repo/create');
const reponame = dynamic_id();
diff --git a/tests/e2e/repo-settings.test.e2e.ts b/tests/e2e/repo-settings.test.e2e.ts
index 3d260866fb..113b15181b 100644
--- a/tests/e2e/repo-settings.test.e2e.ts
+++ b/tests/e2e/repo-settings.test.e2e.ts
@@ -7,13 +7,16 @@
// @watch end
import {expect} from '@playwright/test';
-import {test, save_visual} from './utils_e2e.ts';
+import {test, save_visual, login_user, login} from './utils_e2e.ts';
import {validate_form} from './shared/forms.ts';
-test.use({user: 'user2'});
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
-test('repo webhook settings', async ({page}, workerInfo) => {
+test('repo webhook settings', async ({browser}, workerInfo) => {
test.skip(workerInfo.project.name === 'Mobile Safari', 'Cannot get it to work - as usual');
+ const page = await login({browser}, workerInfo);
const response = await page.goto('/user2/repo1/settings/hooks/forgejo/new');
expect(response?.status()).toBe(200);
@@ -32,8 +35,9 @@ test('repo webhook settings', async ({page}, workerInfo) => {
});
test.describe('repo branch protection settings', () => {
- test('form', async ({page}, {project}) => {
- test.skip(project.name === 'Mobile Safari', 'Cannot get it to work - as usual');
+ test('form', async ({browser}, workerInfo) => {
+ test.skip(workerInfo.project.name === 'Mobile Safari', 'Cannot get it to work - as usual');
+ const page = await login({browser}, workerInfo);
const response = await page.goto('/user2/repo1/settings/branches/edit');
expect(response?.status()).toBe(200);
@@ -52,7 +56,8 @@ test.describe('repo branch protection settings', () => {
await save_visual(page);
});
- test.afterEach(async ({page}) => {
+ test.afterEach(async ({browser}, workerInfo) => {
+ const page = await login({browser}, workerInfo);
// delete the rule for the next test
await page.goto('/user2/repo1/settings/branches/');
await page.waitForLoadState('domcontentloaded');
diff --git a/tests/e2e/repo-wiki.test.e2e.ts b/tests/e2e/repo-wiki.test.e2e.ts
index 4ce66da8bc..f32fe3fc91 100644
--- a/tests/e2e/repo-wiki.test.e2e.ts
+++ b/tests/e2e/repo-wiki.test.e2e.ts
@@ -4,7 +4,7 @@
// @watch end
import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test} from './utils_e2e.ts';
for (const searchTerm of ['space', 'consectetur']) {
for (const width of [null, 2560, 4000]) {
@@ -23,7 +23,6 @@ for (const searchTerm of ['space', 'consectetur']) {
await page.getByPlaceholder('Search wiki').dispatchEvent('keyup');
// timeout is necessary because HTMX search could be slow
await expect(page.locator('#wiki-search a[href]')).toBeInViewport({ratio: 1});
- await save_visual(page);
});
}
}
@@ -37,5 +36,4 @@ test(`Search results show titles (and not file names)`, async ({page}, workerInf
// so we manually "type" the last letter
await page.getByPlaceholder('Search wiki').dispatchEvent('keyup');
await expect(page.locator('#wiki-search a[href] b')).toHaveText('Page With Spaced Name');
- await save_visual(page);
});
diff --git a/tests/e2e/right-settings-button.test.e2e.ts b/tests/e2e/right-settings-button.test.e2e.ts
index 3bea329ba0..bfb1800a27 100644
--- a/tests/e2e/right-settings-button.test.e2e.ts
+++ b/tests/e2e/right-settings-button.test.e2e.ts
@@ -5,12 +5,19 @@
// @watch end
import {expect} from '@playwright/test';
-import {save_visual, test} from './utils_e2e.ts';
+import {test, login_user, load_logged_in_context} from './utils_e2e.ts';
-test.describe('desktop viewport as user 2', () => {
- test.use({user: 'user2', viewport: {width: 1920, height: 300}});
+test.beforeAll(async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user2');
+});
+
+test.describe('desktop viewport', () => {
+ test.use({viewport: {width: 1920, height: 300}});
+
+ test('Settings button on right of repo header', async ({browser}, workerInfo) => {
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ const page = await context.newPage();
- test('Settings button on right of repo header', async ({page}) => {
await page.goto('/user2/repo1');
const settingsBtn = page.locator('.overflow-menu-items>#settings-btn');
@@ -20,21 +27,11 @@ test.describe('desktop viewport as user 2', () => {
await expect(page.locator('.overflow-menu-button')).toHaveCount(0);
});
- test('Settings button on right of org header', async ({page}) => {
- await page.goto('/org3');
+ test('Settings button on right of repo header also when add more button is shown', async ({browser}, workerInfo) => {
+ await login_user(browser, workerInfo, 'user12');
+ const context = await load_logged_in_context(browser, workerInfo, 'user12');
+ const page = await context.newPage();
- const settingsBtn = page.locator('.overflow-menu-items>#settings-btn');
- await expect(settingsBtn).toBeVisible();
- await expect(settingsBtn).toHaveClass(/right/);
-
- await expect(page.locator('.overflow-menu-button')).toHaveCount(0);
- });
-});
-
-test.describe('desktop viewport as user12', () => {
- test.use({user: 'user12', viewport: {width: 1920, height: 300}});
-
- test('Settings button on right of repo header also when add more button is shown', async ({page}) => {
await page.goto('/user12/repo10');
const settingsBtn = page.locator('.overflow-menu-items>#settings-btn');
@@ -43,10 +40,19 @@ test.describe('desktop viewport as user12', () => {
await expect(page.locator('.overflow-menu-button')).toHaveCount(0);
});
-});
-test.describe('desktop viewport, unauthenticated', () => {
- test.use({viewport: {width: 1920, height: 300}});
+ test('Settings button on right of org header', async ({browser}, workerInfo) => {
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ const page = await context.newPage();
+
+ await page.goto('/org3');
+
+ const settingsBtn = page.locator('.overflow-menu-items>#settings-btn');
+ await expect(settingsBtn).toBeVisible();
+ await expect(settingsBtn).toHaveClass(/right/);
+
+ await expect(page.locator('.overflow-menu-button')).toHaveCount(0);
+ });
test('User overview overflow menu should not be influenced', async ({page}) => {
await page.goto('/user2');
@@ -54,14 +60,16 @@ test.describe('desktop viewport, unauthenticated', () => {
await expect(page.locator('.overflow-menu-items>#settings-btn')).toHaveCount(0);
await expect(page.locator('.overflow-menu-button')).toHaveCount(0);
- await save_visual(page);
});
});
test.describe('small viewport', () => {
- test.use({user: 'user2', viewport: {width: 800, height: 300}});
+ test.use({viewport: {width: 800, height: 300}});
+
+ test('Settings button in overflow menu of repo header', async ({browser}, workerInfo) => {
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ const page = await context.newPage();
- test('Settings button in overflow menu of repo header', async ({page}) => {
await page.goto('/user2/repo1');
await expect(page.locator('.overflow-menu-items>#settings-btn')).toHaveCount(0);
@@ -79,10 +87,12 @@ test.describe('small viewport', () => {
const items = shownItems.concat(overflowItems);
expect(Array.from(new Set(items))).toHaveLength(items.length);
- await save_visual(page);
});
- test('Settings button in overflow menu of org header', async ({page}) => {
+ test('Settings button in overflow menu of org header', async ({browser}, workerInfo) => {
+ const context = await load_logged_in_context(browser, workerInfo, 'user2');
+ const page = await context.newPage();
+
await page.goto('/org3');
await expect(page.locator('.overflow-menu-items>#settings-btn')).toHaveCount(0);
@@ -101,10 +111,6 @@ test.describe('small viewport', () => {
const items = shownItems.concat(overflowItems);
expect(Array.from(new Set(items))).toHaveLength(items.length);
});
-});
-
-test.describe('small viewport, unauthenticated', () => {
- test.use({viewport: {width: 800, height: 300}});
test('User overview overflow menu should not be influenced', async ({page}) => {
await page.goto('/user2');
@@ -123,6 +129,5 @@ test.describe('small viewport, unauthenticated', () => {
const items = shownItems.concat(overflowItems);
expect(Array.from(new Set(items))).toHaveLength(items.length);
- await save_visual(page);
});
});
diff --git a/tests/e2e/utils_e2e.ts b/tests/e2e/utils_e2e.ts
index ff921a2cf3..7e25441ea3 100644
--- a/tests/e2e/utils_e2e.ts
+++ b/tests/e2e/utils_e2e.ts
@@ -1,34 +1,21 @@
import {expect, test as baseTest, type Browser, type BrowserContextOptions, type APIRequestContext, type TestInfo, type Page} from '@playwright/test';
-import * as path from 'node:path';
-
-const AUTH_PATH = 'tests/e2e/.auth';
-
-type AuthScope = 'logout' | 'shared' | 'webauthn';
-
-export type TestOptions = {
- forEachTest: void
- user: string | null;
- authScope: AuthScope;
-};
-
-export const test = baseTest.extend
({
- context: async ({browser, user, authScope, contextOptions}, use, {project}) => {
- if (user && authScope) {
- const browserName = project.name.toLowerCase().replace(' ', '-');
- contextOptions.storageState = path.join(AUTH_PATH, `state-${browserName}-${user}-${authScope}.json`);
- } else {
- // if no user is given, ensure to have clean state
- contextOptions.storageState = {cookies: [], origins: []};
- }
-
- return use(await test_context(browser, contextOptions));
+export const test = baseTest.extend({
+ context: async ({browser}, use) => {
+ return use(await test_context(browser));
},
- user: null,
- authScope: 'shared',
+ // see https://playwright.dev/docs/test-fixtures#adding-global-beforeeachaftereach-hooks
+ forEachTest: [async ({page}, use) => {
+ await use();
+ // some tests create a new page which is not yet available here
+ // only operate on tests that make the URL available
+ if (page.url() !== 'about:blank') {
+ await save_visual(page);
+ }
+ }, {auto: true}],
});
-export async function test_context(browser: Browser, options?: BrowserContextOptions) {
+async function test_context(browser: Browser, options?: BrowserContextOptions) {
const context = await browser.newContext(options);
context.on('page', (page) => {
@@ -119,7 +106,6 @@ export async function save_visual(page: Page) {
// update order of recently created repos is not fully deterministic
page.locator('.flex-item-main').filter({hasText: 'relative time in repo'}),
page.locator('#activity-feed'),
- page.locator('#user-heatmap'),
// dynamic IDs in fixed-size inputs
page.locator('input[value*="dyn-id-"]'),
],
diff --git a/tests/e2e/utils_e2e_test.go b/tests/e2e/utils_e2e_test.go
index 96fd905363..bf1a8a418c 100644
--- a/tests/e2e/utils_e2e_test.go
+++ b/tests/e2e/utils_e2e_test.go
@@ -5,27 +5,17 @@ package e2e
import (
"context"
- "crypto/rand"
- "encoding/hex"
- "fmt"
"net"
"net/http"
"net/url"
"os"
- "path/filepath"
"regexp"
- "strings"
"testing"
"time"
- "code.gitea.io/gitea/models/unittest"
- user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/modules/json"
- modules_session "code.gitea.io/gitea/modules/session"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/tests"
- "code.forgejo.org/go-chi/session"
"github.com/stretchr/testify/require"
)
@@ -35,8 +25,6 @@ func onForgejoRunTB(t testing.TB, callback func(testing.TB, *url.URL), prepare .
if len(prepare) == 0 || prepare[0] {
defer tests.PrepareTestEnv(t, 1)()
}
- createSessions(t)
-
s := http.Server{
Handler: testE2eWebRoutes,
}
@@ -76,118 +64,3 @@ func onForgejoRun(t *testing.T, callback func(*testing.T, *url.URL), prepare ...
callback(t.(*testing.T), u)
}, prepare...)
}
-
-func createSessions(t testing.TB) {
- t.Helper()
- // copied from playwright.config.ts
- browsers := []string{
- "chromium",
- "firefox",
- "webkit",
- "Mobile Chrome",
- "Mobile Safari",
- }
- scopes := []string{
- "shared",
- }
- users := []string{
- "user1",
- "user2",
- "user12",
- "user40",
- }
-
- authState := filepath.Join(filepath.Dir(setting.AppPath), "tests", "e2e", ".auth")
- err := os.RemoveAll(authState)
- require.NoError(t, err)
-
- err = os.MkdirAll(authState, os.ModePerm)
- require.NoError(t, err)
-
- createSessionCookie := stateHelper(t)
-
- for _, user := range users {
- u := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: strings.ToLower(user)})
- for _, browser := range browsers {
- for _, scope := range scopes {
- stateFile := strings.ReplaceAll(strings.ToLower(fmt.Sprintf("state-%s-%s-%s.json", browser, user, scope)), " ", "-")
- createSessionCookie(filepath.Join(authState, stateFile), u)
- }
- }
- }
-}
-
-func stateHelper(t testing.TB) func(stateFile string, user *user_model.User) {
- type Cookie struct {
- Name string `json:"name"`
- Value string `json:"value"`
- Domain string `json:"domain"`
- Path string `json:"path"`
- Expires int `json:"expires"`
- HTTPOnly bool `json:"httpOnly"`
- Secure bool `json:"secure"`
- SameSite string `json:"sameSite"`
- }
-
- type BrowserState struct {
- Cookies []Cookie `json:"cookies"`
- Origins []string `json:"origins"`
- }
-
- options := session.Options{
- Provider: setting.SessionConfig.Provider,
- ProviderConfig: setting.SessionConfig.ProviderConfig,
- CookieName: setting.SessionConfig.CookieName,
- CookiePath: setting.SessionConfig.CookiePath,
- Gclifetime: setting.SessionConfig.Gclifetime,
- Maxlifetime: setting.SessionConfig.Maxlifetime,
- Secure: setting.SessionConfig.Secure,
- SameSite: setting.SessionConfig.SameSite,
- Domain: setting.SessionConfig.Domain,
- }
-
- opt := session.PrepareOptions([]session.Options{options})
-
- vsp := modules_session.VirtualSessionProvider{}
- err := vsp.Init(opt.Maxlifetime, opt.ProviderConfig)
- require.NoError(t, err)
-
- return func(stateFile string, user *user_model.User) {
- buf := make([]byte, opt.IDLength/2)
- _, err = rand.Read(buf)
- require.NoError(t, err)
-
- sessionID := hex.EncodeToString(buf)
-
- s, err := vsp.Read(sessionID)
- require.NoError(t, err)
-
- err = s.Set("uid", user.ID)
- require.NoError(t, err)
-
- err = s.Release()
- require.NoError(t, err)
-
- state := BrowserState{
- Cookies: []Cookie{
- {
- Name: opt.CookieName,
- Value: sessionID,
- Domain: setting.Domain,
- Path: "/",
- Expires: -1,
- HTTPOnly: true,
- Secure: false,
- SameSite: "Lax",
- },
- },
- Origins: []string{},
- }
-
- jsonData, err := json.Marshal(state)
- require.NoError(t, err)
-
- err = os.WriteFile(stateFile, jsonData, 0o644)
- require.NoError(t, err)
- }
-}
diff --git a/tests/integration/actions_variables_test.go b/tests/integration/actions_variables_test.go
deleted file mode 100644
index 0179a543dc..0000000000
--- a/tests/integration/actions_variables_test.go
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2025 The Forgejo Authors. All rights reserved.
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-package integration
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- actions_model "code.gitea.io/gitea/models/actions"
- repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/models/unittest"
- user_model "code.gitea.io/gitea/models/user"
- forgejo_context "code.gitea.io/gitea/services/context"
- "code.gitea.io/gitea/tests"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestActionVariablesModification(t *testing.T) {
- defer tests.AddFixtures("tests/integration/fixtures/TestActionVariablesModification")()
- defer tests.PrepareTestEnv(t)()
-
- user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
- userVariable := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{ID: 1001, OwnerID: user.ID})
- userURL := "/user/settings/actions/variables"
- org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3, Type: user_model.UserTypeOrganization})
- orgVariable := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{ID: 1002, OwnerID: org.ID})
- orgURL := "/org/" + org.Name + "/settings/actions/variables"
- repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1, OwnerID: user.ID})
- repoVariable := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{ID: 1003, RepoID: repo.ID})
- repoURL := "/" + repo.FullName() + "/settings/actions/variables"
- admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true})
- globalVariable := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{ID: 1004}, "owner_id = 0 AND repo_id = 0")
- adminURL := "/admin/actions/variables"
-
- adminSess := loginUser(t, admin.Name)
- adminCSRF := GetCSRF(t, adminSess, "/")
- sess := loginUser(t, user.Name)
- csrf := GetCSRF(t, sess, "/")
-
- type errorJSON struct {
- Error string `json:"errorMessage"`
- }
-
- test := func(t *testing.T, fail bool, baseURL string, id int64) {
- defer tests.PrintCurrentTest(t, 1)()
- t.Helper()
-
- sess := sess
- csrf := csrf
- if baseURL == adminURL {
- sess = adminSess
- csrf = adminCSRF
- }
-
- req := NewRequestWithValues(t, "POST", baseURL+fmt.Sprintf("/%d/edit", id), map[string]string{
- "_csrf": csrf,
- "name": "glados_quote",
- "data": "I'm fine. Two plus two is...ten, in base four, I'm fine!",
- })
- if fail {
- resp := sess.MakeRequest(t, req, http.StatusBadRequest)
- var error errorJSON
- DecodeJSON(t, resp, &error)
- assert.EqualValues(t, "Failed to find the variable.", error.Error)
- } else {
- sess.MakeRequest(t, req, http.StatusOK)
- flashCookie := sess.GetCookie(forgejo_context.CookieNameFlash)
- assert.NotNil(t, flashCookie)
- assert.EqualValues(t, "success%3DThe%2Bvariable%2Bhas%2Bbeen%2Bedited.", flashCookie.Value)
- }
-
- req = NewRequestWithValues(t, "POST", baseURL+fmt.Sprintf("/%d/delete", id), map[string]string{
- "_csrf": csrf,
- })
- if fail {
- resp := sess.MakeRequest(t, req, http.StatusBadRequest)
- var error errorJSON
- DecodeJSON(t, resp, &error)
- assert.EqualValues(t, "Failed to find the variable.", error.Error)
- } else {
- sess.MakeRequest(t, req, http.StatusOK)
- flashCookie := sess.GetCookie(forgejo_context.CookieNameFlash)
- assert.NotNil(t, flashCookie)
- assert.EqualValues(t, "success%3DThe%2Bvariable%2Bhas%2Bbeen%2Bremoved.", flashCookie.Value)
- }
- }
-
- t.Run("User variable", func(t *testing.T) {
- t.Run("Organisation", func(t *testing.T) {
- test(t, true, orgURL, userVariable.ID)
- })
- t.Run("Repository", func(t *testing.T) {
- test(t, true, repoURL, userVariable.ID)
- })
- t.Run("Admin", func(t *testing.T) {
- test(t, true, adminURL, userVariable.ID)
- })
- t.Run("User", func(t *testing.T) {
- test(t, false, userURL, userVariable.ID)
- })
- })
-
- t.Run("Organisation variable", func(t *testing.T) {
- t.Run("Repository", func(t *testing.T) {
- test(t, true, repoURL, orgVariable.ID)
- })
- t.Run("User", func(t *testing.T) {
- test(t, true, userURL, orgVariable.ID)
- })
- t.Run("Admin", func(t *testing.T) {
- test(t, true, adminURL, userVariable.ID)
- })
- t.Run("Organisation", func(t *testing.T) {
- test(t, false, orgURL, orgVariable.ID)
- })
- })
-
- t.Run("Repository variable", func(t *testing.T) {
- t.Run("Organisation", func(t *testing.T) {
- test(t, true, orgURL, repoVariable.ID)
- })
- t.Run("User", func(t *testing.T) {
- test(t, true, userURL, repoVariable.ID)
- })
- t.Run("Admin", func(t *testing.T) {
- test(t, true, adminURL, userVariable.ID)
- })
- t.Run("Repository", func(t *testing.T) {
- test(t, false, repoURL, repoVariable.ID)
- })
- })
-
- t.Run("Global variable", func(t *testing.T) {
- t.Run("Organisation", func(t *testing.T) {
- test(t, true, orgURL, globalVariable.ID)
- })
- t.Run("User", func(t *testing.T) {
- test(t, true, userURL, globalVariable.ID)
- })
- t.Run("Repository", func(t *testing.T) {
- test(t, true, repoURL, globalVariable.ID)
- })
- t.Run("Admin", func(t *testing.T) {
- test(t, false, adminURL, globalVariable.ID)
- })
- })
-}
diff --git a/tests/integration/api_token_test.go b/tests/integration/api_token_test.go
index f94a0986f2..01d18ef6f1 100644
--- a/tests/integration/api_token_test.go
+++ b/tests/integration/api_token_test.go
@@ -30,23 +30,6 @@ func TestAPICreateAndDeleteToken(t *testing.T) {
deleteAPIAccessToken(t, newAccessToken, user)
}
-func TestAPIGetTokens(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
- user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
-
- // with basic auth...
- req := NewRequest(t, "GET", "/api/v1/users/user2/tokens").
- AddBasicAuth(user.Name)
- MakeRequest(t, req, http.StatusOK)
-
- // ... or with a token.
- newAccessToken := createAPIAccessTokenWithoutCleanUp(t, "test-key-1", user, []auth_model.AccessTokenScope{auth_model.AccessTokenScopeAll})
- req = NewRequest(t, "GET", "/api/v1/users/user2/tokens").
- AddTokenAuth(newAccessToken.Token)
- MakeRequest(t, req, http.StatusOK)
- deleteAPIAccessToken(t, newAccessToken, user)
-}
-
// TestAPIDeleteMissingToken ensures that error is thrown when token not found
func TestAPIDeleteMissingToken(t *testing.T) {
defer tests.PrepareTestEnv(t)()
diff --git a/tests/integration/explore_org_test.go b/tests/integration/explore_org_test.go
deleted file mode 100644
index e0c48ccf0d..0000000000
--- a/tests/integration/explore_org_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2024 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-package integration
-
-import (
- "net/http"
- "testing"
-
- "code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/test"
- "code.gitea.io/gitea/tests"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestExploreOrg(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
-
- // Set the default sort order
- defer test.MockVariableValue(&setting.UI.ExploreDefaultSort, "alphabetically")()
-
- cases := []struct{ sortOrder, expected string }{
- {"", "?sort=" + setting.UI.ExploreDefaultSort + "&q="},
- {"newest", "?sort=newest&q="},
- {"oldest", "?sort=oldest&q="},
- {"alphabetically", "?sort=alphabetically&q="},
- {"reversealphabetically", "?sort=reversealphabetically&q="},
- }
- for _, c := range cases {
- req := NewRequest(t, "GET", "/explore/organizations?sort="+c.sortOrder)
- resp := MakeRequest(t, req, http.StatusOK)
- h := NewHTMLParser(t, resp.Body)
- href, _ := h.Find(`.ui.dropdown .menu a.active.item[href^="?sort="]`).Attr("href")
- assert.Equal(t, c.expected, href)
- }
-
- // these sort orders shouldn't be supported, to avoid leaking user activity
- cases404 := []string{
- "/explore/organizations?sort=mostMembers",
- "/explore/organizations?sort=leastGroups",
- "/explore/organizations?sort=leastupdate",
- "/explore/organizations?sort=reverseleastupdate",
- }
- for _, c := range cases404 {
- req := NewRequest(t, "GET", c).SetHeader("Accept", "text/html")
- MakeRequest(t, req, http.StatusNotFound)
- }
-}
diff --git a/tests/integration/explore_user_test.go b/tests/integration/explore_user_test.go
index d1e3fd85af..441d89cea5 100644
--- a/tests/integration/explore_user_test.go
+++ b/tests/integration/explore_user_test.go
@@ -7,8 +7,6 @@ import (
"net/http"
"testing"
- "code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
@@ -17,11 +15,8 @@ import (
func TestExploreUser(t *testing.T) {
defer tests.PrepareTestEnv(t)()
- // Set the default sort order
- defer test.MockVariableValue(&setting.UI.ExploreDefaultSort, "reversealphabetically")()
-
cases := []struct{ sortOrder, expected string }{
- {"", "?sort=" + setting.UI.ExploreDefaultSort + "&q="},
+ {"", "?sort=newest&q="},
{"newest", "?sort=newest&q="},
{"oldest", "?sort=oldest&q="},
{"alphabetically", "?sort=alphabetically&q="},
diff --git a/tests/integration/fixtures/TestActionVariablesModification/action_variable.yml b/tests/integration/fixtures/TestActionVariablesModification/action_variable.yml
deleted file mode 100644
index 925838d0f0..0000000000
--- a/tests/integration/fixtures/TestActionVariablesModification/action_variable.yml
+++ /dev/null
@@ -1,31 +0,0 @@
--
- id: 1001
- name: GLADOS_QUOTE
- owner_id: 2
- repo_id: 0
- data: ""
- created_unix: 1737000000
-
--
- id: 1002
- name: GLADOS_QUOTE
- owner_id: 3
- repo_id: 0
- data: ""
- created_unix: 1737000001
-
--
- id: 1003
- name: GLADOS_QUOTE
- owner_id: 0
- repo_id: 1
- data: ""
- created_unix: 1737000002
-
--
- id: 1004
- name: GLADOS_QUOTE
- owner_id: 0
- repo_id: 0
- data: ""
- created_unix: 1737000003
diff --git a/tests/integration/fixtures/TestRunnerModification/action_runner.yml b/tests/integration/fixtures/TestRunnerModification/action_runner.yml
deleted file mode 100644
index 95599b19bd..0000000000
--- a/tests/integration/fixtures/TestRunnerModification/action_runner.yml
+++ /dev/null
@@ -1,31 +0,0 @@
--
- id: 1001
- uuid: "43b5d4d3-401b-42f9-94df-a9d45b447b82"
- name: "User runner"
- owner_id: 2
- repo_id: 0
- deleted: 0
-
--
- id: 1002
- uuid: "bdc77f4f-2b2b-442d-bd44-e808f4306347"
- name: "Organisation runner"
- owner_id: 3
- repo_id: 0
- deleted: 0
-
--
- id: 1003
- uuid: "9268bc8c-efbf-4dbe-aeb5-945733cdd098"
- name: "Repository runner"
- owner_id: 0
- repo_id: 1
- deleted: 0
-
--
- id: 1004
- uuid: "fb857e63-c0ce-4571-a6c9-fde26c128073"
- name: "Global runner"
- owner_id: 0
- repo_id: 0
- deleted: 0
diff --git a/tests/integration/issue_test.go b/tests/integration/issue_test.go
index 3cdb0b8a28..4c0a64ad70 100644
--- a/tests/integration/issue_test.go
+++ b/tests/integration/issue_test.go
@@ -1336,46 +1336,3 @@ func TestIssueCount(t *testing.T) {
allCount := htmlDoc.doc.Find("a[data-test-name='all-issue-count']").Text()
assert.Contains(t, allCount, "2\u00a0All")
}
-
-func TestIssuePostersSearch(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
-
- type userSearchInfo struct {
- UserID int64 `json:"user_id"`
- UserName string `json:"username"`
- }
-
- type userSearchResponse struct {
- Results []*userSearchInfo `json:"results"`
- }
-
- t.Run("Name search", func(t *testing.T) {
- defer tests.PrintCurrentTest(t)()
- defer test.MockVariableValue(&setting.UI.DefaultShowFullName, false)()
-
- req := NewRequest(t, "GET", "/user2/repo1/issues/posters?q=USer2")
- resp := MakeRequest(t, req, http.StatusOK)
-
- var data userSearchResponse
- DecodeJSON(t, resp, &data)
-
- assert.Len(t, data.Results, 1)
- assert.EqualValues(t, "user2", data.Results[0].UserName)
- assert.EqualValues(t, 2, data.Results[0].UserID)
- })
-
- t.Run("Full name search", func(t *testing.T) {
- defer tests.PrintCurrentTest(t)()
- defer test.MockVariableValue(&setting.UI.DefaultShowFullName, true)()
-
- req := NewRequest(t, "GET", "/user2/repo1/issues/posters?q=OnE")
- resp := MakeRequest(t, req, http.StatusOK)
-
- var data userSearchResponse
- DecodeJSON(t, resp, &data)
-
- assert.Len(t, data.Results, 1)
- assert.EqualValues(t, "user1", data.Results[0].UserName)
- assert.EqualValues(t, 1, data.Results[0].UserID)
- })
-}
diff --git a/tests/integration/private_project_test.go b/tests/integration/private_project_test.go
deleted file mode 100644
index 1a4adb4366..0000000000
--- a/tests/integration/private_project_test.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2025 The Forgejo Authors. All rights reserved.
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-package integration
-
-import (
- "net/http"
- "strings"
- "testing"
-
- org_model "code.gitea.io/gitea/models/organization"
- project_model "code.gitea.io/gitea/models/project"
- "code.gitea.io/gitea/models/unittest"
- user_model "code.gitea.io/gitea/models/user"
- "code.gitea.io/gitea/tests"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestPrivateIssueProject(t *testing.T) {
- defer tests.AddFixtures("models/fixtures/PrivateIssueProjects/")()
- defer tests.PrepareTestEnv(t)()
-
- user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
- sess := loginUser(t, user2.Name)
-
- test := func(t *testing.T, sess *TestSession, username string, projectID int64, hasAccess bool) {
- t.Helper()
- defer tests.PrintCurrentTest(t, 1)()
-
- // Test that the projects overview page shows the correct open and close issues.
- req := NewRequestf(t, "GET", "%s/-/projects", username)
- resp := sess.MakeRequest(t, req, http.StatusOK)
-
- htmlDoc := NewHTMLParser(t, resp.Body)
- openCloseStats := htmlDoc.Find(".milestone-toolbar .group").First().Text()
- if hasAccess {
- assert.Contains(t, openCloseStats, "1\u00a0Open")
- } else {
- assert.Contains(t, openCloseStats, "0\u00a0Open")
- }
- assert.Contains(t, openCloseStats, "0\u00a0Closed")
-
- // Check that on the project itself the issue is not shown.
- req = NewRequestf(t, "GET", "%s/-/projects/%d", username, projectID)
- resp = sess.MakeRequest(t, req, http.StatusOK)
-
- htmlDoc = NewHTMLParser(t, resp.Body)
- htmlDoc.AssertElement(t, ".project-column .issue-card", hasAccess)
-
- // And that the issue count is correct.
- issueCount := strings.TrimSpace(htmlDoc.Find(".project-column-issue-count").Text())
- if hasAccess {
- assert.EqualValues(t, "1", issueCount)
- } else {
- assert.EqualValues(t, "0", issueCount)
- }
- }
-
- t.Run("Organization project", func(t *testing.T) {
- org := unittest.AssertExistsAndLoadBean(t, &org_model.Organization{ID: 3})
- orgProject := unittest.AssertExistsAndLoadBean(t, &project_model.Project{ID: 1001, OwnerID: org.ID})
-
- t.Run("Authenticated user", func(t *testing.T) {
- test(t, sess, org.Name, orgProject.ID, true)
- })
-
- t.Run("Anonymous user", func(t *testing.T) {
- test(t, emptyTestSession(t), org.Name, orgProject.ID, false)
- })
- })
-
- t.Run("User project", func(t *testing.T) {
- userProject := unittest.AssertExistsAndLoadBean(t, &project_model.Project{ID: 1002, OwnerID: user2.ID})
-
- t.Run("Authenticated user", func(t *testing.T) {
- test(t, sess, user2.Name, userProject.ID, true)
- })
-
- t.Run("Anonymous user", func(t *testing.T) {
- test(t, emptyTestSession(t), user2.Name, userProject.ID, false)
- })
- })
-}
diff --git a/tests/integration/pull_icon_test.go b/tests/integration/pull_icon_test.go
index b678550c30..8fde547ce9 100644
--- a/tests/integration/pull_icon_test.go
+++ b/tests/integration/pull_icon_test.go
@@ -133,7 +133,7 @@ func testPullRequestListIcon(t *testing.T, doc *HTMLDoc, name, expectedColor, ex
}
func createOpenPullRequest(ctx context.Context, t *testing.T, user *user_model.User, repo *repo_model.Repository) *issues_model.PullRequest {
- pull := createPullRequest(t, user, repo, "branch-open", "open")
+ pull := createPullRequest(t, user, repo, "open")
assert.False(t, pull.Issue.IsClosed)
assert.False(t, pull.HasMerged)
@@ -143,7 +143,7 @@ func createOpenPullRequest(ctx context.Context, t *testing.T, user *user_model.U
}
func createOpenWipPullRequest(ctx context.Context, t *testing.T, user *user_model.User, repo *repo_model.Repository) *issues_model.PullRequest {
- pull := createPullRequest(t, user, repo, "branch-open-wip", "open-wip")
+ pull := createPullRequest(t, user, repo, "open-wip")
err := issue_service.ChangeTitle(ctx, pull.Issue, user, "WIP: "+pull.Issue.Title)
require.NoError(t, err)
@@ -156,7 +156,7 @@ func createOpenWipPullRequest(ctx context.Context, t *testing.T, user *user_mode
}
func createClosedPullRequest(ctx context.Context, t *testing.T, user *user_model.User, repo *repo_model.Repository) *issues_model.PullRequest {
- pull := createPullRequest(t, user, repo, "branch-closed", "closed")
+ pull := createPullRequest(t, user, repo, "closed")
err := issue_service.ChangeStatus(ctx, pull.Issue, user, "", true)
require.NoError(t, err)
@@ -169,7 +169,7 @@ func createClosedPullRequest(ctx context.Context, t *testing.T, user *user_model
}
func createClosedWipPullRequest(ctx context.Context, t *testing.T, user *user_model.User, repo *repo_model.Repository) *issues_model.PullRequest {
- pull := createPullRequest(t, user, repo, "branch-closed-wip", "closed-wip")
+ pull := createPullRequest(t, user, repo, "closed-wip")
err := issue_service.ChangeTitle(ctx, pull.Issue, user, "WIP: "+pull.Issue.Title)
require.NoError(t, err)
@@ -185,7 +185,7 @@ func createClosedWipPullRequest(ctx context.Context, t *testing.T, user *user_mo
}
func createMergedPullRequest(ctx context.Context, t *testing.T, user *user_model.User, repo *repo_model.Repository) *issues_model.PullRequest {
- pull := createPullRequest(t, user, repo, "branch-merged", "merged")
+ pull := createPullRequest(t, user, repo, "merged")
gitRepo, err := git.OpenRepository(ctx, repo.RepoPath())
defer gitRepo.Close()
@@ -202,7 +202,10 @@ func createMergedPullRequest(ctx context.Context, t *testing.T, user *user_model
return pull
}
-func createPullRequest(t *testing.T, user *user_model.User, repo *repo_model.Repository, branch, title string) *issues_model.PullRequest {
+func createPullRequest(t *testing.T, user *user_model.User, repo *repo_model.Repository, name string) *issues_model.PullRequest {
+ branch := "branch-" + name
+ title := "Testing " + name
+
_, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user, &files_service.ChangeRepoFilesOptions{
Files: []*files_service.ChangeRepoFile{
{
diff --git a/tests/integration/pull_review_test.go b/tests/integration/pull_review_test.go
index e1db171f16..1319db29bf 100644
--- a/tests/integration/pull_review_test.go
+++ b/tests/integration/pull_review_test.go
@@ -518,7 +518,7 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) {
resp := testPullCreate(t, user1Session, "user1", "repo1", false, "master", "a-test-branch", "This is a pull title")
elem := strings.Split(test.RedirectURL(resp), "/")
assert.EqualValues(t, "pulls", elem[3])
- testIssueClose(t, user1Session, elem[1], elem[2], elem[4], true)
+ testIssueClose(t, user1Session, elem[1], elem[2], elem[4])
// Get the commit SHA
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{
@@ -579,12 +579,8 @@ func testSubmitReview(t *testing.T, session *TestSession, csrf, owner, repo, pul
return session.MakeRequest(t, req, expectedSubmitStatus)
}
-func testIssueClose(t *testing.T, session *TestSession, owner, repo, issueNumber string, isPull bool) *httptest.ResponseRecorder {
- issueType := "issues"
- if isPull {
- issueType = "pulls"
- }
- req := NewRequest(t, "GET", path.Join(owner, repo, issueType, issueNumber))
+func testIssueClose(t *testing.T, session *TestSession, owner, repo, issueNumber string) *httptest.ResponseRecorder {
+ req := NewRequest(t, "GET", path.Join(owner, repo, "pulls", issueNumber))
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
diff --git a/tests/integration/repo_test.go b/tests/integration/repo_test.go
index 01d905895a..90fc19c193 100644
--- a/tests/integration/repo_test.go
+++ b/tests/integration/repo_test.go
@@ -1462,15 +1462,3 @@ func TestRepoSubmoduleView(t *testing.T) {
htmlDoc.AssertElement(t, fmt.Sprintf(`tr[data-entryname="repo1"] a[href="%s"]`, u.JoinPath("/user2/repo1").String()), true)
})
}
-
-func TestBlameDirectory(t *testing.T) {
- defer tests.PrepareTestEnv(t)()
-
- // Ensure directory exists.
- req := NewRequest(t, "GET", "/user2/repo59/src/branch/master/deep")
- MakeRequest(t, req, http.StatusOK)
-
- // Blame is not allowed
- req = NewRequest(t, "GET", "/user2/repo59/blame/branch/master/deep")
- MakeRequest(t, req, http.StatusNotFound)
-}
diff --git a/tests/integration/runner_test.go b/tests/integration/runner_test.go
deleted file mode 100644
index bab2a67230..0000000000
--- a/tests/integration/runner_test.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2025 The Forgejo Authors. All rights reserved.
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-package integration
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- actions_model "code.gitea.io/gitea/models/actions"
- repo_model "code.gitea.io/gitea/models/repo"
- "code.gitea.io/gitea/models/unittest"
- user_model "code.gitea.io/gitea/models/user"
- forgejo_context "code.gitea.io/gitea/services/context"
- "code.gitea.io/gitea/tests"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestRunnerModification(t *testing.T) {
- defer tests.AddFixtures("tests/integration/fixtures/TestRunnerModification")()
- defer tests.PrepareTestEnv(t)()
-
- user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
- userRunner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 1001, OwnerID: user.ID})
- userURL := "/user/settings/actions/runners"
- org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3, Type: user_model.UserTypeOrganization})
- orgRunner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 1002, OwnerID: org.ID})
- orgURL := "/org/" + org.Name + "/settings/actions/runners"
- repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1, OwnerID: user.ID})
- repoRunner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 1003, RepoID: repo.ID})
- repoURL := "/" + repo.FullName() + "/settings/actions/runners"
- admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true})
- globalRunner := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunner{ID: 1004}, "owner_id = 0 AND repo_id = 0")
- adminURL := "/admin/actions/runners"
-
- adminSess := loginUser(t, admin.Name)
- adminCSRF := GetCSRF(t, adminSess, "/")
- sess := loginUser(t, user.Name)
- csrf := GetCSRF(t, sess, "/")
-
- test := func(t *testing.T, fail bool, baseURL string, id int64) {
- defer tests.PrintCurrentTest(t, 1)()
- t.Helper()
-
- sess := sess
- csrf := csrf
- if baseURL == adminURL {
- sess = adminSess
- csrf = adminCSRF
- }
-
- req := NewRequestWithValues(t, "POST", baseURL+fmt.Sprintf("/%d", id), map[string]string{
- "_csrf": csrf,
- "description": "New Description",
- })
- if fail {
- sess.MakeRequest(t, req, http.StatusNotFound)
- } else {
- sess.MakeRequest(t, req, http.StatusSeeOther)
- flashCookie := sess.GetCookie(forgejo_context.CookieNameFlash)
- assert.NotNil(t, flashCookie)
- assert.EqualValues(t, "success%3DRunner%2Bupdated%2Bsuccessfully", flashCookie.Value)
- }
-
- req = NewRequestWithValues(t, "POST", baseURL+fmt.Sprintf("/%d/delete", id), map[string]string{
- "_csrf": csrf,
- })
- if fail {
- sess.MakeRequest(t, req, http.StatusNotFound)
- } else {
- sess.MakeRequest(t, req, http.StatusOK)
- flashCookie := sess.GetCookie(forgejo_context.CookieNameFlash)
- assert.NotNil(t, flashCookie)
- assert.EqualValues(t, "success%3DRunner%2Bdeleted%2Bsuccessfully", flashCookie.Value)
- }
- }
-
- t.Run("User runner", func(t *testing.T) {
- t.Run("Organisation", func(t *testing.T) {
- test(t, true, orgURL, userRunner.ID)
- })
- t.Run("Repository", func(t *testing.T) {
- test(t, true, repoURL, userRunner.ID)
- })
- t.Run("User", func(t *testing.T) {
- test(t, false, userURL, userRunner.ID)
- })
- })
-
- t.Run("Organisation runner", func(t *testing.T) {
- t.Run("Repository", func(t *testing.T) {
- test(t, true, repoURL, orgRunner.ID)
- })
- t.Run("User", func(t *testing.T) {
- test(t, true, userURL, orgRunner.ID)
- })
- t.Run("Organisation", func(t *testing.T) {
- test(t, false, orgURL, orgRunner.ID)
- })
- })
-
- t.Run("Repository runner", func(t *testing.T) {
- t.Run("Organisation", func(t *testing.T) {
- test(t, true, orgURL, repoRunner.ID)
- })
- t.Run("User", func(t *testing.T) {
- test(t, true, userURL, repoRunner.ID)
- })
- t.Run("Repository", func(t *testing.T) {
- test(t, false, repoURL, repoRunner.ID)
- })
- })
-
- t.Run("Global runner", func(t *testing.T) {
- t.Run("Organisation", func(t *testing.T) {
- test(t, true, orgURL, globalRunner.ID)
- })
- t.Run("User", func(t *testing.T) {
- test(t, true, userURL, globalRunner.ID)
- })
- t.Run("Repository", func(t *testing.T) {
- test(t, true, repoURL, globalRunner.ID)
- })
- t.Run("Admin", func(t *testing.T) {
- test(t, false, adminURL, globalRunner.ID)
- })
- })
-}
diff --git a/tests/integration/user_dashboard_test.go b/tests/integration/user_dashboard_test.go
index 0ed5193c48..abc3e065d9 100644
--- a/tests/integration/user_dashboard_test.go
+++ b/tests/integration/user_dashboard_test.go
@@ -5,21 +5,12 @@ package integration
import (
"net/http"
- "net/url"
- "strconv"
"strings"
"testing"
- "code.gitea.io/gitea/models/db"
- unit_model "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
- user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/translation"
- issue_service "code.gitea.io/gitea/services/issue"
- files_service "code.gitea.io/gitea/services/repository/files"
- "code.gitea.io/gitea/tests"
- "github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -37,45 +28,3 @@ func TestUserDashboardActionLinks(t *testing.T) {
assert.EqualValues(t, locale.TrString("new_migrate.link"), strings.TrimSpace(links.Find("a[href='/repo/migrate']").Text()))
assert.EqualValues(t, locale.TrString("new_org.link"), strings.TrimSpace(links.Find("a[href='/org/create']").Text()))
}
-
-func TestDashboardTitleRendering(t *testing.T) {
- onGiteaRun(t, func(t *testing.T, u *url.URL) {
- user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
- sess := loginUser(t, user4.Name)
-
- repo, _, f := tests.CreateDeclarativeRepo(t, user4, "",
- []unit_model.Type{unit_model.TypePullRequests, unit_model.TypeIssues}, nil,
- []*files_service.ChangeRepoFile{
- {
- Operation: "create",
- TreePath: "test.txt",
- ContentReader: strings.NewReader("Just some text here"),
- },
- },
- )
- defer f()
-
- issue := createIssue(t, user4, repo, "`:exclamation:` not rendered", "Hi there!")
- pr := createPullRequest(t, user4, repo, "testing", "`:exclamation:` not rendered")
-
- _, err := issue_service.CreateIssueComment(db.DefaultContext, user4, repo, issue, "hi", nil)
- require.NoError(t, err)
-
- _, err = issue_service.CreateIssueComment(db.DefaultContext, user4, repo, pr.Issue, "hi", nil)
- require.NoError(t, err)
-
- testIssueClose(t, sess, repo.OwnerName, repo.Name, strconv.Itoa(int(issue.Index)), false)
- testIssueClose(t, sess, repo.OwnerName, repo.Name, strconv.Itoa(int(pr.Issue.Index)), true)
-
- response := sess.MakeRequest(t, NewRequest(t, "GET", "/"), http.StatusOK)
- htmlDoc := NewHTMLParser(t, response.Body)
-
- count := 0
- htmlDoc.doc.Find("#activity-feed .flex-item-main .title").Each(func(i int, s *goquery.Selection) {
- count++
- assert.EqualValues(t, ":exclamation: not rendered", s.Text())
- })
-
- assert.EqualValues(t, 6, count)
- })
-}
diff --git a/web_src/css/features/gitgraph.css b/web_src/css/features/gitgraph.css
index 726ac7e9e2..4da871da61 100644
--- a/web_src/css/features/gitgraph.css
+++ b/web_src/css/features/gitgraph.css
@@ -23,18 +23,6 @@
#git-graph-heading {
align-items: center;
}
-
- #git-graph-heading-left {
- margin-right: 1rem;
- }
-
- #git-graph-heading h2 {
- flex-shrink: 0;
- }
-
- #git-graph-container #flow-select-refs-dropdown {
- min-width: 250px;
- }
}
@media (max-width: 767.98px) {
@@ -46,10 +34,15 @@
#git-graph-heading-left {
margin-bottom: 1rem;
}
+
+ h2,
+ #flow-select-refs-dropdown {
+ max-width: 100%;
+ }
}
#git-graph-container #flow-select-refs-dropdown {
- flex-wrap: wrap;
+ min-width: 250px;
}
#git-graph-container #flow-select-refs-dropdown .ui.label {
diff --git a/web_src/css/repo.css b/web_src/css/repo.css
index c3f3292dd4..651c69c703 100644
--- a/web_src/css/repo.css
+++ b/web_src/css/repo.css
@@ -2426,11 +2426,6 @@ details.repo-search-result summary::marker {
padding-right: 22px !important; /* normal buttons have !important paddings, so we need to override it for dropdown (Add File) icons */
}
-.repo-button-row .button strong {
- /* Workaround where 'overflow: hidden' is clipping the y-axis, force a small amount of extra padding in the y-axis. */
- padding: .1em 0;
-}
-
.repo-button-row input {
height: 30px;
}
diff --git a/web_src/js/components/DashboardRepoList.vue b/web_src/js/components/DashboardRepoList.vue
index 0d8396b6f3..007891a39f 100644
--- a/web_src/js/components/DashboardRepoList.vue
+++ b/web_src/js/components/DashboardRepoList.vue
@@ -1,5 +1,5 @@