-
+
+ + diff --git a/templates/user/settings/navbar.tmpl b/templates/user/settings/navbar.tmpl index d45d89ee9f..eadf2ee9e5 100644 --- a/templates/user/settings/navbar.tmpl +++ b/templates/user/settings/navbar.tmpl @@ -51,6 +51,11 @@ {{ctx.Locale.Tr "settings.repos"}} + {{if .EnableQuota}} + + {{ctx.Locale.Tr "settings.storage_overview"}} + + {{end}} {{ctx.Locale.Tr "settings.blocked_users"}} diff --git a/templates/user/settings/profile.tmpl b/templates/user/settings/profile.tmpl index 5ecaada4e2..3bc8800a76 100644 --- a/templates/user/settings/profile.tmpl +++ b/templates/user/settings/profile.tmpl @@ -16,7 +16,11 @@ {{else}} {{ctx.Locale.Tr "settings.change_username_prompt"}} + {{if gt .CooldownPeriod 0}} + {{ctx.Locale.TrN .CooldownPeriod "settings.change_username_redirect_prompt.with_cooldown.one" "settings.change_username_redirect_prompt.with_cooldown.few" .CooldownPeriod}} + {{else}} {{ctx.Locale.Tr "settings.change_username_redirect_prompt"}} + {{end}} {{end}} @@ -26,38 +30,14 @@ -
-
- +
diff --git a/templates/user/settings/storage_overview.tmpl b/templates/user/settings/storage_overview.tmpl new file mode 100644 index 0000000000..daa0cbd913 --- /dev/null +++ b/templates/user/settings/storage_overview.tmpl @@ -0,0 +1,5 @@ +{{template "user/settings/layout_head" (dict "ctxData" . "pageClass" "user settings size-overview")}} +
+ {{template "shared/quota_overview" .}} +
+{{template "user/settings/layout_footer" .}} diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 8d8858bfd5..35fc5e7d1d 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -250,16 +250,18 @@ test('For anyone', async ({page}) => { If you need a user account, you can use something like: ~~~js -import {test, login_user, login} from './utils_e2e.ts'; +import {test} from './utils_e2e.ts'; -test.beforeAll(async ({browser}, workerInfo) => { - await login_user(browser, workerInfo, 'user2'); // or another user -}); +// reuse user2 token from scope `shared` +test.use({user: 'user2', authScope: 'shared'}) -test('For signed users only', async ({browser}, workerInfo) => { - const page = await login({browser}, workerInfo); +test('For signed users only', async ({page}) => { + +}) ~~~ +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 a66b608080..4e93b89ee0 100644 --- a/tests/e2e/actions.test.e2e.ts +++ b/tests/e2e/actions.test.e2e.ts @@ -10,76 +10,66 @@ // @watch end import {expect} from '@playwright/test'; -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'); -}); +import {save_visual, test} from './utils_e2e.ts'; 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 ({browser}, workerInfo) => { - const context = await load_logged_in_context(browser, workerInfo, 'user2'); - const page = await context.newPage(); + test('workflow dispatch present', async ({page}) => { + await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0'); - await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0'); + await expect(page.getByText(workflow_trigger_notification_text)).toBeVisible(); - await expect(page.getByText(workflow_trigger_notification_text)).toBeVisible(); + const run_workflow_btn = page.locator('#workflow_dispatch_dropdown>button'); + await expect(run_workflow_btn).toBeVisible(); - 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'); + 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); }); - await page.locator('#workflow-dispatch-submit').click(); + 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 expect(page.getByText('Require value for input "String w/o. default".')).toBeVisible(); - await save_visual(page); -}); + await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0'); -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'); + await page.locator('#workflow_dispatch_dropdown>button').click(); - const context = await load_logged_in_context(browser, workerInfo, 'user2'); - const page = await context.newPage(); + // 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'); + }); - await page.goto('/user2/test_workflows/actions?workflow=test-dispatch.yml&actor=0&status=0'); + await page.locator('#workflow-dispatch-submit').click(); - await page.locator('#workflow_dispatch_dropdown>button').click(); + await expect(page.getByText('Require value for input "String w/o. default".')).toBeVisible(); + await save_visual(page); + }); - await page.fill('input[name="inputs[string2]"]', 'abc'); - await save_visual(page); - await page.locator('#workflow-dispatch-submit').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 expect(page.getByText('Workflow run was successfully requested.')).toBeVisible(); + await page.locator('#workflow_dispatch_dropdown>button').click(); - await expect(page.locator('.run-list>:first-child .run-list-meta', {hasText: 'now'})).toBeVisible(); - await save_visual(page); + 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); + }); }); 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/changes.go b/tests/e2e/changes.go index 1e5533bc6b..d1d318fd06 100644 --- a/tests/e2e/changes.go +++ b/tests/e2e/changes.go @@ -8,7 +8,7 @@ import ( "os" "strings" - "code.gitea.io/gitea/modules/log" + "forgejo.org/modules/log" "github.com/gobwas/glob" ) diff --git a/tests/e2e/clipboard-copy.test.e2e.ts b/tests/e2e/clipboard-copy.test.e2e.ts index 70a3425868..2517d07463 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 {test} from './utils_e2e.ts'; +import {save_visual, 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,6 +19,8 @@ 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 expect(page.getByText('Copied')).toBeVisible(); + await save_visual(page); }); test('copy diff file path to clipboard', async ({page}, workerInfo) => { @@ -30,4 +32,6 @@ 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 1d23122b44..d35fe299ff 100644 --- a/tests/e2e/dashboard-ci-status.test.e2e.ts +++ b/tests/e2e/dashboard-ci-status.test.e2e.ts @@ -3,22 +3,26 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, save_visual, load_logged_in_context} from './utils_e2e.ts'; +import {test} from './utils_e2e.ts'; -test.beforeAll(async ({browser}, workerInfo) => { - await login_user(browser, workerInfo, 'user2'); -}); +test.use({user: 'user2'}); -test('Correct link and tooltip', async ({browser}, workerInfo) => { - const context = await load_logged_in_context(browser, workerInfo, 'user2'); - const page = await context.newPage(); +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); 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)$/); - await save_visual(page); + // ToDo: Ensure stable screenshot of dashboard. Known to be flaky: https://code.forgejo.org/forgejo/visual-browser-testing/commit/206d4cfb7a4af6d8d7043026cdd4d63708798b2a + // await save_visual(page); }); diff --git a/tests/e2e/debugserver_test.go b/tests/e2e/debugserver_test.go index 49461fabe5..8742790b14 100644 --- a/tests/e2e/debugserver_test.go +++ b/tests/e2e/debugserver_test.go @@ -17,7 +17,7 @@ import ( "syscall" "testing" - "code.gitea.io/gitea/modules/setting" + "forgejo.org/modules/setting" ) func TestDebugserver(t *testing.T) { diff --git a/tests/e2e/declare_repos_test.go b/tests/e2e/declare_repos_test.go index c55a42ac66..f45687651c 100644 --- a/tests/e2e/declare_repos_test.go +++ b/tests/e2e/declare_repos_test.go @@ -9,12 +9,13 @@ import ( "testing" "time" - 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/git" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/indexer/stats" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -36,6 +37,10 @@ func DeclareGitRepos(t *testing.T) func() { Filename: "testfile", Versions: []string{"hello", "hallo", "hola", "native", "ubuntu-latest", "- runs-on: ubuntu-latest", "- runs-on: debian-latest"}, }}), + newRepo(t, 2, "language-stats-test", []FileChanges{{ + Filename: "main.rs", + Versions: []string{"fn main() {", "println!(\"Hello World!\");", "}"}, + }}), newRepo(t, 2, "mentions-highlighted", []FileChanges{ { Filename: "history1.md", @@ -105,5 +110,8 @@ func newRepo(t *testing.T, userID int64, repoName string, fileChanges []FileChan } } + err := stats.UpdateRepoIndexer(somerepo) + require.NoError(t, err) + return cleanupFunc } diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index b8c89625c0..1961a4b68a 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -16,15 +16,15 @@ import ( "path/filepath" "testing" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/graceful" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/testlogger" - "code.gitea.io/gitea/modules/util" - "code.gitea.io/gitea/modules/web" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + "forgejo.org/models/unittest" + "forgejo.org/modules/graceful" + "forgejo.org/modules/log" + "forgejo.org/modules/setting" + "forgejo.org/modules/testlogger" + "forgejo.org/modules/util" + "forgejo.org/modules/web" + "forgejo.org/routers" + "forgejo.org/tests" ) var testE2eWebRoutes *web.Route @@ -37,16 +37,10 @@ func TestMain(m *testing.M) { defer cancel() tests.InitTest(true) + setting.Quota.Enabled = true initChangedFiles() testE2eWebRoutes = routers.NormalRoutes() - os.Unsetenv("GIT_AUTHOR_NAME") - os.Unsetenv("GIT_AUTHOR_EMAIL") - os.Unsetenv("GIT_AUTHOR_DATE") - os.Unsetenv("GIT_COMMITTER_NAME") - os.Unsetenv("GIT_COMMITTER_EMAIL") - os.Unsetenv("GIT_COMMITTER_DATE") - err := unittest.InitFixtures( unittest.FixturesOptions{ Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"), @@ -89,6 +83,7 @@ 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") @@ -112,6 +107,10 @@ 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() @@ -121,7 +120,7 @@ func TestE2e(t *testing.T) { cmd.Stderr = os.Stderr err := cmd.Run() - if err != nil { + if err != nil && !testVisual { log.Fatal("Playwright Failed: %s", err) } }) diff --git a/tests/e2e/example.test.e2e.ts b/tests/e2e/example.test.e2e.ts index b2a679a82d..97c5b8684b 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 {test} from './utils_e2e.ts'; +import {save_visual, test} from './utils_e2e.ts'; test('Load Homepage', async ({page}) => { const response = await page.goto('/'); @@ -26,6 +26,7 @@ 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 44c9b21f58..1bb5af3cc6 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 {test} from './utils_e2e.ts'; +import {save_visual, test} from './utils_e2e.ts'; test('Explore view taborder', async ({page}) => { await page.goto('/explore/repos'); @@ -42,4 +42,5 @@ test('Explore view taborder', async ({page}) => { } } expect(res).toBe(exp); + await save_visual(page); }); diff --git a/tests/e2e/fixtures/attachment.yml b/tests/e2e/fixtures/attachment.yml new file mode 100644 index 0000000000..26069b95c1 --- /dev/null +++ b/tests/e2e/fixtures/attachment.yml @@ -0,0 +1,12 @@ +- + id: 1001 + uuid: 5792c349-8a26-46b8-b4cd-2c290f118285 + repo_id: 1 + issue_id: 1 + release_id: 0 + uploader_id: 3 + comment_id: 1 + name: forgejo-secrets.txt + download_count: 0 + size: 536870911 + created_unix: 1730000000 diff --git a/tests/e2e/fixtures/quota_group.yml b/tests/e2e/fixtures/quota_group.yml new file mode 100644 index 0000000000..0d04ba6767 --- /dev/null +++ b/tests/e2e/fixtures/quota_group.yml @@ -0,0 +1 @@ +- name: trusted-user diff --git a/tests/e2e/fixtures/quota_group_mapping.yml b/tests/e2e/fixtures/quota_group_mapping.yml new file mode 100644 index 0000000000..8339569185 --- /dev/null +++ b/tests/e2e/fixtures/quota_group_mapping.yml @@ -0,0 +1,5 @@ +- + id: 1001 + kind: 0 + mapped_id: 2 + group_name: trusted-user diff --git a/tests/e2e/fixtures/quota_group_rule_mapping.yml b/tests/e2e/fixtures/quota_group_rule_mapping.yml new file mode 100644 index 0000000000..1144888f21 --- /dev/null +++ b/tests/e2e/fixtures/quota_group_rule_mapping.yml @@ -0,0 +1,14 @@ +- + id: 1001 + group_name: trusted-user + rule_name: git-lfs + +- + id: 1002 + group_name: trusted-user + rule_name: "all:assets" + +- + id: 1003 + group_name: trusted-user + rule_name: "Multi subjects" diff --git a/tests/e2e/fixtures/quota_rule.yml b/tests/e2e/fixtures/quota_rule.yml new file mode 100644 index 0000000000..f6170cbdaa --- /dev/null +++ b/tests/e2e/fixtures/quota_rule.yml @@ -0,0 +1,13 @@ +- + name: git-lfs + limit: 512 + subjects: [6] + +- + name: "all:assets" + limit: -1 + subjects: [7] + +- name: "Multi subjects" + limit: 5000000000 + subjects: [8,6] diff --git a/tests/e2e/fixtures/repository.yml b/tests/e2e/fixtures/repository.yml new file mode 100644 index 0000000000..ac87721d6a --- /dev/null +++ b/tests/e2e/fixtures/repository.yml @@ -0,0 +1,12 @@ +- + id: 1001 + owner_id: 2 + owner_name: user2 + lower_name: large-lfs + name: large-lfs + default_branch: main + is_empty: false + is_archived: false + is_private: true + status: 0 + lfs_size: 8192 diff --git a/tests/e2e/git-notes.test.e2e.ts b/tests/e2e/git-notes.test.e2e.ts index 8b80a3aa77..1e2cbe76fc 100644 --- a/tests/e2e/git-notes.test.e2e.ts +++ b/tests/e2e/git-notes.test.e2e.ts @@ -1,17 +1,16 @@ // @ts-check -import {test, expect} from '@playwright/test'; -import {login_user, save_visual, load_logged_in_context} from './utils_e2e.ts'; +import {expect} from '@playwright/test'; +import {save_visual, test} from './utils_e2e.ts'; -test.beforeAll(async ({browser}, workerInfo) => { - await login_user(browser, workerInfo, 'user2'); -}); +test.use({user: 'user2'}); -test('Change git note', async ({browser}, workerInfo) => { - const context = await load_logged_in_context(browser, workerInfo, 'user2'); - const page = await context.newPage(); +test('Change git note', async ({page}) => { 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 4fce16764b..d2dbafafd0 100644 --- a/tests/e2e/issue-comment.test.e2e.ts +++ b/tests/e2e/issue-comment.test.e2e.ts @@ -5,14 +5,11 @@ // @watch end import {expect} from '@playwright/test'; -import {test, save_visual, login_user, login} from './utils_e2e.ts'; +import {test, save_visual} from './utils_e2e.ts'; -test.beforeAll(async ({browser}, workerInfo) => { - await login_user(browser, workerInfo, 'user2'); -}); +test.use({user: 'user2'}); -test('Menu accessibility', async ({browser}, workerInfo) => { - const page = await login({browser}, workerInfo); +test('Menu accessibility', async ({page}) => { 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(); @@ -24,9 +21,8 @@ test('Menu accessibility', async ({browser}, workerInfo) => { await expect(page.getByLabel('user1, user2 reacted laugh. Remove laugh')).toBeVisible(); }); -test('Hyperlink paste behaviour', async ({browser}, workerInfo) => { +test('Hyperlink paste behaviour', async ({page}, 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 @@ -58,8 +54,7 @@ test('Hyperlink paste behaviour', async ({browser}, workerInfo) => { await page.locator('textarea').fill(''); }); -test('Always focus edit tab first on edit', async ({browser}, workerInfo) => { - const page = await login({browser}, workerInfo); +test('Always focus edit tab first on edit', async ({page}) => { const response = await page.goto('/user2/repo1/issues/1'); expect(response?.status()).toBe(200); @@ -82,9 +77,29 @@ test('Always focus edit tab first on edit', async ({browser}, workerInfo) => { await save_visual(page); }); -test('Quote reply', async ({browser}, workerInfo) => { +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.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); @@ -157,13 +172,12 @@ test('Quote reply', async ({browser}, workerInfo) => { await editorTextarea.fill(''); }); -test('Pull quote reply', async ({browser}, workerInfo) => { +test('Pull quote reply', async ({page}, 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); - const editorTextarea = page.locator('textarea.markdown-text-editor'); + const editorTextarea = page.locator('form.comment-form textarea.markdown-text-editor'); // Full quote with no reply handler being open. await page.click('.comment-code-cloud .context-menu'); diff --git a/tests/e2e/issue-sidebar.test.e2e.ts b/tests/e2e/issue-sidebar.test.e2e.ts index f4d50a13ba..fe2a6cec87 100644 --- a/tests/e2e/issue-sidebar.test.e2e.ts +++ b/tests/e2e/issue-sidebar.test.e2e.ts @@ -7,14 +7,13 @@ /* eslint playwright/expect-expect: ["error", { "assertFunctionNames": ["check_wip"] }] */ import {expect, type Page} from '@playwright/test'; -import {test, save_visual, login_user, login} from './utils_e2e.ts'; +import {save_visual, test} from './utils_e2e.ts'; -test.beforeAll(async ({browser}, workerInfo) => { - await login_user(browser, workerInfo, 'user2'); -}); +test.use({user: 'user2'}); test.describe('Pull: Toggle WIP', () => { const prTitle = 'pull5'; + async function toggle_wip_to({page}, should: boolean) { await page.waitForLoadState('domcontentloaded'); if (should) { @@ -39,8 +38,7 @@ test.describe('Pull: Toggle WIP', () => { } } - test.beforeEach(async ({browser}, workerInfo) => { - const page = await login({browser}, workerInfo); + test.beforeEach(async ({page}) => { const response = await page.goto('/user2/repo1/pulls/5'); expect(response?.status()).toBe(200); // Status OK // ensure original title @@ -50,9 +48,8 @@ test.describe('Pull: Toggle WIP', () => { await check_wip({page}, false); }); - test('simple toggle', async ({browser}, workerInfo) => { + test('simple toggle', async ({page}, 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); @@ -62,9 +59,8 @@ test.describe('Pull: Toggle WIP', () => { await check_wip({page}, false); }); - test('manual edit', async ({browser}, workerInfo) => { + test('manual edit', async ({page}, 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(); @@ -76,9 +72,8 @@ test.describe('Pull: Toggle WIP', () => { await check_wip({page}, false); }); - test('maximum title length', async ({browser}, workerInfo) => { + test('maximum title length', async ({page}, 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); @@ -96,17 +91,16 @@ test.describe('Pull: Toggle WIP', () => { }); }); -test('Issue: Labels', async ({browser}, workerInfo) => { +test('Issue: Labels', async ({page}, 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'); @@ -144,9 +138,8 @@ test('Issue: Labels', async ({browser}, workerInfo) => { await expect(labelList.filter({hasText: 'label1'})).toBeVisible(); }); -test('Issue: Assignees', async ({browser}, workerInfo) => { +test('Issue: Assignees', async ({page}, 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'); @@ -182,9 +175,8 @@ test('Issue: Assignees', async ({browser}, workerInfo) => { await expect(page.locator('.ui.assignees.list .item.no-select')).toBeHidden(); }); -test('New Issue: Assignees', async ({browser}, workerInfo) => { +test('New Issue: Assignees', async ({page}, 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'); @@ -224,9 +216,8 @@ test('New Issue: Assignees', async ({browser}, workerInfo) => { await save_visual(page); }); -test('Issue: Milestone', async ({browser}, workerInfo) => { +test('Issue: Milestone', async ({page}, 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); @@ -248,9 +239,8 @@ test('Issue: Milestone', async ({browser}, workerInfo) => { await expect(page.locator('.timeline-item.event').last()).toContainText('user2 removed this from the milestone1 milestone'); }); -test('New Issue: Milestone', async ({browser}, workerInfo) => { +test('New Issue: Milestone', async ({page}, 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/login.test.e2e.ts b/tests/e2e/login.test.e2e.ts new file mode 100644 index 0000000000..1ffa0b2e5d --- /dev/null +++ b/tests/e2e/login.test.e2e.ts @@ -0,0 +1,33 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +// @watch start +// templates/user/auth/** +// web_src/js/features/user-** +// web_src/js/features/common-global.js +// @watch end + +import {expect} from '@playwright/test'; +import {test, save_visual, test_context} from './utils_e2e.ts'; + +test('Mismatched ROOT_URL', async ({browser}) => { + const context = await test_context(browser); + const page = await context.newPage(); + + // Ugly hack to override the appUrl of `window.config`. + await page.addInitScript(() => { + setInterval(() => { + if (window.config) { + window.config.appUrl = 'https://example.com'; + } + }, 1); + }); + + const response = await page.goto('/user/login'); + expect(response?.status()).toBe(200); + + await save_visual(page); + const globalError = page.locator('.js-global-error'); + await expect(globalError).toContainText('This Forgejo instance is configured to be served on '); + await expect(globalError).toContainText('You are currently viewing Forgejo through a different URL, which may cause parts of the application to break. The canonical URL is controlled by Forgejo admins via the ROOT_URL setting in the app.ini.'); +}); diff --git a/tests/e2e/markdown-editor.test.e2e.ts b/tests/e2e/markdown-editor.test.e2e.ts index ca2d6e01b6..39ced25bc3 100644 --- a/tests/e2e/markdown-editor.test.e2e.ts +++ b/tests/e2e/markdown-editor.test.e2e.ts @@ -5,21 +5,17 @@ // @watch end import {expect} from '@playwright/test'; -import {test, save_visual, load_logged_in_context, login_user} from './utils_e2e.ts'; +import {accessibilityCheck} from './shared/accessibility.ts'; +import {save_visual, test} from './utils_e2e.ts'; -test.beforeAll(async ({browser}, workerInfo) => { - await login_user(browser, workerInfo, 'user2'); -}); +test.use({user: 'user2'}); -test('Markdown image preview behaviour', async ({browser}, workerInfo) => { +test('Markdown image preview behaviour', async ({page}, 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); @@ -43,12 +39,9 @@ test('Markdown image preview behaviour', async ({browser}, workerInfo) => { await save_visual(page); }); -test('markdown indentation', async ({browser}, workerInfo) => { - const context = await load_logged_in_context(browser, workerInfo, 'user2'); - +test('markdown indentation', async ({page}) => { 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); @@ -116,12 +109,9 @@ test('markdown indentation', async ({browser}, workerInfo) => { await expect(textarea).toHaveValue(initText); }); -test('markdown list continuation', async ({browser}, workerInfo) => { - const context = await load_logged_in_context(browser, workerInfo, 'user2'); +test('markdown list continuation', async ({page}) => { + const initText = `* first\n* second`; - 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); @@ -130,25 +120,20 @@ test('markdown list continuation', async ({browser}, workerInfo) => { 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('cond'), it.value.indexOf('cond'))); + // Test continuation of ' * ' prefix + await textarea.evaluate((it:HTMLTextAreaElement) => it.setSelectionRange(it.value.indexOf('rst'), it.value.indexOf('rst'))); + await indent.click(); 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(`* first\n* second\n${tab}* middle\n${tab}* muddle\n* third\n* last`); + await expect(textarea).toHaveValue(`${tab}* first\n${tab}* muddle\n* second`); // 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(`* first\n* second\n${tab}* middle\n${tab}* mutate\n${tab}* meddle\n* third\n* last`); + await expect(textarea).toHaveValue(`${tab}* first\n${tab}* mutate\n${tab}* meddle\n* second`); // Test not triggering when Shift held await textarea.fill(initText); @@ -156,35 +141,36 @@ test('markdown list continuation', async ({browser}, workerInfo) => { await textarea.press('Shift+Enter'); await textarea.press('Enter'); await textarea.pressSequentially('...but not least'); - await expect(textarea).toHaveValue(`* first\n* second\n* third\n* last\n\n...but not least`); + await expect(textarea).toHaveValue(`* first\n* second\n\n...but not least`); // Test continuation of ordered list - await textarea.fill(`1. one\n2. two`); + await textarea.fill(`1. 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('three'); - await expect(textarea).toHaveValue(`1. one\n2. two\n3. three`); + await textarea.press('Enter'); + await textarea.press('Enter'); + await expect(textarea).toHaveValue(`1. one\n2. \n3. three\n\n`); // Test continuation of alternative ordered list syntax - await textarea.fill(`1) one\n2) two`); + await textarea.fill(`1) 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('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.pressSequentially('france is bacon'); - await expect(textarea).toHaveValue(`> knowledge is power\n> france is bacon`); + await textarea.press('Enter'); + await expect(textarea).toHaveValue(`1) one\n2) \n3) three\n\n`); // 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 = [ @@ -200,7 +186,6 @@ test('markdown list continuation', async ({browser}, workerInfo) => { '> ', '> > ', '- [ ] ', - '- [ ]', // This does seem to render, so allow. '* [ ] ', '+ [ ] ', ]; @@ -208,15 +193,16 @@ test('markdown list continuation', async ({browser}, workerInfo) => { 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 expect(textarea).toHaveValue(`${prefix}one\n${prefix}two`); + await textarea.press('Enter'); + await textarea.press('Enter'); + await expect(textarea).toHaveValue(`${prefix}one\n${prefix} \n${prefix}two\n\n`); } }); -test('markdown insert table', async ({browser}, workerInfo) => { - const context = await load_logged_in_context(browser, workerInfo, 'user2'); - - const page = await context.newPage(); +test('markdown insert table', async ({page}) => { const response = await page.goto('/user2/repo1/issues/new'); expect(response?.status()).toBe(200); @@ -238,3 +224,56 @@ test('markdown insert table', async ({browser}, workerInfo) => { await expect(textarea).toHaveValue('| Header | Header |\n|---------|---------|\n| Content | Content |\n| Content | Content |\n| Content | Content |\n'); await save_visual(page); }); + +test('markdown insert link', async ({page}) => { + const response = await page.goto('/user2/repo1/issues/new'); + expect(response?.status()).toBe(200); + + const newLinkButton = page.locator('button[data-md-action="new-link"]'); + await newLinkButton.click(); + + const newLinkModal = page.locator('div[data-markdown-link-modal-id="0"]'); + await expect(newLinkModal).toBeVisible(); + await accessibilityCheck({page}, ['[data-modal-name="new-markdown-link"]'], [], []); + await save_visual(page); + + const url = 'https://example.com'; + const description = 'Where does this lead?'; + + await newLinkModal.locator('input[name="link-url"]').fill(url); + await newLinkModal.locator('input[name="link-description"]').fill(description); + + await newLinkModal.locator('button[data-selector-name="ok-button"]').click(); + + await expect(newLinkModal).toBeHidden(); + + const textarea = page.locator('textarea[name=content]'); + await expect(textarea).toHaveValue(`[${description}](${url})`); + 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 2726942d57..398a0a6300 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 {test} from './utils_e2e.ts'; +import {save_visual, test} from './utils_e2e.ts'; test('markup with #xyz-mode-only', async ({page}) => { const response = await page.goto('/user2/repo1/issues/1'); @@ -13,4 +13,5 @@ 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 22a8bc0e2d..df554e0674 100644 --- a/tests/e2e/org-settings.test.e2e.ts +++ b/tests/e2e/org-settings.test.e2e.ts @@ -5,16 +5,13 @@ // @watch end import {expect} from '@playwright/test'; -import {test, save_visual, login_user, login} from './utils_e2e.ts'; +import {save_visual, test} from './utils_e2e.ts'; import {validate_form} from './shared/forms.ts'; -test.beforeAll(async ({browser}, workerInfo) => { - await login_user(browser, workerInfo, 'user2'); -}); +test.use({user: 'user2'}); -test('org team settings', async ({browser}, workerInfo) => { +test('org team settings', async ({page}, 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/pagination.test.e2e.ts b/tests/e2e/pagination.test.e2e.ts new file mode 100644 index 0000000000..3126b669a6 --- /dev/null +++ b/tests/e2e/pagination.test.e2e.ts @@ -0,0 +1,15 @@ +// @watch start +// template/base/paginate.tmpl +// services/context/pagination.go +// @watch end + +import {expect} from '@playwright/test'; +import {test} from './utils_e2e.ts'; +import {accessibilityCheck} from './shared/accessibility.ts'; + +test('Pagination a11y', async ({page}) => { + await page.goto('/explore/repos'); + + await expect(page.locator('.pagination')).toBeVisible(); + await accessibilityCheck({page}, ['.pagination'], [], []); +}); diff --git a/tests/e2e/pr-review.test.e2e.ts b/tests/e2e/pr-review.test.e2e.ts new file mode 100644 index 0000000000..b619cdbcd1 --- /dev/null +++ b/tests/e2e/pr-review.test.e2e.ts @@ -0,0 +1,25 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +// @watch start +// templates/repo/diff/new_review.tmpl +// web_src/js/features/repo-issue.js +// @watch end + +import {expect} from '@playwright/test'; +import {save_visual, test} from './utils_e2e.ts'; + +test.use({user: 'user2'}); + +test('PR: Finish review', async ({page}) => { + const response = await page.goto('/user2/repo1/pulls/5/files'); + expect(response?.status()).toBe(200); + + await expect(page.locator('.tippy-box .review-box-panel')).toBeHidden(); + await save_visual(page); + + // Review panel should appear after clicking Finish review + await page.locator('#review-box .js-btn-review').click(); + await expect(page.locator('.tippy-box .review-box-panel')).toBeVisible(); + await save_visual(page); +}); diff --git a/tests/e2e/pr-title.test.e2e.ts b/tests/e2e/pr-title.test.e2e.ts new file mode 100644 index 0000000000..390cc81298 --- /dev/null +++ b/tests/e2e/pr-title.test.e2e.ts @@ -0,0 +1,25 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +// @watch start +// templates/repo/issue/view_title.tmpl +// web_src/js/features/repo-issue.js +// @watch end + +import {expect} from '@playwright/test'; +import {save_visual, test} from './utils_e2e.ts'; + +test.use({user: 'user2'}); + +test('PR: title edit', async ({page}) => { + const response = await page.goto('/user2/repo1/pulls/5'); + expect(response?.status()).toBe(200); + + await expect(page.locator('#editable-label')).toBeVisible(); + await save_visual(page); + + // Labels AGit and Editable are hidden when title is in edit mode + await page.locator('#issue-title-edit-show').click(); + await expect(page.locator('#editable-label')).toBeHidden(); + await save_visual(page); +}); diff --git a/tests/e2e/profile_actions.test.e2e.ts b/tests/e2e/profile_actions.test.e2e.ts index 65090e62b2..a66dc43aab 100644 --- a/tests/e2e/profile_actions.test.e2e.ts +++ b/tests/e2e/profile_actions.test.e2e.ts @@ -5,13 +5,11 @@ // @watch end import {expect} from '@playwright/test'; -import {test, save_visual, login_user, load_logged_in_context} from './utils_e2e.ts'; +import {save_visual, test} from './utils_e2e.ts'; -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.use({user: 'user2'}); +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 3ce71b24d7..54b7d91869 100644 --- a/tests/e2e/reaction-selectors.test.e2e.ts +++ b/tests/e2e/reaction-selectors.test.e2e.ts @@ -4,11 +4,9 @@ // @watch end import {expect, type Locator} from '@playwright/test'; -import {test, save_visual, login_user, load_logged_in_context} from './utils_e2e.ts'; +import {save_visual, test} from './utils_e2e.ts'; -test.beforeAll(async ({browser}, workerInfo) => { - await login_user(browser, workerInfo, 'user2'); -}); +test.use({user: 'user2'}); const assertReactionCounts = (comment: Locator, counts: unknown) => expect(async () => { @@ -26,6 +24,7 @@ const assertReactionCounts = (comment: Locator, counts: unknown) => ]), ), ); + // eslint-disable-next-line playwright/no-standalone-expect return expect(reactions).toStrictEqual(counts); }).toPass(); @@ -35,10 +34,7 @@ async function toggleReaction(menu: Locator, reaction: string) { await menu.locator(`[role=menuitem][data-reaction-content="${reaction}"]`).click(); } -test('Reaction Selectors', async ({browser}, workerInfo) => { - const context = await load_logged_in_context(browser, workerInfo, 'user2'); - const page = await context.newPage(); - +test('Reaction Selectors', async ({page}) => { 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 fefa446c59..044e7b93ab 100644 --- a/tests/e2e/release.test.e2e.ts +++ b/tests/e2e/release.test.e2e.ts @@ -9,24 +9,18 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, save_visual, load_logged_in_context} from './utils_e2e.ts'; +import {save_visual, test} from './utils_e2e.ts'; import {validate_form} from './shared/forms.ts'; -test.beforeAll(async ({browser}, workerInfo) => { - await login_user(browser, workerInfo, 'user2'); -}); +test.use({user: 'user2'}); test.describe.configure({ timeout: 30000, }); -test('External Release Attachments', async ({browser, isMobile}, workerInfo) => { +test('External Release Attachments', async ({page, isMobile}) => { 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'); @@ -34,8 +28,9 @@ test('External Release Attachments', async ({browser, isMobile}, workerInfo) => // Fill out form and create new release await expect(page).toHaveURL('/user2/repo2/releases/new'); await validate_form({page}, 'fieldset'); - await page.fill('input[name=tag_name]', '2.0'); - await page.fill('input[name=title]', '2.0'); + const textarea = page.locator('input[name=tag_name]'); + await textarea.pressSequentially('2.0'); + await expect(page.locator('input[name=title]')).toHaveValue('2.0'); await page.click('#add-external-link'); await page.click('#add-external-link'); await page.fill('input[name=attachment-new-name-2]', 'Test'); @@ -47,10 +42,17 @@ test('External Release Attachments', async ({browser, isMobile}, workerInfo) => // Validate release page and click edit await expect(page).toHaveURL('/user2/repo2/releases'); await expect(page.locator('.download[open] li')).toHaveCount(3); + await expect(page.locator('.download[open] li:nth-of-type(1)')).toContainText('Source code (ZIP)'); + await expect(page.locator('.download[open] li:nth-of-type(1) span[data-tooltip-content]')).toHaveAttribute('data-tooltip-content', 'This attachment is automatically generated.'); await expect(page.locator('.download[open] li:nth-of-type(1) a')).toHaveAttribute('href', '/user2/repo2/archive/2.0.zip'); + await expect(page.locator('.download[open] li:nth-of-type(1) a')).toHaveAttribute('type', 'application/zip'); + await expect(page.locator('.download[open] li:nth-of-type(2)')).toContainText('Source code (TAR.GZ)'); + await expect(page.locator('.download[open] li:nth-of-type(2) span[data-tooltip-content]')).toHaveAttribute('data-tooltip-content', 'This attachment is automatically generated.'); await expect(page.locator('.download[open] li:nth-of-type(2) a')).toHaveAttribute('href', '/user2/repo2/archive/2.0.tar.gz'); + await expect(page.locator('.download[open] li:nth-of-type(2) a')).toHaveAttribute('type', 'application/gzip'); + await expect(page.locator('.download[open] li:nth-of-type(3)')).toContainText('Test'); await expect(page.locator('.download[open] li:nth-of-type(3) a')).toHaveAttribute('href', 'https://forgejo.org/'); await save_visual(page); diff --git a/tests/e2e/repo-code.test.e2e.ts b/tests/e2e/repo-code.test.e2e.ts index 264dd3a8e0..11b710c956 100644 --- a/tests/e2e/repo-code.test.e2e.ts +++ b/tests/e2e/repo-code.test.e2e.ts @@ -5,13 +5,9 @@ // @watch end import {expect, type Page} from '@playwright/test'; -import {test, save_visual, login_user, login} from './utils_e2e.ts'; +import {save_visual, test} 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( @@ -53,6 +49,7 @@ 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) => { @@ -79,22 +76,26 @@ test('Readable diff', async ({page}, workerInfo) => { await expect(page.getByText(thisDiff.added, {exact: true})).toHaveCSS('background-color', 'rgb(134, 239, 172)'); } } + await save_visual(page); }); -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 5f0cad117a..e8b85c5997 100644 --- a/tests/e2e/repo-commitgraph.test.e2e.ts +++ b/tests/e2e/repo-commitgraph.test.e2e.ts @@ -5,13 +5,30 @@ // @watch end import {expect} from '@playwright/test'; -import {test} from './utils_e2e.ts'; +import {save_visual, test} from './utils_e2e.ts'; test('Commit graph overflow', async ({page}) => { - await page.goto('/user2/diff-test/graph'); + 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 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}) => { @@ -28,4 +45,5 @@ 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-home.test.e2e.ts b/tests/e2e/repo-home.test.e2e.ts new file mode 100644 index 0000000000..6f3d6c373b --- /dev/null +++ b/tests/e2e/repo-home.test.e2e.ts @@ -0,0 +1,35 @@ +// @watch start +// web_src/js/components/RepoBranchTagSelector.vue +// web_src/js/features/common-global.js +// web_src/css/repo.css +// @watch end + +import {expect} from '@playwright/test'; +import {save_visual, test} from './utils_e2e.ts'; + +test('Language stats bar', async ({page}) => { + const response = await page.goto('/user2/language-stats-test'); + expect(response?.status()).toBe(200); + + await expect(page.locator('#language-stats-legend')).toBeHidden(); + + await page.click('#language-stats-bar'); + await expect(page.locator('#language-stats-legend')).toBeVisible(); + await save_visual(page); + + await page.click('#language-stats-bar'); + await expect(page.locator('#language-stats-legend')).toBeHidden(); + await save_visual(page); +}); + +test('Branch selector commit icon', async ({page}) => { + const response = await page.goto('/user2/repo1'); + expect(response?.status()).toBe(200); + + await expect(page.locator('.branch-dropdown-button svg.octicon-git-branch')).toBeVisible(); + await expect(page.locator('.branch-dropdown-button')).toHaveText('master'); + + await page.goto('/user2/repo1/src/commit/65f1bf27bc3bf70f64657658635e66094edbcb4d'); + await expect(page.locator('.branch-dropdown-button svg.octicon-git-commit')).toBeVisible(); + await expect(page.locator('.branch-dropdown-button')).toHaveText('65f1bf27bc'); +}); diff --git a/tests/e2e/repo-migrate.test.e2e.ts b/tests/e2e/repo-migrate.test.e2e.ts index a0f9ab6c80..5e67f89ed1 100644 --- a/tests/e2e/repo-migrate.test.e2e.ts +++ b/tests/e2e/repo-migrate.test.e2e.ts @@ -3,15 +3,13 @@ // @watch end import {expect} from '@playwright/test'; -import {test, save_visual, login_user, load_logged_in_context} from './utils_e2e.ts'; +import {test, save_visual, test_context} from './utils_e2e.ts'; -test.beforeAll(({browser}, workerInfo) => login_user(browser, workerInfo, 'user2')); +test.use({user: 'user2'}); -test('Migration Progress Page', async ({page: unauthedPage, browser}, workerInfo) => { +test('Migration Progress Page', async ({page, 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'); @@ -23,10 +21,11 @@ test('Migration Progress Page', async ({page: unauthedPage, 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 - expect((await unauthedPage.goto('/user2/invalidrepo'))?.status(), 'public migration page should be accessible').toBe(200); - await expect(unauthedPage.locator('#repo_migrating_progress')).toBeVisible(); + 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(); await page.reload(); await expect(page.locator('#repo_migrating_failed')).toBeVisible(); @@ -37,4 +36,6 @@ test('Migration Progress Page', async ({page: unauthedPage, 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 c9cc29ad56..ad202825a0 100644 --- a/tests/e2e/repo-new.test.e2e.ts +++ b/tests/e2e/repo-new.test.e2e.ts @@ -4,15 +4,12 @@ // @watch end import {expect} from '@playwright/test'; -import {test, dynamic_id, save_visual, login_user, login} from './utils_e2e.ts'; +import {test, dynamic_id, save_visual} from './utils_e2e.ts'; import {validate_form} from './shared/forms.ts'; -test.beforeAll(async ({browser}, workerInfo) => { - await login_user(browser, workerInfo, 'user2'); -}); +test.use({user: 'user2'}); -test('New repo: invalid', async ({browser}, workerInfo) => { - const page = await login({browser}, workerInfo); +test('New repo: invalid', async ({page}) => { const response = await page.goto('/repo/create'); expect(response?.status()).toBe(200); // check that relevant form content is hidden or available @@ -28,8 +25,7 @@ test('New repo: invalid', async ({browser}, workerInfo) => { await save_visual(page); }); -test('New repo: initialize', async ({browser}, workerInfo) => { - const page = await login({browser}, workerInfo); +test('New repo: initialize', async ({page}, workerInfo) => { const response = await page.goto('/repo/create'); expect(response?.status()).toBe(200); // check that relevant form content is hidden or available @@ -62,8 +58,7 @@ test('New repo: initialize', async ({browser}, workerInfo) => { await save_visual(page); }); -test('New repo: initialize later', async ({browser}, workerInfo) => { - const page = await login({browser}, workerInfo); +test('New repo: initialize later', async ({page}) => { const response = await page.goto('/repo/create'); expect(response?.status()).toBe(200); @@ -97,9 +92,8 @@ test('New repo: initialize later', async ({browser}, workerInfo) => { await save_visual(page); }); -test('New repo: from template', async ({browser}, workerInfo) => { +test('New repo: from template', async ({page}, 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); @@ -114,8 +108,7 @@ test('New repo: from template', async ({browser}, workerInfo) => { await save_visual(page); }); -test('New repo: label set', async ({browser}, workerInfo) => { - const page = await login({browser}, workerInfo); +test('New repo: label set', async ({page}) => { 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 113b15181b..3d260866fb 100644 --- a/tests/e2e/repo-settings.test.e2e.ts +++ b/tests/e2e/repo-settings.test.e2e.ts @@ -7,16 +7,13 @@ // @watch end import {expect} from '@playwright/test'; -import {test, save_visual, login_user, login} from './utils_e2e.ts'; +import {test, save_visual} from './utils_e2e.ts'; import {validate_form} from './shared/forms.ts'; -test.beforeAll(async ({browser}, workerInfo) => { - await login_user(browser, workerInfo, 'user2'); -}); +test.use({user: 'user2'}); -test('repo webhook settings', async ({browser}, workerInfo) => { +test('repo webhook settings', async ({page}, 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); @@ -35,9 +32,8 @@ test('repo webhook settings', async ({browser}, workerInfo) => { }); test.describe('repo branch protection settings', () => { - 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); + test('form', async ({page}, {project}) => { + test.skip(project.name === 'Mobile Safari', 'Cannot get it to work - as usual'); const response = await page.goto('/user2/repo1/settings/branches/edit'); expect(response?.status()).toBe(200); @@ -56,8 +52,7 @@ test.describe('repo branch protection settings', () => { await save_visual(page); }); - test.afterEach(async ({browser}, workerInfo) => { - const page = await login({browser}, workerInfo); + test.afterEach(async ({page}) => { // 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 f32fe3fc91..4ce66da8bc 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 {test} from './utils_e2e.ts'; +import {save_visual, test} from './utils_e2e.ts'; for (const searchTerm of ['space', 'consectetur']) { for (const width of [null, 2560, 4000]) { @@ -23,6 +23,7 @@ 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); }); } } @@ -36,4 +37,5 @@ 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 bfb1800a27..3bea329ba0 100644 --- a/tests/e2e/right-settings-button.test.e2e.ts +++ b/tests/e2e/right-settings-button.test.e2e.ts @@ -5,19 +5,12 @@ // @watch end import {expect} from '@playwright/test'; -import {test, login_user, load_logged_in_context} from './utils_e2e.ts'; +import {save_visual, test} from './utils_e2e.ts'; -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.describe('desktop viewport as user 2', () => { + test.use({user: 'user2', viewport: {width: 1920, height: 300}}); + test('Settings button on right of repo header', async ({page}) => { await page.goto('/user2/repo1'); const settingsBtn = page.locator('.overflow-menu-items>#settings-btn'); @@ -27,11 +20,21 @@ test.describe('desktop viewport', () => { await expect(page.locator('.overflow-menu-button')).toHaveCount(0); }); - 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(); + test('Settings button on right of org header', async ({page}) => { + 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.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'); @@ -40,19 +43,10 @@ test.describe('desktop viewport', () => { await expect(page.locator('.overflow-menu-button')).toHaveCount(0); }); +}); - 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.describe('desktop viewport, unauthenticated', () => { + test.use({viewport: {width: 1920, height: 300}}); test('User overview overflow menu should not be influenced', async ({page}) => { await page.goto('/user2'); @@ -60,16 +54,14 @@ test.describe('desktop viewport', () => { 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({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.use({user: 'user2', viewport: {width: 800, height: 300}}); + 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); @@ -87,12 +79,10 @@ 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 ({browser}, workerInfo) => { - const context = await load_logged_in_context(browser, workerInfo, 'user2'); - const page = await context.newPage(); - + test('Settings button in overflow menu of org header', async ({page}) => { await page.goto('/org3'); await expect(page.locator('.overflow-menu-items>#settings-btn')).toHaveCount(0); @@ -111,6 +101,10 @@ 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'); @@ -129,5 +123,6 @@ test.describe('small viewport', () => { const items = shownItems.concat(overflowItems); expect(Array.from(new Set(items))).toHaveLength(items.length); + await save_visual(page); }); }); diff --git a/tests/e2e/shared/forms.ts b/tests/e2e/shared/forms.ts index fc608489b0..adb5b6e3cb 100644 --- a/tests/e2e/shared/forms.ts +++ b/tests/e2e/shared/forms.ts @@ -18,7 +18,6 @@ export async function validate_form({page}: {page: Page}, scope: 'form' | 'field for (const b of await boxes.all()) { await expect(b).toHaveCSS('margin-left', '0px'); await expect(b).toHaveCSS('margin-top', '0px'); - await expect(b).toHaveCSS('vertical-align', 'baseline'); } // assert no (trailing) colon is used in labels diff --git a/tests/e2e/user-settings.test.e2e.ts b/tests/e2e/user-settings.test.e2e.ts index b36a17b5b2..726c7b4f4a 100644 --- a/tests/e2e/user-settings.test.e2e.ts +++ b/tests/e2e/user-settings.test.e2e.ts @@ -16,8 +16,16 @@ test('User: Profile settings', async ({browser}, workerInfo) => { await page.goto('/user/settings'); await page.getByLabel('Full name').fill('SecondUser'); - await page.locator('#pronouns-dropdown').click(); - await page.getByRole('option', {name: 'she/her'}).click(); + + const pronounsInput = page.locator('input[list="pronouns"]'); + await expect(pronounsInput).toHaveAttribute('placeholder', 'Unspecified'); + await pronounsInput.click(); + const pronounsList = page.locator('datalist#pronouns'); + const pronounsOptions = pronounsList.locator('option'); + const pronounsValues = await pronounsOptions.evaluateAll((opts) => opts.map((opt) => opt.value)); + expect(pronounsValues).toEqual(['he/him', 'she/her', 'they/them', 'it/its', 'any pronouns']); + await pronounsInput.fill('she/her'); + await page.getByPlaceholder('Tell others a little bit').fill('I am a playwright test running for several seconds.'); await page.getByPlaceholder('Tell others a little bit').press('Tab'); await page.getByLabel('Website').fill('https://forgejo.org'); @@ -44,9 +52,7 @@ test('User: Profile settings', async ({browser}, workerInfo) => { await save_visual(page); await page.goto('/user/settings'); - await page.locator('#pronouns-dropdown').click(); - await page.getByRole('option', {name: 'Custom'}).click(); - await page.getByLabel('Custom pronouns').fill('rob/ot'); + await page.locator('input[list="pronouns"]').fill('rob/ot'); await page.getByLabel('User visibility').click(); await page.getByLabel('Visible to everyone').click(); await page.getByLabel('Hide email address Your email').check(); @@ -63,3 +69,12 @@ test('User: Profile settings', async ({browser}, workerInfo) => { await page.goto('/user2?tab=activity'); await expect(page.getByText('Your activity is visible to everyone')).toBeVisible(); }); + +test('User: Storage overview', async ({browser}, workerInfo) => { + const page = await login({browser}, workerInfo); + await page.goto('/user/settings/storage_overview'); + await page.waitForLoadState(); + await page.getByLabel('Git LFS – 8 KiB').nth(1).hover({position: {x: 250, y: 2}}); + await expect(page.getByText('Git LFS')).toBeVisible(); + await save_visual(page); +}); diff --git a/tests/e2e/utils_e2e.ts b/tests/e2e/utils_e2e.ts index 7e25441ea3..ff921a2cf3 100644 --- a/tests/e2e/utils_e2e.ts +++ b/tests/e2e/utils_e2e.ts @@ -1,21 +1,34 @@ import {expect, test as baseTest, type Browser, type BrowserContextOptions, type APIRequestContext, type TestInfo, type Page} from '@playwright/test'; -export const test = baseTest.extend({ - context: async ({browser}, use) => { - return use(await test_context(browser)); - }, - // 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); +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: []}; } - }, {auto: true}], + + return use(await test_context(browser, contextOptions)); + }, + user: null, + authScope: 'shared', }); -async function test_context(browser: Browser, options?: BrowserContextOptions) { +export async function test_context(browser: Browser, options?: BrowserContextOptions) { const context = await browser.newContext(options); context.on('page', (page) => { @@ -106,6 +119,7 @@ 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 bf1a8a418c..d57c7bc2d3 100644 --- a/tests/e2e/utils_e2e_test.go +++ b/tests/e2e/utils_e2e_test.go @@ -5,17 +5,27 @@ 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/modules/setting" - "code.gitea.io/gitea/tests" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/json" + modules_session "forgejo.org/modules/session" + "forgejo.org/modules/setting" + "forgejo.org/tests" + "code.forgejo.org/go-chi/session" "github.com/stretchr/testify/require" ) @@ -25,6 +35,8 @@ 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, } @@ -48,7 +60,7 @@ func onForgejoRunTB(t testing.TB, callback func(testing.TB, *url.URL), prepare . defer func() { require.NoError(t, os.WriteFile(setting.CustomConf, conf, 0o644)) - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + ctx, cancel := context.WithTimeout(t.Context(), 2*time.Minute) s.Shutdown(ctx) cancel() }() @@ -64,3 +76,118 @@ 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/fuzz/fuzz_test.go b/tests/fuzz/fuzz_test.go index 25a6ed8213..754c7ef064 100644 --- a/tests/fuzz/fuzz_test.go +++ b/tests/fuzz/fuzz_test.go @@ -9,9 +9,9 @@ import ( "io" "testing" - "code.gitea.io/gitea/modules/markup" - "code.gitea.io/gitea/modules/markup/markdown" - "code.gitea.io/gitea/modules/setting" + "forgejo.org/modules/markup" + "forgejo.org/modules/markup/markdown" + "forgejo.org/modules/setting" ) var renderContext = markup.RenderContext{ @@ -27,6 +27,7 @@ var renderContext = markup.RenderContext{ func FuzzMarkdownRenderRaw(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { + setting.IsInTesting = true setting.AppURL = "http://localhost:3000/" markdown.RenderRaw(&renderContext, bytes.NewReader(data), io.Discard) }) @@ -34,6 +35,7 @@ func FuzzMarkdownRenderRaw(f *testing.F) { func FuzzMarkupPostProcess(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { + setting.IsInTesting = true setting.AppURL = "http://localhost:3000/" markup.PostProcess(&renderContext, bytes.NewReader(data), io.Discard) }) diff --git a/tests/gitea-repositories-meta/user2/commits_search_test.git/config b/tests/gitea-repositories-meta/user2/commits_search_test.git/config index bfbada5989..534a026f8f 100644 --- a/tests/gitea-repositories-meta/user2/commits_search_test.git/config +++ b/tests/gitea-repositories-meta/user2/commits_search_test.git/config @@ -3,6 +3,6 @@ filemode = true bare = true [remote "origin"] - url = /home/mura/go/src/code.gitea.io/gitea/tests/gitea-repositories-meta/user2/commits_search_test/ + url = /home/mura/go/src/forgejo.org/tests/gitea-repositories-meta/user2/commits_search_test/ fetch = +refs/*:refs/* mirror = true diff --git a/tests/integration/actions_commit_status_test.go b/tests/integration/actions_commit_status_test.go index 0dae5db344..a14b427c98 100644 --- a/tests/integration/actions_commit_status_test.go +++ b/tests/integration/actions_commit_status_test.go @@ -7,16 +7,16 @@ import ( "net/url" "testing" - actions_model "code.gitea.io/gitea/models/actions" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/services/actions" - "code.gitea.io/gitea/services/automerge" + actions_model "forgejo.org/models/actions" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/services/actions" + "forgejo.org/services/automerge" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/actions_job_test.go b/tests/integration/actions_job_test.go index 5af3519b93..412215086e 100644 --- a/tests/integration/actions_job_test.go +++ b/tests/integration/actions_job_test.go @@ -8,18 +8,23 @@ import ( "fmt" "net/http" "net/url" + "reflect" "testing" "time" - actions_model "code.gitea.io/gitea/models/actions" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" + actions_model "forgejo.org/models/actions" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/json" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" runnerv1 "code.gitea.io/actions-proto-go/runner/v1" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestJobWithNeeds(t *testing.T) { @@ -354,6 +359,95 @@ jobs: }) } +func TestActionsGiteaContext(t *testing.T) { + if !setting.Database.Type.IsSQLite3() { + t.Skip() + } + + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + user2Session := loginUser(t, user2.Name) + user2Token := getTokenForLoggedInUser(t, user2Session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiBaseRepo := createActionsTestRepo(t, user2Token, "actions-gitea-context", false) + baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiBaseRepo.ID}) + user2APICtx := NewAPITestContext(t, baseRepo.OwnerName, baseRepo.Name, auth_model.AccessTokenScopeWriteRepository) + + runner := newMockRunner() + runner.registerAsRepoRunner(t, baseRepo.OwnerName, baseRepo.Name, "mock-runner", []string{"ubuntu-latest"}) + + // init the workflow + wfTreePath := ".gitea/workflows/pull.yml" + wfFileContent := `name: Pull Request +on: pull_request +jobs: + wf1-job: + runs-on: ubuntu-latest + steps: + - run: echo 'test the pull' +` + opts := getWorkflowCreateFileOptions(user2, baseRepo.DefaultBranch, fmt.Sprintf("create %s", wfTreePath), wfFileContent) + createWorkflowFile(t, user2Token, baseRepo.OwnerName, baseRepo.Name, wfTreePath, opts) + // user2 creates a pull request + doAPICreateFile(user2APICtx, "user2-patch.txt", &api.CreateFileOptions{ + FileOptions: api.FileOptions{ + NewBranchName: "user2/patch-1", + Message: "create user2-patch.txt", + Author: api.Identity{ + Name: user2.Name, + Email: user2.Email, + }, + Committer: api.Identity{ + Name: user2.Name, + Email: user2.Email, + }, + Dates: api.CommitDateOptions{ + Author: time.Now(), + Committer: time.Now(), + }, + }, + ContentBase64: base64.StdEncoding.EncodeToString([]byte("user2-fix")), + })(t) + apiPull, err := doAPICreatePullRequest(user2APICtx, baseRepo.OwnerName, baseRepo.Name, baseRepo.DefaultBranch, "user2/patch-1")(t) + require.NoError(t, err) + task := runner.fetchTask(t) + gtCtx := task.Context.GetFields() + actionTask := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionTask{ID: task.Id}) + actionRunJob := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: actionTask.JobID}) + actionRun := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: actionRunJob.RunID}) + require.NoError(t, actionRun.LoadAttributes(t.Context())) + + assert.Equal(t, user2.Name, gtCtx["actor"].GetStringValue()) + assert.Equal(t, setting.AppURL+"api/v1", gtCtx["api_url"].GetStringValue()) + assert.Equal(t, apiPull.Base.Ref, gtCtx["base_ref"].GetStringValue()) + runEvent := map[string]any{} + require.NoError(t, json.Unmarshal([]byte(actionRun.EventPayload), &runEvent)) + assert.True(t, reflect.DeepEqual(gtCtx["event"].GetStructValue().AsMap(), runEvent)) + assert.Equal(t, actionRun.TriggerEvent, gtCtx["event_name"].GetStringValue()) + assert.Equal(t, apiPull.Head.Ref, gtCtx["head_ref"].GetStringValue()) + assert.Equal(t, actionRunJob.JobID, gtCtx["job"].GetStringValue()) + assert.Equal(t, actionRun.Ref, gtCtx["ref"].GetStringValue()) + assert.Equal(t, (git.RefName(actionRun.Ref)).ShortName(), gtCtx["ref_name"].GetStringValue()) + assert.False(t, gtCtx["ref_protected"].GetBoolValue()) + assert.Equal(t, (git.RefName(actionRun.Ref)).RefType(), gtCtx["ref_type"].GetStringValue()) + assert.Equal(t, actionRun.Repo.OwnerName+"/"+actionRun.Repo.Name, gtCtx["repository"].GetStringValue()) + assert.Equal(t, actionRun.Repo.OwnerName, gtCtx["repository_owner"].GetStringValue()) + assert.Equal(t, actionRun.Repo.HTMLURL(), gtCtx["repositoryUrl"].GetStringValue()) + assert.Equal(t, fmt.Sprint(actionRunJob.RunID), gtCtx["run_id"].GetStringValue()) + assert.Equal(t, fmt.Sprint(actionRun.Index), gtCtx["run_number"].GetStringValue()) + assert.Equal(t, fmt.Sprint(actionRunJob.Attempt), gtCtx["run_attempt"].GetStringValue()) + assert.Equal(t, "Actions", gtCtx["secret_source"].GetStringValue()) + assert.Equal(t, setting.AppURL, gtCtx["server_url"].GetStringValue()) + assert.Equal(t, actionRun.CommitSHA, gtCtx["sha"].GetStringValue()) + assert.Equal(t, actionRun.WorkflowID, gtCtx["workflow"].GetStringValue()) + assert.Equal(t, setting.Actions.DefaultActionsURL.URL(), gtCtx["gitea_default_actions_url"].GetStringValue()) + token := gtCtx["token"].GetStringValue() + assert.Equal(t, actionTask.TokenLastEight, token[len(token)-8:]) + + doAPIDeleteRepository(user2APICtx)(t) + }) +} + func createActionsTestRepo(t *testing.T, authToken, repoName string, isPrivate bool) *api.Repository { req := NewRequestWithJSON(t, "POST", "/api/v1/user/repos", &api.CreateRepoOption{ Name: repoName, diff --git a/tests/integration/actions_log_test.go b/tests/integration/actions_log_test.go index d66eada950..2c2e2e88b3 100644 --- a/tests/integration/actions_log_test.go +++ b/tests/integration/actions_log_test.go @@ -11,13 +11,13 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/storage" - "code.gitea.io/gitea/modules/test" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + "forgejo.org/modules/storage" + "forgejo.org/modules/test" runnerv1 "code.gitea.io/actions-proto-go/runner/v1" "github.com/stretchr/testify/assert" diff --git a/tests/integration/actions_route_test.go b/tests/integration/actions_route_test.go index 10618c89c7..2641fb6a04 100644 --- a/tests/integration/actions_route_test.go +++ b/tests/integration/actions_route_test.go @@ -5,19 +5,18 @@ package integration import ( - "context" "fmt" "net/http" "net/url" "strings" "testing" - actions_model "code.gitea.io/gitea/models/actions" - unit_model "code.gitea.io/gitea/models/unit" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + actions_model "forgejo.org/models/actions" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -71,12 +70,12 @@ func TestActionsWebRouteLatestWorkflowRun(t *testing.T) { // Verify that each points to the correct workflow. workflowOne := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: repo.ID, Index: 1}) - err := workflowOne.LoadAttributes(context.Background()) + err := workflowOne.LoadAttributes(t.Context()) require.NoError(t, err) assert.Equal(t, workflowOneURI, workflowOne.HTMLURL()) workflowTwo := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: repo.ID, Index: 2}) - err = workflowTwo.LoadAttributes(context.Background()) + err = workflowTwo.LoadAttributes(t.Context()) require.NoError(t, err) assert.Equal(t, workflowTwoURI, workflowTwo.HTMLURL()) }) @@ -141,7 +140,7 @@ func TestActionsWebRouteLatestRun(t *testing.T) { // Verify that it redirects to the run we just created workflow := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: repo.ID}) - err := workflow.LoadAttributes(context.Background()) + err := workflow.LoadAttributes(t.Context()) require.NoError(t, err) assert.Equal(t, workflow.HTMLURL(), resp.Header().Get("Location")) @@ -170,7 +169,7 @@ func TestActionsArtifactDeletion(t *testing.T) { // Load the run we just created run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: repo.ID}) - err := run.LoadAttributes(context.Background()) + err := run.LoadAttributes(t.Context()) require.NoError(t, err) // Visit it's web view diff --git a/tests/integration/actions_runner_test.go b/tests/integration/actions_runner_test.go index 0ffd97a208..93f38db9ee 100644 --- a/tests/integration/actions_runner_test.go +++ b/tests/integration/actions_runner_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/modules/setting" + auth_model "forgejo.org/models/auth" + "forgejo.org/modules/setting" pingv1 "code.gitea.io/actions-proto-go/ping/v1" "code.gitea.io/actions-proto-go/ping/v1/pingv1connect" @@ -61,7 +61,7 @@ func newMockRunnerClient(uuid, token string) *mockRunnerClient { } func (r *mockRunner) doPing(t *testing.T) { - resp, err := r.client.pingServiceClient.Ping(context.Background(), connect.NewRequest(&pingv1.PingRequest{ + resp, err := r.client.pingServiceClient.Ping(t.Context(), connect.NewRequest(&pingv1.PingRequest{ Data: "mock-runner", })) require.NoError(t, err) @@ -70,7 +70,7 @@ func (r *mockRunner) doPing(t *testing.T) { func (r *mockRunner) doRegister(t *testing.T, name, token string, labels []string) { r.doPing(t) - resp, err := r.client.runnerServiceClient.Register(context.Background(), connect.NewRequest(&runnerv1.RegisterRequest{ + resp, err := r.client.runnerServiceClient.Register(t.Context(), connect.NewRequest(&runnerv1.RegisterRequest{ Name: name, Token: token, Version: "mock-runner-version", @@ -104,7 +104,7 @@ func (r *mockRunner) fetchTask(t *testing.T, timeout ...time.Duration) *runnerv1 ddl := time.Now().Add(fetchTimeout) var task *runnerv1.Task for time.Now().Before(ddl) { - resp, err := r.client.runnerServiceClient.FetchTask(context.Background(), connect.NewRequest(&runnerv1.FetchTaskRequest{ + resp, err := r.client.runnerServiceClient.FetchTask(t.Context(), connect.NewRequest(&runnerv1.FetchTaskRequest{ TasksVersion: 0, })) require.NoError(t, err) @@ -127,7 +127,7 @@ type mockTaskOutcome struct { func (r *mockRunner) execTask(t *testing.T, task *runnerv1.Task, outcome *mockTaskOutcome) { for idx, lr := range outcome.logRows { - resp, err := r.client.runnerServiceClient.UpdateLog(context.Background(), connect.NewRequest(&runnerv1.UpdateLogRequest{ + resp, err := r.client.runnerServiceClient.UpdateLog(t.Context(), connect.NewRequest(&runnerv1.UpdateLogRequest{ TaskId: task.Id, Index: int64(idx), Rows: []*runnerv1.LogRow{lr}, @@ -138,7 +138,7 @@ func (r *mockRunner) execTask(t *testing.T, task *runnerv1.Task, outcome *mockTa } sentOutputKeys := make([]string, 0, len(outcome.outputs)) for outputKey, outputValue := range outcome.outputs { - resp, err := r.client.runnerServiceClient.UpdateTask(context.Background(), connect.NewRequest(&runnerv1.UpdateTaskRequest{ + resp, err := r.client.runnerServiceClient.UpdateTask(t.Context(), connect.NewRequest(&runnerv1.UpdateTaskRequest{ State: &runnerv1.TaskState{ Id: task.Id, Result: runnerv1.Result_RESULT_UNSPECIFIED, @@ -150,7 +150,7 @@ func (r *mockRunner) execTask(t *testing.T, task *runnerv1.Task, outcome *mockTa assert.ElementsMatch(t, sentOutputKeys, resp.Msg.SentOutputs) } time.Sleep(outcome.execTime) - resp, err := r.client.runnerServiceClient.UpdateTask(context.Background(), connect.NewRequest(&runnerv1.UpdateTaskRequest{ + resp, err := r.client.runnerServiceClient.UpdateTask(t.Context(), connect.NewRequest(&runnerv1.UpdateTaskRequest{ State: &runnerv1.TaskState{ Id: task.Id, Result: outcome.result, diff --git a/tests/integration/actions_trigger_test.go b/tests/integration/actions_trigger_test.go index 25bdc8018f..2d5dd3b957 100644 --- a/tests/integration/actions_trigger_test.go +++ b/tests/integration/actions_trigger_test.go @@ -11,29 +11,29 @@ import ( "testing" "time" - actions_model "code.gitea.io/gitea/models/actions" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - git_model "code.gitea.io/gitea/models/git" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - unit_model "code.gitea.io/gitea/models/unit" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - actions_module "code.gitea.io/gitea/modules/actions" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - webhook_module "code.gitea.io/gitea/modules/webhook" - actions_service "code.gitea.io/gitea/services/actions" - issue_service "code.gitea.io/gitea/services/issue" - pull_service "code.gitea.io/gitea/services/pull" - release_service "code.gitea.io/gitea/services/release" - repo_service "code.gitea.io/gitea/services/repository" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + actions_model "forgejo.org/models/actions" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + git_model "forgejo.org/models/git" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + actions_module "forgejo.org/modules/actions" + "forgejo.org/modules/git" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + webhook_module "forgejo.org/modules/webhook" + actions_service "forgejo.org/services/actions" + issue_service "forgejo.org/services/issue" + pull_service "forgejo.org/services/pull" + release_service "forgejo.org/services/release" + repo_service "forgejo.org/services/repository" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -752,9 +752,18 @@ func TestWorkflowDispatchEvent(t *testing.T) { return "" } - err = workflow.Dispatch(db.DefaultContext, inputGetter, repo, user2) + var r *actions_model.ActionRun + var j []string + r, j, err = workflow.Dispatch(db.DefaultContext, inputGetter, repo, user2) require.NoError(t, err) assert.Equal(t, 1, unittest.GetCount(t, &actions_model.ActionRun{RepoID: repo.ID})) + + assert.Equal(t, "test", r.Title) + assert.Equal(t, "dispatch.yml", r.WorkflowID) + assert.Equal(t, sha, r.CommitSHA) + assert.Equal(t, actions_module.GithubEventWorkflowDispatch, r.TriggerEvent) + assert.Len(t, j, 1) + assert.Equal(t, "test", j[0]) }) } diff --git a/tests/integration/actions_variables_test.go b/tests/integration/actions_variables_test.go new file mode 100644 index 0000000000..b27d30a480 --- /dev/null +++ b/tests/integration/actions_variables_test.go @@ -0,0 +1,150 @@ +// 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 "forgejo.org/models/actions" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + forgejo_context "forgejo.org/services/context" + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" +) + +func TestActionVariablesModification(t *testing.T) { + defer unittest.OverrideFixtures("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/admin_config_test.go b/tests/integration/admin_config_test.go index 860a92d6a3..92faf7ef01 100644 --- a/tests/integration/admin_config_test.go +++ b/tests/integration/admin_config_test.go @@ -7,8 +7,8 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/admin_user_test.go b/tests/integration/admin_user_test.go index 93499e9139..b7a9deb522 100644 --- a/tests/integration/admin_user_test.go +++ b/tests/integration/admin_user_test.go @@ -4,21 +4,20 @@ package integration import ( - "context" "fmt" "net/http" "strconv" "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/timeutil" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/modules/timeutil" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -26,13 +25,36 @@ import ( func TestAdminViewUsers(t *testing.T) { defer tests.PrepareTestEnv(t)() - session := loginUser(t, "user1") - req := NewRequest(t, "GET", "/admin/users") - session.MakeRequest(t, req, http.StatusOK) + t.Run("Admin user", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() - session = loginUser(t, "user2") - req = NewRequest(t, "GET", "/admin/users") - session.MakeRequest(t, req, http.StatusForbidden) + session := loginUser(t, "user1") + req := NewRequest(t, "GET", "/admin/users") + session.MakeRequest(t, req, http.StatusOK) + + req = NewRequest(t, "GET", "/admin/users?status_filter[is_2fa_enabled]=1") + resp := session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + + // 6th column is the 2FA column. + // One user that has TOTP and another user that has WebAuthn. + assert.EqualValues(t, 2, htmlDoc.Find(".admin-setting-content table tbody tr td:nth-child(6) .octicon-check").Length()) + }) + + t.Run("Normal user", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + session := loginUser(t, "user2") + req := NewRequest(t, "GET", "/admin/users") + session.MakeRequest(t, req, http.StatusForbidden) + }) + + t.Run("Anonymous user", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", "/admin/users") + MakeRequest(t, req, http.StatusSeeOther) + }) } func TestAdminViewUser(t *testing.T) { @@ -76,7 +98,7 @@ func makeRequest(t *testing.T, formData user_model.User, headerCode int) { } func TestAdminDeleteUser(t *testing.T) { - defer tests.AddFixtures("tests/integration/fixtures/TestAdminDeleteUser/")() + defer unittest.OverrideFixtures("tests/integration/fixtures/TestAdminDeleteUser")() defer tests.PrepareTestEnv(t)() session := loginUser(t, "user1") @@ -108,7 +130,7 @@ func TestSourceId(t *testing.T) { LoginType: auth_model.Plain, LoginSource: 23, } - defer createUser(context.Background(), t, testUser23)() + defer createUser(t.Context(), t, testUser23)() session := loginUser(t, "user1") token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadAdmin) @@ -140,7 +162,7 @@ func TestAdminViewUsersSorted(t *testing.T) { defer tests.PrepareTestEnv(t)() createTimestamp := time.Now().Unix() - 1000 updateTimestamp := time.Now().Unix() - 500 - sess := db.GetEngine(context.Background()) + sess := db.GetEngine(t.Context()) // Create 10 users with login source 44 for i := int64(1); i <= 10; i++ { diff --git a/tests/integration/api_actions_artifact_test.go b/tests/integration/api_actions_artifact_test.go index 6393fc53cc..dc2b86d28b 100644 --- a/tests/integration/api_actions_artifact_test.go +++ b/tests/integration/api_actions_artifact_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_actions_artifact_v4_test.go b/tests/integration/api_actions_artifact_v4_test.go index 43df1aeee0..9fa7590620 100644 --- a/tests/integration/api_actions_artifact_v4_test.go +++ b/tests/integration/api_actions_artifact_v4_test.go @@ -14,10 +14,10 @@ import ( "testing" "time" - "code.gitea.io/gitea/modules/storage" - "code.gitea.io/gitea/routers/api/actions" - actions_service "code.gitea.io/gitea/services/actions" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/storage" + "forgejo.org/routers/api/actions" + actions_service "forgejo.org/services/actions" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_activitypub_actor_test.go b/tests/integration/api_activitypub_actor_test.go index de4d669c9d..778a34d785 100644 --- a/tests/integration/api_activitypub_actor_test.go +++ b/tests/integration/api_activitypub_actor_test.go @@ -7,10 +7,10 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/tests" ap "github.com/go-ap/activitypub" "github.com/stretchr/testify/assert" diff --git a/tests/integration/api_activitypub_person_test.go b/tests/integration/api_activitypub_person_test.go index 846ae79891..d8492942e5 100644 --- a/tests/integration/api_activitypub_person_test.go +++ b/tests/integration/api_activitypub_person_test.go @@ -9,14 +9,14 @@ import ( "net/url" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/activitypub" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/activitypub" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/tests" ap "github.com/go-ap/activitypub" "github.com/stretchr/testify/assert" diff --git a/tests/integration/api_activitypub_repository_test.go b/tests/integration/api_activitypub_repository_test.go index 2ca7d42e2a..29fbe6d781 100644 --- a/tests/integration/api_activitypub_repository_test.go +++ b/tests/integration/api_activitypub_repository_test.go @@ -1,4 +1,4 @@ -// Copyright 2024 The Forgejo Authors. All rights reserved. +// Copyright 2024, 2025 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT package integration @@ -6,21 +6,20 @@ package integration import ( "fmt" "net/http" - "net/http/httptest" "net/url" "testing" "time" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/forgefed" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/activitypub" - forgefed_modules "code.gitea.io/gitea/modules/forgefed" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/forgefed" + "forgejo.org/models/unittest" + "forgejo.org/models/user" + "forgejo.org/modules/activitypub" + forgefed_modules "forgejo.org/modules/forgefed" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -58,56 +57,8 @@ func TestActivityPubRepositoryInboxValid(t *testing.T) { defer test.MockVariableValue(&setting.Federation.Enabled, true)() defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())() - federatedRoutes := http.NewServeMux() - federatedRoutes.HandleFunc("/.well-known/nodeinfo", - func(res http.ResponseWriter, req *http.Request) { - // curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/.well-known/nodeinfo - // TODO: as soon as content-type will become important: content-type: application/json;charset=utf-8 - fmt.Fprintf(res, `{"links":[{"href":"http://%s/api/v1/nodeinfo","rel":"http://nodeinfo.diaspora.software/ns/schema/2.1"}]}`, req.Host) - }) - federatedRoutes.HandleFunc("/api/v1/nodeinfo", - func(res http.ResponseWriter, req *http.Request) { - // curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/nodeinfo - fmt.Fprint(res, `{"version":"2.1","software":{"name":"forgejo","version":"1.20.0+dev-3183-g976d79044",`+ - `"repository":"https://codeberg.org/forgejo/forgejo.git","homepage":"https://forgejo.org/"},`+ - `"protocols":["activitypub"],"services":{"inbound":[],"outbound":["rss2.0"]},`+ - `"openRegistrations":true,"usage":{"users":{"total":14,"activeHalfyear":2}},"metadata":{}}`) - }) - federatedRoutes.HandleFunc("/api/v1/activitypub/user-id/15", - func(res http.ResponseWriter, req *http.Request) { - // curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/2 - fmt.Fprint(res, `{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1"],`+ - `"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/15","type":"Person",`+ - `"icon":{"type":"Image","mediaType":"image/png","url":"https://federated-repo.prod.meissa.de/avatars/1bb05d9a5f6675ed0272af9ea193063c"},`+ - `"url":"https://federated-repo.prod.meissa.de/stargoose1","inbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/15/inbox",`+ - `"outbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/15/outbox","preferredUsername":"stargoose1",`+ - `"publicKey":{"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/15#main-key","owner":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/15",`+ - `"publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA18H5s7N6ItZUAh9tneII\nIuZdTTa3cZlLa/9ejWAHTkcp3WLW+/zbsumlMrWYfBy2/yTm56qasWt38iY4D6ul\n`+ - `CPiwhAqX3REvVq8tM79a2CEqZn9ka6vuXoDgBg/sBf/BUWqf7orkjUXwk/U0Egjf\nk5jcurF4vqf1u+rlAHH37dvSBaDjNj6Qnj4OP12bjfaY/yvs7+jue/eNXFHjzN4E\n`+ - `T2H4B/yeKTJ4UuAwTlLaNbZJul2baLlHelJPAsxiYaziVuV5P+IGWckY6RSerRaZ\nAkc4mmGGtjAyfN9aewe+lNVfwS7ElFx546PlLgdQgjmeSwLX8FWxbPE5A/PmaXCs\n`+ - `nx+nou+3dD7NluULLtdd7K+2x02trObKXCAzmi5/Dc+yKTzpFqEz+hLNCz7TImP/\ncK//NV9Q+X67J9O27baH9R9ZF4zMw8rv2Pg0WLSw1z7lLXwlgIsDapeMCsrxkVO4\n`+ - `LXX5AQ1xQNtlssnVoUBqBrvZsX2jUUKUocvZqMGuE4hfAgMBAAE=\n-----END PUBLIC KEY-----\n"}}`) - }) - federatedRoutes.HandleFunc("/api/v1/activitypub/user-id/30", - func(res http.ResponseWriter, req *http.Request) { - // curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/3 - fmt.Fprint(res, `{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1"],`+ - `"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/30","type":"Person",`+ - `"icon":{"type":"Image","mediaType":"image/png","url":"https://federated-repo.prod.meissa.de/avatars/9c03f03d1c1f13f21976a22489326fe1"},`+ - `"url":"https://federated-repo.prod.meissa.de/stargoose2","inbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/30/inbox",`+ - `"outbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/30/outbox","preferredUsername":"stargoose2",`+ - `"publicKey":{"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/30#main-key","owner":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/30",`+ - `"publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAyv5NytsfqpWXSrwuk8a3\n0W1zE13QJioXb/e3opgN2CfKZkdm3hb+4+mGKoU/rCqegnL9/AO0Aw+R8fCHXx44\n`+ - `iNkdVpdY8Dzq+tQ9IetPWbyVIBvSzGgvpqfS05JuVPsy8cBX9wByODjr5kq7k1/v\nY1G7E3uh0a/XJc+mZutwGC3gPgR93NSrqsvTPN4wdhCCu9uj02S8OBoKuSYaPkU+\n`+ - `tZ4CEDpnclAOw/eNiH4x2irMvVtruEgtlTA5K2I4YJrmtGLidus47FCyc8/zEKUh\nAeiD8KWDvqsQgOhUwcQgRxAnYVCoMD9cnE+WFFRHTuQecNlmdNFs3Cr0yKcWjDde\n`+ - `trvnehW7LfPveGb0tHRHPuVAJpncTOidUR5h/7pqMyvKHzuAHWomm9rEaGUxd/7a\nL1CFjAf39+QIEgu0Anj8mIc7CTiz+DQhDz+0jBOsQ0iDXc5GeBz7X9Xv4Jp966nq\n`+ - `MUR0GQGXvfZQN9IqMO+WoUVy10Ddhns1EWGlA0x4fecnAgMBAAE=\n-----END PUBLIC KEY-----\n"}}`) - }) - federatedRoutes.HandleFunc("/", - func(res http.ResponseWriter, req *http.Request) { - t.Errorf("Unhandled request: %q", req.URL.EscapedPath()) - }) - federatedSrv := httptest.NewServer(federatedRoutes) + mock := test.NewFederationServerMock() + federatedSrv := mock.DistantServer(t) defer federatedSrv.Close() onGiteaRun(t, func(t *testing.T, u *url.URL) { diff --git a/tests/integration/api_admin_actions_test.go b/tests/integration/api_admin_actions_test.go new file mode 100644 index 0000000000..763c35544a --- /dev/null +++ b/tests/integration/api_admin_actions_test.go @@ -0,0 +1,39 @@ +// Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "fmt" + "net/http" + "testing" + + actions_model "forgejo.org/models/actions" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + api "forgejo.org/modules/structs" + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" +) + +func TestAPISearchActionJobs_GlobalRunner(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + job := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: 393}) + adminUsername := "user1" + token := getUserToken(t, adminUsername, auth_model.AccessTokenScopeWriteAdmin) + + req := NewRequest( + t, + "GET", + fmt.Sprintf("/api/v1/admin/runners/jobs?labels=%s", "ubuntu-latest"), + ).AddTokenAuth(token) + res := MakeRequest(t, req, http.StatusOK) + + var jobs []*api.ActionRunJob + DecodeJSON(t, res, &jobs) + + assert.Len(t, jobs, 1) + assert.EqualValues(t, job.ID, jobs[0].ID) +} diff --git a/tests/integration/api_admin_org_test.go b/tests/integration/api_admin_org_test.go index 823ef2f136..df5e961ec6 100644 --- a/tests/integration/api_admin_org_test.go +++ b/tests/integration/api_admin_org_test.go @@ -8,11 +8,11 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_admin_test.go b/tests/integration/api_admin_test.go index 5f8d360dec..c5f8906bfc 100644 --- a/tests/integration/api_admin_test.go +++ b/tests/integration/api_admin_test.go @@ -9,14 +9,14 @@ import ( "testing" "time" - asymkey_model "code.gitea.io/gitea/models/asymkey" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/json" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + asymkey_model "forgejo.org/models/asymkey" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/json" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/gobwas/glob" "github.com/stretchr/testify/assert" diff --git a/tests/integration/api_block_test.go b/tests/integration/api_block_test.go index a69ee9b74f..8b25ce9283 100644 --- a/tests/integration/api_block_test.go +++ b/tests/integration/api_block_test.go @@ -8,12 +8,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_branch_test.go b/tests/integration/api_branch_test.go index aa22b15ea1..df6b7022cd 100644 --- a/tests/integration/api_branch_test.go +++ b/tests/integration/api_branch_test.go @@ -9,12 +9,12 @@ import ( "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - git_model "code.gitea.io/gitea/models/git" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/git" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + git_model "forgejo.org/models/git" + "forgejo.org/models/unittest" + "forgejo.org/modules/git" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_comment_attachment_test.go b/tests/integration/api_comment_attachment_test.go index db1b98a20f..16eb3c9b12 100644 --- a/tests/integration/api_comment_attachment_test.go +++ b/tests/integration/api_comment_attachment_test.go @@ -12,15 +12,15 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/services/convert" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/services/convert" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_comment_test.go b/tests/integration/api_comment_test.go index a53b56d783..fd0cadbb1a 100644 --- a/tests/integration/api_comment_test.go +++ b/tests/integration/api_comment_test.go @@ -10,21 +10,23 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/references" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/services/convert" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/references" + api "forgejo.org/modules/structs" + "forgejo.org/services/convert" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +const IssueIDNotExist = 10000 + func TestAPIListRepoComments(t *testing.T) { defer tests.PrepareTestEnv(t)() @@ -89,6 +91,10 @@ func TestAPIListIssueComments(t *testing.T) { expectedCount := unittest.GetCount(t, &issues_model.Comment{IssueID: issue.ID}, unittest.Cond("type = ?", issues_model.CommentTypeComment)) assert.Len(t, comments, expectedCount) + + req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/%d/comments", repoOwner.Name, repo.Name, IssueIDNotExist). + AddTokenAuth(token) + MakeRequest(t, req, http.StatusNotFound) } func TestAPICreateComment(t *testing.T) { @@ -111,6 +117,13 @@ func TestAPICreateComment(t *testing.T) { DecodeJSON(t, resp, &updatedComment) assert.EqualValues(t, commentBody, updatedComment.Body) unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: updatedComment.ID, IssueID: issue.ID, Content: commentBody}) + + urlStr = fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/comments", + repoOwner.Name, repo.Name, IssueIDNotExist) + req = NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "body": commentBody, + }).AddTokenAuth(token) + MakeRequest(t, req, http.StatusNotFound) } func TestAPICreateCommentAutoDate(t *testing.T) { @@ -464,4 +477,7 @@ func TestAPIListIssueTimeline(t *testing.T) { DecodeJSON(t, resp, &comments) expectedCount := unittest.GetCount(t, &issues_model.Comment{IssueID: issue.ID}) assert.Len(t, comments, expectedCount) + + req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/%d/timeline", repoOwner.Name, repo.Name, IssueIDNotExist) + MakeRequest(t, req, http.StatusNotFound) } diff --git a/tests/integration/api_feed_plain_text_titles_test.go b/tests/integration/api_feed_plain_text_titles_test.go index b1247780d8..889d0a103a 100644 --- a/tests/integration/api_feed_plain_text_titles_test.go +++ b/tests/integration/api_feed_plain_text_titles_test.go @@ -7,9 +7,9 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_forgejo_root_test.go b/tests/integration/api_forgejo_root_test.go index d21c9449b3..a5c1b8abe0 100644 --- a/tests/integration/api_forgejo_root_test.go +++ b/tests/integration/api_forgejo_root_test.go @@ -7,7 +7,7 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_forgejo_version_test.go b/tests/integration/api_forgejo_version_test.go index 5c95fd373c..b42e4a2bd7 100644 --- a/tests/integration/api_forgejo_version_test.go +++ b/tests/integration/api_forgejo_version_test.go @@ -7,12 +7,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - v1 "code.gitea.io/gitea/routers/api/forgejo/v1" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/routers" + v1 "forgejo.org/routers/api/forgejo/v1" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_fork_test.go b/tests/integration/api_fork_test.go index 6614f4b799..2809af2748 100644 --- a/tests/integration/api_fork_test.go +++ b/tests/integration/api_fork_test.go @@ -9,14 +9,14 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -123,7 +123,7 @@ func TestAPIForkListPrivateRepo(t *testing.T) { }).AddTokenAuth(token) MakeRequest(t, req, http.StatusAccepted) - t.Run("Anomynous", func(t *testing.T) { + t.Run("Anonymous", func(t *testing.T) { defer tests.PrintCurrentTest(t)() req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/forks") diff --git a/tests/integration/api_gitignore_templates_test.go b/tests/integration/api_gitignore_templates_test.go index c58f5eebfe..2412b55d3a 100644 --- a/tests/integration/api_gitignore_templates_test.go +++ b/tests/integration/api_gitignore_templates_test.go @@ -8,10 +8,10 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/modules/options" - repo_module "code.gitea.io/gitea/modules/repository" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/options" + repo_module "forgejo.org/modules/repository" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_gpg_keys_test.go b/tests/integration/api_gpg_keys_test.go index ec0dafc2d6..1acbf91de0 100644 --- a/tests/integration/api_gpg_keys_test.go +++ b/tests/integration/api_gpg_keys_test.go @@ -9,9 +9,9 @@ import ( "strconv" "testing" - auth_model "code.gitea.io/gitea/models/auth" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_health_test.go b/tests/integration/api_health_test.go index 5657f4fd06..22f060e79b 100644 --- a/tests/integration/api_health_test.go +++ b/tests/integration/api_health_test.go @@ -4,9 +4,9 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/routers/web/healthcheck" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + "forgejo.org/routers/web/healthcheck" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_helper_for_declarative_test.go b/tests/integration/api_helper_for_declarative_test.go index 5bd8dc5567..88e1cd2198 100644 --- a/tests/integration/api_helper_for_declarative_test.go +++ b/tests/integration/api_helper_for_declarative_test.go @@ -4,7 +4,6 @@ package integration import ( - "context" "fmt" "net/http" "net/http/httptest" @@ -13,14 +12,14 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/perm" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/json" - "code.gitea.io/gitea/modules/queue" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/services/forms" + "forgejo.org/models/auth" + "forgejo.org/models/perm" + repo_model "forgejo.org/models/repo" + "forgejo.org/modules/git" + "forgejo.org/modules/json" + "forgejo.org/modules/queue" + api "forgejo.org/modules/structs" + "forgejo.org/services/forms" "github.com/google/uuid" "github.com/stretchr/testify/assert" @@ -287,7 +286,7 @@ func doAPIMergePullRequestForm(t *testing.T, ctx APITestContext, owner, repo str if err.Message != "Please try again later" { break } - queue.GetManager().FlushAll(context.Background(), 5*time.Second) + queue.GetManager().FlushAll(t.Context(), 5*time.Second) <-time.After(1 * time.Second) } diff --git a/tests/integration/api_httpsig_test.go b/tests/integration/api_httpsig_test.go index 30aed3cacc..48a0b267eb 100644 --- a/tests/integration/api_httpsig_test.go +++ b/tests/integration/api_httpsig_test.go @@ -9,13 +9,13 @@ import ( "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/tests" - "github.com/go-fed/httpsig" + "github.com/42wim/httpsig" "golang.org/x/crypto/ssh" ) diff --git a/tests/integration/api_issue_attachment_test.go b/tests/integration/api_issue_attachment_test.go index 77e752d122..ef7e6183f9 100644 --- a/tests/integration/api_issue_attachment_test.go +++ b/tests/integration/api_issue_attachment_test.go @@ -12,13 +12,13 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_issue_config_test.go b/tests/integration/api_issue_config_test.go index 16f81e785d..809be572da 100644 --- a/tests/integration/api_issue_config_test.go +++ b/tests/integration/api_issue_config_test.go @@ -9,11 +9,11 @@ import ( "net/http" "testing" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_issue_label_test.go b/tests/integration/api_issue_label_test.go index ebcf29a13d..7b2fbd18be 100644 --- a/tests/integration/api_issue_label_test.go +++ b/tests/integration/api_issue_label_test.go @@ -10,13 +10,13 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_issue_milestone_test.go b/tests/integration/api_issue_milestone_test.go index 32ac56298f..2ab7f9a346 100644 --- a/tests/integration/api_issue_milestone_test.go +++ b/tests/integration/api_issue_milestone_test.go @@ -8,13 +8,13 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_issue_pin_test.go b/tests/integration/api_issue_pin_test.go index 2f257a89e0..2073241903 100644 --- a/tests/integration/api_issue_pin_test.go +++ b/tests/integration/api_issue_pin_test.go @@ -8,13 +8,13 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_issue_reaction_test.go b/tests/integration/api_issue_reaction_test.go index 4ca909f281..817c07898c 100644 --- a/tests/integration/api_issue_reaction_test.go +++ b/tests/integration/api_issue_reaction_test.go @@ -9,15 +9,15 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/services/convert" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/services/convert" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_issue_stopwatch_test.go b/tests/integration/api_issue_stopwatch_test.go index 4765787e6f..f395ad1a61 100644 --- a/tests/integration/api_issue_stopwatch_test.go +++ b/tests/integration/api_issue_stopwatch_test.go @@ -7,14 +7,14 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_issue_subscription_test.go b/tests/integration/api_issue_subscription_test.go index 7a716301c4..4d1b9b2fb1 100644 --- a/tests/integration/api_issue_subscription_test.go +++ b/tests/integration/api_issue_subscription_test.go @@ -8,14 +8,14 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_issue_templates_test.go b/tests/integration/api_issue_templates_test.go index d634329514..49b1a6f277 100644 --- a/tests/integration/api_issue_templates_test.go +++ b/tests/integration/api_issue_templates_test.go @@ -9,11 +9,11 @@ import ( "net/url" "testing" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_issue_test.go b/tests/integration/api_issue_test.go index 4051f95ed9..99fc158fdd 100644 --- a/tests/integration/api_issue_test.go +++ b/tests/integration/api_issue_test.go @@ -12,15 +12,15 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -74,6 +74,50 @@ func TestAPIListIssues(t *testing.T) { if assert.Len(t, apiIssues, 1) { assert.EqualValues(t, 1, apiIssues[0].ID) } + + t.Run("Sort", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + link.RawQuery = url.Values{"token": {token}, "sort": {"oldest"}}.Encode() + resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) + DecodeJSON(t, resp, &apiIssues) + if assert.Len(t, apiIssues, 4) { + assert.EqualValues(t, 1, apiIssues[0].ID) + assert.EqualValues(t, 2, apiIssues[1].ID) + assert.EqualValues(t, 3, apiIssues[2].ID) + assert.EqualValues(t, 11, apiIssues[3].ID) + } + + link.RawQuery = url.Values{"token": {token}, "sort": {"newest"}}.Encode() + resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) + DecodeJSON(t, resp, &apiIssues) + if assert.Len(t, apiIssues, 4) { + assert.EqualValues(t, 11, apiIssues[0].ID) + assert.EqualValues(t, 3, apiIssues[1].ID) + assert.EqualValues(t, 2, apiIssues[2].ID) + assert.EqualValues(t, 1, apiIssues[3].ID) + } + + link.RawQuery = url.Values{"token": {token}, "sort": {"recentupdate"}}.Encode() + resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) + DecodeJSON(t, resp, &apiIssues) + if assert.Len(t, apiIssues, 4) { + assert.EqualValues(t, 11, apiIssues[0].ID) + assert.EqualValues(t, 1, apiIssues[1].ID) + assert.EqualValues(t, 2, apiIssues[2].ID) + assert.EqualValues(t, 3, apiIssues[3].ID) + } + + link.RawQuery = url.Values{"token": {token}, "sort": {"leastupdate"}}.Encode() + resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) + DecodeJSON(t, resp, &apiIssues) + if assert.Len(t, apiIssues, 4) { + assert.EqualValues(t, 3, apiIssues[0].ID) + assert.EqualValues(t, 2, apiIssues[1].ID) + assert.EqualValues(t, 1, apiIssues[2].ID) + assert.EqualValues(t, 11, apiIssues[3].ID) + } + }) } func TestAPIListIssuesPublicOnly(t *testing.T) { diff --git a/tests/integration/api_issue_tracked_time_test.go b/tests/integration/api_issue_tracked_time_test.go index 90a59fb481..41def89a55 100644 --- a/tests/integration/api_issue_tracked_time_test.go +++ b/tests/integration/api_issue_tracked_time_test.go @@ -9,13 +9,13 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_keys_test.go b/tests/integration/api_keys_test.go index 86daa8c506..a6f0fbe69b 100644 --- a/tests/integration/api_keys_test.go +++ b/tests/integration/api_keys_test.go @@ -9,14 +9,14 @@ import ( "net/url" "testing" - asymkey_model "code.gitea.io/gitea/models/asymkey" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/perm" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + asymkey_model "forgejo.org/models/asymkey" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/perm" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_label_templates_test.go b/tests/integration/api_label_templates_test.go index 3039f8c60c..545a1736d0 100644 --- a/tests/integration/api_label_templates_test.go +++ b/tests/integration/api_label_templates_test.go @@ -10,9 +10,9 @@ import ( "strings" "testing" - repo_module "code.gitea.io/gitea/modules/repository" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + repo_module "forgejo.org/modules/repository" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_license_templates_test.go b/tests/integration/api_license_templates_test.go index e12aab7c2c..7bdd1bc7dc 100644 --- a/tests/integration/api_license_templates_test.go +++ b/tests/integration/api_license_templates_test.go @@ -9,10 +9,10 @@ import ( "net/url" "testing" - "code.gitea.io/gitea/modules/options" - repo_module "code.gitea.io/gitea/modules/repository" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/options" + repo_module "forgejo.org/modules/repository" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_nodeinfo_test.go b/tests/integration/api_nodeinfo_test.go index d000083717..c4f2309aac 100644 --- a/tests/integration/api_nodeinfo_test.go +++ b/tests/integration/api_nodeinfo_test.go @@ -7,11 +7,11 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_notification_test.go b/tests/integration/api_notification_test.go index ad233d9e73..b9efaa43a3 100644 --- a/tests/integration/api_notification_test.go +++ b/tests/integration/api_notification_test.go @@ -8,14 +8,14 @@ import ( "net/http" "testing" - activities_model "code.gitea.io/gitea/models/activities" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + activities_model "forgejo.org/models/activities" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_oauth2_apps_test.go b/tests/integration/api_oauth2_apps_test.go index 85c7184b64..2490a11888 100644 --- a/tests/integration/api_oauth2_apps_test.go +++ b/tests/integration/api_oauth2_apps_test.go @@ -8,11 +8,11 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_org_actions_test.go b/tests/integration/api_org_actions_test.go new file mode 100644 index 0000000000..ed8f91e5c2 --- /dev/null +++ b/tests/integration/api_org_actions_test.go @@ -0,0 +1,38 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "fmt" + "net/http" + "testing" + + actions_model "forgejo.org/models/actions" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + api "forgejo.org/modules/structs" + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" +) + +func TestAPISearchActionJobs_OrgRunner(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + session := loginUser(t, "user1") + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization) + + job := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: 395}) + + req := NewRequest(t, "GET", + fmt.Sprintf("/api/v1/orgs/org3/actions/runners/jobs?labels=%s", "fedora")). + AddTokenAuth(token) + res := MakeRequest(t, req, http.StatusOK) + + var jobs []*api.ActionRunJob + DecodeJSON(t, res, &jobs) + + assert.Len(t, jobs, 1) + assert.EqualValues(t, job.ID, jobs[0].ID) +} diff --git a/tests/integration/api_org_avatar_test.go b/tests/integration/api_org_avatar_test.go index bbe116cd60..aa5ca0fa08 100644 --- a/tests/integration/api_org_avatar_test.go +++ b/tests/integration/api_org_avatar_test.go @@ -9,9 +9,9 @@ import ( "os" "testing" - auth_model "code.gitea.io/gitea/models/auth" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_org_test.go b/tests/integration/api_org_test.go index c26cf196de..37e6035045 100644 --- a/tests/integration/api_org_test.go +++ b/tests/integration/api_org_test.go @@ -9,17 +9,17 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - org_model "code.gitea.io/gitea/models/organization" - "code.gitea.io/gitea/models/perm" - 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/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + org_model "forgejo.org/models/organization" + "forgejo.org/models/perm" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -99,6 +99,29 @@ func TestAPIOrgCreate(t *testing.T) { assert.EqualValues(t, "user1", users[0].UserName) } +func TestAPIOrgRename(t *testing.T) { + defer tests.PrepareTestEnv(t)() + token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization) + + org := api.CreateOrgOption{ + UserName: "user1_org", + FullName: "User1's organization", + Description: "This organization created by user1", + Website: "https://try.gitea.io", + Location: "Shanghai", + Visibility: "limited", + } + req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &org). + AddTokenAuth(token) + MakeRequest(t, req, http.StatusCreated) + + req = NewRequestWithJSON(t, "POST", "/api/v1/orgs/user1_org/rename", &api.RenameOrgOption{ + NewName: "renamed_org", + }).AddTokenAuth(token) + MakeRequest(t, req, http.StatusNoContent) + unittest.AssertExistsAndLoadBean(t, &org_model.Organization{Name: "renamed_org"}) +} + func TestAPIOrgEdit(t *testing.T) { defer tests.PrepareTestEnv(t)() session := loginUser(t, "user1") diff --git a/tests/integration/api_packages_alpine_test.go b/tests/integration/api_packages_alpine_test.go index 2264625556..d3cf56394c 100644 --- a/tests/integration/api_packages_alpine_test.go +++ b/tests/integration/api_packages_alpine_test.go @@ -14,13 +14,13 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - alpine_module "code.gitea.io/gitea/modules/packages/alpine" - alpine_service "code.gitea.io/gitea/services/packages/alpine" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + alpine_module "forgejo.org/modules/packages/alpine" + alpine_service "forgejo.org/services/packages/alpine" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_packages_alt_test.go b/tests/integration/api_packages_alt_test.go new file mode 100644 index 0000000000..e84af7dd15 --- /dev/null +++ b/tests/integration/api_packages_alt_test.go @@ -0,0 +1,658 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "bytes" + "compress/gzip" + "crypto/sha256" + "encoding/base64" + "encoding/binary" + "fmt" + "io" + "net/http" + "strconv" + "strings" + "testing" + + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + packages_module "forgejo.org/modules/packages" + rpm_module "forgejo.org/modules/packages/rpm" + "forgejo.org/modules/setting" + "forgejo.org/modules/util" + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/ulikunitz/xz" +) + +func TestPackageAlt(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + packageName := "gitea-test" + packageVersion := "1.0.2-1" + packageArchitecture := "x86_64" + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + + base64RpmPackageContent := `H4sICFayB2QCAGdpdGVhLXRlc3QtMS4wLjItMS14ODZfNjQucnBtAO2YV4gTQRjHJzl7wbNhhxVF +VNwk2zd2PdvZ9Sxnd3Z3NllNsmF3o6congVFsWFHRWwIImIXfRER0QcRfPBJEXvvBQvWSfZTT0VQ +8TF/MuU33zcz3+zOJGEe73lyuQBRBWKWRzDrEddjuVAkxLMc+lsFUOWfm5bvvReAalWECg/TsivU +dyKa0U61aVnl6wj0Uxe4nc8F92hZiaYE8CO/P0r7/Quegr0c7M/AvoCaGZEIWNGUqMHrhhGROIUT +Zc7gOAOraoQzCNZ0WdU0HpEI5jiB4zlek3gT85wqCBomhomxoGCs8wImWMImbxqKgXVNUKKaqShR +STKVKK9glFUNcf2g+/t27xs16v5x/eyOKftVGlIhyiuvvPLKK6+88sorr7zyyiuvvPKCO5HPnz+v +pGVhhXsTsFVeSstuWR9anwU+Bk3Vch5wTwL3JkHg+8C1gR8A169wj1KdpobAj4HbAT+Be5VewE+h +fz/g52AvBX4N9vHAb4AnA7+F8ePAH8BuA38ELgf+BLzQ50oIeBlw0OdAOXAlP57AGuCsbwGtbgCu +DrwRuAb4bwau6T/PwFbgWsDXgWuD/y3gOmC/B1wI/Bi4AcT3Arih3z9YCNzI9w9m/YKUG4Nd9N9z +pSZgHwrcFPgccFt//OADGE+F/q+Ao+D/FrijzwV1gbv4/QvaAHcFDgF3B5aB+wB3Be7rz1dQCtwP +eDxwMcw3GbgU7AasdwzYE8DjwT4L/CeAvRx4IvBCYA3iWQds+FzpDjABfghsAj8BTgA/A/b8+StX +A84A1wKe5s9fuRB4JpzHZv55rL8a/Dv49vpn/PErR4BvQX8Z+Db4l2W5CH2/f0W5+1fEoeFDBzFp +rE/FMcK4mWQSOzN+aDOIqztW2rPsFKIyqh7sQERR42RVMSKihnzVHlQ8Ag0YLBYNEIajkhmuR5Io +7nlpt2M4nJs0ZNkoYaUyZahMlSfJImr1n1WjFVNCPCaTZgYNGdGL8YN2mX8WHfA/C7ViHJK0pxHG +SrkeTiSI4T+7ubf85yrzRCQRQ5EVxVAjvIBVRY/KRFAVReIkhfARSddNSceayQkGliIKb0q8RAxJ +5QWNVxHIsW3Pz369bw+5jh5y0klE9Znqm0dF57b0HbGy2A5lVUBTZZrqZjdUjYoprFmpsBtHP5d0 ++ISltS2yk2mHuC4x+lgJMhgnidvuqy3b0suK0bm+tw3FMxI2zjm7/fA0MtQhplX2s7nYLZ2ZC0yg +CxJZDokhORTJlrlcCvG5OieGBERlVCs7CfuS6WzQ/T2j+9f92BWxTFEcp2IkYccYGp2LYySEfreq +irue4WRF5XkpKovw2wgpq2rZBI8bQZkzxEkiYaNwxnXCCVvHidzIiB3CM2yMYdNWmjDsaLovaE4c +x3a6mLaTxB7rEj3jWN4M2p7uwPaa1GfI8BHFfcZMKhkycnhR7y781/a+A4t7FpWWTupRUtKbegwZ +XMKwJinTSe70uhRcj55qNu3YHtE922Fdz7FTMTq9Q3TbMdiYrrPudMvT44S6u2miu138eC0tTN9D +2CFGHHtQsHHsGCRFDFbXuT9wx6mUTZfseydlkWZeJkW6xOgYjqXT+LA7I6XHaUx2xmUzqelWymA9 +rCXI9+D1BHbjsITssqhBNysw0tOWjcpmIh6+aViYPfftw8ZSGfRVPUqKiosZj5R5qGmk/8AjjRbZ +d8b3vvngdPHx3HvMeCarIk7VVSwbgoZVkceEVyOmyUmGxBGNYDVKSFSOGlIkGqWnUZFkiY/wsmhK +Mu0UFYgZ/bYnuvn/vz4wtCz8qMwsHUvP0PX3tbYFUctAPdrY6tiiDtcCddDECahx7SuVNP5dpmb5 +9tMDyaXb7OAlk5acuPn57ss9mw6Wym0m1Fq2cej7tUt2LL4/b8enXU2fndk+fvv57ndnt55/cQob +7tpp/pEjDS7cGPZ6BY430+7danDq6f42Nw49b9F7zp6BiKpJb9s5P0AYN2+L159cnrur636rx+v1 +7ae1K28QbMMcqI8CqwIrgwg9nTOp8Oj9q81plUY7ZuwXN8Vvs8wbAAA=` + rpmPackageContent, err := base64.StdEncoding.DecodeString(base64RpmPackageContent) + require.NoError(t, err) + + zr, err := gzip.NewReader(bytes.NewReader(rpmPackageContent)) + require.NoError(t, err) + + content, err := io.ReadAll(zr) + require.NoError(t, err) + + rootURL := fmt.Sprintf("/api/packages/%s/alt", user.Name) + + for _, group := range []string{"", "el9", "el9/stable"} { + t.Run(fmt.Sprintf("[Group:%s]", group), func(t *testing.T) { + var groupParts []string + uploadURL := rootURL + if group != "" { + groupParts = strings.Split(group, "/") + uploadURL = strings.Join(append([]string{rootURL}, groupParts...), "/") + } else { + groupParts = strings.Split("alt", "/") + } + groupURL := strings.Join(append([]string{rootURL}, groupParts...), "/") + + t.Run("RepositoryConfig", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", groupURL+".repo") + resp := MakeRequest(t, req, http.StatusOK) + + expected := fmt.Sprintf(`[gitea-%s] +name=%s +baseurl=%s +enabled=1`, + strings.Join(append([]string{user.LowerName}, groupParts...), "-"), + strings.Join(append([]string{user.Name, setting.AppName}, groupParts...), " - "), + util.URLJoin(setting.AppURL, groupURL), + ) + + assert.Equal(t, expected, resp.Body.String()) + }) + + t.Run("Upload", func(t *testing.T) { + url := uploadURL + "/upload" + + req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)) + MakeRequest(t, req, http.StatusUnauthorized) + + req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)). + AddBasicAuth(user.Name) + MakeRequest(t, req, http.StatusCreated) + + pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeAlt) + require.NoError(t, err) + assert.Len(t, pvs, 1) + + pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0]) + require.NoError(t, err) + assert.Nil(t, pd.SemVer) + assert.IsType(t, &rpm_module.VersionMetadata{}, pd.Metadata) + assert.Equal(t, packageName, pd.Package.Name) + assert.Equal(t, packageVersion, pd.Version.Version) + + pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID) + require.NoError(t, err) + assert.Len(t, pfs, 1) + assert.Equal(t, fmt.Sprintf("%s-%s.%s.rpm", packageName, packageVersion, packageArchitecture), pfs[0].Name) + assert.True(t, pfs[0].IsLead) + + pb, err := packages.GetBlobByID(db.DefaultContext, pfs[0].BlobID) + require.NoError(t, err) + assert.Equal(t, int64(len(content)), pb.Size) + + req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)). + AddBasicAuth(user.Name) + MakeRequest(t, req, http.StatusConflict) + }) + + t.Run("Download", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", fmt.Sprintf("%s.repo/%s/RPMS.classic/%s-%s.%s.rpm", groupURL, packageArchitecture, packageName, packageVersion, packageArchitecture)) + resp := MakeRequest(t, req, http.StatusOK) + + assert.Equal(t, content, resp.Body.Bytes()) + }) + + t.Run("Repository", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + url := fmt.Sprintf("%s.repo/%s/base", groupURL, packageArchitecture) + + req := NewRequest(t, "HEAD", url+"/dummy.xml") + MakeRequest(t, req, http.StatusNotFound) + + req = NewRequest(t, "GET", url+"/dummy.xml") + MakeRequest(t, req, http.StatusNotFound) + + t.Run("release.classic", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req = NewRequest(t, "HEAD", url+"/release.classic") + MakeRequest(t, req, http.StatusOK) + + req = NewRequest(t, "GET", url+"/release.classic") + resp := MakeRequest(t, req, http.StatusOK).Body.String() + + type ReleaseClassic struct { + Archive string + Component string + Origin string + Label string + Architecture string + NotAutomatic bool + } + + var result ReleaseClassic + + lines := strings.Split(resp, "\n") + + for _, line := range lines { + parts := strings.SplitN(line, ": ", 2) + if len(parts) < 2 { + continue + } + + switch parts[0] { + case "Archive": + result.Archive = parts[1] + case "Component": + result.Component = parts[1] + case "Origin": + result.Origin = parts[1] + case "Label": + result.Label = parts[1] + case "Architecture": + result.Architecture = parts[1] + case "NotAutomatic": + notAuto, err := strconv.ParseBool(parts[1]) + if err != nil { + require.NoError(t, err) + } + result.NotAutomatic = notAuto + } + } + + assert.Equal(t, "classic", result.Component) + assert.Equal(t, "Alt Linux Team", result.Origin) + assert.Equal(t, "Forgejo", result.Label) + assert.Equal(t, "x86_64", result.Architecture) + assert.False(t, result.NotAutomatic) + assert.NotEmpty(t, result.Archive) + }) + + t.Run("release", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req = NewRequest(t, "HEAD", url+"/release") + MakeRequest(t, req, http.StatusOK) + + req = NewRequest(t, "GET", url+"/release") + resp := MakeRequest(t, req, http.StatusOK).Body.String() + + type Checksum struct { + Hash string + Size int + File string + } + + type Release struct { + Origin string + Label string + Suite string + Architectures string + MD5Sum []Checksum + BLAKE2B []Checksum + } + + var result Release + + lines := strings.Split(resp, "\n") + + var isMD5Sum, isBLAKE2b bool + + for _, line := range lines { + line = strings.TrimSpace(line) + + if line == "" { + continue + } + switch { + case strings.HasPrefix(line, "Origin:"): + result.Origin = strings.TrimSpace(strings.TrimPrefix(line, "Origin:")) + case strings.HasPrefix(line, "Label:"): + result.Label = strings.TrimSpace(strings.TrimPrefix(line, "Label:")) + case strings.HasPrefix(line, "Suite:"): + result.Suite = strings.TrimSpace(strings.TrimPrefix(line, "Suite:")) + case strings.HasPrefix(line, "Architectures:"): + result.Architectures = strings.TrimSpace(strings.TrimPrefix(line, "Architectures:")) + case line == "MD5Sum:": + isMD5Sum = true + isBLAKE2b = false + case line == "BLAKE2b:": + isBLAKE2b = true + isMD5Sum = false + case isMD5Sum || isBLAKE2b: + parts := strings.Fields(line) + if len(parts) >= 3 { + hash := parts[0] + size, err := strconv.Atoi(parts[1]) + if err != nil { + continue + } + file := parts[2] + + checksum := Checksum{ + Hash: hash, + Size: size, + File: file, + } + + if isMD5Sum { + result.MD5Sum = append(result.MD5Sum, checksum) + } else if isBLAKE2b { + result.BLAKE2B = append(result.BLAKE2B, checksum) + } + } + } + } + + assert.Equal(t, "Forgejo", result.Origin) + assert.Equal(t, "Forgejo", result.Label) + assert.Equal(t, "Sisyphus", result.Suite) + assert.Equal(t, "x86_64", result.Architectures) + + assert.Len(t, result.MD5Sum, 3) + assert.Equal(t, "bbf7ae6b2f540673ed1cfc0266b5f319", result.MD5Sum[0].Hash) + assert.Equal(t, 1003, result.MD5Sum[0].Size) + assert.Equal(t, "base/pkglist.classic", result.MD5Sum[0].File) + + assert.Len(t, result.BLAKE2B, 3) + assert.Equal(t, "b527bf038895ce29107ec3a6d2eebd7c365e8ce5ab767276eeddd7c549a159025225cb0ecfdbf7b71da13db7e865e77bcb0e2dae4d21335df01a4a17e0056a70", result.BLAKE2B[0].Hash) + assert.Equal(t, 1003, result.BLAKE2B[0].Size) + assert.Equal(t, "base/pkglist.classic", result.BLAKE2B[0].File) + }) + + t.Run("pkglist.classic", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req = NewRequest(t, "GET", url+"/pkglist.classic") + resp := MakeRequest(t, req, http.StatusOK) + + body := resp.Body + defer body.Reset() + + type RpmHeader struct { + Magic [8]byte + Nindex uint32 + Hsize uint32 + } + + type RpmHdrIndex struct { + Tag uint32 + Type uint32 + Offset uint32 + Count uint32 + } + + type Metadata struct { + Name string + Version string + Release string + Summary []string + Description []string + BuildTime int + Size int + License string + Packager string + Group []string + URL string + Arch string + SourceRpm string + ProvideNames []string + RequireFlags []int + RequireNames []string + RequireVersions []string + ChangeLogTimes []int + ChangeLogNames []string + ChangeLogTexts []string + ProvideFlags []int + ProvideVersions []string + DirIndexes []int + BaseNames []string + DirNames []string + DistTag string + AptIndexLegacyFileName string + AptIndexLegacyFileSize int + MD5Sum string + BLAKE2B string + AptIndexLegacyDirectory string + } + + var result Metadata + + const rpmHeaderMagic = "\x8e\xad\xe8\x01\x00\x00\x00\x00" + + var hdr RpmHeader + for { + if err := binary.Read(body, binary.BigEndian, &hdr); err != nil { + if err == io.EOF { + break + } + require.NoError(t, err) + } + + if !bytes.Equal(hdr.Magic[:], []byte(rpmHeaderMagic)) { + require.NoError(t, err) + } + + nindex := hdr.Nindex + index := make([]RpmHdrIndex, nindex) + if err := binary.Read(body, binary.BigEndian, &index); err != nil { + require.NoError(t, err) + } + + data := make([]byte, hdr.Hsize) + if err := binary.Read(body, binary.BigEndian, &data); err != nil { + require.NoError(t, err) + } + + var indexPtrs []*RpmHdrIndex + for i := range index { + indexPtrs = append(indexPtrs, &index[i]) + } + + for _, idx := range indexPtrs { + tag := binary.BigEndian.Uint32([]byte{byte(idx.Tag >> 24), byte(idx.Tag >> 16), byte(idx.Tag >> 8), byte(idx.Tag)}) + typ := binary.BigEndian.Uint32([]byte{byte(idx.Type >> 24), byte(idx.Type >> 16), byte(idx.Type >> 8), byte(idx.Type)}) + offset := binary.BigEndian.Uint32([]byte{byte(idx.Offset >> 24), byte(idx.Offset >> 16), byte(idx.Offset >> 8), byte(idx.Offset)}) + count := binary.BigEndian.Uint32([]byte{byte(idx.Count >> 24), byte(idx.Count >> 16), byte(idx.Count >> 8), byte(idx.Count)}) + + if typ == 6 || typ == 8 || typ == 9 { + elem := data[offset:] + for j := uint32(0); j < count; j++ { + strEnd := bytes.IndexByte(elem, 0) + if strEnd == -1 { + require.NoError(t, err) + } + switch tag { + case 1000: + result.Name = string(elem[:strEnd]) + case 1001: + result.Version = string(elem[:strEnd]) + case 1002: + result.Release = string(elem[:strEnd]) + case 1004: + var summaries []string + for i := uint32(0); i < count; i++ { + summaries = append(summaries, string(elem[:strEnd])) + } + result.Summary = summaries + case 1005: + var descriptions []string + for i := uint32(0); i < count; i++ { + descriptions = append(descriptions, string(elem[:strEnd])) + } + result.Description = descriptions + case 1014: + result.License = string(elem[:strEnd]) + case 1015: + result.Packager = string(elem[:strEnd]) + case 1016: + var groups []string + for i := uint32(0); i < count; i++ { + groups = append(groups, string(elem[:strEnd])) + } + result.Group = groups + case 1020: + result.URL = string(elem[:strEnd]) + case 1022: + result.Arch = string(elem[:strEnd]) + case 1044: + result.SourceRpm = string(elem[:strEnd]) + case 1047: + var provideNames []string + for i := uint32(0); i < count; i++ { + provideNames = append(provideNames, string(elem[:strEnd])) + } + result.ProvideNames = provideNames + case 1049: + var requireNames []string + for i := uint32(0); i < count; i++ { + requireNames = append(requireNames, string(elem[:strEnd])) + } + result.RequireNames = requireNames + case 1050: + var requireVersions []string + for i := uint32(0); i < count; i++ { + requireVersions = append(requireVersions, string(elem[:strEnd])) + } + result.RequireVersions = requireVersions + case 1081: + var changeLogNames []string + for i := uint32(0); i < count; i++ { + changeLogNames = append(changeLogNames, string(elem[:strEnd])) + } + result.ChangeLogNames = changeLogNames + case 1082: + var changeLogTexts []string + for i := uint32(0); i < count; i++ { + changeLogTexts = append(changeLogTexts, string(elem[:strEnd])) + } + result.ChangeLogTexts = changeLogTexts + case 1113: + var provideVersions []string + for i := uint32(0); i < count; i++ { + provideVersions = append(provideVersions, string(elem[:strEnd])) + } + result.ProvideVersions = provideVersions + case 1117: + var baseNames []string + for i := uint32(0); i < count; i++ { + baseNames = append(baseNames, string(elem[:strEnd])) + } + result.BaseNames = baseNames + case 1118: + var dirNames []string + for i := uint32(0); i < count; i++ { + dirNames = append(dirNames, string(elem[:strEnd])) + } + result.DirNames = dirNames + case 1155: + result.DistTag = string(elem[:strEnd]) + case 1000000: + result.AptIndexLegacyFileName = string(elem[:strEnd]) + case 1000005: + result.MD5Sum = string(elem[:strEnd]) + case 1000009: + result.BLAKE2B = string(elem[:strEnd]) + case 1000010: + result.AptIndexLegacyDirectory = string(elem[:strEnd]) + } + elem = elem[strEnd+1:] + } + } else if typ == 4 { + elem := data[offset:] + for j := uint32(0); j < count; j++ { + val := binary.BigEndian.Uint32(elem) + switch tag { + case 1006: + result.BuildTime = int(val) + case 1009: + result.Size = int(val) + case 1048: + var requireFlags []int + for i := uint32(0); i < count; i++ { + requireFlags = append(requireFlags, int(val)) + } + result.RequireFlags = requireFlags + case 1080: + var changeLogTimes []int + for i := uint32(0); i < count; i++ { + changeLogTimes = append(changeLogTimes, int(val)) + } + result.ChangeLogTimes = changeLogTimes + case 1112: + var provideFlags []int + for i := uint32(0); i < count; i++ { + provideFlags = append(provideFlags, int(val)) + } + result.ProvideFlags = provideFlags + case 1116: + var dirIndexes []int + for i := uint32(0); i < count; i++ { + dirIndexes = append(dirIndexes, int(val)) + } + result.DirIndexes = dirIndexes + case 1000001: + result.AptIndexLegacyFileSize = int(val) + } + elem = elem[4:] + } + } else { + require.NoError(t, err) + } + } + } + assert.Equal(t, "gitea-test", result.Name) + assert.Equal(t, "1.0.2", result.Version) + assert.Equal(t, "1", result.Release) + assert.Equal(t, []string{"RPM package summary"}, result.Summary) + assert.Equal(t, []string{"RPM package description"}, result.Description) + assert.Equal(t, 1678225964, result.BuildTime) + assert.Equal(t, 13, result.Size) + assert.Equal(t, "MIT", result.License) + assert.Equal(t, "KN4CK3R", result.Packager) + assert.Equal(t, []string{"System"}, result.Group) + assert.Equal(t, "https://gitea.io", result.URL) + assert.Equal(t, "x86_64", result.Arch) + assert.Equal(t, "gitea-test-1.0.2-1.src.rpm", result.SourceRpm) + assert.Equal(t, []string{"", ""}, result.ProvideNames) + assert.Equal(t, []int{16777226, 16777226, 16777226, 16777226, 16777226, 16777226, 16777226}, result.RequireFlags) + assert.Equal(t, []string{"", "", "", "", "", "", ""}, result.RequireNames) + assert.Equal(t, []string{"5.2-1", "5.2-1", "5.2-1", "5.2-1", "5.2-1", "5.2-1", "5.2-1"}, result.RequireVersions) + assert.Equal(t, []int{1678276800}, result.ChangeLogTimes) + assert.Equal(t, []string{"KN4CK3R "}, result.ChangeLogNames) + assert.Equal(t, []string{"- Changelog message."}, result.ChangeLogTexts) + assert.Equal(t, []int{8, 8}, result.ProvideFlags) + assert.Equal(t, []string{"1.0.2-1", "1.0.2-1"}, result.ProvideVersions) + assert.Equal(t, []int(nil), result.DirIndexes) + assert.Equal(t, []string{"hello"}, result.BaseNames) + assert.Equal(t, []string{"/usr/local/bin/"}, result.DirNames) + assert.Equal(t, "", result.DistTag) + assert.Equal(t, "gitea-test-1.0.2-1.x86_64.rpm", result.AptIndexLegacyFileName) + assert.Equal(t, 7116, result.AptIndexLegacyFileSize) + assert.Equal(t, "9ea82dd62968719aea19c08cd2ced79a", result.MD5Sum) + assert.Equal(t, "8ba7f1f52a47b23997aa2de21b305cc71974d51f0c54fb53cb927156284dafdcc233d514a46c020e4a0666e218529e0284933c5873d24c2555830d7627140f7d", result.BLAKE2B) + assert.Equal(t, "RPMS.classic", result.AptIndexLegacyDirectory) + }) + + t.Run("pkglist.classic.xz", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", url+"/pkglist.classic.xz") + pkglistXZResp := MakeRequest(t, req, http.StatusOK) + pkglistXZ := pkglistXZResp.Body + defer pkglistXZ.Reset() + + req2 := NewRequest(t, "GET", url+"/pkglist.classic") + pkglistResp := MakeRequest(t, req2, http.StatusOK) + pkglist := pkglistResp.Body + defer pkglist.Reset() + + assert.Less(t, pkglistXZ.Len(), pkglist.Len()) + + xzReader, err := xz.NewReader(pkglistXZ) + require.NoError(t, err) + + var unxzData bytes.Buffer + _, err = io.Copy(&unxzData, xzReader) + require.NoError(t, err) + + assert.Equal(t, unxzData.Len(), pkglist.Len()) + + content, _ := packages_module.NewHashedBuffer() + defer content.Close() + + h := sha256.New() + w := io.MultiWriter(content, h) + + _, err = io.Copy(w, pkglist) + require.NoError(t, err) + + hashMD5Classic, _, hashSHA256Classic, _, hashBlake2bClassic := content.Sums() + + contentUnxz, _ := packages_module.NewHashedBuffer() + defer contentUnxz.Close() + + _, err = io.Copy(io.MultiWriter(contentUnxz, sha256.New()), &unxzData) + require.NoError(t, err) + + hashMD5Unxz, _, hashSHA256Unxz, _, hashBlake2bUnxz := contentUnxz.Sums() + + assert.Equal(t, fmt.Sprintf("%x", hashSHA256Classic), fmt.Sprintf("%x", hashSHA256Unxz)) + assert.Equal(t, fmt.Sprintf("%x", hashBlake2bClassic), fmt.Sprintf("%x", hashBlake2bUnxz)) + assert.Equal(t, fmt.Sprintf("%x", hashMD5Classic), fmt.Sprintf("%x", hashMD5Unxz)) + }) + }) + + t.Run("Delete", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "DELETE", fmt.Sprintf("%s.repo/%s/RPMS.classic/%s-%s.%s.rpm", groupURL, packageArchitecture, packageName, packageVersion, packageArchitecture)) + MakeRequest(t, req, http.StatusUnauthorized) + + req = NewRequest(t, "DELETE", fmt.Sprintf("%s.repo/%s/RPMS.classic/%s-%s.%s.rpm", groupURL, packageArchitecture, packageName, packageVersion, packageArchitecture)). + AddBasicAuth(user.Name) + MakeRequest(t, req, http.StatusNoContent) + + pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeAlt) + require.NoError(t, err) + assert.Empty(t, pvs) + req = NewRequest(t, "DELETE", fmt.Sprintf("%s.repo/%s/RPMS.classic/%s-%s.%s.rpm", groupURL, packageArchitecture, packageName, packageVersion, packageArchitecture)). + AddBasicAuth(user.Name) + MakeRequest(t, req, http.StatusNotFound) + }) + }) + } +} diff --git a/tests/integration/api_packages_arch_test.go b/tests/integration/api_packages_arch_test.go index 57db324a2f..2463fd1c8e 100644 --- a/tests/integration/api_packages_arch_test.go +++ b/tests/integration/api_packages_arch_test.go @@ -18,12 +18,12 @@ import ( "testing" "testing/fstest" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - arch_model "code.gitea.io/gitea/modules/packages/arch" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + arch_model "forgejo.org/modules/packages/arch" + "forgejo.org/tests" "github.com/ProtonMail/go-crypto/openpgp/armor" "github.com/ProtonMail/go-crypto/openpgp/packet" diff --git a/tests/integration/api_packages_cargo_test.go b/tests/integration/api_packages_cargo_test.go index 7a9105eb3a..048859e312 100644 --- a/tests/integration/api_packages_cargo_test.go +++ b/tests/integration/api_packages_cargo_test.go @@ -12,19 +12,19 @@ import ( neturl "net/url" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/json" - cargo_module "code.gitea.io/gitea/modules/packages/cargo" - "code.gitea.io/gitea/modules/setting" - cargo_router "code.gitea.io/gitea/routers/api/packages/cargo" - gitea_context "code.gitea.io/gitea/services/context" - cargo_service "code.gitea.io/gitea/services/packages/cargo" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/json" + cargo_module "forgejo.org/modules/packages/cargo" + "forgejo.org/modules/setting" + cargo_router "forgejo.org/routers/api/packages/cargo" + gitea_context "forgejo.org/services/context" + cargo_service "forgejo.org/services/packages/cargo" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_packages_chef_test.go b/tests/integration/api_packages_chef_test.go index febb1a8b6c..390ac50688 100644 --- a/tests/integration/api_packages_chef_test.go +++ b/tests/integration/api_packages_chef_test.go @@ -25,14 +25,14 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - chef_module "code.gitea.io/gitea/modules/packages/chef" - "code.gitea.io/gitea/modules/setting" - chef_router "code.gitea.io/gitea/routers/api/packages/chef" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + chef_module "forgejo.org/modules/packages/chef" + "forgejo.org/modules/setting" + chef_router "forgejo.org/routers/api/packages/chef" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_packages_composer_test.go b/tests/integration/api_packages_composer_test.go index 9d25cc4d64..9c906a8959 100644 --- a/tests/integration/api_packages_composer_test.go +++ b/tests/integration/api_packages_composer_test.go @@ -11,14 +11,15 @@ import ( neturl "net/url" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - composer_module "code.gitea.io/gitea/modules/packages/composer" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/routers/api/packages/composer" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + composer_module "forgejo.org/modules/packages/composer" + "forgejo.org/modules/setting" + "forgejo.org/routers/api/packages/composer" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -218,5 +219,39 @@ func TestPackageComposer(t *testing.T) { assert.Equal(t, "4f5fa464c3cb808a1df191dbf6cb75363f8b7072", pkgs[0].Dist.Checksum) assert.Len(t, pkgs[0].Bin, 1) assert.Equal(t, packageBin, pkgs[0].Bin[0]) + + // Test package linked to repository + repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + userPkgs, err := packages.GetPackagesByType(db.DefaultContext, user.ID, packages.TypeComposer) + require.NoError(t, err) + assert.Len(t, userPkgs, 1) + assert.EqualValues(t, 0, userPkgs[0].RepoID) + + err = packages.SetRepositoryLink(db.DefaultContext, userPkgs[0].ID, repo1.ID) + require.NoError(t, err) + + req = NewRequest(t, "GET", fmt.Sprintf("%s/p2/%s/%s.json", url, vendorName, projectName)). + AddBasicAuth(user.Name) + resp = MakeRequest(t, req, http.StatusOK) + + result = composer.PackageMetadataResponse{} + DecodeJSON(t, resp, &result) + + assert.Contains(t, result.Packages, packageName) + pkgs = result.Packages[packageName] + assert.Len(t, pkgs, 1) + assert.Equal(t, packageName, pkgs[0].Name) + assert.Equal(t, packageVersion, pkgs[0].Version) + assert.Equal(t, packageType, pkgs[0].Type) + assert.Equal(t, packageDescription, pkgs[0].Description) + assert.Len(t, pkgs[0].Authors, 1) + assert.Equal(t, packageAuthor, pkgs[0].Authors[0].Name) + assert.Equal(t, "zip", pkgs[0].Dist.Type) + assert.Equal(t, "4f5fa464c3cb808a1df191dbf6cb75363f8b7072", pkgs[0].Dist.Checksum) + assert.Len(t, pkgs[0].Bin, 1) + assert.Equal(t, packageBin, pkgs[0].Bin[0]) + assert.Equal(t, repo1.HTMLURL(), pkgs[0].Source.URL) + assert.Equal(t, "git", pkgs[0].Source.Type) + assert.Equal(t, packageVersion, pkgs[0].Source.Reference) }) } diff --git a/tests/integration/api_packages_conan_test.go b/tests/integration/api_packages_conan_test.go index 9d8f435068..c0185c852d 100644 --- a/tests/integration/api_packages_conan_test.go +++ b/tests/integration/api_packages_conan_test.go @@ -11,16 +11,16 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - conan_model "code.gitea.io/gitea/models/packages/conan" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - conan_module "code.gitea.io/gitea/modules/packages/conan" - "code.gitea.io/gitea/modules/setting" - conan_router "code.gitea.io/gitea/routers/api/packages/conan" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/packages" + conan_model "forgejo.org/models/packages/conan" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + conan_module "forgejo.org/modules/packages/conan" + "forgejo.org/modules/setting" + conan_router "forgejo.org/routers/api/packages/conan" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_packages_conda_test.go b/tests/integration/api_packages_conda_test.go index 4625c5854c..6924968d35 100644 --- a/tests/integration/api_packages_conda_test.go +++ b/tests/integration/api_packages_conda_test.go @@ -12,13 +12,13 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - conda_module "code.gitea.io/gitea/modules/packages/conda" - "code.gitea.io/gitea/modules/zstd" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + conda_module "forgejo.org/modules/packages/conda" + "forgejo.org/modules/zstd" + "forgejo.org/tests" "github.com/dsnet/compress/bzip2" "github.com/stretchr/testify/assert" diff --git a/tests/integration/api_packages_container_cleanup_sha256_test.go b/tests/integration/api_packages_container_cleanup_sha256_test.go index eb63eff720..b1ed435b80 100644 --- a/tests/integration/api_packages_container_cleanup_sha256_test.go +++ b/tests/integration/api_packages_container_cleanup_sha256_test.go @@ -12,17 +12,17 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" - packages_model "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/log" - packages_module "code.gitea.io/gitea/modules/packages" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - packages_cleanup "code.gitea.io/gitea/services/packages/cleanup" - packages_container "code.gitea.io/gitea/services/packages/container" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + packages_model "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/log" + packages_module "forgejo.org/modules/packages" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + packages_cleanup "forgejo.org/services/packages/cleanup" + packages_container "forgejo.org/services/packages/container" + "forgejo.org/tests" oci "github.com/opencontainers/image-spec/specs-go/v1" "github.com/stretchr/testify/assert" diff --git a/tests/integration/api_packages_container_test.go b/tests/integration/api_packages_container_test.go index 3c28f45660..223c865dec 100644 --- a/tests/integration/api_packages_container_test.go +++ b/tests/integration/api_packages_container_test.go @@ -13,17 +13,17 @@ import ( "sync" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - packages_model "code.gitea.io/gitea/models/packages" - container_model "code.gitea.io/gitea/models/packages/container" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - container_module "code.gitea.io/gitea/modules/packages/container" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + packages_model "forgejo.org/models/packages" + container_model "forgejo.org/models/packages/container" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + container_module "forgejo.org/modules/packages/container" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/tests" oci "github.com/opencontainers/image-spec/specs-go/v1" "github.com/stretchr/testify/assert" diff --git a/tests/integration/api_packages_cran_test.go b/tests/integration/api_packages_cran_test.go index d64b592327..2326d36171 100644 --- a/tests/integration/api_packages_cran_test.go +++ b/tests/integration/api_packages_cran_test.go @@ -12,12 +12,12 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - cran_module "code.gitea.io/gitea/modules/packages/cran" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + cran_module "forgejo.org/modules/packages/cran" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_packages_debian_test.go b/tests/integration/api_packages_debian_test.go index d85f56fdbb..67498ec043 100644 --- a/tests/integration/api_packages_debian_test.go +++ b/tests/integration/api_packages_debian_test.go @@ -13,13 +13,13 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/base" - debian_module "code.gitea.io/gitea/modules/packages/debian" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/base" + debian_module "forgejo.org/modules/packages/debian" + "forgejo.org/tests" "github.com/blakesmith/ar" "github.com/stretchr/testify/assert" diff --git a/tests/integration/api_packages_generic_test.go b/tests/integration/api_packages_generic_test.go index 1a53f33387..5a3727cae5 100644 --- a/tests/integration/api_packages_generic_test.go +++ b/tests/integration/api_packages_generic_test.go @@ -10,12 +10,12 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_packages_goproxy_test.go b/tests/integration/api_packages_goproxy_test.go index 716d90b242..1534fa73cc 100644 --- a/tests/integration/api_packages_goproxy_test.go +++ b/tests/integration/api_packages_goproxy_test.go @@ -11,11 +11,11 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_packages_helm_test.go b/tests/integration/api_packages_helm_test.go index 4b48b74ce0..df19e7cd03 100644 --- a/tests/integration/api_packages_helm_test.go +++ b/tests/integration/api_packages_helm_test.go @@ -12,13 +12,13 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - helm_module "code.gitea.io/gitea/modules/packages/helm" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + helm_module "forgejo.org/modules/packages/helm" + "forgejo.org/modules/setting" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_packages_maven_test.go b/tests/integration/api_packages_maven_test.go index b453f10b69..438c2f0fb5 100644 --- a/tests/integration/api_packages_maven_test.go +++ b/tests/integration/api_packages_maven_test.go @@ -11,12 +11,12 @@ import ( "sync" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/packages/maven" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/packages/maven" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_packages_npm_test.go b/tests/integration/api_packages_npm_test.go index d0c54c306b..38c7ee54c0 100644 --- a/tests/integration/api_packages_npm_test.go +++ b/tests/integration/api_packages_npm_test.go @@ -11,14 +11,14 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/packages/npm" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/packages/npm" + "forgejo.org/modules/setting" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_packages_nuget_test.go b/tests/integration/api_packages_nuget_test.go index 03e2176fe5..b4da9695f0 100644 --- a/tests/integration/api_packages_nuget_test.go +++ b/tests/integration/api_packages_nuget_test.go @@ -17,16 +17,16 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - nuget_module "code.gitea.io/gitea/modules/packages/nuget" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/routers/api/packages/nuget" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + nuget_module "forgejo.org/modules/packages/nuget" + "forgejo.org/modules/setting" + "forgejo.org/modules/structs" + "forgejo.org/routers/api/packages/nuget" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -49,6 +49,9 @@ func TestPackageNuGet(t *testing.T) { Version string `xml:"Version"` NormalizedVersion string `xml:"NormalizedVersion"` Authors string `xml:"Authors"` + Owners string `xml:"Owners,omitempty"` + Copyright string `xml:"Copyright,omitempty"` + Language string `xml:"Language,omitempty"` Dependencies string `xml:"Dependencies"` Description string `xml:"Description"` VersionDownloadCount nuget.TypedValue[int64] `xml:"VersionDownloadCount"` @@ -58,9 +61,15 @@ func TestPackageNuGet(t *testing.T) { LastUpdated nuget.TypedValue[time.Time] `xml:"LastUpdated"` Published nuget.TypedValue[time.Time] `xml:"Published"` ProjectURL string `xml:"ProjectUrl,omitempty"` + LicenseURL string `xml:"LicenseUrl,omitempty"` + IconURL string `xml:"IconUrl,omitempty"` ReleaseNotes string `xml:"ReleaseNotes,omitempty"` RequireLicenseAcceptance nuget.TypedValue[bool] `xml:"RequireLicenseAcceptance"` + DevelopmentDependency nuget.TypedValue[bool] `xml:"DevelopmentDependency"` Title string `xml:"Title"` + MinClientVersion string `xml:"MinClientVersion,omitempty"` + Tags string `xml:"Tags,omitempty"` + ID string `xml:"Id,omitempty"` } type FeedEntry struct { @@ -87,21 +96,43 @@ func TestPackageNuGet(t *testing.T) { packageName := "test.package" packageVersion := "1.0.3" packageAuthors := "KN4CK3R" - packageDescription := "Gitea Test Package" + packageDescription := "Forgejo Test Package" symbolFilename := "test.pdb" symbolID := "d910bb6948bd4c6cb40155bcf52c3c94" + packageTitle := "Package Title" + packageLanguage := "Package Language" + packageOwners := "Package Owners" + packageCopyright := "Package Copyright" + packageProjectURL := "https://forgejo.org" + packageLicenseURL := "https://forgejo.org/docs/latest/license/" + packageIconURL := "https://codeberg.org/forgejo/governance/raw/branch/main/branding/logo/forgejo.png" + packageReleaseNotes := "Package Release Notes" + packageTags := "tag_1 tag_2 tag_3" + packageMinClientVersion := "1.0.0.0" + createPackage := func(id, version string) io.Reader { var buf bytes.Buffer archive := zip.NewWriter(&buf) w, _ := archive.Create("package.nuspec") w.Write([]byte(` - + ` + id + ` + ` + packageTitle + ` + ` + packageLanguage + ` ` + version + ` ` + packageAuthors + ` + ` + packageOwners + ` + ` + packageCopyright + ` + true + true + ` + packageProjectURL + ` + ` + packageLicenseURL + ` + ` + packageIconURL + ` ` + packageDescription + ` + ` + packageReleaseNotes + ` + ` + packageTags + ` @@ -115,11 +146,22 @@ func TestPackageNuGet(t *testing.T) { nuspec := ` - + ` + packageName + ` + ` + packageTitle + ` + ` + packageLanguage + ` ` + packageVersion + ` ` + packageAuthors + ` + ` + packageOwners + ` + ` + packageCopyright + ` + true + true + ` + packageProjectURL + ` + ` + packageLicenseURL + ` + ` + packageIconURL + ` ` + packageDescription + ` + ` + packageReleaseNotes + ` + ` + packageTags + ` @@ -325,7 +367,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID) require.NoError(t, err) - assert.Equal(t, int64(414), pb.Size) + assert.Equal(t, int64(len(content)), pb.Size) case fmt.Sprintf("%s.%s.snupkg", packageName, packageVersion): assert.False(t, pf.IsLead) @@ -337,7 +379,7 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID) require.NoError(t, err) - assert.Equal(t, int64(453), pb.Size) + assert.Equal(t, int64(len([]byte(nuspec))), pb.Size) case symbolFilename: assert.False(t, pf.IsLead) @@ -668,10 +710,22 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`) var result FeedEntry decodeXML(t, resp, &result) - assert.Equal(t, packageName, result.Properties.Title) + assert.Equal(t, packageName, result.Properties.ID) assert.Equal(t, packageVersion, result.Properties.Version) assert.Equal(t, packageAuthors, result.Properties.Authors) assert.Equal(t, packageDescription, result.Properties.Description) + assert.Equal(t, packageTitle, result.Properties.Title) + assert.Equal(t, packageLanguage, result.Properties.Language) + assert.Equal(t, packageOwners, result.Properties.Owners) + assert.Equal(t, packageCopyright, result.Properties.Copyright) + assert.Equal(t, packageProjectURL, result.Properties.ProjectURL) + assert.Equal(t, packageLicenseURL, result.Properties.LicenseURL) + assert.Equal(t, packageIconURL, result.Properties.IconURL) + assert.Equal(t, packageReleaseNotes, result.Properties.ReleaseNotes) + assert.Equal(t, packageTags, result.Properties.Tags) + assert.Equal(t, packageMinClientVersion, result.Properties.MinClientVersion) + assert.True(t, result.Properties.DevelopmentDependency.Value) + assert.True(t, result.Properties.RequireLicenseAcceptance.Value) assert.Equal(t, "Microsoft.CSharp:4.5.0:.NETStandard2.0", result.Properties.Dependencies) }) diff --git a/tests/integration/api_packages_pub_test.go b/tests/integration/api_packages_pub_test.go index d6bce3055e..72ba2f14cd 100644 --- a/tests/integration/api_packages_pub_test.go +++ b/tests/integration/api_packages_pub_test.go @@ -15,13 +15,13 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - pub_module "code.gitea.io/gitea/modules/packages/pub" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + pub_module "forgejo.org/modules/packages/pub" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_packages_pypi_test.go b/tests/integration/api_packages_pypi_test.go index ef03dbe509..f025f8e577 100644 --- a/tests/integration/api_packages_pypi_test.go +++ b/tests/integration/api_packages_pypi_test.go @@ -13,12 +13,12 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/packages/pypi" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/packages/pypi" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -33,15 +33,16 @@ func TestPackagePyPI(t *testing.T) { packageVersion := "1!1.0.1+r1234" packageAuthor := "KN4CK3R" packageDescription := "Test Description" + projectURL := "https://example.com" content := "test" hashSHA256 := "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" root := fmt.Sprintf("/api/packages/%s/pypi", user.Name) - uploadFile := func(t *testing.T, filename, content string, expectedStatus int) { - body := &bytes.Buffer{} - writer := multipart.NewWriter(body) + createBasicMultipartFile := func(filename, packageName, content string) (body *bytes.Buffer, writer *multipart.Writer, closer func() error) { + body = &bytes.Buffer{} + writer = multipart.NewWriter(body) part, _ := writer.CreateFormFile("content", filename) _, _ = io.Copy(part, strings.NewReader(content)) @@ -53,14 +54,27 @@ func TestPackagePyPI(t *testing.T) { writer.WriteField("sha256_digest", hashSHA256) writer.WriteField("requires_python", "3.6") - _ = writer.Close() + return body, writer, writer.Close + } + uploadHelper := func(t *testing.T, body *bytes.Buffer, contentType string, expectedStatus int) { req := NewRequestWithBody(t, "POST", root, body). - SetHeader("Content-Type", writer.FormDataContentType()). + SetHeader("Content-Type", contentType). AddBasicAuth(user.Name) MakeRequest(t, req, expectedStatus) } + uploadFile := func(t *testing.T, filename, content string, expectedStatus int) { + body, writer, closeFunc := createBasicMultipartFile(filename, packageName, content) + + writer.WriteField("project_urls", "DOCUMENTATION , https://readthedocs.org") + writer.WriteField("project_urls", fmt.Sprintf("Home-page, %s", projectURL)) + + _ = closeFunc() + + uploadHelper(t, body, writer.FormDataContentType(), expectedStatus) + } + t.Run("Upload", func(t *testing.T) { defer tests.PrintCurrentTest(t)() @@ -75,6 +89,7 @@ func TestPackagePyPI(t *testing.T) { require.NoError(t, err) assert.Nil(t, pd.SemVer) assert.IsType(t, &pypi.Metadata{}, pd.Metadata) + assert.Equal(t, projectURL, pd.Metadata.(*pypi.Metadata).ProjectURL) assert.Equal(t, packageName, pd.Package.Name) assert.Equal(t, packageVersion, pd.Version.Version) @@ -134,6 +149,48 @@ func TestPackagePyPI(t *testing.T) { uploadFile(t, "test.tar.gz", content, http.StatusConflict) }) + t.Run("UploadUsingDeprecatedHomepageMetadata", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + pkgName := "homepage-package" + body, writer, closeFunc := createBasicMultipartFile("test.whl", pkgName, content) + + writer.WriteField("home_page", projectURL) + + _ = closeFunc() + + uploadHelper(t, body, writer.FormDataContentType(), http.StatusCreated) + + pvs, err := packages.GetVersionsByPackageName(db.DefaultContext, user.ID, packages.TypePyPI, pkgName) + require.NoError(t, err) + assert.Len(t, pvs, 1) + + pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0]) + require.NoError(t, err) + assert.IsType(t, &pypi.Metadata{}, pd.Metadata) + assert.Equal(t, projectURL, pd.Metadata.(*pypi.Metadata).ProjectURL) + }) + + t.Run("UploadWithoutAnyHomepageURLMetadata", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + pkgName := "no-project-url-or-homepage-package" + body, writer, closeFunc := createBasicMultipartFile("test.whl", pkgName, content) + + _ = closeFunc() + + uploadHelper(t, body, writer.FormDataContentType(), http.StatusCreated) + + pvs, err := packages.GetVersionsByPackageName(db.DefaultContext, user.ID, packages.TypePyPI, pkgName) + require.NoError(t, err) + assert.Len(t, pvs, 1) + + pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0]) + require.NoError(t, err) + assert.IsType(t, &pypi.Metadata{}, pd.Metadata) + assert.Empty(t, pd.Metadata.(*pypi.Metadata).ProjectURL) + }) + t.Run("Download", func(t *testing.T) { defer tests.PrintCurrentTest(t)() @@ -148,7 +205,7 @@ func TestPackagePyPI(t *testing.T) { downloadFile("test.whl") downloadFile("test.tar.gz") - pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypePyPI) + pvs, err := packages.GetVersionsByPackageName(db.DefaultContext, user.ID, packages.TypePyPI, packageName) require.NoError(t, err) assert.Len(t, pvs, 1) assert.Equal(t, int64(2), pvs[0].DownloadCount) diff --git a/tests/integration/api_packages_rpm_test.go b/tests/integration/api_packages_rpm_test.go index 853c8f0f69..3abaec3462 100644 --- a/tests/integration/api_packages_rpm_test.go +++ b/tests/integration/api_packages_rpm_test.go @@ -15,14 +15,14 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - rpm_module "code.gitea.io/gitea/modules/packages/rpm" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/util" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + rpm_module "forgejo.org/modules/packages/rpm" + "forgejo.org/modules/setting" + "forgejo.org/modules/util" + "forgejo.org/tests" "github.com/ProtonMail/go-crypto/openpgp" "github.com/sassoftware/go-rpmutils" diff --git a/tests/integration/api_packages_rubygems_test.go b/tests/integration/api_packages_rubygems_test.go index eb3dc0e7f2..97c2c8bb5f 100644 --- a/tests/integration/api_packages_rubygems_test.go +++ b/tests/integration/api_packages_rubygems_test.go @@ -14,12 +14,12 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/packages/rubygems" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/packages/rubygems" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -201,6 +201,137 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==`) holaChecksum := fmt.Sprintf("%x", sha256.Sum256(holaGemContent)) + binaryPackageName := "debug_inspector" + binaryPackageVersion := "0.0.3" + binaryRubyGemsRequirements := "ruby:~> 3.1.0" + binaryGemContent, _ := base64.StdEncoding.DecodeString(`bWV0YWRhdGEuZ3oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDA0NDQAMDAwMDAw +MAAwMDAwMDAwADAwMDAwMDAxMTM0ADE0NDQyNjI3NzcyADAxMzQ1NAAgMAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMHdoZWVsAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAd2hlZWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAw +MDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf +iwgA+i+LZAIDxVRbb9MwFH73rzB9KTzksnYrkyUmKm1CRaqECuIBhCInOU28xRdsZ7Sa4LdznN7W +bExcHkgi5ficz+d852JHUUSf2TZfJzq/hsKzNyAZe2+gEEtRcC+0IopLYLSEvK0yoRzavLbkFqxD +K3tk+8eNiVC6B6VxGo+JabhfaisZXZ1Psslp1AjVriLZuobw1tfaOkYi+lbXis65sPR5zpVwHuxS +gCpfBJC28LUVFhjJhSqFZRT/pADrs6LmAmN9/kJK7pHyKD15GaVnUXpO05R1X5zuHvqJlGDQK6hC +QBf3YSaXO8Qak9nUQQolPDiPii0TCco/VobFwYzgIziGC5oI38HFq0G3CMunarl59hUdng1R6dcG +ObESbqHRZhvKWLDQAHdoWvLGwaET2RGJ/0K6BFdYYXynmNIFbqbfLDcGLMXhoL4GOl/M6ChO+0NH +p+9mBCQXTWjXtUXJvq7COi60JLCCovU8b7CdYQpg5UGFwPul5ZktdZEtxQ6zkdAbEg8ySour6eX8 +KpZlkPkNbNU9LnEFMohoQcdJz5qgrtBqGdscAY3I+4BfGpJtsQKg1hIMr7CNtffGsSSphK/bPGSb +7I5G3wFpRIFpb7Kazz4QCZ7jgeCM3n0nRjsfsJ43TSbBueCedEXRXU82Zdm2PTPc150jZLpTlllo +ePbEBXA8RP0R6gbox8WA/N747OOM45M4PSYRevCPRHaT/AdEhumQHJ+jULEHdMbxOB5NiBOVEqrK +bmDNiLt/sx6gp8S1UnK7/qsTEa6jeyP9E+HiLnPUBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGF0 +YS50YXIuZ3oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDA0NDQAMDAwMDAwMAAw +MDAwMDAwADAwMDAwMDA1MzMzADE0NDQyNjI3NzcyADAxMzM3NwAgMAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMHdoZWVsAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAd2hlZWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAwMDAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiwgA ++i+LZAID7Fp7U9tIEs/f+hR94m79KCMTnleuZfcMCNCtsSnbJJsiOSNLY3uCLGn1CMvl8dnv16OH +sQnZvatdbjfFFBU0M/2e7p7uISdiPpGeePZ7jo3nGxu729vPNrKx+hubW8+eb29vb+5u7u3tbQJ+ +c3dr4xltPHuEkcaJHUGUm5kQ3hfgfml/Vbk/yYiDNHIE6bMkCeNWsxml49upmMdGEE11TePPUDjq +gyqRfS0q2rOn8fWMvtk+OjONufv/i//tnZ3te/G/ufMU/48xXDFOpyPpc5QnQUSXf7k8SKXn0iCx +kzR+Uy0SQxLZ72S87kjODM2x7cs4EVFzBd+I302/H0e278z25zZD1P5bEjVtf3lo2qhNfeQluons +MBQRTSBoMhPkixs661u0aWyQovL6jibtc2ukaUOAXa1wuKJDEj8nwo9l4JPtuwxLNyISoBLLqS9c +tTqGIRIC38sfAunMJA3s2HbthUJTmczSseEE8+Z18LzWgFAypjAK3oKPhs+38C6yCclTTqRjJ8wv +mBBD3QTRtaFp9Xq3NzQHrXod3zTkHU/CgNEtzZFtY0pjwSiFukoVWtISs8IKxkaD6nU3ID9IFGZy +l2CQJrF0FTlFZir9KcUySZVgcb1uQISe790q4WIKFnSpL35KZcQIMuGN1I/TMAyiBLbC2UhIeiM9 +jyIRpzAaRLIhxHoQatpFbE+Fts5D066urviK0SJFT1Bl5WwqmrZGvVD4uaZO4Cc4Kyye23EMZleu +UyHJwkFO20nkO5FxG3uBc62xn7w4a7WOGNsq3TJgiu/pg+t80IjWaGw713BH3HzAytSnaiSSNMKH +DXJRZN+yoYazSNhuq3VQILRanaA4yTGfc1wDRVCJaZ9cxygpj0rKmmJ5G6TkgPRUJNAtTGZMHsnH +uaZJZM8F7Ie1K6ZkxPLfuGgzsmpiJHIOE+NkP0jWQOkgfZcPBGTkOlAd2/M4OBSxhTJ0UMApcQlO +40uvpoiELLFCGOXUqrKm5fRlLH76ReKFvWHqJEod1neAoxU+TPtlhkz+DjfHw/l+lt0qooJkTCLh +u9pH9ilNO4SjwB0yP2NPO4+CsYfyhflDoDg7ZCcDI2hhJ3SZRXAW0csBXaQnCNiRDnKFWJCuclY5 +s4aU79SYfXgbyeksoapTo01cYev4Z4uq/wxmCCNbMqFzEc1lrLIOPHiGhIPkMkW2RBQ1oKxQsenM +7GgqkEwCeOItIeHFytkSW/o4Ic2GEuFtlhRAJg4myY2NUOKUBcsEjrQ5Kt3ASecC2ipf5SIfLo40 +olUGOUalppi4wvY4hDjFFFvKGZEvOJ6TSKpzbQDI8VL2Eq3Y9uRc5hwYXVkgZqJIPg0lZ4PmgSsn +/FsotcJ07Ml41tBcyaTHaYLFmBeVLRusRxNnFgukE1Dg1JInwEI6BQMuWsgGTXITKb43s2C+rAlM +NIGzgqVwlboBTKY4Ku8EFQafBJ4X3HCYwENcqZyllV0f9jhAjnHKA0ZuhaiZCCrfL04134pncF8a +Cy0zGPhyhrqjTsTsEft+ImF7TqPKOVfUxPUwPDVp0Dsevmz3TbIGdN7vvbCOzCOqtAeYVxr00hqe +9i6GBIh+uzt8Rb1jandf0Q9W96ihmT+e983BgHp9ss7OO5Z51CCre9i5OLK6J3QAPFw/1LHgzCA6 +7BEzzElZJvCOtTOzf3iKafvA6ljDVw06toZdpnkMom06b/eH1uFFp92n84v+eW9ggv0RyHat7nEf +XMwzszs0NKuLNTJfYEKD03ano1i1LyB9X8l32Dt/1bdOTod02uscmVg8MCFZ+6BjZqy6r7TDTts6 +a9BR+6x9YiqsHqj0FVgu3ctTUy2BXxs/h0Or12WbHPa6wz6mDW3Y6w9L1JfWwGxQu28N2CDH/R7I +szmB0VNEgNc1MypsapZaK08EIKzFxcBcyHJktjugNWDku8dn/CEbpz6KjN/7AYDr/72dnYfq/63t +3b2V+n9rY/Op/3+U8deWgVJuJicJVVAnVhaFGTf7TccTtr9Y1FeqteY7ZF6kLn0FLcGtkdjxNao5 +10P5htKoP8YNPZHTVgsRdWydXFaOOuaPw8ob3AORcABxDDc0xM8hEusotJNZVS1g18etXx2Njq2O +ORrVasgCvYMDs2/k2bWq1+vNurH2XrH6qDdILXwqPtbqxZfhBdPyO9CZktnuLugAvXmPVrmYI5fz +QG+o0mQxyr1PdwEz/gu08dv7kq3VjfrD5AxXTJZohO64wBxNvFvuFBSB5aVS1WjsQFmNY73VGuJs +hjgbA+1EtcUnVVN1ZcJ1ZWLACWL69lvSeUdXS/w1ygqI7JQ6uLkvFYASZ8RfYKK/UeC4urhOASwq +QqGW4CbjAO1IvsRlm4ZWyyF9MAtuqPQi9hlq5VNIBeQQTcs9vyswWrT2frnSb7Ve4OpAtv6o32UT +pShQIGVc8IBFbW5U9r+jyxbqvRBqNUiZ442Ww4Tome7I4AW2qqNXZZE+qgrAsrHiGemMth5BMuXY +H5uw6GqPuyTbWPXbfPGjBrcjFAiFkLlcmRDODPRIL8myM6yGo56BZnJwn8V9LgqaCZ9OucG+QSqy +l9cWMyekRRCQYTTxw2roec29kL6i6KShkr9squNKoUG+q8RSQs1hmwl9xiaLoPsflK0sdKpwzeqk +gpuOe+LqaF1qIJFwNYa2vLB0JIpFOESLHztLiXmS+sX26kEuMyvgC+h1b+EGK5jrD3uuoQRTQmfS +3ZWtlHTZfXg79OxkEsDC/GrL7U2ALqzQkMXKnJ2NBFeP5gz2ZlnRjNhDMhv5c/ByaIk518f3BChN +q/gseUBJv65UvWvDe3HBZXaYAhG0EZxLpHldEV86NOU7VcWhVrjIkYwu9YzbG0PYzkylvGn2x48P +ed4tjKDYrb3Pdz9mYcGCLbzpq3n/feCEH/P99/nzvZ2V+m+X/yT0VP89wlij9fo63NoJ+G5rUZpM +1v/Oa2VFd68sq+SXwQO1IHrSslbTtBMxb7UGgCgfQA31jInoiznuYoOrOw6w/Xu3vLpQjaIa2KcH +8qWCstNkFkRcoFzq5ZMLVYtXnIlE1NZUgRIbYm5LT0G+jfAZ/WPKC/zqkwPMgrkI7SnXK/pn3nof +ernO5I3T+ZxfW4H7wLP10pP18ot1RoLzXyTDJFO7JKn2sjqsGPt0BcHIi9fV+pURh55MqvprX68p +8DIl75M6ivN83mr1Lw5eZeYob21lk89dtXeqiMxC+WMNECpn1rCSHYHrjlzxTnhByO9O+A5hdLjW +La5n6UtO33COynf7tFP5urLon3d8+bQfpf/f2MH3cv7f29p4yv+PdP9PaILaeTTPH4IQyirj819M +sg78bSD9B3pxNJhnOZ7Okxu9Ru8/TLKCamKovulvl3nB2nrtv06EMwtI79qubahU8rGo+CY0j+Ro +83usYSJ94X5f5RQ1MrsnVtes0Tff0J057e9nHY6ODcVObeZXAu1/oua/NpsZcSJN3iFfPlXMr+cT +Tl1OJFBblhao3vubVE0TXsyWWbbU15DCPteI/VZx/2v//8/zvdX439l9iv/HGYt3u7Gj3ud+1ZOd +NhZT6d+JJf3hZj5v7jqB7ZpRFERZTD7dvH/Y+C8K+d/0/v/i///b2V29/zf3nuL/UcY8cFNPrLRW +COzyIiV9w9gwtvSngv1pPI2n8TS+qvEfAAAA//8DAME4UCsAMAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjaGVja3N1bXMu +eWFtbC5negAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMDQ0NAAwMDAwMDAwADAwMDAwMDAA +MDAwMDAwMDA0NTAAMTQ0NDI2Mjc3NzIAMDE0NjIyACAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAHVzdGFyADAwd2hlZWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAB3aGVlbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAAMDAwMDAwMAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+LCAD6L4tkAgNl +kD2yFEAIhPM9xV5grWH4f5mZuSeAAYxMrBd5escNNaOrmuajX6/X4/u3r5vl4/F8/uzPqPiMLz9+ +fzwJjNOXQnXMQG2UxSyqlbBnU0v7VVtpLZeNBsO8dMgBO+ncvHfWZ/x6500p68qBNVRwl5Y5AJep +Z0LobkCdNR5XnVkeiyDF0sM7kf5yMuz/ODmDGF2Sz+6oMt5mMb5zT/PQkcM3NesOZYI5MzsADNzo +PbhIKiAsZCrqa5IcQ7ZAG6Ktw+UXT1dIYIeTph5BaF20//2TSsE1OfAscfPUe1zJLiSagTIZUCLe +5lCp02ap4MA5xT7iRbhh9Tbqi3MpZBBIvGtOlF/vuf8dWJs5tNWlSy6ajvbt1R9/AA8NE1rUAQAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==`) + binaryChecksum := fmt.Sprintf("%x", sha256.Sum256(binaryGemContent)) + root := fmt.Sprintf("/api/packages/%s/rubygems", user.Name) uploadFile := func(t *testing.T, content []byte, expectedStatus int) { @@ -234,6 +365,8 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==`) pb, err := packages.GetBlobByID(db.DefaultContext, pfs[0].BlobID) require.NoError(t, err) assert.Equal(t, int64(4608), pb.Size) + + assert.Equal(t, "ruby", pd.Metadata.(*rubygems.Metadata).Platform) }) t.Run("UploadExists", func(t *testing.T) { @@ -322,6 +455,33 @@ gAAAAP//MS06Gw==`) sep, holaPackageVersion, holaPackageDependency, holaChecksum, holaRubyGemsRequirements) assert.Equal(t, expected, resp.Body.String()) }) + + t.Run("UploadBinary", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + uploadFile(t, binaryGemContent, http.StatusCreated) + + pvs, err := packages.GetVersionsByPackageName(db.DefaultContext, user.ID, packages.TypeRubyGems, binaryPackageName) + require.NoError(t, err) + + pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0]) + require.NoError(t, err) + + assert.Equal(t, binaryPackageName, pd.Package.Name) + assert.Equal(t, "x86_64-linux-musl", pd.Metadata.(*rubygems.Metadata).Platform) + }) + + t.Run("BinaryPackageInfo", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", fmt.Sprintf("%s/info/%s", root, binaryPackageName)). + AddBasicAuth(user.Name) + resp := MakeRequest(t, req, http.StatusOK) + expected := fmt.Sprintf("%s\n%s-x86_64-linux-musl |checksum:%s,%s\n", + sep, binaryPackageVersion, binaryChecksum, binaryRubyGemsRequirements) + assert.Equal(t, expected, resp.Body.String()) + }) + t.Run("Versions", func(t *testing.T) { defer tests.PrintCurrentTest(t)() @@ -334,12 +494,16 @@ gAAAAP//MS06Gw==`) holaInfoReq := NewRequest(t, "GET", fmt.Sprintf("%s/info/%s", root, holaPackageName)). AddBasicAuth(user.Name) holaInfoResp := MakeRequest(t, holaInfoReq, http.StatusOK) + binaryInfoReq := NewRequest(t, "GET", fmt.Sprintf("%s/info/%s", root, binaryPackageName)). + AddBasicAuth(user.Name) + binaryInfoResp := MakeRequest(t, binaryInfoReq, http.StatusOK) // expected := fmt.Sprintf("%s\n%s %s %x\n", // sep, packageName, packageVersion, md5.Sum(infoResp.Body.Bytes())) lines := versionsResp.Body.String() assert.ElementsMatch(t, strings.Split(lines, "\n"), []string{ sep, + fmt.Sprintf("%s %s_x86_64-linux-musl %x", binaryPackageName, binaryPackageVersion, md5.Sum(binaryInfoResp.Body.Bytes())), fmt.Sprintf("%s %s %x", packageName, packageVersion, md5.Sum(infoResp.Body.Bytes())), fmt.Sprintf("%s %s %x", holaPackageName, holaPackageVersion, md5.Sum(holaInfoResp.Body.Bytes())), "", @@ -361,6 +525,21 @@ gAAAAP//MS06Gw==`) MakeRequest(t, req, http.StatusOK) }) + t.Run("DeleteBinary", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + body := bytes.Buffer{} + writer := multipart.NewWriter(&body) + writer.WriteField("gem_name", binaryPackageName) + writer.WriteField("version", binaryPackageVersion) + writer.Close() + + req := NewRequestWithBody(t, "DELETE", fmt.Sprintf("%s/api/v1/gems/yank", root), &body). + SetHeader("Content-Type", writer.FormDataContentType()). + AddBasicAuth(user.Name) + MakeRequest(t, req, http.StatusOK) + }) + t.Run("Delete", func(t *testing.T) { defer tests.PrintCurrentTest(t)() diff --git a/tests/integration/api_packages_swift_test.go b/tests/integration/api_packages_swift_test.go index 3c2a8b0694..ec0d4a2b81 100644 --- a/tests/integration/api_packages_swift_test.go +++ b/tests/integration/api_packages_swift_test.go @@ -13,14 +13,14 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - swift_module "code.gitea.io/gitea/modules/packages/swift" - "code.gitea.io/gitea/modules/setting" - swift_router "code.gitea.io/gitea/routers/api/packages/swift" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + swift_module "forgejo.org/modules/packages/swift" + "forgejo.org/modules/setting" + swift_router "forgejo.org/routers/api/packages/swift" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_packages_test.go b/tests/integration/api_packages_test.go index 27aed0feb1..a157d18cd5 100644 --- a/tests/integration/api_packages_test.go +++ b/tests/integration/api_packages_test.go @@ -12,18 +12,19 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - packages_model "code.gitea.io/gitea/models/packages" - container_model "code.gitea.io/gitea/models/packages/container" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/util" - packages_service "code.gitea.io/gitea/services/packages" - packages_cleanup_service "code.gitea.io/gitea/services/packages/cleanup" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + packages_model "forgejo.org/models/packages" + container_model "forgejo.org/models/packages/container" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/util" + packages_service "forgejo.org/services/packages" + packages_cleanup_service "forgejo.org/services/packages/cleanup" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -35,7 +36,7 @@ func TestPackageAPI(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) session := loginUser(t, user.Name) tokenReadPackage := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadPackage) - tokenDeletePackage := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWritePackage) + tokenWritePackage := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWritePackage) packageName := "test-package" packageVersion := "1.0.3" @@ -99,8 +100,13 @@ func TestPackageAPI(t *testing.T) { DecodeJSON(t, resp, &ap1) assert.Nil(t, ap1.Repository) + // create a repository + repo, _, f := tests.CreateDeclarativeRepo(t, user, "", []unit_model.Type{unit_model.TypeCode}, nil, nil) + defer f() + // link to public repository - require.NoError(t, packages_model.SetRepositoryLink(db.DefaultContext, p.ID, 1)) + req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/packages/%s/generic/%s/-/link/%s", user.Name, packageName, repo.Name)).AddTokenAuth(tokenWritePackage) + MakeRequest(t, req, http.StatusCreated) req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)). AddTokenAuth(tokenReadPackage) @@ -109,10 +115,15 @@ func TestPackageAPI(t *testing.T) { var ap2 *api.Package DecodeJSON(t, resp, &ap2) assert.NotNil(t, ap2.Repository) - assert.EqualValues(t, 1, ap2.Repository.ID) + assert.EqualValues(t, repo.ID, ap2.Repository.ID) - // link to private repository - require.NoError(t, packages_model.SetRepositoryLink(db.DefaultContext, p.ID, 2)) + // link to repository without write access, should fail + req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/packages/%s/generic/%s/-/link/%s", user.Name, packageName, "repo3")).AddTokenAuth(tokenWritePackage) + MakeRequest(t, req, http.StatusNotFound) + + // remove link + req = NewRequest(t, "POST", fmt.Sprintf("/api/v1/packages/%s/generic/%s/-/unlink", user.Name, packageName)).AddTokenAuth(tokenWritePackage) + MakeRequest(t, req, http.StatusNoContent) req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)). AddTokenAuth(tokenReadPackage) @@ -122,7 +133,18 @@ func TestPackageAPI(t *testing.T) { DecodeJSON(t, resp, &ap3) assert.Nil(t, ap3.Repository) - require.NoError(t, packages_model.UnlinkRepositoryFromAllPackages(db.DefaultContext, 2)) + // force link to a repository the currently logged-in user doesn't have access to + privateRepoID := int64(6) + require.NoError(t, packages_model.SetRepositoryLink(db.DefaultContext, p.ID, privateRepoID)) + + req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)).AddTokenAuth(tokenReadPackage) + resp = MakeRequest(t, req, http.StatusOK) + + var ap4 *api.Package + DecodeJSON(t, resp, &ap4) + assert.Nil(t, ap4.Repository) + + require.NoError(t, packages_model.UnlinkRepositoryFromAllPackages(db.DefaultContext, privateRepoID)) }) }) @@ -153,11 +175,11 @@ func TestPackageAPI(t *testing.T) { defer tests.PrintCurrentTest(t)() req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/packages/%s/dummy/%s/%s", user.Name, packageName, packageVersion)). - AddTokenAuth(tokenDeletePackage) + AddTokenAuth(tokenWritePackage) MakeRequest(t, req, http.StatusNotFound) req = NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s", user.Name, packageName, packageVersion)). - AddTokenAuth(tokenDeletePackage) + AddTokenAuth(tokenWritePackage) MakeRequest(t, req, http.StatusNoContent) }) } diff --git a/tests/integration/api_packages_vagrant_test.go b/tests/integration/api_packages_vagrant_test.go index b446466296..b9977d61c5 100644 --- a/tests/integration/api_packages_vagrant_test.go +++ b/tests/integration/api_packages_vagrant_test.go @@ -12,14 +12,14 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/json" - vagrant_module "code.gitea.io/gitea/modules/packages/vagrant" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/json" + vagrant_module "forgejo.org/modules/packages/vagrant" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_private_serv_test.go b/tests/integration/api_private_serv_test.go index 3339fc4430..a7dc59a611 100644 --- a/tests/integration/api_private_serv_test.go +++ b/tests/integration/api_private_serv_test.go @@ -8,9 +8,9 @@ import ( "net/url" "testing" - asymkey_model "code.gitea.io/gitea/models/asymkey" - "code.gitea.io/gitea/models/perm" - "code.gitea.io/gitea/modules/private" + asymkey_model "forgejo.org/models/asymkey" + "forgejo.org/models/perm" + "forgejo.org/modules/private" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -18,7 +18,7 @@ import ( func TestAPIPrivateNoServ(t *testing.T) { onGiteaRun(t, func(*testing.T, *url.URL) { - ctx, cancel := context.WithCancel(context.Background()) + ctx, cancel := context.WithCancel(t.Context()) defer cancel() key, user, err := private.ServNoCommand(ctx, 1) require.NoError(t, err) @@ -40,7 +40,7 @@ func TestAPIPrivateNoServ(t *testing.T) { func TestAPIPrivateServ(t *testing.T) { onGiteaRun(t, func(*testing.T, *url.URL) { - ctx, cancel := context.WithCancel(context.Background()) + ctx, cancel := context.WithCancel(t.Context()) defer cancel() // Can push to a repo we own diff --git a/tests/integration/api_pull_commits_test.go b/tests/integration/api_pull_commits_test.go index d62b9d9140..bfdcd79e66 100644 --- a/tests/integration/api_pull_commits_test.go +++ b/tests/integration/api_pull_commits_test.go @@ -7,12 +7,12 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_pull_review_test.go b/tests/integration/api_pull_review_test.go index b66e65ee41..930f9b816b 100644 --- a/tests/integration/api_pull_review_test.go +++ b/tests/integration/api_pull_review_test.go @@ -8,16 +8,16 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/json" - api "code.gitea.io/gitea/modules/structs" - issue_service "code.gitea.io/gitea/services/issue" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/json" + api "forgejo.org/modules/structs" + issue_service "forgejo.org/services/issue" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_pull_test.go b/tests/integration/api_pull_test.go index 7b95d441dd..e35eca38cf 100644 --- a/tests/integration/api_pull_test.go +++ b/tests/integration/api_pull_test.go @@ -11,18 +11,18 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/services/forms" - issue_service "code.gitea.io/gitea/services/issue" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/services/forms" + issue_service "forgejo.org/services/issue" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_push_mirror_test.go b/tests/integration/api_push_mirror_test.go index f2135cec62..282c3aaba0 100644 --- a/tests/integration/api_push_mirror_test.go +++ b/tests/integration/api_push_mirror_test.go @@ -17,22 +17,22 @@ import ( "testing" "time" - asymkey_model "code.gitea.io/gitea/models/asymkey" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - "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/git" - "code.gitea.io/gitea/modules/optional" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/services/migrations" - mirror_service "code.gitea.io/gitea/services/mirror" - repo_service "code.gitea.io/gitea/services/repository" - "code.gitea.io/gitea/tests" + asymkey_model "forgejo.org/models/asymkey" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/optional" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/services/migrations" + mirror_service "forgejo.org/services/mirror" + repo_service "forgejo.org/services/repository" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_quota_management_test.go b/tests/integration/api_quota_management_test.go index 6337e66516..c46c857197 100644 --- a/tests/integration/api_quota_management_test.go +++ b/tests/integration/api_quota_management_test.go @@ -8,16 +8,16 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - quota_model "code.gitea.io/gitea/models/quota" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + quota_model "forgejo.org/models/quota" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_quota_use_test.go b/tests/integration/api_quota_use_test.go index 11cbdcf145..2b50cca4ab 100644 --- a/tests/integration/api_quota_use_test.go +++ b/tests/integration/api_quota_use_test.go @@ -14,22 +14,22 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - quota_model "code.gitea.io/gitea/models/quota" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/migration" - "code.gitea.io/gitea/modules/optional" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/services/context" - "code.gitea.io/gitea/services/forms" - repo_service "code.gitea.io/gitea/services/repository" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + quota_model "forgejo.org/models/quota" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/migration" + "forgejo.org/modules/optional" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/services/context" + "forgejo.org/services/forms" + repo_service "forgejo.org/services/repository" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_releases_test.go b/tests/integration/api_releases_test.go index 1327daf57e..98fc293fbc 100644 --- a/tests/integration/api_releases_test.go +++ b/tests/integration/api_releases_test.go @@ -13,14 +13,14 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/gitrepo" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_repo_actions_test.go b/tests/integration/api_repo_actions_test.go new file mode 100644 index 0000000000..42c1038a0e --- /dev/null +++ b/tests/integration/api_repo_actions_test.go @@ -0,0 +1,103 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "fmt" + "net/http" + "net/url" + "strings" + "testing" + + actions_model "forgejo.org/models/actions" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" +) + +func TestAPISearchActionJobs_RepoRunner(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + token := getUserToken(t, user2.LowerName, auth_model.AccessTokenScopeWriteRepository) + job := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: 393}) + + req := NewRequestf( + t, + "GET", + "/api/v1/repos/%s/%s/actions/runners/jobs?labels=%s", + repo.OwnerName, repo.Name, + "ubuntu-latest", + ).AddTokenAuth(token) + res := MakeRequest(t, req, http.StatusOK) + + var jobs []*api.ActionRunJob + DecodeJSON(t, res, &jobs) + + assert.Len(t, jobs, 1) + assert.EqualValues(t, job.ID, jobs[0].ID) +} + +func TestAPIWorkflowDispatchReturnInfo(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + workflowName := "dispatch.yml" + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + token := getUserToken(t, user2.LowerName, auth_model.AccessTokenScopeWriteRepository) + + // create the repo + repo, _, f := tests.CreateDeclarativeRepo(t, user2, "api-repo-workflow-dispatch", + []unit_model.Type{unit_model.TypeActions}, nil, + []*files_service.ChangeRepoFile{ + { + Operation: "create", + TreePath: fmt.Sprintf(".forgejo/workflows/%s", workflowName), + ContentReader: strings.NewReader(`name: WD +on: [workflow-dispatch] +jobs: + t1: + runs-on: docker + steps: + - run: echo "test 1" + t2: + runs-on: docker + steps: + - run: echo "test 2" +`, + ), + }, + }, + ) + defer f() + + req := NewRequestWithJSON( + t, + http.MethodPost, + fmt.Sprintf( + "/api/v1/repos/%s/%s/actions/workflows/%s/dispatches", + repo.OwnerName, repo.Name, workflowName, + ), + &api.DispatchWorkflowOption{ + Ref: repo.DefaultBranch, + ReturnRunInfo: true, + }, + ) + req.AddTokenAuth(token) + + res := MakeRequest(t, req, http.StatusCreated) + run := new(api.DispatchWorkflowRun) + DecodeJSON(t, res, run) + + assert.NotZero(t, run.ID) + assert.NotZero(t, run.RunNumber) + assert.Len(t, run.Jobs, 2) + }) +} diff --git a/tests/integration/api_repo_activities_test.go b/tests/integration/api_repo_activities_test.go index dbdedec372..ea966c1cfe 100644 --- a/tests/integration/api_repo_activities_test.go +++ b/tests/integration/api_repo_activities_test.go @@ -8,11 +8,11 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_archive_test.go b/tests/integration/api_repo_archive_test.go index fab3dedfab..30e62943f0 100644 --- a/tests/integration/api_repo_archive_test.go +++ b/tests/integration/api_repo_archive_test.go @@ -11,11 +11,11 @@ import ( "regexp" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_repo_avatar_test.go b/tests/integration/api_repo_avatar_test.go index 8ee256ec9f..0bd0a54f27 100644 --- a/tests/integration/api_repo_avatar_test.go +++ b/tests/integration/api_repo_avatar_test.go @@ -10,12 +10,12 @@ import ( "os" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_repo_branch_test.go b/tests/integration/api_repo_branch_test.go index 83159022ea..caadea7e39 100644 --- a/tests/integration/api_repo_branch_test.go +++ b/tests/integration/api_repo_branch_test.go @@ -11,14 +11,14 @@ import ( "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/json" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/json" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_repo_collaborator_test.go b/tests/integration/api_repo_collaborator_test.go index 59cf85fef3..61f4f578d7 100644 --- a/tests/integration/api_repo_collaborator_test.go +++ b/tests/integration/api_repo_collaborator_test.go @@ -8,12 +8,12 @@ import ( "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/perm" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/perm" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" "github.com/stretchr/testify/assert" ) @@ -52,6 +52,20 @@ func TestAPIRepoCollaboratorPermission(t *testing.T) { DecodeJSON(t, resp, &repoPermission) assert.Equal(t, "read", repoPermission.Permission) + + t.Run("CollaboratorCanReadTheirPermission", func(t *testing.T) { + session := loginUser(t, user4.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository) + + req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user4.Name). + AddTokenAuth(token) + resp := MakeRequest(t, req, http.StatusOK) + + var repoPermission api.RepoCollaboratorPermission + DecodeJSON(t, resp, &repoPermission) + + assert.Equal(t, "read", repoPermission.Permission) + }) }) t.Run("CollaboratorWithWriteAccess", func(t *testing.T) { diff --git a/tests/integration/api_repo_compare_test.go b/tests/integration/api_repo_compare_test.go index 765d0cef08..35f0a21d82 100644 --- a/tests/integration/api_repo_compare_test.go +++ b/tests/integration/api_repo_compare_test.go @@ -7,11 +7,11 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -35,6 +35,7 @@ func TestAPICompareBranches(t *testing.T) { assert.Equal(t, 2, apiResp.TotalCommits) assert.Len(t, apiResp.Commits, 2) + assert.Len(t, apiResp.Files, 3) } func TestAPICompareCommits(t *testing.T) { @@ -54,4 +55,5 @@ func TestAPICompareCommits(t *testing.T) { assert.Equal(t, 2, apiResp.TotalCommits) assert.Len(t, apiResp.Commits, 2) + assert.Len(t, apiResp.Files, 3) } diff --git a/tests/integration/api_repo_edit_test.go b/tests/integration/api_repo_edit_test.go index 7de8910ee0..341cb0961f 100644 --- a/tests/integration/api_repo_edit_test.go +++ b/tests/integration/api_repo_edit_test.go @@ -6,16 +6,16 @@ package integration import ( "fmt" "net/http" - "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - unit_model "code.gitea.io/gitea/models/unit" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -137,232 +137,260 @@ func getNewRepoEditOption(opts *api.EditRepoOption) *api.EditRepoOption { } func TestAPIRepoEdit(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { - bFalse, bTrue := false, true + defer tests.PrepareTestEnv(t)() + bFalse, bTrue := false, true - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo1 & repo16 - org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) // owner of the repo3, is an org - user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) // owner of neither repos - repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) // public repo - repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // public repo - repo15 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15}) // empty repo - repo16 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) // private repo + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo1 & repo16 + org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) // owner of the repo3, is an org + user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) // owner of neither repos + repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) // public repo + repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // public repo + repo15 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15}) // empty repo + repo16 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) // private repo - // Get user2's token - session := loginUser(t, user2.Name) - token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) - // Get user4's token - session = loginUser(t, user4.Name) - token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) + // Get user2's token + session := loginUser(t, user2.Name) + token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) + // Get user4's token + session = loginUser(t, user4.Name) + token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) - // Test editing a repo1 which user2 owns, changing name and many properties - origRepoEditOption := getRepoEditOptionFromRepo(repo1) - repoEditOption := getNewRepoEditOption(origRepoEditOption) - req := NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo1.Name), &repoEditOption). - AddTokenAuth(token2) - resp := MakeRequest(t, req, http.StatusOK) - var repo api.Repository - DecodeJSON(t, resp, &repo) - assert.NotNil(t, repo) - // check response - assert.Equal(t, *repoEditOption.Name, repo.Name) - assert.Equal(t, *repoEditOption.Description, repo.Description) - assert.Equal(t, *repoEditOption.Website, repo.Website) - assert.Equal(t, *repoEditOption.Archived, repo.Archived) - // check repo1 from database - repo1edited := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repo1editedOption := getRepoEditOptionFromRepo(repo1edited) - assert.Equal(t, *repoEditOption.Name, *repo1editedOption.Name) - assert.Equal(t, *repoEditOption.Description, *repo1editedOption.Description) - assert.Equal(t, *repoEditOption.Website, *repo1editedOption.Website) - assert.Equal(t, *repoEditOption.Archived, *repo1editedOption.Archived) - assert.Equal(t, *repoEditOption.Private, *repo1editedOption.Private) - assert.Equal(t, *repoEditOption.HasWiki, *repo1editedOption.HasWiki) + // Test editing a repo1 which user2 owns, changing name and many properties + origRepoEditOption := getRepoEditOptionFromRepo(repo1) + repoEditOption := getNewRepoEditOption(origRepoEditOption) + req := NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo1.Name), &repoEditOption). + AddTokenAuth(token2) + resp := MakeRequest(t, req, http.StatusOK) + var repo api.Repository + DecodeJSON(t, resp, &repo) + assert.NotNil(t, repo) + // check response + assert.Equal(t, *repoEditOption.Name, repo.Name) + assert.Equal(t, *repoEditOption.Description, repo.Description) + assert.Equal(t, *repoEditOption.Website, repo.Website) + assert.Equal(t, *repoEditOption.Archived, repo.Archived) + // check repo1 from database + repo1edited := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + repo1editedOption := getRepoEditOptionFromRepo(repo1edited) + assert.Equal(t, *repoEditOption.Name, *repo1editedOption.Name) + assert.Equal(t, *repoEditOption.Description, *repo1editedOption.Description) + assert.Equal(t, *repoEditOption.Website, *repo1editedOption.Website) + assert.Equal(t, *repoEditOption.Archived, *repo1editedOption.Archived) + assert.Equal(t, *repoEditOption.Private, *repo1editedOption.Private) + assert.Equal(t, *repoEditOption.HasWiki, *repo1editedOption.HasWiki) - // Test editing repo1 to use internal issue and wiki (default) - *repoEditOption.HasIssues = true - repoEditOption.ExternalTracker = nil - repoEditOption.InternalTracker = &api.InternalTracker{ - EnableTimeTracker: false, - AllowOnlyContributorsToTrackTime: false, - EnableIssueDependencies: false, - } - *repoEditOption.HasWiki = true - repoEditOption.ExternalWiki = nil - url := fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name) - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - resp = MakeRequest(t, req, http.StatusOK) - DecodeJSON(t, resp, &repo) - assert.NotNil(t, repo) - // check repo1 was written to database - repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repo1editedOption = getRepoEditOptionFromRepo(repo1edited) - assert.True(t, *repo1editedOption.HasIssues) - assert.Nil(t, repo1editedOption.ExternalTracker) - assert.Equal(t, *repo1editedOption.InternalTracker, *repoEditOption.InternalTracker) - assert.True(t, *repo1editedOption.HasWiki) - assert.Nil(t, repo1editedOption.ExternalWiki) + // Test editing repo1 to use internal issue and wiki (default) + *repoEditOption.HasIssues = true + repoEditOption.ExternalTracker = nil + repoEditOption.InternalTracker = &api.InternalTracker{ + EnableTimeTracker: false, + AllowOnlyContributorsToTrackTime: false, + EnableIssueDependencies: false, + } + *repoEditOption.HasWiki = true + repoEditOption.ExternalWiki = nil + url := fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name) + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + resp = MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &repo) + assert.NotNil(t, repo) + // check repo1 was written to database + repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + repo1editedOption = getRepoEditOptionFromRepo(repo1edited) + assert.True(t, *repo1editedOption.HasIssues) + assert.Nil(t, repo1editedOption.ExternalTracker) + assert.Equal(t, *repo1editedOption.InternalTracker, *repoEditOption.InternalTracker) + assert.True(t, *repo1editedOption.HasWiki) + assert.Nil(t, repo1editedOption.ExternalWiki) - // Test editing repo1 to use external issue and wiki - repoEditOption.ExternalTracker = &api.ExternalTracker{ - ExternalTrackerURL: "http://www.somewebsite.com", - ExternalTrackerFormat: "http://www.somewebsite.com/{user}/{repo}?issue={index}", - ExternalTrackerStyle: "alphanumeric", - } - repoEditOption.ExternalWiki = &api.ExternalWiki{ - ExternalWikiURL: "http://www.somewebsite.com", - } - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - resp = MakeRequest(t, req, http.StatusOK) - DecodeJSON(t, resp, &repo) - assert.NotNil(t, repo) - // check repo1 was written to database - repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repo1editedOption = getRepoEditOptionFromRepo(repo1edited) - assert.True(t, *repo1editedOption.HasIssues) - assert.Equal(t, *repo1editedOption.ExternalTracker, *repoEditOption.ExternalTracker) - assert.True(t, *repo1editedOption.HasWiki) - assert.Equal(t, *repo1editedOption.ExternalWiki, *repoEditOption.ExternalWiki) + // Test editing repo1 to use external issue and wiki + repoEditOption.ExternalTracker = &api.ExternalTracker{ + ExternalTrackerURL: "http://www.somewebsite.com", + ExternalTrackerFormat: "http://www.somewebsite.com/{user}/{repo}?issue={index}", + ExternalTrackerStyle: "alphanumeric", + } + repoEditOption.ExternalWiki = &api.ExternalWiki{ + ExternalWikiURL: "http://www.somewebsite.com", + } + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + resp = MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &repo) + assert.NotNil(t, repo) + // check repo1 was written to database + repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + repo1editedOption = getRepoEditOptionFromRepo(repo1edited) + assert.True(t, *repo1editedOption.HasIssues) + assert.Equal(t, *repo1editedOption.ExternalTracker, *repoEditOption.ExternalTracker) + assert.True(t, *repo1editedOption.HasWiki) + assert.Equal(t, *repo1editedOption.ExternalWiki, *repoEditOption.ExternalWiki) - repoEditOption.ExternalTracker.ExternalTrackerStyle = "regexp" - repoEditOption.ExternalTracker.ExternalTrackerRegexpPattern = `(\d+)` - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - resp = MakeRequest(t, req, http.StatusOK) - DecodeJSON(t, resp, &repo) - assert.NotNil(t, repo) - repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repo1editedOption = getRepoEditOptionFromRepo(repo1edited) - assert.True(t, *repo1editedOption.HasIssues) - assert.Equal(t, *repo1editedOption.ExternalTracker, *repoEditOption.ExternalTracker) + repoEditOption.ExternalTracker.ExternalTrackerStyle = "regexp" + repoEditOption.ExternalTracker.ExternalTrackerRegexpPattern = `(\d+)` + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + resp = MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &repo) + assert.NotNil(t, repo) + repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + repo1editedOption = getRepoEditOptionFromRepo(repo1edited) + assert.True(t, *repo1editedOption.HasIssues) + assert.Equal(t, *repo1editedOption.ExternalTracker, *repoEditOption.ExternalTracker) - // Do some tests with invalid URL for external tracker and wiki - repoEditOption.ExternalTracker.ExternalTrackerURL = "htp://www.somewebsite.com" - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - MakeRequest(t, req, http.StatusUnprocessableEntity) - repoEditOption.ExternalTracker.ExternalTrackerURL = "http://www.somewebsite.com" - repoEditOption.ExternalTracker.ExternalTrackerFormat = "http://www.somewebsite.com/{user/{repo}?issue={index}" - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - MakeRequest(t, req, http.StatusUnprocessableEntity) - repoEditOption.ExternalTracker.ExternalTrackerFormat = "http://www.somewebsite.com/{user}/{repo}?issue={index}" - repoEditOption.ExternalWiki.ExternalWikiURL = "htp://www.somewebsite.com" - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - MakeRequest(t, req, http.StatusUnprocessableEntity) + // Do some tests with invalid URL for external tracker and wiki + repoEditOption.ExternalTracker.ExternalTrackerURL = "htp://www.somewebsite.com" + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + MakeRequest(t, req, http.StatusUnprocessableEntity) + repoEditOption.ExternalTracker.ExternalTrackerURL = "http://www.somewebsite.com" + repoEditOption.ExternalTracker.ExternalTrackerFormat = "http://www.somewebsite.com/{user/{repo}?issue={index}" + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + MakeRequest(t, req, http.StatusUnprocessableEntity) + repoEditOption.ExternalTracker.ExternalTrackerFormat = "http://www.somewebsite.com/{user}/{repo}?issue={index}" + repoEditOption.ExternalWiki.ExternalWikiURL = "htp://www.somewebsite.com" + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + MakeRequest(t, req, http.StatusUnprocessableEntity) - // Test small repo change through API with issue and wiki option not set; They shall not be touched. - *repoEditOption.Description = "small change" - repoEditOption.HasIssues = nil - repoEditOption.ExternalTracker = nil - repoEditOption.HasWiki = nil - repoEditOption.ExternalWiki = nil - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - resp = MakeRequest(t, req, http.StatusOK) - DecodeJSON(t, resp, &repo) - assert.NotNil(t, repo) - // check repo1 was written to database - repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repo1editedOption = getRepoEditOptionFromRepo(repo1edited) - assert.Equal(t, *repo1editedOption.Description, *repoEditOption.Description) - assert.True(t, *repo1editedOption.HasIssues) - assert.NotNil(t, *repo1editedOption.ExternalTracker) - assert.True(t, *repo1editedOption.HasWiki) - assert.NotNil(t, *repo1editedOption.ExternalWiki) + // Test small repo change through API with issue and wiki option not set; They shall not be touched. + *repoEditOption.Description = "small change" + repoEditOption.HasIssues = nil + repoEditOption.ExternalTracker = nil + repoEditOption.HasWiki = nil + repoEditOption.ExternalWiki = nil + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + resp = MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &repo) + assert.NotNil(t, repo) + // check repo1 was written to database + repo1edited = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + repo1editedOption = getRepoEditOptionFromRepo(repo1edited) + assert.Equal(t, *repo1editedOption.Description, *repoEditOption.Description) + assert.True(t, *repo1editedOption.HasIssues) + assert.NotNil(t, *repo1editedOption.ExternalTracker) + assert.True(t, *repo1editedOption.HasWiki) + assert.NotNil(t, *repo1editedOption.ExternalWiki) - // reset repo in db - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name), &origRepoEditOption). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) + // reset repo in db + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name), &origRepoEditOption). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) - // Test editing a non-existing repo - name := "repodoesnotexist" - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, name), &api.EditRepoOption{Name: &name}). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusNotFound) + // Test editing a non-existing repo + name := "repodoesnotexist" + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, name), &api.EditRepoOption{Name: &name}). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusNotFound) - // Test editing repo16 by user4 who does not have write access - origRepoEditOption = getRepoEditOptionFromRepo(repo16) - repoEditOption = getNewRepoEditOption(origRepoEditOption) - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name), &repoEditOption). - AddTokenAuth(token4) - MakeRequest(t, req, http.StatusNotFound) + // Test editing repo16 by user4 who does not have write access + origRepoEditOption = getRepoEditOptionFromRepo(repo16) + repoEditOption = getNewRepoEditOption(origRepoEditOption) + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name), &repoEditOption). + AddTokenAuth(token4) + MakeRequest(t, req, http.StatusNotFound) - // Tests a repo with no token given so will fail - origRepoEditOption = getRepoEditOptionFromRepo(repo16) - repoEditOption = getNewRepoEditOption(origRepoEditOption) - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name), &repoEditOption) - _ = MakeRequest(t, req, http.StatusNotFound) + // Tests a repo with no token given so will fail + origRepoEditOption = getRepoEditOptionFromRepo(repo16) + repoEditOption = getNewRepoEditOption(origRepoEditOption) + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name), &repoEditOption) + _ = MakeRequest(t, req, http.StatusNotFound) - // Test using access token for a private repo that the user of the token owns - origRepoEditOption = getRepoEditOptionFromRepo(repo16) - repoEditOption = getNewRepoEditOption(origRepoEditOption) - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name), &repoEditOption). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) - // reset repo in db - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name), &origRepoEditOption). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) + // Test using access token for a private repo that the user of the token owns + origRepoEditOption = getRepoEditOptionFromRepo(repo16) + repoEditOption = getNewRepoEditOption(origRepoEditOption) + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name), &repoEditOption). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) + // reset repo in db + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, *repoEditOption.Name), &origRepoEditOption). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) - // Test making a repo public that is private - repo16 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) - assert.True(t, repo16.IsPrivate) - repoEditOption = &api.EditRepoOption{ - Private: &bFalse, - } - url = fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name) - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) - repo16 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) - assert.False(t, repo16.IsPrivate) - // Make it private again - repoEditOption.Private = &bTrue - req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) + // Test making a repo public that is private + repo16 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) + assert.True(t, repo16.IsPrivate) + repoEditOption = &api.EditRepoOption{ + Private: &bFalse, + } + url = fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo16.Name) + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) + repo16 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) + assert.False(t, repo16.IsPrivate) + // Make it private again + repoEditOption.Private = &bTrue + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) - // Test to change empty repo - assert.False(t, repo15.IsArchived) - url = fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo15.Name) - req = NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ - Archived: &bTrue, - }).AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) - repo15 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15}) - assert.True(t, repo15.IsArchived) - req = NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ - Archived: &bFalse, - }).AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) + // Test to change empty repo + assert.False(t, repo15.IsArchived) + url = fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo15.Name) + req = NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ + Archived: &bTrue, + }).AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) + repo15 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15}) + assert.True(t, repo15.IsArchived) + req = NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ + Archived: &bFalse, + }).AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) - // Test using org repo "org3/repo3" where user2 is a collaborator - origRepoEditOption = getRepoEditOptionFromRepo(repo3) - repoEditOption = getNewRepoEditOption(origRepoEditOption) - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", org3.Name, repo3.Name), &repoEditOption). - AddTokenAuth(token2) - MakeRequest(t, req, http.StatusOK) - // reset repo in db - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", org3.Name, *repoEditOption.Name), &origRepoEditOption). - AddTokenAuth(token2) - _ = MakeRequest(t, req, http.StatusOK) + // Test using org repo "org3/repo3" where user2 is a collaborator + origRepoEditOption = getRepoEditOptionFromRepo(repo3) + repoEditOption = getNewRepoEditOption(origRepoEditOption) + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", org3.Name, repo3.Name), &repoEditOption). + AddTokenAuth(token2) + MakeRequest(t, req, http.StatusOK) + // reset repo in db + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", org3.Name, *repoEditOption.Name), &origRepoEditOption). + AddTokenAuth(token2) + _ = MakeRequest(t, req, http.StatusOK) - // Test using org repo "org3/repo3" with no user token - origRepoEditOption = getRepoEditOptionFromRepo(repo3) - repoEditOption = getNewRepoEditOption(origRepoEditOption) - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", org3.Name, repo3.Name), &repoEditOption) - MakeRequest(t, req, http.StatusNotFound) + // Test using org repo "org3/repo3" with no user token + origRepoEditOption = getRepoEditOptionFromRepo(repo3) + repoEditOption = getNewRepoEditOption(origRepoEditOption) + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", org3.Name, repo3.Name), &repoEditOption) + MakeRequest(t, req, http.StatusNotFound) - // Test using repo "user2/repo1" where user4 is a NOT collaborator - origRepoEditOption = getRepoEditOptionFromRepo(repo1) - repoEditOption = getNewRepoEditOption(origRepoEditOption) - req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo1.Name), &repoEditOption). - AddTokenAuth(token4) - MakeRequest(t, req, http.StatusForbidden) + // Test using repo "user2/repo1" where user4 is a NOT collaborator + origRepoEditOption = getRepoEditOptionFromRepo(repo1) + repoEditOption = getNewRepoEditOption(origRepoEditOption) + req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/repos/%s/%s", user2.Name, repo1.Name), &repoEditOption). + AddTokenAuth(token4) + MakeRequest(t, req, http.StatusForbidden) + + t.Run("Default merge style", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + updateStyle := "invalid" + MakeRequest(t, NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ + DefaultUpdateStyle: &updateStyle, + }).AddTokenAuth(token2), http.StatusUnprocessableEntity) + + MakeRequest(t, NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ + DefaultMergeStyle: &updateStyle, + }).AddTokenAuth(token2), http.StatusUnprocessableEntity) + + var apiRepo api.Repository + DecodeJSON(t, MakeRequest(t, NewRequest(t, "GET", url).AddTokenAuth(token2), http.StatusOK), &apiRepo) + assert.Equal(t, "merge", apiRepo.DefaultMergeStyle) + assert.Equal(t, "merge", apiRepo.DefaultUpdateStyle) + + updateStyle = "rebase" + MakeRequest(t, NewRequestWithJSON(t, "PATCH", url, &api.EditRepoOption{ + DefaultMergeStyle: &updateStyle, + DefaultUpdateStyle: &updateStyle, + HasPullRequests: &bTrue, + }).AddTokenAuth(token2), http.StatusOK) + + DecodeJSON(t, MakeRequest(t, NewRequest(t, "GET", url).AddTokenAuth(token2), http.StatusOK), &apiRepo) + assert.Equal(t, "rebase", apiRepo.DefaultMergeStyle) + assert.Equal(t, "rebase", apiRepo.DefaultUpdateStyle) }) } diff --git a/tests/integration/api_repo_file_create_test.go b/tests/integration/api_repo_file_create_test.go index c7c30db1ff..cff891f6d8 100644 --- a/tests/integration/api_repo_file_create_test.go +++ b/tests/integration/api_repo_file_create_test.go @@ -4,7 +4,6 @@ package integration import ( - stdCtx "context" "encoding/base64" "fmt" "net/http" @@ -13,15 +12,15 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/services/context" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/services/context" "github.com/stretchr/testify/assert" ) @@ -172,7 +171,7 @@ func TestAPICreateFile(t *testing.T) { req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo1.Name, treePath), &createFileOptions). AddTokenAuth(token2) resp := MakeRequest(t, req, http.StatusCreated) - gitRepo, _ := gitrepo.OpenRepository(stdCtx.Background(), repo1) + gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo1) commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName) latestCommit, _ := gitRepo.GetCommitByPath(treePath) expectedFileResponse := getExpectedFileResponseForCreate("user2/repo1", commitID, treePath, latestCommit.ID.String()) @@ -292,7 +291,7 @@ func TestAPICreateFile(t *testing.T) { AddTokenAuth(token2) resp = MakeRequest(t, req, http.StatusCreated) emptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: reponame}) // public repo - gitRepo, _ := gitrepo.OpenRepository(stdCtx.Background(), emptyRepo) + gitRepo, _ := gitrepo.OpenRepository(t.Context(), emptyRepo) commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName) latestCommit, _ := gitRepo.GetCommitByPath(treePath) expectedFileResponse := getExpectedFileResponseForCreate("user2/"+reponame, commitID, treePath, latestCommit.ID.String()) diff --git a/tests/integration/api_repo_file_delete_test.go b/tests/integration/api_repo_file_delete_test.go index 7c93307e19..b76edf45ca 100644 --- a/tests/integration/api_repo_file_delete_test.go +++ b/tests/integration/api_repo_file_delete_test.go @@ -9,11 +9,11 @@ import ( "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_file_get_test.go b/tests/integration/api_repo_file_get_test.go index 1a4e670bc1..7bd7393b01 100644 --- a/tests/integration/api_repo_file_get_test.go +++ b/tests/integration/api_repo_file_get_test.go @@ -8,10 +8,10 @@ import ( "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/modules/git" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/modules/git" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_file_helpers.go b/tests/integration/api_repo_file_helpers.go index 4350092b8b..09cf93d8a5 100644 --- a/tests/integration/api_repo_file_helpers.go +++ b/tests/integration/api_repo_file_helpers.go @@ -6,12 +6,12 @@ package integration import ( "strings" - "code.gitea.io/gitea/models" - repo_model "code.gitea.io/gitea/models/repo" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - api "code.gitea.io/gitea/modules/structs" - files_service "code.gitea.io/gitea/services/repository/files" + "forgejo.org/models" + repo_model "forgejo.org/models/repo" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + api "forgejo.org/modules/structs" + files_service "forgejo.org/services/repository/files" ) func createFileInBranch(user *user_model.User, repo *repo_model.Repository, treePath, branchName, content string) (*api.FilesResponse, error) { diff --git a/tests/integration/api_repo_file_update_test.go b/tests/integration/api_repo_file_update_test.go index ac28e0c0a2..4ed0df2b08 100644 --- a/tests/integration/api_repo_file_update_test.go +++ b/tests/integration/api_repo_file_update_test.go @@ -4,7 +4,6 @@ package integration import ( - stdCtx "context" "encoding/base64" "fmt" "net/http" @@ -12,14 +11,14 @@ import ( "path/filepath" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/services/context" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/services/context" "github.com/stretchr/testify/assert" ) @@ -135,7 +134,7 @@ func TestAPIUpdateFile(t *testing.T) { req := NewRequestWithJSON(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo1.Name, treePath), &updateFileOptions). AddTokenAuth(token2) resp := MakeRequest(t, req, http.StatusOK) - gitRepo, _ := gitrepo.OpenRepository(stdCtx.Background(), repo1) + gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo1) commitID, _ := gitRepo.GetBranchCommitID(updateFileOptions.NewBranchName) lasCommit, _ := gitRepo.GetCommitByPath(treePath) expectedFileResponse := getExpectedFileResponseForUpdate(commitID, treePath, lasCommit.ID.String()) diff --git a/tests/integration/api_repo_files_change_test.go b/tests/integration/api_repo_files_change_test.go index fb3ae5e4dd..d188751dab 100644 --- a/tests/integration/api_repo_files_change_test.go +++ b/tests/integration/api_repo_files_change_test.go @@ -4,21 +4,20 @@ package integration import ( - stdCtx "context" "encoding/base64" "fmt" "net/http" "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/services/context" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/services/context" "github.com/stretchr/testify/assert" ) @@ -96,7 +95,7 @@ func TestAPIChangeFiles(t *testing.T) { req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents", user2.Name, repo1.Name), &changeFilesOptions). AddTokenAuth(token2) resp := MakeRequest(t, req, http.StatusCreated) - gitRepo, _ := gitrepo.OpenRepository(stdCtx.Background(), repo1) + gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo1) commitID, _ := gitRepo.GetBranchCommitID(changeFilesOptions.NewBranchName) createLasCommit, _ := gitRepo.GetCommitByPath(createTreePath) updateLastCommit, _ := gitRepo.GetCommitByPath(updateTreePath) diff --git a/tests/integration/api_repo_get_contents_list_test.go b/tests/integration/api_repo_get_contents_list_test.go index e76ccd9932..543f10f6d2 100644 --- a/tests/integration/api_repo_get_contents_list_test.go +++ b/tests/integration/api_repo_get_contents_list_test.go @@ -9,15 +9,15 @@ import ( "path/filepath" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - repo_service "code.gitea.io/gitea/services/repository" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + repo_service "forgejo.org/services/repository" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_repo_get_contents_test.go b/tests/integration/api_repo_get_contents_test.go index cb321b8b1f..9cf266b3dd 100644 --- a/tests/integration/api_repo_get_contents_test.go +++ b/tests/integration/api_repo_get_contents_test.go @@ -9,15 +9,15 @@ import ( "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - repo_service "code.gitea.io/gitea/services/repository" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + repo_service "forgejo.org/services/repository" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_repo_git_blobs_test.go b/tests/integration/api_repo_git_blobs_test.go index 184362e7e3..980fff1e52 100644 --- a/tests/integration/api_repo_git_blobs_test.go +++ b/tests/integration/api_repo_git_blobs_test.go @@ -7,12 +7,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_git_commits_test.go b/tests/integration/api_repo_git_commits_test.go index c4c626eb49..e80c0024b8 100644 --- a/tests/integration/api_repo_git_commits_test.go +++ b/tests/integration/api_repo_git_commits_test.go @@ -7,11 +7,11 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_git_hook_test.go b/tests/integration/api_repo_git_hook_test.go index 9917b41790..aadc231d82 100644 --- a/tests/integration/api_repo_git_hook_test.go +++ b/tests/integration/api_repo_git_hook_test.go @@ -8,12 +8,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_git_notes_test.go b/tests/integration/api_repo_git_notes_test.go index 1b5e5d652c..dfafec7135 100644 --- a/tests/integration/api_repo_git_notes_test.go +++ b/tests/integration/api_repo_git_notes_test.go @@ -9,11 +9,11 @@ import ( "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_git_ref_test.go b/tests/integration/api_repo_git_ref_test.go index 875752ae3f..a4c05e208c 100644 --- a/tests/integration/api_repo_git_ref_test.go +++ b/tests/integration/api_repo_git_ref_test.go @@ -7,10 +7,10 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" ) func TestAPIReposGitRefs(t *testing.T) { diff --git a/tests/integration/api_repo_git_tags_test.go b/tests/integration/api_repo_git_tags_test.go index c5883a8058..73d7250c46 100644 --- a/tests/integration/api_repo_git_tags_test.go +++ b/tests/integration/api_repo_git_tags_test.go @@ -8,15 +8,15 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/util" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/gitrepo" + api "forgejo.org/modules/structs" + "forgejo.org/modules/util" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_git_trees_test.go b/tests/integration/api_repo_git_trees_test.go index 8eec6d8d22..f321760218 100644 --- a/tests/integration/api_repo_git_trees_test.go +++ b/tests/integration/api_repo_git_trees_test.go @@ -7,11 +7,11 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" ) func TestAPIReposGitTrees(t *testing.T) { diff --git a/tests/integration/api_repo_hook_test.go b/tests/integration/api_repo_hook_test.go index 9ae8119b28..b2b8b47d40 100644 --- a/tests/integration/api_repo_hook_test.go +++ b/tests/integration/api_repo_hook_test.go @@ -8,12 +8,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_lfs_locks_test.go b/tests/integration/api_repo_lfs_locks_test.go index 4ba01e6d9b..b3a295c2de 100644 --- a/tests/integration/api_repo_lfs_locks_test.go +++ b/tests/integration/api_repo_lfs_locks_test.go @@ -9,13 +9,13 @@ import ( "testing" "time" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/lfs" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/lfs" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_lfs_migrate_test.go b/tests/integration/api_repo_lfs_migrate_test.go index de85b9160d..fcfa43cac4 100644 --- a/tests/integration/api_repo_lfs_migrate_test.go +++ b/tests/integration/api_repo_lfs_migrate_test.go @@ -8,14 +8,14 @@ import ( "path" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/lfs" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/services/migrations" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/lfs" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/services/migrations" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_repo_lfs_test.go b/tests/integration/api_repo_lfs_test.go index 7a2a92d415..078cedf78e 100644 --- a/tests/integration/api_repo_lfs_test.go +++ b/tests/integration/api_repo_lfs_test.go @@ -11,17 +11,17 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - git_model "code.gitea.io/gitea/models/git" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/json" - "code.gitea.io/gitea/modules/lfs" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + git_model "forgejo.org/models/git" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/json" + "forgejo.org/modules/lfs" + "forgejo.org/modules/setting" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_repo_pulls_test.go b/tests/integration/api_repo_pulls_test.go new file mode 100644 index 0000000000..aec492e65f --- /dev/null +++ b/tests/integration/api_repo_pulls_test.go @@ -0,0 +1,34 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "fmt" + "net/http" + "testing" + + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + api "forgejo.org/modules/structs" + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" +) + +func TestAPIRepoPulls(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + // repo = user2/repo1 + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + + // issue id without assigned review member or review team + issueID := 5 + req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d", repo.OwnerName, repo.Name, issueID)) + res := MakeRequest(t, req, http.StatusOK) + var pr *api.PullRequest + DecodeJSON(t, res, &pr) + + assert.NotNil(t, pr.RequestedReviewers) + assert.NotNil(t, pr.RequestedReviewersTeams) +} diff --git a/tests/integration/api_repo_raw_test.go b/tests/integration/api_repo_raw_test.go index e5f83d1c80..5ae11a8e71 100644 --- a/tests/integration/api_repo_raw_test.go +++ b/tests/integration/api_repo_raw_test.go @@ -7,10 +7,10 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_secrets_test.go b/tests/integration/api_repo_secrets_test.go index c3074d9ece..a2c9439f03 100644 --- a/tests/integration/api_repo_secrets_test.go +++ b/tests/integration/api_repo_secrets_test.go @@ -8,12 +8,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" ) func TestAPIRepoSecrets(t *testing.T) { diff --git a/tests/integration/api_repo_tags_test.go b/tests/integration/api_repo_tags_test.go index 09f17ef475..81475249a1 100644 --- a/tests/integration/api_repo_tags_test.go +++ b/tests/integration/api_repo_tags_test.go @@ -8,12 +8,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_teams_test.go b/tests/integration/api_repo_teams_test.go index 91bfd66b3a..c75714d003 100644 --- a/tests/integration/api_repo_teams_test.go +++ b/tests/integration/api_repo_teams_test.go @@ -8,14 +8,14 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unit" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/util" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/modules/util" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_test.go b/tests/integration/api_repo_test.go index b635b7099e..d00b6feb66 100644 --- a/tests/integration/api_repo_test.go +++ b/tests/integration/api_repo_test.go @@ -9,18 +9,18 @@ import ( "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - access_model "code.gitea.io/gitea/models/perm/access" - repo_model "code.gitea.io/gitea/models/repo" - 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/git" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - repo_service "code.gitea.io/gitea/services/repository" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + access_model "forgejo.org/models/perm/access" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + repo_service "forgejo.org/services/repository" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -396,6 +396,7 @@ func TestAPIRepoMigrate(t *testing.T) { CloneAddr: testCase.cloneURL, RepoOwnerID: testCase.userID, RepoName: testCase.repoName, + Wiki: true, }).AddTokenAuth(token) resp := MakeRequest(t, req, NoExpectedStatus) if resp.Code == http.StatusUnprocessableEntity { @@ -764,3 +765,58 @@ func TestAPIRepoCommitPull(t *testing.T) { req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/not-a-commit/pull") MakeRequest(t, req, http.StatusNotFound) } + +func TestAPIListOwnRepoSorting(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository, auth_model.AccessTokenScopeReadUser) + + t.Run("No sorting", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + MakeRequest(t, NewRequest(t, "GET", "/api/v1/user/repos").AddTokenAuth(token), http.StatusOK) + }) + + t.Run("ID sorting", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + var repos []api.Repository + resp := MakeRequest(t, NewRequest(t, "GET", "/api/v1/user/repos?limit=2&order_by=id").AddTokenAuth(token), http.StatusOK) + DecodeJSON(t, resp, &repos) + + assert.Len(t, repos, 2) + assert.EqualValues(t, 1, repos[0].ID) + assert.EqualValues(t, 2, repos[1].ID) + }) + + t.Run("Name sorting", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + var repos []api.Repository + resp := MakeRequest(t, NewRequest(t, "GET", "/api/v1/user/repos?limit=2&order_by=name").AddTokenAuth(token), http.StatusOK) + DecodeJSON(t, resp, &repos) + + assert.Len(t, repos, 2) + assert.EqualValues(t, "big_test_private_4", repos[0].Name) + // Postgres doesn't do ascii sorting. + if setting.Database.Type.IsPostgreSQL() { + assert.EqualValues(t, "commitsonpr", repos[1].Name) + } else { + assert.EqualValues(t, "commits_search_test", repos[1].Name) + } + }) + + t.Run("Reverse alphabetic sorting", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + var repos []api.Repository + resp := MakeRequest(t, NewRequest(t, "GET", "/api/v1/user/repos?limit=2&order_by=reversealphabetically").AddTokenAuth(token), http.StatusOK) + DecodeJSON(t, resp, &repos) + + assert.Len(t, repos, 2) + assert.EqualValues(t, "utf8", repos[0].Name) + assert.EqualValues(t, "test_workflows", repos[1].Name) + }) +} diff --git a/tests/integration/api_repo_topic_test.go b/tests/integration/api_repo_topic_test.go index dcb8ae09da..c826fbd818 100644 --- a/tests/integration/api_repo_topic_test.go +++ b/tests/integration/api_repo_topic_test.go @@ -10,12 +10,12 @@ import ( "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_repo_variables_test.go b/tests/integration/api_repo_variables_test.go index 7847962b07..6e3e8c1db6 100644 --- a/tests/integration/api_repo_variables_test.go +++ b/tests/integration/api_repo_variables_test.go @@ -8,12 +8,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" ) func TestAPIRepoVariables(t *testing.T) { diff --git a/tests/integration/api_settings_test.go b/tests/integration/api_settings_test.go index 9881578fba..e13f4062da 100644 --- a/tests/integration/api_settings_test.go +++ b/tests/integration/api_settings_test.go @@ -7,9 +7,9 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_team_test.go b/tests/integration/api_team_test.go index 4fee39d687..41d34dcd50 100644 --- a/tests/integration/api_team_test.go +++ b/tests/integration/api_team_test.go @@ -9,17 +9,17 @@ import ( "sort" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/organization" - "code.gitea.io/gitea/models/perm" - "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unit" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/services/convert" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/organization" + "forgejo.org/models/perm" + "forgejo.org/models/repo" + "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/services/convert" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_team_user_test.go b/tests/integration/api_team_user_test.go index 6c80bc9f80..0c76dd459d 100644 --- a/tests/integration/api_team_user_test.go +++ b/tests/integration/api_team_user_test.go @@ -8,13 +8,13 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/services/convert" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/services/convert" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_token_test.go b/tests/integration/api_token_test.go index 01d18ef6f1..aba6a25256 100644 --- a/tests/integration/api_token_test.go +++ b/tests/integration/api_token_test.go @@ -8,12 +8,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/log" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/log" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -30,6 +30,23 @@ 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/api_twofa_test.go b/tests/integration/api_twofa_test.go index 9de096ed2f..6441b23199 100644 --- a/tests/integration/api_twofa_test.go +++ b/tests/integration/api_twofa_test.go @@ -8,11 +8,11 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" "github.com/pquerna/otp/totp" "github.com/stretchr/testify/assert" diff --git a/tests/integration/api_user_actions_test.go b/tests/integration/api_user_actions_test.go new file mode 100644 index 0000000000..1eb5089ee4 --- /dev/null +++ b/tests/integration/api_user_actions_test.go @@ -0,0 +1,38 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "fmt" + "net/http" + "testing" + + actions_model "forgejo.org/models/actions" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + api "forgejo.org/modules/structs" + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" +) + +func TestAPISearchActionJobs_UserRunner(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + normalUsername := "user2" + session := loginUser(t, normalUsername) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser) + job := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: 394}) + + req := NewRequest(t, "GET", + fmt.Sprintf("/api/v1/user/actions/runners/jobs?labels=%s", "debian-latest")). + AddTokenAuth(token) + res := MakeRequest(t, req, http.StatusOK) + + var jobs []*api.ActionRunJob + DecodeJSON(t, res, &jobs) + + assert.Len(t, jobs, 1) + assert.EqualValues(t, job.ID, jobs[0].ID) +} diff --git a/tests/integration/api_user_avatar_test.go b/tests/integration/api_user_avatar_test.go index 22dc09a6b7..858e6cf71f 100644 --- a/tests/integration/api_user_avatar_test.go +++ b/tests/integration/api_user_avatar_test.go @@ -9,9 +9,9 @@ import ( "os" "testing" - auth_model "code.gitea.io/gitea/models/auth" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/api_user_email_test.go b/tests/integration/api_user_email_test.go index 6441e2ed8e..b0907ad1cf 100644 --- a/tests/integration/api_user_email_test.go +++ b/tests/integration/api_user_email_test.go @@ -7,9 +7,9 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_user_follow_test.go b/tests/integration/api_user_follow_test.go index 68443eff48..703d8ff494 100644 --- a/tests/integration/api_user_follow_test.go +++ b/tests/integration/api_user_follow_test.go @@ -8,9 +8,9 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_user_heatmap_test.go b/tests/integration/api_user_heatmap_test.go index a23536735b..69d2524aaa 100644 --- a/tests/integration/api_user_heatmap_test.go +++ b/tests/integration/api_user_heatmap_test.go @@ -9,10 +9,10 @@ import ( "testing" "time" - activities_model "code.gitea.io/gitea/models/activities" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/modules/timeutil" - "code.gitea.io/gitea/tests" + activities_model "forgejo.org/models/activities" + auth_model "forgejo.org/models/auth" + "forgejo.org/modules/timeutil" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_user_info_test.go b/tests/integration/api_user_info_test.go index 89f7266859..eefabe52ac 100644 --- a/tests/integration/api_user_info_test.go +++ b/tests/integration/api_user_info_test.go @@ -8,11 +8,11 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_user_org_perm_test.go b/tests/integration/api_user_org_perm_test.go index 85bb1db170..9a09a34087 100644 --- a/tests/integration/api_user_org_perm_test.go +++ b/tests/integration/api_user_org_perm_test.go @@ -8,9 +8,9 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_user_orgs_test.go b/tests/integration/api_user_orgs_test.go index e31199406d..ca3fc7df34 100644 --- a/tests/integration/api_user_orgs_test.go +++ b/tests/integration/api_user_orgs_test.go @@ -8,12 +8,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_user_search_test.go b/tests/integration/api_user_search_test.go index ab52b26531..3df3e45778 100644 --- a/tests/integration/api_user_search_test.go +++ b/tests/integration/api_user_search_test.go @@ -7,13 +7,13 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_user_secrets_test.go b/tests/integration/api_user_secrets_test.go index 56bf30e804..50ecdedfd6 100644 --- a/tests/integration/api_user_secrets_test.go +++ b/tests/integration/api_user_secrets_test.go @@ -8,9 +8,9 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + api "forgejo.org/modules/structs" + "forgejo.org/tests" ) func TestAPIUserSecrets(t *testing.T) { diff --git a/tests/integration/api_user_star_test.go b/tests/integration/api_user_star_test.go index aafe9cfb8b..27e5b9e0ca 100644 --- a/tests/integration/api_user_star_test.go +++ b/tests/integration/api_user_star_test.go @@ -8,12 +8,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_user_variables_test.go b/tests/integration/api_user_variables_test.go index 9fd84ddf81..2e219be7ec 100644 --- a/tests/integration/api_user_variables_test.go +++ b/tests/integration/api_user_variables_test.go @@ -8,9 +8,9 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + api "forgejo.org/modules/structs" + "forgejo.org/tests" ) func TestAPIUserVariables(t *testing.T) { diff --git a/tests/integration/api_user_watch_test.go b/tests/integration/api_user_watch_test.go index 953e00551d..fd8964a8ed 100644 --- a/tests/integration/api_user_watch_test.go +++ b/tests/integration/api_user_watch_test.go @@ -8,9 +8,9 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/api_wiki_test.go b/tests/integration/api_wiki_test.go index 638b90a4aa..1720587dd4 100644 --- a/tests/integration/api_wiki_test.go +++ b/tests/integration/api_wiki_test.go @@ -5,22 +5,21 @@ package integration import ( - "context" "encoding/base64" "fmt" "net/http" "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - 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/optional" - api "code.gitea.io/gitea/modules/structs" - repo_service "code.gitea.io/gitea/services/repository" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/optional" + api "forgejo.org/modules/structs" + repo_service "forgejo.org/services/repository" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -320,7 +319,7 @@ func TestAPIEditOtherWikiPage(t *testing.T) { testCreateWiki(http.StatusForbidden) // Update the repo settings for user2's repo to enable globally writeable wiki - ctx := context.Background() + ctx := t.Context() repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) var units []repo_model.RepoUnit units = append(units, repo_model.RepoUnit{ diff --git a/tests/integration/appearance_settings_test.go b/tests/integration/appearance_settings_test.go new file mode 100644 index 0000000000..33ca9f97aa --- /dev/null +++ b/tests/integration/appearance_settings_test.go @@ -0,0 +1,57 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package integration + +import ( + "net/http" + "strings" + "testing" + + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" +) + +func TestThemeChange(t *testing.T) { + defer tests.PrepareTestEnv(t)() + user := loginUser(t, "user2") + + // Verify default theme + testSelectedTheme(t, user, "forgejo-auto", "Forgejo (follow system theme)") + + // Change theme to forgejo-dark and verify it works fine + testChangeTheme(t, user, "forgejo-dark") + testSelectedTheme(t, user, "forgejo-dark", "Forgejo dark") + + // Change theme to gitea-dark and also verify that it's name is not translated + testChangeTheme(t, user, "gitea-dark") + testSelectedTheme(t, user, "gitea-dark", "gitea-dark") +} + +// testSelectedTheme checks that the expected theme is used in html[data-theme] +// and is default on appearance page +func testSelectedTheme(t *testing.T, session *TestSession, expectedTheme, expectedName string) { + t.Helper() + response := session.MakeRequest(t, NewRequest(t, "GET", "/user/settings/appearance"), http.StatusOK) + page := NewHTMLParser(t, response.Body) + + dataTheme, dataThemeExists := page.Find("html").Attr("data-theme") + assert.True(t, dataThemeExists) + assert.EqualValues(t, expectedTheme, dataTheme) + + selectedTheme := page.Find("form[action='/user/settings/appearance/theme'] .menu .item.selected") + selectorTheme, selectorThemeExists := selectedTheme.Attr("data-value") + assert.True(t, selectorThemeExists) + assert.EqualValues(t, expectedTheme, selectorTheme) + assert.EqualValues(t, expectedName, strings.TrimSpace(selectedTheme.Text())) +} + +// testSelectedTheme changes user's theme +func testChangeTheme(t *testing.T, session *TestSession, newTheme string) { + t.Helper() + session.MakeRequest(t, NewRequestWithValues(t, "POST", "/user/settings/appearance/theme", map[string]string{ + "_csrf": GetCSRF(t, session, "/user/settings/appearance"), + "theme": newTheme, + }), http.StatusSeeOther) +} diff --git a/tests/integration/attachment_test.go b/tests/integration/attachment_test.go index 7bd3e680f7..5920620f48 100644 --- a/tests/integration/attachment_test.go +++ b/tests/integration/attachment_test.go @@ -13,10 +13,10 @@ import ( "strings" "testing" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/modules/storage" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + repo_model "forgejo.org/models/repo" + "forgejo.org/modules/storage" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/auth_ldap_test.go b/tests/integration/auth_ldap_test.go index 62a7d18904..6b9a71a5aa 100644 --- a/tests/integration/auth_ldap_test.go +++ b/tests/integration/auth_ldap_test.go @@ -4,22 +4,21 @@ package integration import ( - "context" "net/http" "os" "strings" "testing" - "code.gitea.io/gitea/models" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/organization" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/translation" - "code.gitea.io/gitea/services/auth" - "code.gitea.io/gitea/services/auth/source/ldap" - "code.gitea.io/gitea/tests" + "forgejo.org/models" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/organization" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/translation" + "forgejo.org/services/auth" + "forgejo.org/services/auth/source/ldap" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -244,7 +243,7 @@ func TestLDAPUserSync(t *testing.T) { } defer tests.PrepareTestEnv(t)() addAuthSourceLDAP(t, "", "", "", "") - auth.SyncExternalUsers(context.Background(), true) + auth.SyncExternalUsers(t.Context(), true) // Check if users exists for _, gitLDAPUser := range gitLDAPUsers { @@ -283,7 +282,7 @@ func TestLDAPUserSyncWithEmptyUsernameAttribute(t *testing.T) { htmlDoc := NewHTMLParser(t, resp.Body) - tr := htmlDoc.doc.Find("table.table tbody tr") + tr := htmlDoc.doc.Find("table.table tbody tr:not(.no-results-row)") assert.Equal(t, 0, tr.Length()) } @@ -296,7 +295,7 @@ func TestLDAPUserSyncWithEmptyUsernameAttribute(t *testing.T) { MakeRequest(t, req, http.StatusSeeOther) } - auth.SyncExternalUsers(context.Background(), true) + auth.SyncExternalUsers(t.Context(), true) authSource := unittest.AssertExistsAndLoadBean(t, &auth_model.Source{ Name: payload["name"], @@ -331,7 +330,7 @@ func TestLDAPUserSyncWithGroupFilter(t *testing.T) { u := otherLDAPUsers[0] testLoginFailed(t, u.UserName, u.Password, translation.NewLocale("en-US").TrString("form.username_password_incorrect")) - auth.SyncExternalUsers(context.Background(), true) + auth.SyncExternalUsers(t.Context(), true) // Assert members of LDAP group "cn=git" are added for _, gitLDAPUser := range gitLDAPUsers { @@ -354,7 +353,7 @@ func TestLDAPUserSyncWithGroupFilter(t *testing.T) { ldapConfig.GroupFilter = "(cn=ship_crew)" auth_model.UpdateSource(db.DefaultContext, ldapSource) - auth.SyncExternalUsers(context.Background(), true) + auth.SyncExternalUsers(t.Context(), true) for _, gitLDAPUser := range gitLDAPUsers { if gitLDAPUser.UserName == "fry" || gitLDAPUser.UserName == "leela" || gitLDAPUser.UserName == "bender" { @@ -393,7 +392,7 @@ func TestLDAPUserSSHKeySync(t *testing.T) { defer tests.PrepareTestEnv(t)() addAuthSourceLDAP(t, "sshPublicKey", "", "", "") - auth.SyncExternalUsers(context.Background(), true) + auth.SyncExternalUsers(t.Context(), true) // Check if users has SSH keys synced for _, u := range gitLDAPUsers { @@ -429,7 +428,7 @@ func TestLDAPGroupTeamSyncAddMember(t *testing.T) { require.NoError(t, err) team, err := organization.GetTeam(db.DefaultContext, org.ID, "team11") require.NoError(t, err) - auth.SyncExternalUsers(context.Background(), true) + auth.SyncExternalUsers(t.Context(), true) for _, gitLDAPUser := range gitLDAPUsers { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ Name: gitLDAPUser.UserName, @@ -518,7 +517,7 @@ func TestLDAPUserSyncInvalidMail(t *testing.T) { } defer tests.PrepareTestEnv(t)() addAuthSourceLDAP(t, "", "nonexisting", "", "") - auth.SyncExternalUsers(context.Background(), true) + auth.SyncExternalUsers(t.Context(), true) // Check if users exists for _, gitLDAPUser := range gitLDAPUsers { @@ -544,7 +543,7 @@ func TestLDAPUserSyncInvalidMailDefaultDomain(t *testing.T) { } defer tests.PrepareTestEnv(t)() addAuthSourceLDAP(t, "", "nonexisting", "test.org", "") - auth.SyncExternalUsers(context.Background(), true) + auth.SyncExternalUsers(t.Context(), true) // Check if users exists for _, gitLDAPUser := range gitLDAPUsers { diff --git a/tests/integration/auth_token_test.go b/tests/integration/auth_token_test.go index d1fd5dda83..b4242c2681 100644 --- a/tests/integration/auth_token_test.go +++ b/tests/integration/auth_token_test.go @@ -10,13 +10,13 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/timeutil" - "code.gitea.io/gitea/tests" + "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + "forgejo.org/modules/timeutil" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/benchmarks_test.go b/tests/integration/benchmarks_test.go index 62da761d2d..40875e0c7d 100644 --- a/tests/integration/benchmarks_test.go +++ b/tests/integration/benchmarks_test.go @@ -9,9 +9,9 @@ import ( "net/url" "testing" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - api "code.gitea.io/gitea/modules/structs" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + api "forgejo.org/modules/structs" ) // StringWithCharset random string (from https://www.calhoun.io/creating-random-strings-in-go/) diff --git a/tests/integration/block_test.go b/tests/integration/block_test.go index b17a445bf8..7a2756522b 100644 --- a/tests/integration/block_test.go +++ b/tests/integration/block_test.go @@ -11,15 +11,15 @@ import ( "strconv" "testing" - "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/db" - issue_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/translation" - forgejo_context "code.gitea.io/gitea/services/context" - "code.gitea.io/gitea/tests" + "forgejo.org/models/activities" + "forgejo.org/models/db" + issue_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/translation" + forgejo_context "forgejo.org/services/context" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -147,13 +147,27 @@ func TestBlockUserFromOrganization(t *testing.T) { session.MakeRequest(t, req, http.StatusInternalServerError) }) }) + + t.Run("Block the doer", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequestWithValues(t, "POST", org.OrganisationLink()+"/settings/blocked_users/block", map[string]string{ + "_csrf": GetCSRF(t, session, org.OrganisationLink()+"/settings/blocked_users"), + "uname": doer.Name, + }) + session.MakeRequest(t, req, http.StatusSeeOther) + assert.False(t, unittest.BeanExists(t, &user_model.BlockedUser{BlockID: doer.ID, UserID: org.ID})) + flashCookie := session.GetCookie(forgejo_context.CookieNameFlash) + assert.NotNil(t, flashCookie) + assert.EqualValues(t, "error%3DYou%2Bcannot%2Bblock%2Byourself.", flashCookie.Value) + }) } // TestBlockActions ensures that certain actions cannot be performed as a doer // and as a blocked user and are handled cleanly after the blocking has taken // place. func TestBlockActions(t *testing.T) { - defer tests.AddFixtures("tests/integration/fixtures/TestBlockActions/")() + defer unittest.OverrideFixtures("tests/integration/fixtures/TestBlockActions")() defer tests.PrepareTestEnv(t)() doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) @@ -239,6 +253,12 @@ func TestBlockActions(t *testing.T) { DecodeJSON(t, resp, &errorResp) assert.EqualValues(t, expectedMessage, errorResp.Error) + + req = NewRequest(t, "GET", issue10URL) + resp = session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + msg := htmlDoc.doc.Find("div .warning").Text() + assert.Contains(t, msg, "You cannot comment on this issue because you are blocked") }) t.Run("Blocked by issue poster", func(t *testing.T) { @@ -260,6 +280,12 @@ func TestBlockActions(t *testing.T) { DecodeJSON(t, resp, &errorResp) assert.EqualValues(t, expectedMessage, errorResp.Error) + + req = NewRequest(t, "GET", issue10URL) + resp = session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + msg := htmlDoc.doc.Find("div .warning").Text() + assert.Contains(t, msg, "You cannot comment on this issue because you are blocked") }) }) @@ -412,7 +438,7 @@ func TestBlockActions(t *testing.T) { } func TestBlockedNotification(t *testing.T) { - defer tests.AddFixtures("tests/integration/fixtures/TestBlockedNotifications")() + defer unittest.OverrideFixtures("tests/integration/fixtures/TestBlockedNotifications")() defer tests.PrepareTestEnv(t)() doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) diff --git a/tests/integration/branches_test.go b/tests/integration/branches_test.go index e0482b6f2e..c599106866 100644 --- a/tests/integration/branches_test.go +++ b/tests/integration/branches_test.go @@ -9,10 +9,10 @@ import ( "net/url" "testing" - git_model "code.gitea.io/gitea/models/git" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - gitea_context "code.gitea.io/gitea/services/context" + git_model "forgejo.org/models/git" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + gitea_context "forgejo.org/services/context" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/change_default_branch_test.go b/tests/integration/change_default_branch_test.go index 703834b712..84f02e41f9 100644 --- a/tests/integration/change_default_branch_test.go +++ b/tests/integration/change_default_branch_test.go @@ -8,10 +8,10 @@ import ( "net/http" "testing" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" ) func TestChangeDefaultBranch(t *testing.T) { diff --git a/tests/integration/cmd_admin_test.go b/tests/integration/cmd_admin_test.go index b493dff919..043ecef346 100644 --- a/tests/integration/cmd_admin_test.go +++ b/tests/integration/cmd_admin_test.go @@ -7,10 +7,10 @@ import ( "net/url" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/cmd_forgejo_actions_test.go b/tests/integration/cmd_forgejo_actions_test.go index bda69edb80..bee50a6d98 100644 --- a/tests/integration/cmd_forgejo_actions_test.go +++ b/tests/integration/cmd_forgejo_actions_test.go @@ -3,7 +3,6 @@ package integration import ( - gocontext "context" "io" "net/url" "os" @@ -11,11 +10,11 @@ import ( "strings" "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" - "code.gitea.io/gitea/tests" + actions_model "forgejo.org/models/actions" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -189,7 +188,7 @@ func Test_CmdForgejo_Actions(t *testing.T) { require.NoError(t, err) if assert.EqualValues(t, testCase.uuid, uuid) { ownerName, repoName, found := strings.Cut(testCase.scope, "/") - action, err := actions_model.GetRunnerByUUID(gocontext.Background(), uuid) + action, err := actions_model.GetRunnerByUUID(t.Context(), uuid) require.NoError(t, err) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: action.OwnerID}) diff --git a/tests/integration/cmd_forgejo_f3_test.go b/tests/integration/cmd_forgejo_f3_test.go index 9156405220..1eda413e4c 100644 --- a/tests/integration/cmd_forgejo_f3_test.go +++ b/tests/integration/cmd_forgejo_f3_test.go @@ -9,14 +9,14 @@ import ( "fmt" "testing" - "code.gitea.io/gitea/cmd/forgejo" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/services/f3/driver/options" - "code.gitea.io/gitea/tests" + "forgejo.org/cmd/forgejo" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/services/f3/driver/options" + "forgejo.org/tests" - _ "code.gitea.io/gitea/services/f3/driver" - _ "code.gitea.io/gitea/services/f3/driver/tests" + _ "forgejo.org/services/f3/driver" + _ "forgejo.org/services/f3/driver/tests" f3_filesystem_options "code.forgejo.org/f3/gof3/v3/forges/filesystem/options" f3_logger "code.forgejo.org/f3/gof3/v3/logger" @@ -59,7 +59,7 @@ func TestF3_CmdMirror_LocalForgejo(t *testing.T) { defer tests.PrepareTestEnv(t)() defer test.MockVariableValue(&setting.F3.Enabled, true)() - ctx := context.Background() + ctx := t.Context() mirrorOptions := f3_tests_forge.GetFactory(options.Name)().NewOptions(t) mirrorTree := f3_generic.GetFactory("f3")(ctx, mirrorOptions) diff --git a/tests/integration/cmd_keys_test.go b/tests/integration/cmd_keys_test.go index e93a8b5b57..c76055c4a8 100644 --- a/tests/integration/cmd_keys_test.go +++ b/tests/integration/cmd_keys_test.go @@ -9,8 +9,8 @@ import ( "os/exec" "testing" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/util" + "forgejo.org/modules/setting" + "forgejo.org/modules/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/codeowner_test.go b/tests/integration/codeowner_test.go index e8200219c4..e2eeb843d8 100644 --- a/tests/integration/codeowner_test.go +++ b/tests/integration/codeowner_test.go @@ -4,7 +4,6 @@ package integration import ( - "context" "fmt" "net/http" "net/url" @@ -14,15 +13,15 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - 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/git" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/require" ) @@ -48,7 +47,7 @@ func TestCodeOwner(t *testing.T) { r := fmt.Sprintf("%suser2/%s.git", u.String(), repo.Name) cloneURL, _ := url.Parse(r) cloneURL.User = url.UserPassword("user2", userPassword) - require.NoError(t, git.CloneWithArgs(context.Background(), nil, cloneURL.String(), dstPath, git.CloneRepoOptions{})) + require.NoError(t, git.CloneWithArgs(t.Context(), nil, cloneURL.String(), dstPath, git.CloneRepoOptions{})) t.Run("Normal", func(t *testing.T) { defer tests.PrintCurrentTest(t)() diff --git a/tests/integration/comment_roles_system_test.go b/tests/integration/comment_roles_system_test.go new file mode 100644 index 0000000000..0b4e78048a --- /dev/null +++ b/tests/integration/comment_roles_system_test.go @@ -0,0 +1,56 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package integration + +import ( + "net/http" + "testing" + + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" +) + +// TestSystemCommentRoles verifies that system users don't have role labels. +// As it is not possible to do actions as system users, the tests are done using fixtures. + +func TestSystemCommentRoles(t *testing.T) { + defer unittest.OverrideFixtures("tests/integration/fixtures/TestSystemCommentRoles")() + defer tests.PrepareTestEnv(t)() + + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + + testCases := []struct { + name string + username string + index int64 + roleCount int64 + }{ + {"user2", "user2", 1000, 1}, // As a verification, also check a normal user with one role. + {"Ghost", "Ghost", 1001, 0}, // System users should not have any roles, so 0. + {"Actions", "forgejo-actions", 1002, 0}, + {"APActor", "Ghost", 1003, 0}, // actor is displayed as Ghost, could be a bug. + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ + RepoID: repo.ID, + Index: tc.index, + }) + + req := NewRequestf(t, "GET", "%s/issues/%d", repo.Link(), issue.Index) + resp := MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + + assert.EqualValues(t, tc.username, htmlDoc.Find("a.author").Text()) + assert.EqualValues(t, tc.roleCount, htmlDoc.Find(".role-label").Length()) + }) + } +} diff --git a/tests/integration/issues_comment_labels_test.go b/tests/integration/comment_roles_test.go similarity index 98% rename from tests/integration/issues_comment_labels_test.go rename to tests/integration/comment_roles_test.go index 5299d8a057..00bec95722 100644 --- a/tests/integration/issues_comment_labels_test.go +++ b/tests/integration/comment_roles_test.go @@ -14,8 +14,8 @@ import ( "github.com/stretchr/testify/assert" ) -// TestIssuesCommentLabels is a test for user (role) labels in comment headers in PRs and issues. -func TestIssuesCommentLabels(t *testing.T) { +// TestCommentRoles is a test for role labels of normal users in comment headers in PRs and issues. +func TestCommentRoles(t *testing.T) { user := "user2" repo := "repo1" diff --git a/tests/integration/commit_status_test.go b/tests/integration/commit_status_test.go index 924fc5b074..9dd1bcd283 100644 --- a/tests/integration/commit_status_test.go +++ b/tests/integration/commit_status_test.go @@ -6,11 +6,11 @@ package integration import ( "testing" - "code.gitea.io/gitea/models/db" - git_model "code.gitea.io/gitea/models/git" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + git_model "forgejo.org/models/git" + "forgejo.org/models/unittest" + "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/compare_test.go b/tests/integration/compare_test.go index 2d27a430ac..3c3e8adf94 100644 --- a/tests/integration/compare_test.go +++ b/tests/integration/compare_test.go @@ -11,18 +11,19 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - 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/gitrepo" - "code.gitea.io/gitea/modules/optional" - "code.gitea.io/gitea/modules/test" - repo_service "code.gitea.io/gitea/services/repository" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/optional" + "forgejo.org/modules/test" + repo_service "forgejo.org/services/repository" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" + "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -67,6 +68,114 @@ func inspectCompare(t *testing.T, htmlDoc *HTMLDoc, diffCount int, diffChanges [ } } +func TestComparePatchAndDiffMenuEntries(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + session := loginUser(t, "user2") + req := NewRequest(t, "GET", "/user2/repo-release/compare/v1.0...v2.0") + resp := session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + downloadOptions := htmlDoc.doc.Find("a.item[download]") + var patchDownloadEntryPresent bool + var diffDownloadEntryPresent bool + downloadOptions.Each(func(idx int, c *goquery.Selection) { + value, exists := c.Attr("download") + if exists && strings.HasSuffix(value, ".patch") { + patchDownloadEntryPresent = true + } + + if exists && strings.HasSuffix(value, ".diff") { + diffDownloadEntryPresent = true + } + }) + + assert.True(t, patchDownloadEntryPresent, "Patch file download entry should be present") + assert.True(t, diffDownloadEntryPresent, "Diff file download entry should be present") +} + +func TestComparePatchDownload(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + session := loginUser(t, "user2") + req := NewRequest(t, "GET", "/user2/repo-release/compare/v1.0...v2.0.patch") + attendedResponse := `From 4380f99290b2b3922733ff82c57afad915ace907 Mon Sep 17 00:00:00 2001 +From: user1 +Date: Mon, 17 Apr 2023 14:39:35 +0200 +Subject: [PATCH 1/3] feature v2 + +--- + feature | 0 + 1 file changed, 0 insertions(+), 0 deletions(-) + create mode 100644 feature + +diff --git a/feature b/feature +new file mode 100644 +index 0000000..e69de29 + +From 79f9d88f1b054d650f88da0bd658e21f7b0cf6ec Mon Sep 17 00:00:00 2001 +From: user1 +Date: Mon, 17 Apr 2023 14:38:53 +0200 +Subject: [PATCH 2/3] bugfix + +--- + bugfix | 0 + 1 file changed, 0 insertions(+), 0 deletions(-) + create mode 100644 bugfix + +diff --git a/bugfix b/bugfix +new file mode 100644 +index 0000000..e69de29 + +From 7197b56fdc75b453f47c9110938cb46a303579fd Mon Sep 17 00:00:00 2001 +From: user1 +Date: Mon, 17 Apr 2023 14:42:34 +0200 +Subject: [PATCH 3/3] readme: v2 + +--- + README.md | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/README.md b/README.md +index 6dfe48a..bc7068d 100644 +--- a/README.md ++++ b/README.md +@@ -1,3 +1,3 @@ + # Releases test repo + +-With a v1.0 ++With a v1.0 and a v2.0 +` + + resp := session.MakeRequest(t, req, http.StatusOK) + assert.Equal(t, attendedResponse, resp.Body.String()) +} + +func TestCompareDiffDownload(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + session := loginUser(t, "user2") + req := NewRequest(t, "GET", "/user2/repo-release/compare/v1.0...v2.0.diff") + attendedResponse := `diff --git a/README.md b/README.md +index 6dfe48a..bc7068d 100644 +--- a/README.md ++++ b/README.md +@@ -1,3 +1,3 @@ + # Releases test repo + +-With a v1.0 ++With a v1.0 and a v2.0 +diff --git a/bugfix b/bugfix +new file mode 100644 +index 0000000..e69de29 +diff --git a/feature b/feature +new file mode 100644 +index 0000000..e69de29 +` + + resp := session.MakeRequest(t, req, http.StatusOK) + assert.Equal(t, attendedResponse, resp.Body.String()) +} + // Git commit graph for repo20 // * 8babce9 (origin/remove-files-b) Add a dummy file // * b67e43a Delete test.csv and link_hi diff --git a/tests/integration/cors_test.go b/tests/integration/cors_test.go index 25dfbabf41..a050693035 100644 --- a/tests/integration/cors_test.go +++ b/tests/integration/cors_test.go @@ -7,10 +7,10 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/create_no_session_test.go b/tests/integration/create_no_session_test.go index ca2a775459..ed547c5b5a 100644 --- a/tests/integration/create_no_session_test.go +++ b/tests/integration/create_no_session_test.go @@ -10,10 +10,10 @@ import ( "path/filepath" "testing" - "code.gitea.io/gitea/modules/json" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/json" + "forgejo.org/modules/setting" + "forgejo.org/routers" + "forgejo.org/tests" "code.forgejo.org/go-chi/session" "github.com/stretchr/testify/assert" diff --git a/tests/integration/csrf_test.go b/tests/integration/csrf_test.go index fcb9661b8a..100614cbb4 100644 --- a/tests/integration/csrf_test.go +++ b/tests/integration/csrf_test.go @@ -7,9 +7,9 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/db_collation_test.go b/tests/integration/db_collation_test.go index 0e5bf00ed7..6bfe656b9b 100644 --- a/tests/integration/db_collation_test.go +++ b/tests/integration/db_collation_test.go @@ -9,10 +9,10 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/delete_user_test.go b/tests/integration/delete_user_test.go index fa407a75ad..767d6c9724 100644 --- a/tests/integration/delete_user_test.go +++ b/tests/integration/delete_user_test.go @@ -8,13 +8,13 @@ import ( "net/http" "testing" - issues_model "code.gitea.io/gitea/models/issues" - "code.gitea.io/gitea/models/organization" - access_model "code.gitea.io/gitea/models/perm/access" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + issues_model "forgejo.org/models/issues" + "forgejo.org/models/organization" + access_model "forgejo.org/models/perm/access" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" ) func assertUserDeleted(t *testing.T, userID int64, purged bool) { diff --git a/tests/integration/disable_forgotten_password_test.go b/tests/integration/disable_forgotten_password_test.go new file mode 100644 index 0000000000..7a1e502d93 --- /dev/null +++ b/tests/integration/disable_forgotten_password_test.go @@ -0,0 +1,39 @@ +package integration + +import ( + "net/http" + "testing" + + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/tests" +) + +func TestDisableForgottenPasswordFalse(t *testing.T) { + defer tests.PrepareTestEnv(t)() + defer test.MockVariableValue(&setting.Service.EnableInternalSignIn, true)() + + req := NewRequest(t, "GET", "/user/login/") + resp := MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + htmlDoc.AssertElement(t, "a[href='/user/forgot_password']", true) +} + +func TestDisableForgottenPasswordTrue(t *testing.T) { + defer tests.PrepareTestEnv(t)() + defer test.MockVariableValue(&setting.Service.EnableInternalSignIn, false)() + + req := NewRequest(t, "GET", "/user/login/") + resp := MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + htmlDoc.AssertElement(t, "a[href='/user/forgot_password']", false) +} + +func TestDisableForgottenPasswordDefault(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + req := NewRequest(t, "GET", "/user/login/") + resp := MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + htmlDoc.AssertElement(t, "a[href='/user/forgot_password']", true) +} diff --git a/tests/integration/doctor_packages_nuget_test.go b/tests/integration/doctor_packages_nuget_test.go index a012567efc..e505799730 100644 --- a/tests/integration/doctor_packages_nuget_test.go +++ b/tests/integration/doctor_packages_nuget_test.go @@ -11,17 +11,17 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - packages_model "code.gitea.io/gitea/models/packages" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/log" - packages_module "code.gitea.io/gitea/modules/packages" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - doctor "code.gitea.io/gitea/services/doctor" - packages_service "code.gitea.io/gitea/services/packages" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + packages_model "forgejo.org/models/packages" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/log" + packages_module "forgejo.org/modules/packages" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + doctor "forgejo.org/services/doctor" + packages_service "forgejo.org/services/packages" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/download_test.go b/tests/integration/download_test.go index efe5ac791c..d5e68402c5 100644 --- a/tests/integration/download_test.go +++ b/tests/integration/download_test.go @@ -7,8 +7,8 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/dummy_lang_test.go b/tests/integration/dummy_lang_test.go index d26ea6edc4..08c5176731 100644 --- a/tests/integration/dummy_lang_test.go +++ b/tests/integration/dummy_lang_test.go @@ -7,7 +7,7 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/dump_restore_test.go b/tests/integration/dump_restore_test.go index fa65695150..239170a256 100644 --- a/tests/integration/dump_restore_test.go +++ b/tests/integration/dump_restore_test.go @@ -4,7 +4,6 @@ package integration import ( - "context" "errors" "fmt" "net/url" @@ -14,15 +13,14 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - base "code.gitea.io/gitea/modules/migration" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/util" - "code.gitea.io/gitea/services/migrations" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + base "forgejo.org/modules/migration" + "forgejo.org/modules/setting" + "forgejo.org/modules/structs" + "forgejo.org/services/migrations" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -45,9 +43,7 @@ func TestDumpRestore(t *testing.T) { reponame := "repo1" - basePath, err := os.MkdirTemp("", reponame) - require.NoError(t, err) - defer util.RemoveAll(basePath) + basePath := t.TempDir() repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame}) repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) @@ -58,7 +54,7 @@ func TestDumpRestore(t *testing.T) { // Phase 1: dump repo1 from the Gitea instance to the filesystem // - ctx := context.Background() + ctx := t.Context() opts := migrations.MigrateOptions{ GitServiceType: structs.GiteaService, Issues: true, @@ -70,7 +66,7 @@ func TestDumpRestore(t *testing.T) { CloneAddr: repo.CloneLink().HTTPS, RepoName: reponame, } - err = migrations.DumpRepository(ctx, basePath, repoOwner.Name, opts) + err := migrations.DumpRepository(ctx, basePath, repoOwner.Name, opts) require.NoError(t, err) // diff --git a/tests/integration/easymde_test.go b/tests/integration/easymde_test.go index 2b4630d8b4..7ecbe4f5b7 100644 --- a/tests/integration/easymde_test.go +++ b/tests/integration/easymde_test.go @@ -7,7 +7,7 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" ) func TestEasyMDESwitch(t *testing.T) { diff --git a/tests/integration/editor_test.go b/tests/integration/editor_test.go index 96d388ddb9..7321aa26c9 100644 --- a/tests/integration/editor_test.go +++ b/tests/integration/editor_test.go @@ -15,14 +15,14 @@ import ( "path" "testing" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/json" - "code.gitea.io/gitea/modules/translation" - gitea_context "code.gitea.io/gitea/services/context" - "code.gitea.io/gitea/tests" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/json" + "forgejo.org/modules/translation" + gitea_context "forgejo.org/services/context" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/empty_repo_test.go b/tests/integration/empty_repo_test.go index 4122c78ec2..baea2566ff 100644 --- a/tests/integration/empty_repo_test.go +++ b/tests/integration/empty_repo_test.go @@ -11,15 +11,15 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/json" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/json" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -136,3 +136,24 @@ func TestEmptyRepoAddFileByAPI(t *testing.T) { DecodeJSON(t, resp, &apiRepo) assert.Equal(t, "new_branch", apiRepo.DefaultBranch) } + +func TestEmptyRepoAPIRequestsReturn404(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + session := loginUser(t, "user30") + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository) + + t.Run("Raw", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", "/api/v1/repos/user30/empty/raw/main/something").AddTokenAuth(token) + _ = session.MakeRequest(t, req, http.StatusNotFound) + }) + + t.Run("Media", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", "/api/v1/repos/user30/empty/media/main/something").AddTokenAuth(token) + _ = session.MakeRequest(t, req, http.StatusNotFound) + }) +} diff --git a/tests/integration/eventsource_test.go b/tests/integration/eventsource_test.go index e081df0e57..8eb5110e54 100644 --- a/tests/integration/eventsource_test.go +++ b/tests/integration/eventsource_test.go @@ -9,15 +9,15 @@ import ( "testing" "time" - activities_model "code.gitea.io/gitea/models/activities" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/eventsource" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + activities_model "forgejo.org/models/activities" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/eventsource" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/explore_code_test.go b/tests/integration/explore_code_test.go index d84b47cf05..97cc97b996 100644 --- a/tests/integration/explore_code_test.go +++ b/tests/integration/explore_code_test.go @@ -4,9 +4,9 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" @@ -20,11 +20,6 @@ func TestExploreCodeSearchIndexer(t *testing.T) { resp := MakeRequest(t, req, http.StatusOK) doc := NewHTMLParser(t, resp.Body).Find(".explore") - msg := doc. - Find(".ui.container"). - Find(".ui.message[data-test-tag=grep]") - assert.EqualValues(t, 0, msg.Length()) - doc.Find(".file-body").Each(func(i int, sel *goquery.Selection) { assert.Positive(t, sel.Find(".code-inner").Find(".search-highlight").Length(), 0) }) diff --git a/tests/integration/explore_org_test.go b/tests/integration/explore_org_test.go new file mode 100644 index 0000000000..111fd2dda7 --- /dev/null +++ b/tests/integration/explore_org_test.go @@ -0,0 +1,49 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "net/http" + "testing" + + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/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_repos_test.go b/tests/integration/explore_repos_test.go index c0179c50da..604d473ac5 100644 --- a/tests/integration/explore_repos_test.go +++ b/tests/integration/explore_repos_test.go @@ -7,7 +7,7 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/explore_user_test.go b/tests/integration/explore_user_test.go index 441d89cea5..689e623e69 100644 --- a/tests/integration/explore_user_test.go +++ b/tests/integration/explore_user_test.go @@ -7,7 +7,9 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -15,8 +17,11 @@ 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=newest&q="}, + {"", "?sort=" + setting.UI.ExploreDefaultSort + "&q="}, {"newest", "?sort=newest&q="}, {"oldest", "?sort=oldest&q="}, {"alphabetically", "?sort=alphabetically&q="}, diff --git a/tests/integration/feed_repo_test.go b/tests/integration/feed_repo_test.go new file mode 100644 index 0000000000..a4d5ef2610 --- /dev/null +++ b/tests/integration/feed_repo_test.go @@ -0,0 +1,36 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "encoding/xml" + "net/http" + "testing" + + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestFeedRepo(t *testing.T) { + t.Run("RSS", func(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + req := NewRequest(t, "GET", "/user2/repo1.rss") + resp := MakeRequest(t, req, http.StatusOK) + + data := resp.Body.String() + assert.Contains(t, data, ` .search > .input > input") placeholder, _ := search.Attr("placeholder") - assert.Equal(t, "Search issues...", placeholder) + assert.Equal(t, "Search issues…", placeholder) } func TestViewIssuesSortByType(t *testing.T) { @@ -120,7 +119,7 @@ func TestViewIssuesKeyword(t *testing.T) { RepoID: repo.ID, Index: 1, }) - issues.UpdateIssueIndexer(context.Background(), issue.ID) + issues.UpdateIssueIndexer(t.Context(), issue.ID) time.Sleep(time.Second * 1) const keyword = "first" @@ -138,27 +137,25 @@ func TestViewIssuesKeyword(t *testing.T) { }) // keyword: 'firstt' - // should not match when fuzzy searching is disabled - req = NewRequestf(t, "GET", "%s/issues?q=%st&fuzzy=false", repo.Link(), keyword) + // should not match when using phrase search + req = NewRequestf(t, "GET", "%s/issues?q=\"%st\"", repo.Link(), keyword) resp = MakeRequest(t, req, http.StatusOK) htmlDoc = NewHTMLParser(t, resp.Body) issuesSelection = getIssuesSelection(t, htmlDoc) assert.EqualValues(t, 0, issuesSelection.Length()) - // should match as 'first' when fuzzy seaeching is enabled - for _, fmt := range []string{"%s/issues?q=%st&fuzzy=true", "%s/issues?q=%st"} { - req = NewRequestf(t, "GET", fmt, repo.Link(), keyword) - resp = MakeRequest(t, req, http.StatusOK) - htmlDoc = NewHTMLParser(t, resp.Body) - issuesSelection = getIssuesSelection(t, htmlDoc) - assert.EqualValues(t, 1, issuesSelection.Length()) - issuesSelection.Each(func(_ int, selection *goquery.Selection) { - issue := getIssue(t, repo.ID, selection) - assert.False(t, issue.IsClosed) - assert.False(t, issue.IsPull) - assertMatch(t, issue, keyword) - }) - } + // should match as 'first' when using a standard query + req = NewRequestf(t, "GET", "%s/issues?q=%st", repo.Link(), keyword) + resp = MakeRequest(t, req, http.StatusOK) + htmlDoc = NewHTMLParser(t, resp.Body) + issuesSelection = getIssuesSelection(t, htmlDoc) + assert.EqualValues(t, 1, issuesSelection.Length()) + issuesSelection.Each(func(_ int, selection *goquery.Selection) { + issue := getIssue(t, repo.ID, selection) + assert.False(t, issue.IsClosed) + assert.False(t, issue.IsPull) + assertMatch(t, issue, keyword) + }) } func TestViewIssuesSearchOptions(t *testing.T) { @@ -1087,7 +1084,7 @@ func TestIssueReferenceURL(t *testing.T) { } func TestGetContentHistory(t *testing.T) { - defer tests.AddFixtures("tests/integration/fixtures/TestGetContentHistory/")() + defer unittest.OverrideFixtures("tests/integration/fixtures/TestGetContentHistory")() defer tests.PrepareTestEnv(t)() issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) @@ -1139,7 +1136,7 @@ func TestGetContentHistory(t *testing.T) { } func TestCommitRefComment(t *testing.T) { - defer tests.AddFixtures("tests/integration/fixtures/TestCommitRefComment/")() + defer unittest.OverrideFixtures("tests/integration/fixtures/TestCommitRefComment")() defer tests.PrepareTestEnv(t)() t.Run("Pull request", func(t *testing.T) { @@ -1336,3 +1333,46 @@ 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/last_updated_time_test.go b/tests/integration/last_updated_time_test.go index 34ba9a471f..0b3f08677c 100644 --- a/tests/integration/last_updated_time_test.go +++ b/tests/integration/last_updated_time_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" diff --git a/tests/integration/lfs_getobject_test.go b/tests/integration/lfs_getobject_test.go index 351c1a38a4..ddaef827ef 100644 --- a/tests/integration/lfs_getobject_test.go +++ b/tests/integration/lfs_getobject_test.go @@ -11,14 +11,14 @@ import ( "net/http/httptest" "testing" - "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - git_model "code.gitea.io/gitea/models/git" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/modules/json" - "code.gitea.io/gitea/modules/lfs" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/tests" + "forgejo.org/models/auth" + "forgejo.org/models/db" + git_model "forgejo.org/models/git" + repo_model "forgejo.org/models/repo" + "forgejo.org/modules/json" + "forgejo.org/modules/lfs" + "forgejo.org/modules/setting" + "forgejo.org/tests" "github.com/klauspost/compress/gzhttp" gzipp "github.com/klauspost/compress/gzip" diff --git a/tests/integration/lfs_local_endpoint_test.go b/tests/integration/lfs_local_endpoint_test.go index d42888bbe1..8962e0a710 100644 --- a/tests/integration/lfs_local_endpoint_test.go +++ b/tests/integration/lfs_local_endpoint_test.go @@ -10,8 +10,8 @@ import ( "path/filepath" "testing" - "code.gitea.io/gitea/modules/lfs" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/lfs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/lfs_view_test.go b/tests/integration/lfs_view_test.go index 06cea0dac2..6df5855ed6 100644 --- a/tests/integration/lfs_view_test.go +++ b/tests/integration/lfs_view_test.go @@ -4,18 +4,17 @@ package integration import ( - "context" "fmt" "net/http" "strings" "testing" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/lfs" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/lfs" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -158,7 +157,7 @@ func TestLFSLockView(t *testing.T) { defer tests.PrintCurrentTest(t)() // make sure the display names are different, or the test is meaningless - require.NoError(t, repo3.LoadOwner(context.Background())) + require.NoError(t, repo3.LoadOwner(t.Context())) require.NotEqual(t, user2.DisplayName(), repo3.Owner.DisplayName()) req := NewRequest(t, "GET", fmt.Sprintf("/%s/settings/lfs/locks", repo3.FullName())) diff --git a/tests/integration/linguist_test.go b/tests/integration/linguist_test.go index 73423ee6a4..85080c1d2e 100644 --- a/tests/integration/linguist_test.go +++ b/tests/integration/linguist_test.go @@ -4,21 +4,20 @@ package integration import ( - "context" "net/http" "net/url" "strings" "testing" "time" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/indexer/stats" - "code.gitea.io/gitea/modules/queue" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/indexer/stats" + "forgejo.org/modules/queue" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -82,7 +81,7 @@ func TestLinguistSupport(t *testing.T) { err := stats.UpdateRepoIndexer(repo) require.NoError(t, err) - require.NoError(t, queue.GetManager().FlushAll(context.Background(), 10*time.Second)) + require.NoError(t, queue.GetManager().FlushAll(t.Context(), 10*time.Second)) status, err := repo_model.GetIndexerStatus(db.DefaultContext, repo, repo_model.RepoIndexerTypeStats) require.NoError(t, err) diff --git a/tests/integration/links_test.go b/tests/integration/links_test.go index e9ad933b24..3d240f900a 100644 --- a/tests/integration/links_test.go +++ b/tests/integration/links_test.go @@ -9,11 +9,11 @@ import ( "path" "testing" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - forgejo_context "code.gitea.io/gitea/services/context" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + forgejo_context "forgejo.org/services/context" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/markup_external_test.go b/tests/integration/markup_external_test.go index 0eaa9669f4..e77d9682a4 100644 --- a/tests/integration/markup_external_test.go +++ b/tests/integration/markup_external_test.go @@ -10,8 +10,8 @@ import ( "strings" "testing" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/markup_test.go b/tests/integration/markup_test.go index d63190a885..ab6b437390 100644 --- a/tests/integration/markup_test.go +++ b/tests/integration/markup_test.go @@ -9,9 +9,9 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/migrate_test.go b/tests/integration/migrate_test.go index 343cf752cc..32b3ef867d 100644 --- a/tests/integration/migrate_test.go +++ b/tests/integration/migrate_test.go @@ -12,18 +12,20 @@ import ( "path/filepath" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/modules/translation" - "code.gitea.io/gitea/services/migrations" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/optional" + "forgejo.org/modules/setting" + "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/modules/translation" + "forgejo.org/services/migrations" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -112,6 +114,121 @@ func TestMigrate(t *testing.T) { }) } +func TestMigrateWithWiki(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + defer test.MockVariableValue(&setting.Migrations.AllowLocalNetworks, true)() + defer test.MockVariableValue(&setting.AppVer, "1.16.0")() + require.NoError(t, migrations.Init()) + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + repo, _, f := tests.CreateDeclarativeRepoWithOptions(t, user, tests.DeclarativeRepoOptions{ + WikiBranch: optional.Some("obscure-name"), + }) + defer f() + + session := loginUser(t, user.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeReadMisc) + + for _, s := range []struct { + svc structs.GitServiceType + }{ + {svc: structs.GiteaService}, + {svc: structs.ForgejoService}, + } { + t.Run(s.svc.Name(), func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + // Step 0: verify the repo is available + req := NewRequestf(t, "GET", "/%s", repo.FullName()) + _ = session.MakeRequest(t, req, http.StatusOK) + // Step 1: get the Gitea migration form + req = NewRequestf(t, "GET", "/repo/migrate/?service_type=%d", s.svc) + resp := session.MakeRequest(t, req, http.StatusOK) + // Step 2: load the form + htmlDoc := NewHTMLParser(t, resp.Body) + // Check form title + title := htmlDoc.doc.Find("title").Text() + assert.Contains(t, title, translation.NewLocale("en-US").TrString("new_migrate.title")) + // Step 4: submit the migration to only migrate issues + migratedRepoName := "otherrepo-" + s.svc.Name() + req = NewRequestWithValues(t, "POST", "/repo/migrate", map[string]string{ + "_csrf": GetCSRF(t, session, "/repo/migrate"), + "service": fmt.Sprintf("%d", s.svc), + "clone_addr": fmt.Sprintf("%s%s", u, repo.FullName()), + "auth_token": token, + "issues": "on", + "wiki": "on", + "repo_name": migratedRepoName, + "description": "", + "uid": fmt.Sprintf("%d", user.ID), + }) + resp = session.MakeRequest(t, req, http.StatusSeeOther) + // Step 5: a redirection displays the migrated repository + assert.EqualValues(t, fmt.Sprintf("/%s/%s", user.Name, migratedRepoName), test.RedirectURL(resp)) + // Step 6: check the repo was created and load the repo + migratedRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: migratedRepoName, WikiBranch: "obscure-name"}) + // Step 7: check if the wiki is enabled + assert.True(t, migratedRepo.UnitEnabled(db.DefaultContext, unit.TypeWiki)) + }) + } + }) +} + +func TestMigrateWithReleases(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + defer test.MockVariableValue(&setting.Migrations.AllowLocalNetworks, true)() + defer test.MockVariableValue(&setting.AppVer, "1.16.0")() + require.NoError(t, migrations.Init()) + + ownerName := "user2" + repoName := "repo1" + repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: ownerName}) + session := loginUser(t, ownerName) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeReadMisc) + + for _, s := range []struct { + svc structs.GitServiceType + }{ + {svc: structs.GiteaService}, + {svc: structs.ForgejoService}, + } { + t.Run(s.svc.Name(), func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + // Step 0: verify the repo is available + req := NewRequestf(t, "GET", "/%s/%s", ownerName, repoName) + _ = session.MakeRequest(t, req, http.StatusOK) + // Step 1: get the Gitea migration form + req = NewRequestf(t, "GET", "/repo/migrate/?service_type=%d", s.svc) + resp := session.MakeRequest(t, req, http.StatusOK) + // Step 2: load the form + htmlDoc := NewHTMLParser(t, resp.Body) + // Check form title + title := htmlDoc.doc.Find("title").Text() + assert.Contains(t, title, translation.NewLocale("en-US").TrString("new_migrate.title")) + // Step 4: submit the migration to only migrate issues + migratedRepoName := "otherrepo-" + s.svc.Name() + req = NewRequestWithValues(t, "POST", "/repo/migrate", map[string]string{ + "_csrf": GetCSRF(t, session, "/repo/migrate"), + "service": fmt.Sprintf("%d", s.svc), + "clone_addr": fmt.Sprintf("%s%s/%s", u, ownerName, repoName), + "auth_token": token, + "issues": "on", + "releases": "on", + "repo_name": migratedRepoName, + "description": "", + "uid": fmt.Sprintf("%d", repoOwner.ID), + }) + resp = session.MakeRequest(t, req, http.StatusSeeOther) + // Step 5: a redirection displays the migrated repository + assert.EqualValues(t, fmt.Sprintf("/%s/%s", ownerName, migratedRepoName), test.RedirectURL(resp)) + // Step 6: check the repo was created and load the repo + migratedRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: migratedRepoName}) + // Step 7: check if releases are enabled + assert.True(t, migratedRepo.UnitEnabled(db.DefaultContext, unit.TypeReleases)) + }) + } + }) +} + func Test_UpdateCommentsMigrationsByType(t *testing.T) { require.NoError(t, unittest.PrepareTestDatabase()) diff --git a/tests/integration/migration-test/migration_test.go b/tests/integration/migration-test/migration_test.go index a391296c35..8076dfa452 100644 --- a/tests/integration/migration-test/migration_test.go +++ b/tests/integration/migration-test/migration_test.go @@ -5,7 +5,6 @@ package migrations import ( "compress/gzip" - "context" "database/sql" "fmt" "io" @@ -17,18 +16,18 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/migrations" - migrate_base "code.gitea.io/gitea/models/migrations/base" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/base" - "code.gitea.io/gitea/modules/charset" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/testlogger" - "code.gitea.io/gitea/modules/util" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/migrations" + migrate_base "forgejo.org/models/migrations/base" + "forgejo.org/models/unittest" + "forgejo.org/modules/base" + "forgejo.org/modules/charset" + "forgejo.org/modules/git" + "forgejo.org/modules/log" + "forgejo.org/modules/setting" + "forgejo.org/modules/testlogger" + "forgejo.org/modules/util" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -87,7 +86,7 @@ func initMigrationTest(t *testing.T) func() { } } - require.NoError(t, git.InitFull(context.Background())) + require.NoError(t, git.InitFull(t.Context())) setting.LoadDBSetting() setting.InitLoggersForTest() return deferFn @@ -279,13 +278,13 @@ func doMigrationTest(t *testing.T, version string) { setting.InitSQLLoggersForCli(log.INFO) - err := db.InitEngineWithMigration(context.Background(), wrappedMigrate) + err := db.InitEngineWithMigration(t.Context(), wrappedMigrate) require.NoError(t, err) currentEngine.Close() beans, _ := db.NamesToBean() - err = db.InitEngineWithMigration(context.Background(), func(x *xorm.Engine) error { + err = db.InitEngineWithMigration(t.Context(), func(x *xorm.Engine) error { currentEngine = x return migrate_base.RecreateTables(beans...)(x) }) @@ -293,7 +292,7 @@ func doMigrationTest(t *testing.T, version string) { currentEngine.Close() // We do this a second time to ensure that there is not a problem with retained indices - err = db.InitEngineWithMigration(context.Background(), func(x *xorm.Engine) error { + err = db.InitEngineWithMigration(t.Context(), func(x *xorm.Engine) error { currentEngine = x return migrate_base.RecreateTables(beans...)(x) }) diff --git a/tests/integration/milestone_test.go b/tests/integration/milestone_test.go index 0a475e0967..bdfdd2c6d9 100644 --- a/tests/integration/milestone_test.go +++ b/tests/integration/milestone_test.go @@ -7,7 +7,7 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -21,7 +21,7 @@ func TestViewMilestones(t *testing.T) { htmlDoc := NewHTMLParser(t, resp.Body) search := htmlDoc.doc.Find(".list-header-search > .search > .input > input") placeholder, _ := search.Attr("placeholder") - assert.Equal(t, "Search milestones...", placeholder) + assert.Equal(t, "Search milestones…", placeholder) } func TestMilestonesCount(t *testing.T) { diff --git a/tests/integration/mirror_pull_test.go b/tests/integration/mirror_pull_test.go index 60fb47e94b..c9c8037e27 100644 --- a/tests/integration/mirror_pull_test.go +++ b/tests/integration/mirror_pull_test.go @@ -4,20 +4,19 @@ package integration import ( - "context" "testing" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/migration" - mirror_service "code.gitea.io/gitea/services/mirror" - release_service "code.gitea.io/gitea/services/release" - repo_service "code.gitea.io/gitea/services/repository" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/migration" + mirror_service "forgejo.org/services/mirror" + release_service "forgejo.org/services/release" + repo_service "forgejo.org/services/repository" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -50,7 +49,7 @@ func TestMirrorPull(t *testing.T) { require.NoError(t, err) assert.True(t, mirrorRepo.IsMirror, "expected pull-mirror repo to be marked as a mirror immediately after its creation") - ctx := context.Background() + ctx := t.Context() mirror, err := repo_service.MigrateRepositoryGitData(ctx, user, mirrorRepo, opts, nil) require.NoError(t, err) diff --git a/tests/integration/mirror_push_test.go b/tests/integration/mirror_push_test.go index fa62219707..ca8d536e46 100644 --- a/tests/integration/mirror_push_test.go +++ b/tests/integration/mirror_push_test.go @@ -5,7 +5,6 @@ package integration import ( - "context" "fmt" "net" "net/http" @@ -17,23 +16,23 @@ import ( "testing" "time" - asymkey_model "code.gitea.io/gitea/models/asymkey" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - "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/git" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/optional" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - gitea_context "code.gitea.io/gitea/services/context" - doctor "code.gitea.io/gitea/services/doctor" - "code.gitea.io/gitea/services/migrations" - mirror_service "code.gitea.io/gitea/services/mirror" - repo_service "code.gitea.io/gitea/services/repository" - "code.gitea.io/gitea/tests" + asymkey_model "forgejo.org/models/asymkey" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/optional" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + gitea_context "forgejo.org/services/context" + doctor "forgejo.org/services/doctor" + "forgejo.org/services/migrations" + mirror_service "forgejo.org/services/mirror" + repo_service "forgejo.org/services/repository" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -66,7 +65,7 @@ func testMirrorPush(t *testing.T, u *url.URL) { require.NoError(t, err) assert.Len(t, mirrors, 2) - ok := mirror_service.SyncPushMirror(context.Background(), mirrors[0].ID) + ok := mirror_service.SyncPushMirror(t.Context(), mirrors[0].ID) assert.True(t, ok) srcGitRepo, err := gitrepo.OpenRepository(git.DefaultContext, srcRepo) diff --git a/tests/integration/new_org_test.go b/tests/integration/new_org_test.go index ec9f2f244c..ab9ee4bc18 100644 --- a/tests/integration/new_org_test.go +++ b/tests/integration/new_org_test.go @@ -9,7 +9,7 @@ import ( "strings" "testing" - "code.gitea.io/gitea/modules/translation" + "forgejo.org/modules/translation" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/nonascii_branches_test.go b/tests/integration/nonascii_branches_test.go index 8917a9b574..2b27c8be45 100644 --- a/tests/integration/nonascii_branches_test.go +++ b/tests/integration/nonascii_branches_test.go @@ -9,7 +9,7 @@ import ( "path" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/notification_test.go b/tests/integration/notification_test.go index 6195ec2282..be1eecd1d1 100644 --- a/tests/integration/notification_test.go +++ b/tests/integration/notification_test.go @@ -7,9 +7,9 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" ) func TestNotification(t *testing.T) { diff --git a/tests/integration/oauth_test.go b/tests/integration/oauth_test.go index f385b99e46..2097afcfae 100644 --- a/tests/integration/oauth_test.go +++ b/tests/integration/oauth_test.go @@ -5,7 +5,6 @@ package integration import ( "bytes" - "context" "crypto/sha256" "encoding/base64" "fmt" @@ -16,17 +15,17 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/json" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers/web/auth" - forgejo_context "code.gitea.io/gitea/services/context" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/json" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/routers/web/auth" + forgejo_context "forgejo.org/services/context" + "forgejo.org/tests" "github.com/markbates/goth" "github.com/stretchr/testify/assert" @@ -518,7 +517,7 @@ func TestSignInOAuthCallbackSignIn(t *testing.T) { LoginSource: gitlab.ID, LoginName: userGitLabUserID, } - defer createUser(context.Background(), t, userGitLab)() + defer createUser(t.Context(), t, userGitLab)() // // A request for user information sent to Goth will return a @@ -556,7 +555,7 @@ func TestSignInOAuthCallbackWithoutPKCEWhenUnsupported(t *testing.T) { LoginSource: gitlab.ID, LoginName: userGitLabUserID, } - defer createUser(context.Background(), t, userGitLab)() + defer createUser(t.Context(), t, userGitLab)() // initial redirection (to generate the code_challenge) session := emptyTestSession(t) @@ -598,7 +597,7 @@ func TestSignInOAuthCallbackPKCE(t *testing.T) { LoginSource: authSource.ID, LoginName: userID, } - defer createUser(context.Background(), t, user)() + defer createUser(t.Context(), t, user)() // initial redirection (to generate the code_challenge) session := emptyTestSession(t) @@ -656,7 +655,7 @@ func TestSignInOAuthCallbackRedirectToEscaping(t *testing.T) { LoginSource: gitlab.ID, LoginName: userGitLabUserID, } - defer createUser(context.Background(), t, userGitLab)() + defer createUser(t.Context(), t, userGitLab)() // // A request for user information sent to Goth will return a @@ -691,6 +690,117 @@ func TestSignInOAuthCallbackRedirectToEscaping(t *testing.T) { assert.Equal(t, "/login/oauth/authorize?redirect_uri=https://translate.example.org", test.RedirectURL(resp)) } +func setupMockOIDCServer() *httptest.Server { + var mockServer *httptest.Server + mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case "/.well-known/openid-configuration": + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{ + "issuer": "` + mockServer.URL + `", + "authorization_endpoint": "` + mockServer.URL + `/authorize", + "token_endpoint": "` + mockServer.URL + `/token", + "userinfo_endpoint": "` + mockServer.URL + `/userinfo" + }`)) + default: + http.NotFound(w, r) + } + })) + return mockServer +} + +func TestSignInOauthCallbackSyncSSHKeys(t *testing.T) { + defer tests.PrepareTestEnv(t)() + mockServer := setupMockOIDCServer() + defer mockServer.Close() + + sourceName := "oidc" + authPayload := authSourcePayloadOpenIDConnect(sourceName, mockServer.URL+"/") + authPayload["oauth2_attribute_ssh_public_key"] = "sshpubkey" + authSource := addAuthSource(t, authPayload) + + userID := "5678" + user := &user_model.User{ + Name: "oidc.user", + Email: "oidc.user@example.com", + Passwd: "oidc.userpassword", + Type: user_model.UserTypeIndividual, + LoginType: auth_model.OAuth2, + LoginSource: authSource.ID, + LoginName: userID, + IsActive: true, + } + defer createUser(t.Context(), t, user)() + + for _, tt := range []struct { + name string + rawData map[string]any + parsedKeySets []string + }{ + { + name: "Add keys", + rawData: map[string]any{ + "sshpubkey": []any{ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINDRDoephkaFELacrNNe2fqAwedhRB1MKOpLEHlPuczO nocomment", + }, + }, + parsedKeySets: []string{ + "SHA256:X/mW7JUQ8J8yhrKBbZ/pJni8qx7zPA1DTFsi8ftpDwg", + }, + }, + { + name: "Update keys", + rawData: map[string]any{ + "sshpubkey": []any{ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMLLMOLFMouSJmzOASKKv178d+7op4utSxcugF9tVVch nocomment", + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGyDh9sg1IGQGa0U363wcGXrDlGBhZI3UHvS7we/0d+T nocomment", + }, + }, + parsedKeySets: []string{ + "SHA256:gsyG4JNmY5XoLBK5lSzuwD3EXcaDBiDKBkqDkpQTH6Q", + "SHA256:bbEKB1Qpumgk6QrgiN6t/kIvtUZvIQ8rqQBz8yYPzYw", + }, + }, + { + name: "Remove keys", + rawData: map[string]any{ + "sshpubkey": []any{}, + }, + parsedKeySets: []string{}, + }, + } { + t.Run(tt.name, func(t *testing.T) { + defer mockCompleteUserAuth(func(res http.ResponseWriter, req *http.Request) (goth.User, error) { + return goth.User{ + Provider: sourceName, + UserID: userID, + Email: user.Email, + RawData: tt.rawData, + }, nil + })() + + session := emptyTestSession(t) + + req := NewRequest(t, "GET", fmt.Sprintf("/user/oauth2/%s/callback?code=XYZ&state=XYZ", sourceName)) + resp := session.MakeRequest(t, req, http.StatusSeeOther) + assert.Equal(t, "/", test.RedirectURL(resp)) + + req = NewRequest(t, "GET", "/user/settings/keys") + resp = session.MakeRequest(t, req, http.StatusOK) + + htmlDoc := NewHTMLParser(t, resp.Body) + divs := htmlDoc.doc.Find("#keys-ssh .flex-item .flex-item-body:not(:last-child)") + + syncedKeys := make([]string, divs.Length()) + for i := 0; i < divs.Length(); i++ { + syncedKeys[i] = strings.TrimSpace(divs.Eq(i).Text()) + } + + assert.ElementsMatch(t, tt.parsedKeySets, syncedKeys, "Unequal number of keys") + }) + } +} + func TestSignUpViaOAuthWithMissingFields(t *testing.T) { defer tests.PrepareTestEnv(t)() // enable auto-creation of accounts via OAuth2 @@ -1321,3 +1431,94 @@ func TestOAuth_GrantScopesReadPublicGroupsWithTheReadScope(t *testing.T) { assert.Contains(t, parsedUserInfo.Groups, privOrg) } } + +func TestSignUpViaOAuthDefaultRestricted(t *testing.T) { + defer tests.PrepareTestEnv(t)() + defer test.MockVariableValue(&setting.OAuth2Client.EnableAutoRegistration, true)() + defer test.MockVariableValue(&setting.Service.DefaultUserIsRestricted, true)() + + gitlabName := "gitlab" + addAuthSource(t, authSourcePayloadGitLabCustom(gitlabName)) + userGitLabUserID := "BB(5)=47176870" + + defer mockCompleteUserAuth(func(res http.ResponseWriter, req *http.Request) (goth.User, error) { + return goth.User{ + Provider: gitlabName, + UserID: userGitLabUserID, + Name: "gitlab-user", + NickName: "gitlab-user", + Email: "gitlab@example.com", + }, nil + })() + req := NewRequest(t, "GET", fmt.Sprintf("/user/oauth2/%s/callback?code=XYZ&state=XYZ", gitlabName)) + resp := MakeRequest(t, req, http.StatusSeeOther) + assert.Equal(t, "/", test.RedirectURL(resp)) + + unittest.AssertExistsIf(t, true, &user_model.User{Name: "gitlab-user"}, "is_restricted = true") +} + +func TestSignUpViaOAuthLinking2FA(t *testing.T) { + defer tests.PrepareTestEnv(t)() + defer test.MockVariableValue(&setting.OAuth2Client.EnableAutoRegistration, true)() + defer test.MockVariableValue(&setting.OAuth2Client.AccountLinking, setting.OAuth2AccountLinkingAuto)() + + // Fake that user 2 is enrolled into WebAuthn. + t.Cleanup(func() { + unittest.AssertSuccessfulDelete(t, &auth_model.WebAuthnCredential{UserID: 2}) + }) + unittest.AssertSuccessfulInsert(t, &auth_model.WebAuthnCredential{UserID: 2}) + + gitlabName := "gitlab" + addAuthSource(t, authSourcePayloadGitLabCustom(gitlabName)) + userGitLabUserID := "BB(4)=107" + + defer mockCompleteUserAuth(func(res http.ResponseWriter, req *http.Request) (goth.User, error) { + return goth.User{ + Provider: gitlabName, + UserID: userGitLabUserID, + NickName: "user2", + Email: "user2@example.com", + }, nil + })() + req := NewRequest(t, "GET", fmt.Sprintf("/user/oauth2/%s/callback?code=XYZ&state=XYZ", gitlabName)) + resp := MakeRequest(t, req, http.StatusSeeOther) + + // Make sure the user has to go through 2FA after linking. + assert.Equal(t, "/user/webauthn", test.RedirectURL(resp)) +} + +func TestSignUpViaOAuth2FA(t *testing.T) { + defer tests.PrepareTestEnv(t)() + defer test.MockVariableValue(&setting.OAuth2Client.EnableAutoRegistration, true)() + defer test.MockVariableValue(&setting.OAuth2Client.AccountLinking, setting.OAuth2AccountLinkingAuto)() + + gitlabName := "gitlab" + addAuthSource(t, authSourcePayloadGitLabCustom(gitlabName)) + userGitLabUserID := "BB(3)=21" + + defer mockCompleteUserAuth(func(res http.ResponseWriter, req *http.Request) (goth.User, error) { + return goth.User{ + Provider: gitlabName, + UserID: userGitLabUserID, + NickName: "user2", + Email: "user2@example.com", + }, nil + })() + req := NewRequest(t, "GET", fmt.Sprintf("/user/oauth2/%s/callback?code=XYZ&state=XYZ", gitlabName)) + resp := MakeRequest(t, req, http.StatusSeeOther) + + // Make sure the user can login normally and is linked. + assert.Equal(t, "/", test.RedirectURL(resp)) + + // Fake that user 2 is enrolled into WebAuthn. + t.Cleanup(func() { + unittest.AssertSuccessfulDelete(t, &auth_model.WebAuthnCredential{UserID: 2}) + }) + unittest.AssertSuccessfulInsert(t, &auth_model.WebAuthnCredential{UserID: 2}) + + req = NewRequest(t, "GET", fmt.Sprintf("/user/oauth2/%s/callback?code=XYZ&state=XYZ", gitlabName)) + resp = MakeRequest(t, req, http.StatusSeeOther) + + // Make sure user has to go through 2FA. + assert.Equal(t, "/user/webauthn", test.RedirectURL(resp)) +} diff --git a/tests/integration/opengraph_test.go b/tests/integration/opengraph_test.go index d54f59c9b8..38998d0c76 100644 --- a/tests/integration/opengraph_test.go +++ b/tests/integration/opengraph_test.go @@ -8,8 +8,8 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" diff --git a/tests/integration/org_count_test.go b/tests/integration/org_count_test.go index e3de9257f0..93035c8e5b 100644 --- a/tests/integration/org_count_test.go +++ b/tests/integration/org_count_test.go @@ -8,12 +8,12 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/organization" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/organization" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/org_nav_test.go b/tests/integration/org_nav_test.go index 37b62921ae..09736d12a0 100644 --- a/tests/integration/org_nav_test.go +++ b/tests/integration/org_nav_test.go @@ -8,8 +8,8 @@ import ( "strings" "testing" - "code.gitea.io/gitea/modules/translation" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/translation" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/org_project_test.go b/tests/integration/org_project_test.go index 31d10f16ff..3ab2379b5e 100644 --- a/tests/integration/org_project_test.go +++ b/tests/integration/org_project_test.go @@ -8,8 +8,8 @@ import ( "slices" "testing" - unit_model "code.gitea.io/gitea/models/unit" - "code.gitea.io/gitea/tests" + unit_model "forgejo.org/models/unit" + "forgejo.org/tests" ) func TestOrgProjectAccess(t *testing.T) { diff --git a/tests/integration/org_settings_test.go b/tests/integration/org_settings_test.go index 56b7b02271..fde57e2e26 100644 --- a/tests/integration/org_settings_test.go +++ b/tests/integration/org_settings_test.go @@ -8,9 +8,9 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/org_team_invite_test.go b/tests/integration/org_team_invite_test.go index 2fe296e8c3..3ca236a5dd 100644 --- a/tests/integration/org_team_invite_test.go +++ b/tests/integration/org_team_invite_test.go @@ -10,14 +10,14 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/organization" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/organization" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/org_test.go b/tests/integration/org_test.go index 74579d7d51..bc1a5bbe72 100644 --- a/tests/integration/org_test.go +++ b/tests/integration/org_test.go @@ -9,14 +9,16 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/organization" - "code.gitea.io/gitea/models/perm" - "code.gitea.io/gitea/models/unit" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/organization" + "forgejo.org/models/perm" + "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -266,3 +268,32 @@ func TestOwnerTeamUnit(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{TeamID: 1, Type: unit.TypeIssues, AccessMode: perm.AccessModeOwner}) } + +func TestOrgNewMigrationButton(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + migrateSelector := `a[href^="/repo/migrate?org="]` + + session := loginUser(t, "user2") + t.Run("Migration disabled", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + defer test.MockVariableValue(&setting.Repository.DisableMigrations, true)() + + req := NewRequest(t, "GET", "/org3") + resp := session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + + htmlDoc.AssertElement(t, migrateSelector, false) + }) + + t.Run("Migration enabled", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + defer test.MockVariableValue(&setting.Repository.DisableMigrations, false)() + + req := NewRequest(t, "GET", "/org3") + resp := session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + + htmlDoc.AssertElement(t, migrateSelector, true) + }) +} diff --git a/tests/integration/private_project_test.go b/tests/integration/private_project_test.go new file mode 100644 index 0000000000..ea6788cb64 --- /dev/null +++ b/tests/integration/private_project_test.go @@ -0,0 +1,91 @@ +// 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 "forgejo.org/models/organization" + project_model "forgejo.org/models/project" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" +) + +func TestPrivateIssueProject(t *testing.T) { + defer unittest.OverrideFixtures("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, publicIssueHref ...string) { + 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, "2\u00a0Open") + } else { + assert.Contains(t, openCloseStats, "1\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) + issueCardsLen := htmlDoc.Find(".project-column .issue-card").Length() + if hasAccess { + assert.EqualValues(t, 2, issueCardsLen) + } else { + assert.EqualValues(t, 1, issueCardsLen) + // Ensure that the public issue is shown. + assert.EqualValues(t, publicIssueHref[0], htmlDoc.Find(".project-column .issue-card .issue-card-title").AttrOr("href", "")) + } + + // And that the issue count is correct. + issueCount := strings.TrimSpace(htmlDoc.Find(".project-column-issue-count").Text()) + if hasAccess { + assert.EqualValues(t, "2", issueCount) + } else { + assert.EqualValues(t, "1", 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, "/org3/repo21/issues/1") + }) + }) + + 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, "/user2/repo1/issues/1") + }) + }) +} diff --git a/tests/integration/privateactivity_test.go b/tests/integration/privateactivity_test.go index 5362462f7d..84f09c64e1 100644 --- a/tests/integration/privateactivity_test.go +++ b/tests/integration/privateactivity_test.go @@ -8,13 +8,13 @@ import ( "net/http" "testing" - activities_model "code.gitea.io/gitea/models/activities" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + activities_model "forgejo.org/models/activities" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/proctected_branch_test.go b/tests/integration/proctected_branch_test.go index 9c6e5e3cae..5024b63c42 100644 --- a/tests/integration/proctected_branch_test.go +++ b/tests/integration/proctected_branch_test.go @@ -10,10 +10,10 @@ import ( "strings" "testing" - git_model "code.gitea.io/gitea/models/git" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/tests" + git_model "forgejo.org/models/git" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/project_test.go b/tests/integration/project_test.go index fc2986e1eb..7dc8bf112d 100644 --- a/tests/integration/project_test.go +++ b/tests/integration/project_test.go @@ -8,11 +8,11 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/models/db" - project_model "code.gitea.io/gitea/models/project" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + project_model "forgejo.org/models/project" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/pull_commit_test.go b/tests/integration/pull_commit_test.go index 5ef6d6ceca..90d16d725d 100644 --- a/tests/integration/pull_commit_test.go +++ b/tests/integration/pull_commit_test.go @@ -7,8 +7,8 @@ import ( "net/http" "testing" - pull_service "code.gitea.io/gitea/services/pull" - "code.gitea.io/gitea/tests" + pull_service "forgejo.org/services/pull" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/pull_compare_test.go b/tests/integration/pull_compare_test.go index f5baf05965..adb24c60f6 100644 --- a/tests/integration/pull_compare_test.go +++ b/tests/integration/pull_compare_test.go @@ -7,7 +7,7 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/pull_create_test.go b/tests/integration/pull_create_test.go index 7ccbce2eae..42155076a8 100644 --- a/tests/integration/pull_create_test.go +++ b/tests/integration/pull_create_test.go @@ -14,17 +14,17 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - 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/git" - "code.gitea.io/gitea/modules/graceful" - "code.gitea.io/gitea/modules/test" - repo_service "code.gitea.io/gitea/services/repository" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/graceful" + "forgejo.org/modules/test" + repo_service "forgejo.org/services/repository" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/pull_diff_test.go b/tests/integration/pull_diff_test.go index 5411250935..70e0d5d33a 100644 --- a/tests/integration/pull_diff_test.go +++ b/tests/integration/pull_diff_test.go @@ -7,7 +7,7 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" diff --git a/tests/integration/pull_editable_test.go b/tests/integration/pull_editable_test.go new file mode 100644 index 0000000000..f2e6f2f52c --- /dev/null +++ b/tests/integration/pull_editable_test.go @@ -0,0 +1,54 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package integration + +import ( + "net/http" + "net/url" + "testing" + + auth_model "forgejo.org/models/auth" + api "forgejo.org/modules/structs" + "forgejo.org/tests" +) + +func TestPullEditable_ShowEditableLabel(t *testing.T) { + onGiteaRun(t, func(t *testing.T, forgejoURL *url.URL) { + t.Run("Show editable label if PR is editable", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + editable := true + + setPREditable(t, editable) + testEditableLabelShown(t, editable) + }) + + t.Run("Don't show editable label if PR is not editable", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + editable := false + + setPREditable(t, editable) + testEditableLabelShown(t, editable) + }) + }) +} + +func setPREditable(t *testing.T, editable bool) { + t.Helper() + session := loginUser(t, "user1") + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) + + req := NewRequestWithJSON(t, "PATCH", "/api/v1/repos/user2/repo1/pulls/3", &api.EditPullRequestOption{ + AllowMaintainerEdit: &editable, + }).AddTokenAuth(token) + session.MakeRequest(t, req, http.StatusCreated) +} + +func testEditableLabelShown(t *testing.T, expectLabel bool) { + t.Helper() + session := loginUser(t, "user2") + req := NewRequest(t, "GET", "/user2/repo1/pulls/3") + resp := session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + htmlDoc.AssertElement(t, "#editable-label", expectLabel) +} diff --git a/tests/integration/pull_icon_test.go b/tests/integration/pull_icon_test.go index 8fde547ce9..9ab8f244cf 100644 --- a/tests/integration/pull_icon_test.go +++ b/tests/integration/pull_icon_test.go @@ -12,17 +12,17 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - 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/git" - issue_service "code.gitea.io/gitea/services/issue" - pull_service "code.gitea.io/gitea/services/pull" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + issue_service "forgejo.org/services/issue" + pull_service "forgejo.org/services/pull" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" @@ -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, "open") + pull := createPullRequest(t, user, repo, "branch-open", "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, "open-wip") + pull := createPullRequest(t, user, repo, "branch-open-wip", "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, "closed") + pull := createPullRequest(t, user, repo, "branch-closed", "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, "closed-wip") + pull := createPullRequest(t, user, repo, "branch-closed-wip", "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, "merged") + pull := createPullRequest(t, user, repo, "branch-merged", "merged") gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) defer gitRepo.Close() @@ -202,10 +202,7 @@ 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, name string) *issues_model.PullRequest { - branch := "branch-" + name - title := "Testing " + name - +func createPullRequest(t *testing.T, user *user_model.User, repo *repo_model.Repository, branch, title string) *issues_model.PullRequest { _, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, user, &files_service.ChangeRepoFilesOptions{ Files: []*files_service.ChangeRepoFile{ { diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go index a0ba99f3b9..f60fc27bb3 100644 --- a/tests/integration/pull_merge_test.go +++ b/tests/integration/pull_merge_test.go @@ -5,7 +5,6 @@ package integration import ( "bytes" - "context" "fmt" "net/http" "net/http/httptest" @@ -18,32 +17,32 @@ import ( "testing" "time" - "code.gitea.io/gitea/models" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - git_model "code.gitea.io/gitea/models/git" - issues_model "code.gitea.io/gitea/models/issues" - pull_model "code.gitea.io/gitea/models/pull" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/models/webhook" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/hostmatcher" - "code.gitea.io/gitea/modules/queue" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/modules/translation" - "code.gitea.io/gitea/services/automerge" - forgejo_context "code.gitea.io/gitea/services/context" - "code.gitea.io/gitea/services/forms" - "code.gitea.io/gitea/services/pull" - commitstatus_service "code.gitea.io/gitea/services/repository/commitstatus" - files_service "code.gitea.io/gitea/services/repository/files" - webhook_service "code.gitea.io/gitea/services/webhook" - "code.gitea.io/gitea/tests" + "forgejo.org/models" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + git_model "forgejo.org/models/git" + issues_model "forgejo.org/models/issues" + pull_model "forgejo.org/models/pull" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/models/webhook" + "forgejo.org/modules/git" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/hostmatcher" + "forgejo.org/modules/queue" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/modules/translation" + "forgejo.org/services/automerge" + forgejo_context "forgejo.org/services/context" + "forgejo.org/services/forms" + "forgejo.org/services/pull" + commitstatus_service "forgejo.org/services/repository/commitstatus" + files_service "forgejo.org/services/repository/files" + webhook_service "forgejo.org/services/webhook" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -303,11 +302,11 @@ func TestCantMergeConflict(t *testing.T) { gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo1) require.NoError(t, err) - err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "CONFLICT", false) + err = pull.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "CONFLICT", false) require.Error(t, err, "Merge should return an error due to conflict") assert.True(t, models.IsErrMergeConflicts(err), "Merge error is not a conflict error") - err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleRebase, "", "CONFLICT", false) + err = pull.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleRebase, "", "CONFLICT", false) require.Error(t, err, "Merge should return an error due to conflict") assert.True(t, models.IsErrRebaseConflicts(err), "Merge error is not a conflict error") gitRepo.Close() @@ -402,7 +401,7 @@ func TestCantMergeUnrelated(t *testing.T) { BaseBranch: "base", }) - err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "UNRELATED", false) + err = pull.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "UNRELATED", false) require.Error(t, err, "Merge should return an error due to unrelated") assert.True(t, models.IsErrMergeUnrelatedHistories(err), "Merge error is not a unrelated histories error") gitRepo.Close() @@ -442,7 +441,7 @@ func TestFastForwardOnlyMerge(t *testing.T) { gitRepo, err := git.OpenRepository(git.DefaultContext, repo_model.RepoPath(user1.Name, repo1.Name)) require.NoError(t, err) - err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleFastForwardOnly, "", "FAST-FORWARD-ONLY", false) + err = pull.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleFastForwardOnly, "", "FAST-FORWARD-ONLY", false) require.NoError(t, err) @@ -484,7 +483,7 @@ func TestCantFastForwardOnlyMergeDiverging(t *testing.T) { gitRepo, err := git.OpenRepository(git.DefaultContext, repo_model.RepoPath(user1.Name, repo1.Name)) require.NoError(t, err) - err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleFastForwardOnly, "", "DIVERGING", false) + err = pull.Merge(t.Context(), pr, user1, gitRepo, repo_model.MergeStyleFastForwardOnly, "", "DIVERGING", false) require.Error(t, err, "Merge should return an error due to being for a diverging branch") assert.True(t, models.IsErrMergeDivergingFastForwardOnly(err), "Merge error is not a diverging fast-forward-only error") @@ -633,7 +632,7 @@ func TestPullMergeIndexerNotifier(t *testing.T) { testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n") createPullResp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "Indexer notifier test pull") - require.NoError(t, queue.GetManager().FlushAll(context.Background(), 0)) + require.NoError(t, queue.GetManager().FlushAll(t.Context(), 0)) time.Sleep(time.Second) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ @@ -672,7 +671,7 @@ func TestPullMergeIndexerNotifier(t *testing.T) { }) assert.True(t, issue.IsClosed) - require.NoError(t, queue.GetManager().FlushAll(context.Background(), 0)) + require.NoError(t, queue.GetManager().FlushAll(t.Context(), 0)) time.Sleep(time.Second) // search issues again @@ -692,7 +691,7 @@ func testResetRepo(t *testing.T, repoPath, branch, commitID string) { require.NoError(t, err) f.Close() - repo, err := git.OpenRepository(context.Background(), repoPath) + repo, err := git.OpenRepository(t.Context(), repoPath) require.NoError(t, err) defer repo.Close() id, err := repo.GetBranchCommitID(branch) diff --git a/tests/integration/pull_reopen_test.go b/tests/integration/pull_reopen_test.go index e510d59626..cf95f6b730 100644 --- a/tests/integration/pull_reopen_test.go +++ b/tests/integration/pull_reopen_test.go @@ -12,20 +12,20 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" - git_model "code.gitea.io/gitea/models/git" - issues_model "code.gitea.io/gitea/models/issues" - 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/git" - "code.gitea.io/gitea/modules/translation" - gitea_context "code.gitea.io/gitea/services/context" - issue_service "code.gitea.io/gitea/services/issue" - pull_service "code.gitea.io/gitea/services/pull" - repo_service "code.gitea.io/gitea/services/repository" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + git_model "forgejo.org/models/git" + issues_model "forgejo.org/models/issues" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/translation" + gitea_context "forgejo.org/services/context" + issue_service "forgejo.org/services/issue" + pull_service "forgejo.org/services/pull" + repo_service "forgejo.org/services/repository" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/pull_request_task_test.go b/tests/integration/pull_request_task_test.go index 4366d97c39..777aac08a5 100644 --- a/tests/integration/pull_request_task_test.go +++ b/tests/integration/pull_request_task_test.go @@ -4,23 +4,22 @@ package integration import ( - "context" "testing" "time" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/log" - repo_module "code.gitea.io/gitea/modules/repository" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/modules/timeutil" - pull_service "code.gitea.io/gitea/services/pull" - repo_service "code.gitea.io/gitea/services/repository" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/log" + repo_module "forgejo.org/modules/repository" + "forgejo.org/modules/test" + "forgejo.org/modules/timeutil" + pull_service "forgejo.org/services/pull" + repo_service "forgejo.org/services/repository" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -100,7 +99,7 @@ func TestPullRequestSynchronized(t *testing.T) { logChecker.Filter("Updating PR").StopMark("TestPullRequest ") defer cleanup() - pull_service.TestPullRequest(context.Background(), owner, repo.ID, testCase.olderThan, "branch2", true, pull.HeadCommitID, pull.HeadCommitID) + pull_service.TestPullRequest(t.Context(), owner, repo.ID, testCase.olderThan, "branch2", true, pull.HeadCommitID, pull.HeadCommitID) logFiltered, logStopped := logChecker.Check(5 * time.Second) assert.True(t, logStopped) assert.Equal(t, testCase.expected, logFiltered[0]) diff --git a/tests/integration/pull_review_test.go b/tests/integration/pull_review_test.go index 1319db29bf..4be493b196 100644 --- a/tests/integration/pull_review_test.go +++ b/tests/integration/pull_review_test.go @@ -1,10 +1,10 @@ // Copyright 2019 The Gitea Authors. All rights reserved. +// Copyright 2024 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT package integration import ( - "context" "fmt" "net/http" "net/http/httptest" @@ -14,18 +14,19 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/gitrepo" - repo_module "code.gitea.io/gitea/modules/repository" - "code.gitea.io/gitea/modules/test" - issue_service "code.gitea.io/gitea/services/issue" - repo_service "code.gitea.io/gitea/services/repository" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/gitrepo" + repo_module "forgejo.org/modules/repository" + "forgejo.org/modules/test" + issue_service "forgejo.org/services/issue" + "forgejo.org/services/mailer" + repo_service "forgejo.org/services/repository" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" @@ -178,7 +179,7 @@ func TestPullView_ResolveInvalidatedReviewComment(t *testing.T) { // (to invalidate it properly, one should push a commit which should trigger this logic, // in the meantime, use this quick-and-dirty trick) comment := loadComment(t, commentID) - require.NoError(t, issues_model.UpdateCommentInvalidate(context.Background(), &issues_model.Comment{ + require.NoError(t, issues_model.UpdateCommentInvalidate(t.Context(), &issues_model.Comment{ ID: comment.ID, Invalidated: true, })) @@ -240,7 +241,7 @@ func TestPullView_ResolveInvalidatedReviewComment(t *testing.T) { // (to invalidate it properly, one should push a commit which should trigger this logic, // in the meantime, use this quick-and-dirty trick) comment := loadComment(t, commentID) - require.NoError(t, issues_model.UpdateCommentInvalidate(context.Background(), &issues_model.Comment{ + require.NoError(t, issues_model.UpdateCommentInvalidate(t.Context(), &issues_model.Comment{ ID: comment.ID, Invalidated: true, })) @@ -362,6 +363,8 @@ func TestPullView_CodeOwner(t *testing.T) { defer f() t.Run("First Pull Request", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + // create a new branch to prepare for pull request _, err := files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{ NewBranch: "codeowner-basebranch", @@ -409,6 +412,8 @@ func TestPullView_CodeOwner(t *testing.T) { require.NoError(t, err) t.Run("Second Pull Request", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + // create a new branch to prepare for pull request _, err = files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{ NewBranch: "codeowner-basebranch2", @@ -431,6 +436,8 @@ func TestPullView_CodeOwner(t *testing.T) { }) t.Run("Forked Repo Pull Request", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}) forkedRepo, err := repo_service.ForkRepositoryAndUpdates(db.DefaultContext, user2, user5, repo_service.ForkRepoOptions{ BaseRepo: repo, @@ -483,6 +490,8 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) { defer baseGitRepo.Close() t.Run("Submit approve/reject review on merged PR", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + // Create a merged PR (made by user1) in the upstream repo1. testEditFile(t, user1Session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n") resp := testPullCreate(t, user1Session, "user1", "repo1", false, "master", "master", "This is a pull title") @@ -513,12 +522,14 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) { }) t.Run("Submit approve/reject review on closed PR", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + // Created a closed PR (made by user1) in the upstream repo1. testEditFileToNewBranch(t, user1Session, "user1", "repo1", "master", "a-test-branch", "README.md", "Hello, World (Edited...again)\n") 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]) + testIssueClose(t, user1Session, elem[1], elem[2], elem[4], true) // Get the commit SHA pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ @@ -544,6 +555,41 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) { }) } +func TestPullReviewInArchivedRepo(t *testing.T) { + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + session := loginUser(t, "user2") + + // Open a PR + testEditFileToNewBranch(t, session, "user2", "repo1", "master", "for-pr", "README.md", "Hi!\n") + resp := testPullCreate(t, session, "user2", "repo1", true, "master", "for-pr", "PR title") + elem := strings.Split(test.RedirectURL(resp), "/") + + t.Run("Review box normally", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + // The "Finish review button" must be available + resp = session.MakeRequest(t, NewRequest(t, "GET", path.Join(elem[1], elem[2], "pulls", elem[4], "files")), http.StatusOK) + button := NewHTMLParser(t, resp.Body).Find("#review-box button") + assert.False(t, button.HasClass("disabled")) + }) + + t.Run("Review box in archived repo", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + // Archive the repo + resp = session.MakeRequest(t, NewRequestWithValues(t, "POST", path.Join(elem[1], elem[2], "settings"), map[string]string{ + "_csrf": GetCSRF(t, session, path.Join(elem[1], elem[2], "settings")), + "action": "archive", + }), http.StatusSeeOther) + + // The "Finish review button" must be disabled + resp = session.MakeRequest(t, NewRequest(t, "GET", path.Join(elem[1], elem[2], "pulls", elem[4], "files")), http.StatusOK) + button := NewHTMLParser(t, resp.Body).Find("#review-box button") + assert.True(t, button.HasClass("disabled")) + }) + }) +} + func testNofiticationCount(t *testing.T, session *TestSession, csrf string, expectedSubmitStatus int) *httptest.ResponseRecorder { options := map[string]string{ "_csrf": csrf, @@ -579,8 +625,12 @@ 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) *httptest.ResponseRecorder { - req := NewRequest(t, "GET", path.Join(owner, repo, "pulls", issueNumber)) +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)) resp := session.MakeRequest(t, req, http.StatusOK) htmlDoc := NewHTMLParser(t, resp.Body) @@ -600,3 +650,115 @@ func getUserNotificationCount(t *testing.T, session *TestSession, csrf string) s doc := NewHTMLParser(t, resp.Body) return doc.Find(`.notification_count`).Text() } + +func TestPullRequestReplyMail(t *testing.T) { + defer unittest.OverrideFixtures("tests/integration/fixtures/TestPullRequestReplyMail")() + defer tests.PrepareTestEnv(t)() + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user.Name) + + t.Run("Reply to pending review comment", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + called := false + defer test.MockVariableValue(&mailer.SendAsync, func(...*mailer.Message) { + called = true + })() + + review := unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 1002}, "type = 0") + + req := NewRequestWithValues(t, "POST", "/user2/repo1/pulls/2/files/reviews/comments", map[string]string{ + "_csrf": GetCSRF(t, session, "/user2/repo1/pulls/2"), + "origin": "diff", + "content": "Just a comment!", + "side": "proposed", + "line": "4", + "path": "README.md", + "reply": strconv.FormatInt(review.ID, 10), + }) + session.MakeRequest(t, req, http.StatusOK) + + assert.False(t, called) + unittest.AssertExistsIf(t, true, &issues_model.Comment{Content: "Just a comment!", ReviewID: review.ID, IssueID: 2}) + }) + + t.Run("Start a review", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + called := false + defer test.MockVariableValue(&mailer.SendAsync, func(msgs ...*mailer.Message) { + called = true + })() + + req := NewRequestWithValues(t, "POST", "/user2/repo1/pulls/2/files/reviews/comments", map[string]string{ + "_csrf": GetCSRF(t, session, "/user2/repo1/pulls/2"), + "origin": "diff", + "content": "Notification time 2!", + "side": "proposed", + "line": "2", + "path": "README.md", + }) + session.MakeRequest(t, req, http.StatusOK) + + assert.False(t, called) + unittest.AssertExistsIf(t, true, &issues_model.Comment{Content: "Notification time 2!", IssueID: 2}) + }) + + t.Run("Create a single comment", func(t *testing.T) { + t.Run("As a reply", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + called := false + defer test.MockVariableValue(&mailer.SendAsync, func(msgs ...*mailer.Message) { + assert.Len(t, msgs, 2) + assert.Equal(t, "user1@example.com", msgs[0].To) + assert.EqualValues(t, "Re: [user2/repo1] issue2 (PR #2)", msgs[0].Subject) + assert.Contains(t, msgs[0].Body, "Notification time!") + called = true + })() + + review := unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 1001, Type: issues_model.ReviewTypeComment}) + + req := NewRequestWithValues(t, "POST", "/user2/repo1/pulls/2/files/reviews/comments", map[string]string{ + "_csrf": GetCSRF(t, session, "/user2/repo1/pulls/2"), + "origin": "diff", + "content": "Notification time!", + "side": "proposed", + "line": "3", + "path": "README.md", + "reply": strconv.FormatInt(review.ID, 10), + }) + session.MakeRequest(t, req, http.StatusOK) + + assert.True(t, called) + unittest.AssertExistsIf(t, true, &issues_model.Comment{Content: "Notification time!", ReviewID: review.ID, IssueID: 2}) + }) + t.Run("On a new line", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + called := false + defer test.MockVariableValue(&mailer.SendAsync, func(msgs ...*mailer.Message) { + assert.Len(t, msgs, 2) + assert.Equal(t, "user1@example.com", msgs[0].To) + assert.EqualValues(t, "Re: [user2/repo1] issue2 (PR #2)", msgs[0].Subject) + assert.Contains(t, msgs[0].Body, "Notification time 2!") + called = true + })() + + req := NewRequestWithValues(t, "POST", "/user2/repo1/pulls/2/files/reviews/comments", map[string]string{ + "_csrf": GetCSRF(t, session, "/user2/repo1/pulls/2"), + "origin": "diff", + "content": "Notification time 2!", + "side": "proposed", + "line": "5", + "path": "README.md", + "single_review": "true", + }) + session.MakeRequest(t, req, http.StatusOK) + + assert.True(t, called) + unittest.AssertExistsIf(t, true, &issues_model.Comment{Content: "Notification time 2!", IssueID: 2}) + }) + }) +} diff --git a/tests/integration/pull_status_test.go b/tests/integration/pull_status_test.go index 80eea34513..1fdc871bb3 100644 --- a/tests/integration/pull_status_test.go +++ b/tests/integration/pull_status_test.go @@ -11,11 +11,11 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - git_model "code.gitea.io/gitea/models/git" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - api "code.gitea.io/gitea/modules/structs" + auth_model "forgejo.org/models/auth" + git_model "forgejo.org/models/git" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + api "forgejo.org/modules/structs" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/pull_test.go b/tests/integration/pull_test.go index 8f951f05ab..d5321f6ae5 100644 --- a/tests/integration/pull_test.go +++ b/tests/integration/pull_test.go @@ -7,12 +7,12 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unit" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -27,7 +27,7 @@ func TestViewPulls(t *testing.T) { htmlDoc := NewHTMLParser(t, resp.Body) search := htmlDoc.doc.Find(".list-header-search > .search > .input > input") placeholder, _ := search.Attr("placeholder") - assert.Equal(t, "Search pulls...", placeholder) + assert.Equal(t, "Search pulls…", placeholder) } func TestPullManuallyMergeWarning(t *testing.T) { @@ -67,7 +67,7 @@ func TestPullManuallyMergeWarning(t *testing.T) { } func TestPullCombinedReviewRequest(t *testing.T) { - defer tests.AddFixtures("tests/integration/fixtures/TestPullCombinedReviewRequest/")() + defer unittest.OverrideFixtures("tests/integration/fixtures/TestPullCombinedReviewRequest")() defer tests.PrepareTestEnv(t)() session := loginUser(t, "user2") diff --git a/tests/integration/pull_update_test.go b/tests/integration/pull_update_test.go index f36ea88c2b..e1fec8c77e 100644 --- a/tests/integration/pull_update_test.go +++ b/tests/integration/pull_update_test.go @@ -11,19 +11,19 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - pull_service "code.gitea.io/gitea/services/pull" - repo_service "code.gitea.io/gitea/services/repository" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + pull_service "forgejo.org/services/pull" + repo_service "forgejo.org/services/repository" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -273,3 +273,19 @@ func createOutdatedPR(t *testing.T, actor, forkOrg *user_model.User) *issues_mod return issue.PullRequest } + +func TestStatusDuringUpdate(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + session := loginUser(t, "user2") + + // Adjust this pull request to be in the conflict checker and having a head + // branch that is pointing to the an incorrect commit ID. + _, err := db.GetEngine(t.Context()).Cols("status", "head_branch").Update(&issues_model.PullRequest{ID: 5, Status: issues_model.PullRequestStatusChecking, HeadBranch: "master"}) + require.NoError(t, err) + + resp := session.MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/pulls/5"), http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + + assert.Contains(t, htmlDoc.Find(".merge-section .item").Text(), "Merge conflict checking is in progress. Try again in few moments.") + }) +} diff --git a/tests/integration/quota_use_test.go b/tests/integration/quota_use_test.go index 39c5c1ae5c..314dcff6e9 100644 --- a/tests/integration/quota_use_test.go +++ b/tests/integration/quota_use_test.go @@ -14,20 +14,20 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - org_model "code.gitea.io/gitea/models/organization" - quota_model "code.gitea.io/gitea/models/quota" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - forgejo_context "code.gitea.io/gitea/services/context" - repo_service "code.gitea.io/gitea/services/repository" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + org_model "forgejo.org/models/organization" + quota_model "forgejo.org/models/quota" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/routers" + forgejo_context "forgejo.org/services/context" + repo_service "forgejo.org/services/repository" + "forgejo.org/tests" gouuid "github.com/google/uuid" "github.com/stretchr/testify/assert" diff --git a/tests/integration/release_feed_test.go b/tests/integration/release_feed_test.go new file mode 100644 index 0000000000..0ab299f617 --- /dev/null +++ b/tests/integration/release_feed_test.go @@ -0,0 +1,91 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package integration + +import ( + "net/http" + "regexp" + "testing" + + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" +) + +func TestReleaseFeed(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + normalize := func(body string) string { + // Remove port. + body = regexp.MustCompile(`localhost:\d+`).ReplaceAllString(body, "localhost") + // date is timezone dependent. + body = regexp.MustCompile(`.*`).ReplaceAllString(body, "") + body = regexp.MustCompile(`.*`).ReplaceAllString(body, "") + return body + } + t.Run("RSS feed", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + resp := MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/releases.rss"), http.StatusOK) + assert.EqualValues(t, ` + + Releases for user2/repo1 + http://localhost/user2/repo1/release + + + + pre-release + http://localhost/user2/repo1/releases/tag/v1.0 + + some text for a pre release

+]]>
+ user2 + 5: http://localhost/user2/repo1/releases/tag/v1.0 + +
+ + testing-release + http://localhost/user2/repo1/releases/tag/v1.1 + + user2 + 1: http://localhost/user2/repo1/releases/tag/v1.1 + + +
+
`, normalize(resp.Body.String())) + }) + + t.Run("Atom feed", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + resp := MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/releases.atom"), http.StatusOK) + assert.EqualValues(t, ` + Releases for user2/repo1 + http://localhost/user2/repo1/release + + + + pre-release + + 5: http://localhost/user2/repo1/releases/tag/v1.0 + <p dir="auto">some text for a pre release</p> + + + user2 + user2@noreply.example.org + + + + testing-release + + 1: http://localhost/user2/repo1/releases/tag/v1.1 + + + user2 + user2@noreply.example.org + + +`, normalize(resp.Body.String())) + }) +} diff --git a/tests/integration/release_test.go b/tests/integration/release_test.go index c535c6c93d..b1162780ab 100644 --- a/tests/integration/release_test.go +++ b/tests/integration/release_test.go @@ -11,15 +11,15 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/modules/translation" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/modules/translation" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" diff --git a/tests/integration/remote_test.go b/tests/integration/remote_test.go index c59b4c7d32..506ee8ecaa 100644 --- a/tests/integration/remote_test.go +++ b/tests/integration/remote_test.go @@ -4,17 +4,16 @@ package integration import ( - "context" "fmt" "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/test" - remote_service "code.gitea.io/gitea/services/remote" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/test" + remote_service "forgejo.org/services/remote" + "forgejo.org/tests" "github.com/markbates/goth" "github.com/stretchr/testify/assert" @@ -48,7 +47,7 @@ func TestRemote_MaybePromoteUserSuccess(t *testing.T) { LoginSource: remote.ID, LoginName: gitlabUserID, } - defer createUser(context.Background(), t, userBeforeSignIn)() + defer createUser(t.Context(), t, userBeforeSignIn)() // // A request for user information sent to Goth will return a @@ -81,7 +80,7 @@ func TestRemote_MaybePromoteUserSuccess(t *testing.T) { func TestRemote_MaybePromoteUserFail(t *testing.T) { defer tests.PrepareTestEnv(t)() - ctx := context.Background() + ctx := t.Context() // // OAuth2 authentication source GitLab // @@ -126,7 +125,7 @@ func TestRemote_MaybePromoteUserFail(t *testing.T) { LoginName: remoteUserID, Email: "some@example.com", } - defer createUser(context.Background(), t, remoteUser)() + defer createUser(t.Context(), t, remoteUser)() promoted, reason, err := remote_service.MaybePromoteRemoteUser(ctx, gitlabSource, remoteUserID, "") require.NoError(t, err) assert.False(t, promoted) @@ -143,7 +142,7 @@ func TestRemote_MaybePromoteUserFail(t *testing.T) { LoginSource: nonexistentloginsource, LoginName: remoteUserID, } - defer createUser(context.Background(), t, remoteUser)() + defer createUser(t.Context(), t, remoteUser)() promoted, reason, err := remote_service.MaybePromoteRemoteUser(ctx, gitlabSource, remoteUserID, "") require.NoError(t, err) assert.False(t, promoted) @@ -159,7 +158,7 @@ func TestRemote_MaybePromoteUserFail(t *testing.T) { LoginSource: gitlabSource.ID, LoginName: remoteUserID, } - defer createUser(context.Background(), t, remoteUser)() + defer createUser(t.Context(), t, remoteUser)() promoted, reason, err := remote_service.MaybePromoteRemoteUser(ctx, gitlabSource, remoteUserID, "") require.NoError(t, err) assert.False(t, promoted) @@ -180,7 +179,7 @@ func TestRemote_MaybePromoteUserFail(t *testing.T) { LoginSource: remoteSource.ID, LoginName: remoteUserID, } - defer createUser(context.Background(), t, remoteUser)() + defer createUser(t.Context(), t, remoteUser)() promoted, reason, err := remote_service.MaybePromoteRemoteUser(ctx, unrelatedSource, remoteUserID, remoteEmail) require.NoError(t, err) assert.False(t, promoted) @@ -197,7 +196,7 @@ func TestRemote_MaybePromoteUserFail(t *testing.T) { LoginSource: remoteSource.ID, LoginName: remoteUserID, } - defer createUser(context.Background(), t, remoteUser)() + defer createUser(t.Context(), t, remoteUser)() promoted, reason, err := remote_service.MaybePromoteRemoteUser(ctx, gitlabSource, remoteUserID, remoteEmail) require.NoError(t, err) assert.True(t, promoted) diff --git a/tests/integration/rename_branch_test.go b/tests/integration/rename_branch_test.go index 20d4c9b48f..d7440e5125 100644 --- a/tests/integration/rename_branch_test.go +++ b/tests/integration/rename_branch_test.go @@ -8,11 +8,11 @@ import ( "net/url" "testing" - git_model "code.gitea.io/gitea/models/git" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - gitea_context "code.gitea.io/gitea/services/context" - "code.gitea.io/gitea/tests" + git_model "forgejo.org/models/git" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + gitea_context "forgejo.org/services/context" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/repo_activity_test.go b/tests/integration/repo_activity_test.go index c1177fac11..6199373119 100644 --- a/tests/integration/repo_activity_test.go +++ b/tests/integration/repo_activity_test.go @@ -11,15 +11,15 @@ import ( "strings" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - 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/test" - repo_service "code.gitea.io/gitea/services/repository" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/test" + repo_service "forgejo.org/services/repository" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" diff --git a/tests/integration/repo_archive_test.go b/tests/integration/repo_archive_test.go index 75fe78eeed..f0ffedfd9b 100644 --- a/tests/integration/repo_archive_test.go +++ b/tests/integration/repo_archive_test.go @@ -1,18 +1,26 @@ // Copyright 2024 The Gitea Authors. All rights reserved. +// Copyright 2024 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT package integration import ( + "archive/tar" + "compress/gzip" + "fmt" "io" "net/http" + "net/url" "testing" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/routers/web" - "code.gitea.io/gitea/tests" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/routers/web" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -31,4 +39,53 @@ func TestRepoDownloadArchive(t *testing.T) { require.NoError(t, err) assert.Empty(t, resp.Header().Get("Content-Encoding")) assert.Len(t, bs, 320) + + // Verify that unrecognized archive type returns 404 + req = NewRequest(t, "GET", "/user2/repo1/archive/master.invalid") + MakeRequest(t, req, http.StatusNotFound) +} + +func TestRepoDownloadArchiveSubdir(t *testing.T) { + onGiteaRun(t, func(*testing.T, *url.URL) { + defer test.MockVariableValue(&setting.EnableGzip, true)() + defer test.MockVariableValue(&web.GzipMinSize, 10)() + defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())() + + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + + // Create a subdirectory + err := createOrReplaceFileInBranch(user, repo, "subdir/test.txt", "master", "Test") + require.NoError(t, err) + + t.Run("Frontend", func(t *testing.T) { + resp := MakeRequest(t, NewRequestf(t, "GET", "/%s/src/branch/master/subdir", repo.FullName()), http.StatusOK) + page := NewHTMLParser(t, resp.Body) + + page.AssertElement(t, fmt.Sprintf(".folder-actions a.archive-link[href='/%s/archive/master:subdir.zip'][type='application/zip']", repo.FullName()), true) + page.AssertElement(t, fmt.Sprintf(".folder-actions a.archive-link[href='/%s/archive/master:subdir.tar.gz'][type='application/gzip']", repo.FullName()), true) + }) + + t.Run("Backend", func(t *testing.T) { + resp := MakeRequest(t, NewRequestf(t, "GET", "/%s/archive/master:subdir.tar.gz", repo.FullName()), http.StatusOK) + + uncompressedStream, err := gzip.NewReader(resp.Body) + require.NoError(t, err) + + tarReader := tar.NewReader(uncompressedStream) + + header, err := tarReader.Next() + require.NoError(t, err) + assert.Equal(t, tar.TypeDir, int32(header.Typeflag)) + assert.Equal(t, fmt.Sprintf("%s/", repo.Name), header.Name) + + header, err = tarReader.Next() + require.NoError(t, err) + assert.Equal(t, tar.TypeReg, int32(header.Typeflag)) + assert.Equal(t, fmt.Sprintf("%s/test.txt", repo.Name), header.Name) + + _, err = tarReader.Next() + assert.Equal(t, io.EOF, err) + }) + }) } diff --git a/tests/integration/repo_archive_text_test.go b/tests/integration/repo_archive_text_test.go index e759246aa4..db133ce7d7 100644 --- a/tests/integration/repo_archive_text_test.go +++ b/tests/integration/repo_archive_text_test.go @@ -10,10 +10,10 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/translation" - "code.gitea.io/gitea/tests" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/translation" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" diff --git a/tests/integration/repo_badges_test.go b/tests/integration/repo_badges_test.go index a74d3979c2..baaa8c136a 100644 --- a/tests/integration/repo_badges_test.go +++ b/tests/integration/repo_badges_test.go @@ -12,19 +12,19 @@ import ( "strings" "testing" - actions_model "code.gitea.io/gitea/models/actions" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - 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/git" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/services/release" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + actions_model "forgejo.org/models/actions" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/services/release" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/repo_branch_test.go b/tests/integration/repo_branch_test.go index df9ea9a97c..3cb6e42c89 100644 --- a/tests/integration/repo_branch_test.go +++ b/tests/integration/repo_branch_test.go @@ -12,16 +12,16 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - git_model "code.gitea.io/gitea/models/git" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/graceful" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/modules/translation" - repo_service "code.gitea.io/gitea/services/repository" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + git_model "forgejo.org/models/git" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + "forgejo.org/modules/git" + "forgejo.org/modules/graceful" + "forgejo.org/modules/test" + "forgejo.org/modules/translation" + repo_service "forgejo.org/services/repository" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -204,3 +204,28 @@ func TestDatabaseMissingABranch(t *testing.T) { assert.Equal(t, firstBranchCount-1, secondBranchCount) }) } + +func TestCreateBranchButtonVisibility(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + session := loginUser(t, "user1") + + t.Run("Check create branch button", func(t *testing.T) { + t.Run("Normal repository", func(t *testing.T) { + repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + + // Check that the button is present + resp := session.MakeRequest(t, NewRequest(t, "GET", "/"+repo1.FullName()+"/branches"), http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + assert.Positive(t, htmlDoc.doc.Find(".show-create-branch-modal").Length()) + }) + t.Run("Mirrored repository", func(t *testing.T) { + repo5 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 5}) + + // Check that the button is NOT present + resp := session.MakeRequest(t, NewRequest(t, "GET", "/"+repo5.FullName()+"/branches"), http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + assert.Equal(t, 0, htmlDoc.doc.Find(".show-create-branch-modal").Length()) + }) + }) + }) +} diff --git a/tests/integration/repo_citation_test.go b/tests/integration/repo_citation_test.go index 4f7e24ee51..5651ac3db3 100644 --- a/tests/integration/repo_citation_test.go +++ b/tests/integration/repo_citation_test.go @@ -9,12 +9,12 @@ import ( "strings" "testing" - repo_model "code.gitea.io/gitea/models/repo" - unit_model "code.gitea.io/gitea/models/unit" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/repo_collaborator_test.go b/tests/integration/repo_collaborator_test.go index 292cd5862b..e18308e7cb 100644 --- a/tests/integration/repo_collaborator_test.go +++ b/tests/integration/repo_collaborator_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -33,5 +33,5 @@ func TestRepoCollaborators(t *testing.T) { // Veirfy placeholder placeholder, exists := page.Find("#search-user-box input").Attr("placeholder") assert.True(t, exists) - assert.EqualValues(t, "Search users...", placeholder) + assert.EqualValues(t, "Search users…", placeholder) } diff --git a/tests/integration/repo_commits_search_test.go b/tests/integration/repo_commits_search_test.go index 74ac25c0f5..92ff74ba68 100644 --- a/tests/integration/repo_commits_search_test.go +++ b/tests/integration/repo_commits_search_test.go @@ -9,7 +9,7 @@ import ( "strings" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/repo_commits_test.go b/tests/integration/repo_commits_test.go index e399898958..f3d3a145ae 100644 --- a/tests/integration/repo_commits_test.go +++ b/tests/integration/repo_commits_test.go @@ -11,11 +11,11 @@ import ( "sync" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/modules/json" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/modules/json" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/repo_delete_test.go b/tests/integration/repo_delete_test.go index 44ef26f19a..faabd13432 100644 --- a/tests/integration/repo_delete_test.go +++ b/tests/integration/repo_delete_test.go @@ -6,13 +6,13 @@ package integration import ( "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/organization" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - webhook_model "code.gitea.io/gitea/models/webhook" - repo_service "code.gitea.io/gitea/services/repository" + "forgejo.org/models/db" + "forgejo.org/models/organization" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + webhook_model "forgejo.org/models/webhook" + repo_service "forgejo.org/services/repository" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/repo_flags_test.go b/tests/integration/repo_flags_test.go index 8b64776a5a..c52610cd10 100644 --- a/tests/integration/repo_flags_test.go +++ b/tests/integration/repo_flags_test.go @@ -10,16 +10,16 @@ import ( "slices" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/repo_fork_test.go b/tests/integration/repo_fork_test.go index b2e40671ba..03bbba1b2c 100644 --- a/tests/integration/repo_fork_test.go +++ b/tests/integration/repo_fork_test.go @@ -12,16 +12,16 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - repo_service "code.gitea.io/gitea/services/repository" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/routers" + repo_service "forgejo.org/services/repository" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -249,7 +249,7 @@ func TestForkListPrivateRepo(t *testing.T) { testRepoFork(t, session, "user2", "repo1", org23.Name, "repo1") - t.Run("Anomynous", func(t *testing.T) { + t.Run("Anonymous", func(t *testing.T) { defer tests.PrintCurrentTest(t)() req := NewRequest(t, "GET", "/user2/repo1/forks") diff --git a/tests/integration/repo_generate_test.go b/tests/integration/repo_generate_test.go index bcee0df417..fd29156e4e 100644 --- a/tests/integration/repo_generate_test.go +++ b/tests/integration/repo_generate_test.go @@ -12,15 +12,15 @@ import ( "strings" "testing" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/optional" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/modules/translation" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/optional" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/modules/translation" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -194,7 +194,7 @@ func TestRepoGenerateTemplating(t *testing.T) { }) defer f() - // The repo.TemplateID field is not initalized. Luckly the ID field holds the expected value + // The repo.TemplateID field is not initialized. Luckily, the ID field holds the expected value templateID := strconv.FormatInt(template.ID, 10) testRepoGenerate( diff --git a/tests/integration/repo_git_note_test.go b/tests/integration/repo_git_note_test.go index 6ad57c81b0..e6b23754db 100644 --- a/tests/integration/repo_git_note_test.go +++ b/tests/integration/repo_git_note_test.go @@ -5,7 +5,7 @@ import ( "net/url" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/repo_issue_title_test.go b/tests/integration/repo_issue_title_test.go index cf517a7a40..587db43223 100644 --- a/tests/integration/repo_issue_title_test.go +++ b/tests/integration/repo_issue_title_test.go @@ -10,16 +10,16 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - issue_service "code.gitea.io/gitea/services/issue" - pull_service "code.gitea.io/gitea/services/pull" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + issue_service "forgejo.org/services/issue" + pull_service "forgejo.org/services/pull" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/repo_mergecommit_revert_test.go b/tests/integration/repo_mergecommit_revert_test.go index eb75d45c15..600ee991f8 100644 --- a/tests/integration/repo_mergecommit_revert_test.go +++ b/tests/integration/repo_mergecommit_revert_test.go @@ -7,7 +7,7 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/repo_migrate_test.go b/tests/integration/repo_migrate_test.go index 9fb7a73379..233a55ef8f 100644 --- a/tests/integration/repo_migrate_test.go +++ b/tests/integration/repo_migrate_test.go @@ -9,8 +9,8 @@ import ( "net/http/httptest" "testing" - "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/repo_migration_ui_test.go b/tests/integration/repo_migration_ui_test.go index 594b09b490..5e2f0c0a76 100644 --- a/tests/integration/repo_migration_ui_test.go +++ b/tests/integration/repo_migration_ui_test.go @@ -7,7 +7,7 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" diff --git a/tests/integration/repo_pagination_test.go b/tests/integration/repo_pagination_test.go index 1c1f2ac82e..692936353b 100644 --- a/tests/integration/repo_pagination_test.go +++ b/tests/integration/repo_pagination_test.go @@ -8,11 +8,11 @@ import ( "path" "testing" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/repo_search_test.go b/tests/integration/repo_search_test.go index 6189dc1150..909668d3ca 100644 --- a/tests/integration/repo_search_test.go +++ b/tests/integration/repo_search_test.go @@ -7,13 +7,13 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - code_indexer "code.gitea.io/gitea/modules/indexer/code" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + code_indexer "forgejo.org/modules/indexer/code" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" @@ -82,19 +82,10 @@ func testSearchRepo(t *testing.T, indexer bool) { testSearch(t, "/user2/glob/search?q=loren&page=1", []string{"a.txt"}, indexer) testSearch(t, "/user2/glob/search?q=loren&page=1&mode=exact", []string{"a.txt"}, indexer) - if indexer { - // fuzzy search: matches both file3 (x/b.txt) and file1 (a.txt) - // when indexer is enabled - testSearch(t, "/user2/glob/search?q=file3&mode=fuzzy&page=1", []string{"x/b.txt", "a.txt"}, indexer) - testSearch(t, "/user2/glob/search?q=file4&mode=fuzzy&page=1", []string{"x/b.txt", "a.txt"}, indexer) - testSearch(t, "/user2/glob/search?q=file5&mode=fuzzy&page=1", []string{"x/b.txt", "a.txt"}, indexer) - } else { - // fuzzy search: Union/OR of all the keywords - // when indexer is disabled - testSearch(t, "/user2/glob/search?q=file3+file1&mode=union&page=1", []string{"a.txt", "x/b.txt"}, indexer) - testSearch(t, "/user2/glob/search?q=file4&mode=union&page=1", []string{}, indexer) - testSearch(t, "/user2/glob/search?q=file5&mode=union&page=1", []string{}, indexer) - } + // union search: Union/OR of all the keywords + testSearch(t, "/user2/glob/search?q=file3+file1&mode=union&page=1", []string{"a.txt", "x/b.txt"}, indexer) + testSearch(t, "/user2/glob/search?q=file4&mode=union&page=1", []string{}, indexer) + testSearch(t, "/user2/glob/search?q=file5&mode=union&page=1", []string{}, indexer) testSearch(t, "/user2/glob/search?q=file3&page=1&mode=exact", []string{"x/b.txt"}, indexer) testSearch(t, "/user2/glob/search?q=file4&page=1&mode=exact", []string{}, indexer) @@ -108,9 +99,6 @@ func testSearch(t *testing.T, url string, expected []string, indexer bool) { doc := NewHTMLParser(t, resp.Body) container := doc.Find(".repository").Find(".ui.container") - grepMsg := container.Find(".ui.message[data-test-tag=grep]") - assert.EqualValues(t, indexer, len(grepMsg.Nodes) == 0) - branchDropdown := container.Find(".js-branch-tag-selector") assert.EqualValues(t, indexer, len(branchDropdown.Nodes) == 0) @@ -124,11 +112,11 @@ func testSearch(t *testing.T, url string, expected []string, indexer bool) { }) if indexer { - assert.EqualValues(t, []string{"exact", "fuzzy"}, dropdownOptions) + assert.EqualValues(t, []string{"exact", "union"}, dropdownOptions) } else { assert.EqualValues(t, []string{"exact", "union", "regexp"}, dropdownOptions) } filenames := resultFilenames(t, doc) - assert.EqualValues(t, expected, filenames) + assert.ElementsMatch(t, expected, filenames) } diff --git a/tests/integration/repo_settings_hook_test.go b/tests/integration/repo_settings_hook_test.go index 0a3dd57160..f7349d4e66 100644 --- a/tests/integration/repo_settings_hook_test.go +++ b/tests/integration/repo_settings_hook_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/repo_settings_test.go b/tests/integration/repo_settings_test.go index ff138532f9..f78df96a93 100644 --- a/tests/integration/repo_settings_test.go +++ b/tests/integration/repo_settings_test.go @@ -5,27 +5,26 @@ package integration import ( "fmt" - "io" "net/http" - "net/http/httptest" "strings" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/forgefed" - git_model "code.gitea.io/gitea/models/git" - repo_model "code.gitea.io/gitea/models/repo" - unit_model "code.gitea.io/gitea/models/unit" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - fm "code.gitea.io/gitea/modules/forgefed" - "code.gitea.io/gitea/modules/optional" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/validation" - gitea_context "code.gitea.io/gitea/services/context" - repo_service "code.gitea.io/gitea/services/repository" - user_service "code.gitea.io/gitea/services/user" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/forgefed" + git_model "forgejo.org/models/git" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + fm "forgejo.org/modules/forgefed" + "forgejo.org/modules/optional" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/modules/validation" + gitea_context "forgejo.org/services/context" + repo_service "forgejo.org/services/repository" + user_service "forgejo.org/services/user" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -278,59 +277,8 @@ func TestRepoFollowing(t *testing.T) { setting.Federation.Enabled = false }() - federatedRoutes := http.NewServeMux() - federatedRoutes.HandleFunc("/.well-known/nodeinfo", - func(res http.ResponseWriter, req *http.Request) { - // curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/.well-known/nodeinfo - responseBody := fmt.Sprintf(`{"links":[{"href":"http://%s/api/v1/nodeinfo","rel":"http://nodeinfo.diaspora.software/ns/schema/2.1"}]}`, req.Host) - t.Logf("response: %s", responseBody) - // TODO: as soon as content-type will become important: content-type: application/json;charset=utf-8 - fmt.Fprint(res, responseBody) - }) - federatedRoutes.HandleFunc("/api/v1/nodeinfo", - func(res http.ResponseWriter, req *http.Request) { - // curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/nodeinfo - responseBody := fmt.Sprintf(`{"version":"2.1","software":{"name":"forgejo","version":"1.20.0+dev-3183-g976d79044",` + - `"repository":"https://codeberg.org/forgejo/forgejo.git","homepage":"https://forgejo.org/"},` + - `"protocols":["activitypub"],"services":{"inbound":[],"outbound":["rss2.0"]},` + - `"openRegistrations":true,"usage":{"users":{"total":14,"activeHalfyear":2}},"metadata":{}}`) - fmt.Fprint(res, responseBody) - }) - repo1InboxReceivedLike := false - federatedRoutes.HandleFunc("/api/v1/activitypub/repository-id/1/inbox/", - func(res http.ResponseWriter, req *http.Request) { - if req.Method != "POST" { - t.Errorf("Unhandled request: %q", req.URL.EscapedPath()) - } - buf := new(strings.Builder) - _, err := io.Copy(buf, req.Body) - if err != nil { - t.Errorf("Error reading body: %q", err) - } - like := fm.ForgeLike{} - err = like.UnmarshalJSON([]byte(buf.String())) - if err != nil { - t.Errorf("Error unmarshalling ForgeLike: %q", err) - } - if isValid, err := validation.IsValid(like); !isValid { - t.Errorf("ForgeLike is not valid: %q", err) - } - - activityType := like.Type - object := like.Object.GetLink().String() - isLikeType := activityType == "Like" - isCorrectObject := strings.HasSuffix(object, "/api/v1/activitypub/repository-id/1") - if !isLikeType || !isCorrectObject { - t.Errorf("Activity is not a like for this repo") - } - - repo1InboxReceivedLike = true - }) - federatedRoutes.HandleFunc("/", - func(res http.ResponseWriter, req *http.Request) { - t.Errorf("Unhandled request: %q", req.URL.EscapedPath()) - }) - federatedSrv := httptest.NewServer(federatedRoutes) + mock := test.NewFederationServerMock() + federatedSrv := mock.DistantServer(t) defer federatedSrv.Close() user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) @@ -363,8 +311,24 @@ func TestRepoFollowing(t *testing.T) { req := NewRequestWithValues(t, "POST", link, map[string]string{ "_csrf": GetCSRF(t, session, repoLink), }) - assert.False(t, repo1InboxReceivedLike) + session.MakeRequest(t, req, http.StatusOK) - assert.True(t, repo1InboxReceivedLike) + + // Verify distant server received a like activity + like := fm.ForgeLike{} + err := like.UnmarshalJSON([]byte(mock.LastPost)) + if err != nil { + t.Errorf("Error unmarshalling ForgeLike: %q", err) + } + if isValid, err := validation.IsValid(like); !isValid { + t.Errorf("ForgeLike is not valid: %q", err) + } + activityType := like.Type + object := like.Object.GetLink().String() + isLikeType := activityType == "Like" + isCorrectObject := strings.HasSuffix(object, "/api/v1/activitypub/repository-id/1") + if !isLikeType || !isCorrectObject { + t.Errorf("Activity is not a like for this repo") + } }) } diff --git a/tests/integration/repo_signed_tag_test.go b/tests/integration/repo_signed_tag_test.go index 41e663ce52..16d8841304 100644 --- a/tests/integration/repo_signed_tag_test.go +++ b/tests/integration/repo_signed_tag_test.go @@ -10,16 +10,16 @@ import ( "os/exec" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/graceful" - repo_module "code.gitea.io/gitea/modules/repository" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/graceful" + repo_module "forgejo.org/modules/repository" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/require" ) diff --git a/tests/integration/repo_starwatch_test.go b/tests/integration/repo_starwatch_test.go index a8bad30109..3bcfa29fe3 100644 --- a/tests/integration/repo_starwatch_test.go +++ b/tests/integration/repo_starwatch_test.go @@ -9,10 +9,10 @@ import ( "strings" "testing" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/repo_tag_test.go b/tests/integration/repo_tag_test.go index 0ce0e142b9..9be33ec8a8 100644 --- a/tests/integration/repo_tag_test.go +++ b/tests/integration/repo_tag_test.go @@ -11,16 +11,16 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/services/release" - "code.gitea.io/gitea/tests" + "forgejo.org/models" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + repo_module "forgejo.org/modules/repository" + api "forgejo.org/modules/structs" + "forgejo.org/services/release" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/repo_test.go b/tests/integration/repo_test.go index 90fc19c193..308942e4fe 100644 --- a/tests/integration/repo_test.go +++ b/tests/integration/repo_test.go @@ -12,18 +12,18 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - 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/git" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/modules/translation" - repo_service "code.gitea.io/gitea/services/repository" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/modules/translation" + repo_service "forgejo.org/services/repository" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" @@ -1120,7 +1120,6 @@ func TestRepoIssueFilterLinks(t *testing.T) { assert.Contains(t, href, "&project=") assert.Contains(t, href, "&assignee=") assert.Contains(t, href, "&poster=") - assert.Contains(t, href, "&fuzzy=") }) assert.True(t, called) }) @@ -1145,32 +1144,6 @@ func TestRepoIssueFilterLinks(t *testing.T) { assert.Contains(t, href, "&project=") assert.Contains(t, href, "&assignee=") assert.Contains(t, href, "&poster=") - assert.Contains(t, href, "&fuzzy=") - }) - assert.True(t, called) - }) - - t.Run("Fuzzy", func(t *testing.T) { - defer tests.PrintCurrentTest(t)() - - req := NewRequest(t, "GET", "/user2/repo1/issues?fuzzy=false") - resp := MakeRequest(t, req, http.StatusOK) - htmlDoc := NewHTMLParser(t, resp.Body) - - called := false - htmlDoc.Find("#issue-filters a[href^='?']").Each(func(_ int, s *goquery.Selection) { - called = true - href, _ := s.Attr("href") - assert.Contains(t, href, "?q=&") - assert.Contains(t, href, "&type=") - assert.Contains(t, href, "&sort=") - assert.Contains(t, href, "&state=") - assert.Contains(t, href, "&labels=") - assert.Contains(t, href, "&milestone=") - assert.Contains(t, href, "&project=") - assert.Contains(t, href, "&assignee=") - assert.Contains(t, href, "&poster=") - assert.Contains(t, href, "&fuzzy=false") }) assert.True(t, called) }) @@ -1195,7 +1168,6 @@ func TestRepoIssueFilterLinks(t *testing.T) { assert.Contains(t, href, "&project=") assert.Contains(t, href, "&assignee=") assert.Contains(t, href, "&poster=") - assert.Contains(t, href, "&fuzzy=") }) assert.True(t, called) }) @@ -1220,7 +1192,6 @@ func TestRepoIssueFilterLinks(t *testing.T) { assert.Contains(t, href, "&project=") assert.Contains(t, href, "&assignee=") assert.Contains(t, href, "&poster=") - assert.Contains(t, href, "&fuzzy=") }) assert.True(t, called) }) @@ -1245,7 +1216,6 @@ func TestRepoIssueFilterLinks(t *testing.T) { assert.Contains(t, href, "&project=") assert.Contains(t, href, "&assignee=") assert.Contains(t, href, "&poster=") - assert.Contains(t, href, "&fuzzy=") }) assert.True(t, called) }) @@ -1270,7 +1240,6 @@ func TestRepoIssueFilterLinks(t *testing.T) { assert.Contains(t, href, "&project=") assert.Contains(t, href, "&assignee=") assert.Contains(t, href, "&poster=") - assert.Contains(t, href, "&fuzzy=") }) assert.True(t, called) }) @@ -1295,7 +1264,6 @@ func TestRepoIssueFilterLinks(t *testing.T) { assert.Contains(t, href, "&project=") assert.Contains(t, href, "&assignee=") assert.Contains(t, href, "&poster=") - assert.Contains(t, href, "&fuzzy=") }) assert.True(t, called) }) @@ -1320,7 +1288,6 @@ func TestRepoIssueFilterLinks(t *testing.T) { assert.Contains(t, href, "&project=1") assert.Contains(t, href, "&assignee=") assert.Contains(t, href, "&poster=") - assert.Contains(t, href, "&fuzzy=") }) assert.True(t, called) }) @@ -1345,7 +1312,6 @@ func TestRepoIssueFilterLinks(t *testing.T) { assert.Contains(t, href, "&project=") assert.Contains(t, href, "&assignee=1") assert.Contains(t, href, "&poster=") - assert.Contains(t, href, "&fuzzy=") }) assert.True(t, called) }) @@ -1370,7 +1336,6 @@ func TestRepoIssueFilterLinks(t *testing.T) { assert.Contains(t, href, "&project=") assert.Contains(t, href, "&assignee=") assert.Contains(t, href, "&poster=1") - assert.Contains(t, href, "&fuzzy=") }) assert.True(t, called) }) @@ -1395,7 +1360,6 @@ func TestRepoIssueFilterLinks(t *testing.T) { assert.Contains(t, href, "&project=") assert.Contains(t, href, "&assignee=") assert.Contains(t, href, "&poster=") - assert.Contains(t, href, "&fuzzy=") }) assert.True(t, called) }) @@ -1420,7 +1384,6 @@ func TestRepoIssueFilterLinks(t *testing.T) { assert.Contains(t, href, "&project=") assert.Contains(t, href, "&assignee=") assert.Contains(t, href, "&poster=") - assert.Contains(t, href, "&fuzzy=") assert.Contains(t, href, "&archived=true") }) assert.True(t, called) @@ -1460,5 +1423,23 @@ func TestRepoSubmoduleView(t *testing.T) { htmlDoc := NewHTMLParser(t, resp.Body) htmlDoc.AssertElement(t, fmt.Sprintf(`tr[data-entryname="repo1"] a[href="%s"]`, u.JoinPath("/user2/repo1").String()), true) + + // Check that a link to the submodule returns a redirect and that the redirect link is correct. + req = NewRequest(t, "GET", "/"+repo.FullName()+"/src/branch/"+repo.DefaultBranch+"/repo1") + resp = MakeRequest(t, req, http.StatusSeeOther) + + assert.Equal(t, u.JoinPath("/user2/repo1").String(), resp.Header().Get("Location")) }) } + +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/repo_topic_test.go b/tests/integration/repo_topic_test.go index f5778a2861..6dc60e2c3a 100644 --- a/tests/integration/repo_topic_test.go +++ b/tests/integration/repo_topic_test.go @@ -9,12 +9,12 @@ import ( "net/url" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/repo_view_test.go b/tests/integration/repo_view_test.go index 46e75063bc..7ea4aeb4c6 100644 --- a/tests/integration/repo_view_test.go +++ b/tests/integration/repo_view_test.go @@ -10,14 +10,14 @@ import ( "strings" "testing" - 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/routers/web/repo" - "code.gitea.io/gitea/services/context" - "code.gitea.io/gitea/services/contexttest" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/routers/web/repo" + "forgejo.org/services/context" + "forgejo.org/services/contexttest" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/repo_watch_test.go b/tests/integration/repo_watch_test.go index ef3028f293..0bcb039b01 100644 --- a/tests/integration/repo_watch_test.go +++ b/tests/integration/repo_watch_test.go @@ -7,9 +7,9 @@ import ( "net/url" "testing" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/setting" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + "forgejo.org/modules/setting" ) func TestRepoWatch(t *testing.T) { diff --git a/tests/integration/repo_webhook_test.go b/tests/integration/repo_webhook_test.go index 37bad56b9e..be1b9cbcec 100644 --- a/tests/integration/repo_webhook_test.go +++ b/tests/integration/repo_webhook_test.go @@ -9,9 +9,9 @@ import ( "net/url" "testing" - gitea_context "code.gitea.io/gitea/services/context" - "code.gitea.io/gitea/services/webhook" - "code.gitea.io/gitea/tests" + gitea_context "forgejo.org/services/context" + "forgejo.org/services/webhook" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" diff --git a/tests/integration/repo_wiki_test.go b/tests/integration/repo_wiki_test.go index 6115010ba4..5cd893702d 100644 --- a/tests/integration/repo_wiki_test.go +++ b/tests/integration/repo_wiki_test.go @@ -8,12 +8,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" @@ -89,3 +89,27 @@ func TestWikiBranchNormalize(t *testing.T) { assert.Equal(t, setting.Repository.DefaultBranch, repo.GetWikiBranchName()) assertNormalizeButton(false) } + +func TestWikiTOC(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + username := "user2" + session := loginUser(t, username) + + t.Run("Link in heading", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequestWithValues(t, "POST", "/user2/repo1/wiki/Home?action=_edit", map[string]string{ + "_csrf": GetCSRF(t, session, "/user2/repo1/wiki/Home"), + "title": "Home", + "content": "# [Helpdesk](Helpdesk)", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + req = NewRequest(t, "GET", "/user2/repo1/wiki/Home") + resp := MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + + assert.EqualValues(t, "Helpdesk", htmlDoc.Find(".wiki-content-toc a").Text()) + }) +} diff --git a/tests/integration/repofiles_change_test.go b/tests/integration/repofiles_change_test.go index 1896971046..dce310b0fc 100644 --- a/tests/integration/repofiles_change_test.go +++ b/tests/integration/repofiles_change_test.go @@ -10,15 +10,15 @@ import ( "testing" "time" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/git" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/runner_test.go b/tests/integration/runner_test.go new file mode 100644 index 0000000000..09555caacf --- /dev/null +++ b/tests/integration/runner_test.go @@ -0,0 +1,130 @@ +// 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 "forgejo.org/models/actions" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + forgejo_context "forgejo.org/services/context" + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" +) + +func TestRunnerModification(t *testing.T) { + defer unittest.OverrideFixtures("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/session_test.go b/tests/integration/session_test.go index a5bcab269a..7af5645dec 100644 --- a/tests/integration/session_test.go +++ b/tests/integration/session_test.go @@ -6,10 +6,10 @@ package integration import ( "testing" - "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/tests" + "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/unittest" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/setting_test.go b/tests/integration/setting_test.go index 5635faad38..66790e5835 100644 --- a/tests/integration/setting_test.go +++ b/tests/integration/setting_test.go @@ -8,12 +8,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/signin_test.go b/tests/integration/signin_test.go index f8e2e079ca..dd8322214a 100644 --- a/tests/integration/signin_test.go +++ b/tests/integration/signin_test.go @@ -10,12 +10,12 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/modules/translation" - "code.gitea.io/gitea/tests" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/modules/translation" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/signout_test.go b/tests/integration/signout_test.go index 7fd0b5c64a..efcf54f14d 100644 --- a/tests/integration/signout_test.go +++ b/tests/integration/signout_test.go @@ -7,7 +7,7 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" ) func TestSignOut(t *testing.T) { diff --git a/tests/integration/signup_test.go b/tests/integration/signup_test.go index 39533bbf89..91752d415e 100644 --- a/tests/integration/signup_test.go +++ b/tests/integration/signup_test.go @@ -10,13 +10,13 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/cache" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/modules/translation" - "code.gitea.io/gitea/tests" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/cache" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/modules/translation" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/ssh_key_test.go b/tests/integration/ssh_key_test.go index ebf0d26c2d..aece9c3fd9 100644 --- a/tests/integration/ssh_key_test.go +++ b/tests/integration/ssh_key_test.go @@ -12,9 +12,9 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/modules/git" - api "code.gitea.io/gitea/modules/structs" + auth_model "forgejo.org/models/auth" + "forgejo.org/modules/git" + api "forgejo.org/modules/structs" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/swagger_test.go b/tests/integration/swagger_test.go index 584601f7f9..ac10a91691 100644 --- a/tests/integration/swagger_test.go +++ b/tests/integration/swagger_test.go @@ -8,8 +8,8 @@ import ( "strings" "testing" - "code.gitea.io/gitea/modules/json" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/json" + "forgejo.org/tests" swagger_spec "github.com/go-openapi/spec" "github.com/stretchr/testify/require" diff --git a/tests/integration/timetracking_test.go b/tests/integration/timetracking_test.go index 10e539cbe6..49ae92033e 100644 --- a/tests/integration/timetracking_test.go +++ b/tests/integration/timetracking_test.go @@ -9,8 +9,8 @@ import ( "testing" "time" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/test" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/size_translations_test.go b/tests/integration/translations_test.go similarity index 74% rename from tests/integration/size_translations_test.go rename to tests/integration/translations_test.go index a0b88291f4..9cfa3423b7 100644 --- a/tests/integration/size_translations_test.go +++ b/tests/integration/translations_test.go @@ -1,6 +1,5 @@ // Copyright 2024 The Forgejo Authors. All rights reserved. -// SPDX-License-Identifier: MIT - +// SPDX-License-Identifier: GPL-3.0-or-later package integration import ( @@ -11,15 +10,39 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/translation/i18n" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" ) +func TestMissingTranslationHandling(t *testing.T) { + // Currently new languages can only be added to localestore via AddLocaleByIni + // so this line is here to make the other one work. When INI locales are removed, + // it will not be needed by this test. + i18n.DefaultLocales.AddLocaleByIni("fun", "Funlang", nil, []byte(""), nil) + + // Add a testing locale to the store + i18n.DefaultLocales.AddToLocaleFromJSON("fun", []byte(`{ + "meta.last_line": "This language only has one line that is never used by the UI. It will never have a translation for incorrect_root_url" + }`)) + + // Get "fun" locale, make sure it's available + funLocale, found := i18n.DefaultLocales.Locale("fun") + assert.True(t, found) + + // Get translation for a string that this locale doesn't have + s := funLocale.TrString("incorrect_root_url") + + // Verify fallback to English + assert.True(t, strings.HasPrefix(s, "This Forgejo instance")) +} + +// TestDataSizeTranslation is a test for usage of TrSize in file size display func TestDataSizeTranslation(t *testing.T) { onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { testUser := "user2" @@ -103,14 +126,14 @@ func testFileSizeTranslated(t *testing.T, session *TestSession, filePath, correc resp := session.MakeRequest(t, req, http.StatusOK) // Check if file size is translated - sizeCorrent := false + sizeCorrect := false fileInfo := NewHTMLParser(t, resp.Body).Find(".file-info .file-info-entry") fileInfo.Each(func(i int, info *goquery.Selection) { infoText := strings.TrimSpace(info.Text()) if infoText == correctSize { - sizeCorrent = true + sizeCorrect = true } }) - assert.True(t, sizeCorrent) + assert.True(t, sizeCorrect) } diff --git a/tests/integration/user_avatar_test.go b/tests/integration/user_avatar_test.go index a7c0264aaa..b0d930d71f 100644 --- a/tests/integration/user_avatar_test.go +++ b/tests/integration/user_avatar_test.go @@ -12,11 +12,11 @@ import ( "net/http" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/avatar" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/avatar" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/user_count_test.go b/tests/integration/user_count_test.go index 8fb78a61ee..5f762ca317 100644 --- a/tests/integration/user_count_test.go +++ b/tests/integration/user_count_test.go @@ -9,15 +9,15 @@ import ( "strconv" "testing" - "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/models/organization" - packages_model "code.gitea.io/gitea/models/packages" - project_model "code.gitea.io/gitea/models/project" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/optional" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + "forgejo.org/models/organization" + packages_model "forgejo.org/models/packages" + project_model "forgejo.org/models/project" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/optional" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" diff --git a/tests/integration/user_dashboard_test.go b/tests/integration/user_dashboard_test.go index abc3e065d9..b95bdab078 100644 --- a/tests/integration/user_dashboard_test.go +++ b/tests/integration/user_dashboard_test.go @@ -1,16 +1,25 @@ // Copyright 2024 The Forgejo Authors. All rights reserved. -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later package integration import ( "net/http" + "net/url" + "strconv" "strings" "testing" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/translation" + "forgejo.org/models/db" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/translation" + issue_service "forgejo.org/services/issue" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" + "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -28,3 +37,68 @@ 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 TestUserDashboardFeedWelcome(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + + // User2 has some activity in feed + session := loginUser(t, "user2") + page := NewHTMLParser(t, session.MakeRequest(t, NewRequest(t, "GET", "/"), http.StatusOK).Body) + testUserDashboardFeedType(t, page, false) + + // User1 doesn't have any activity in feed + session = loginUser(t, "user1") + page = NewHTMLParser(t, session.MakeRequest(t, NewRequest(t, "GET", "/"), http.StatusOK).Body) + testUserDashboardFeedType(t, page, true) +} + +func testUserDashboardFeedType(t *testing.T, page *HTMLDoc, isEmpty bool) { + page.AssertElement(t, "#activity-feed", !isEmpty) + page.AssertElement(t, "#empty-feed", isEmpty) +} + +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++ + if s.IsMatcher(goquery.Single("a")) { + assert.EqualValues(t, "❗ not rendered", s.Text()) + } else { + assert.EqualValues(t, ":exclamation: not rendered", s.Text()) + } + }) + + assert.EqualValues(t, 6, count) + }) +} diff --git a/tests/integration/user_profile_activity_test.go b/tests/integration/user_profile_activity_test.go index f1269e5e93..eb9bfa1741 100644 --- a/tests/integration/user_profile_activity_test.go +++ b/tests/integration/user_profile_activity_test.go @@ -8,8 +8,8 @@ import ( "strconv" "testing" - "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/structs" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/user_profile_follows_test.go b/tests/integration/user_profile_follows_test.go index 24b74268e6..08bd58db16 100644 --- a/tests/integration/user_profile_follows_test.go +++ b/tests/integration/user_profile_follows_test.go @@ -9,7 +9,7 @@ import ( "strings" "testing" - "code.gitea.io/gitea/tests" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/user_profile_test.go b/tests/integration/user_profile_test.go index 5532403510..04d87c49ab 100644 --- a/tests/integration/user_profile_test.go +++ b/tests/integration/user_profile_test.go @@ -9,10 +9,10 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/user_redirect_test.go b/tests/integration/user_redirect_test.go new file mode 100644 index 0000000000..52dc5d9d3a --- /dev/null +++ b/tests/integration/user_redirect_test.go @@ -0,0 +1,274 @@ +// Copyright 2024 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package integration + +import ( + "net/http" + "testing" + "time" + + "forgejo.org/models/db" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "forgejo.org/modules/timeutil" + forgejo_context "forgejo.org/services/context" + "forgejo.org/tests" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestUserRedirect(t *testing.T) { + defer tests.PrepareTestEnv(t)() + defer test.MockVariableValue(&setting.Service.UsernameCooldownPeriod, 1)() + + session := loginUser(t, "user2") + + t.Run("Rename user normally", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{ + "_csrf": GetCSRF(t, session, "/user/settings"), + "name": "user2-new", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + flashCookie := session.GetCookie(forgejo_context.CookieNameFlash) + assert.NotNil(t, flashCookie) + assert.EqualValues(t, "success%3DYour%2Bprofile%2Bhas%2Bbeen%2Bupdated.", flashCookie.Value) + + unittest.AssertExistsIf(t, true, &user_model.Redirect{LowerName: "user2", RedirectUserID: 2}) + }) + + t.Run("Create new user", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{ + "_csrf": GetCSRF(t, emptyTestSession(t), "/user/sign_up"), + "user_name": "user2", + "email": "doesnotexist@example.com", + "password": "examplePassword!1", + "retype": "examplePassword!1", + }) + resp := MakeRequest(t, req, http.StatusOK) + + htmlDoc := NewHTMLParser(t, resp.Body) + flashMessage := htmlDoc.Find(`.flash-message`).Text() + assert.Contains(t, flashMessage, "The username cannot be claimed, because its cooldown period is not yet over. It can be claimed on") + }) + + t.Run("Rename another user", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + session := loginUser(t, "user4") + req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{ + "_csrf": GetCSRF(t, session, "/user/settings"), + "name": "user2", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + flashCookie := session.GetCookie(forgejo_context.CookieNameFlash) + assert.NotNil(t, flashCookie) + assert.Contains(t, flashCookie.Value, "error%3DThe%2Busername%2Bcannot%2Bbe%2Bclaimed%252C%2Bbecause%2Bits%2Bcooldown%2Bperiod%2Bis%2Bnot%2Byet%2Bover.%2BIt%2Bcan%2Bbe%2Bclaimed%2Bon") + }) + + t.Run("Admin rename user", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + session := loginUser(t, "user1") + req := NewRequestWithValues(t, "POST", "/admin/users/4/edit", map[string]string{ + "_csrf": GetCSRF(t, session, "/admin/users/4/edit"), + "user_name": "user2", + "email": "user4@example.com", + "login_type": "0-0", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + flashCookie := session.GetCookie(forgejo_context.CookieNameFlash) + assert.NotNil(t, flashCookie) + assert.EqualValues(t, "success%3DThe%2Buser%2Baccount%2Bhas%2Bbeen%2Bupdated.", flashCookie.Value) + + unittest.AssertExistsIf(t, true, &user_model.User{LowerName: "user2"}) + unittest.AssertExistsIf(t, false, &user_model.Redirect{LowerName: "user2", RedirectUserID: 2}) + }) + + t.Run("Reclaim username", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{ + "_csrf": GetCSRF(t, session, "/user/settings"), + "name": "user2-new-2", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + flashCookie := session.GetCookie(forgejo_context.CookieNameFlash) + assert.NotNil(t, flashCookie) + assert.EqualValues(t, "success%3DYour%2Bprofile%2Bhas%2Bbeen%2Bupdated.", flashCookie.Value) + + unittest.AssertExistsIf(t, true, &user_model.Redirect{LowerName: "user2-new", RedirectUserID: 2}) + + req = NewRequestWithValues(t, "POST", "/user/settings", map[string]string{ + "_csrf": GetCSRF(t, session, "/user/settings"), + "name": "user2-new", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + flashCookie = session.GetCookie(forgejo_context.CookieNameFlash) + assert.NotNil(t, flashCookie) + assert.EqualValues(t, "success%3DYour%2Bprofile%2Bhas%2Bbeen%2Bupdated.", flashCookie.Value) + + unittest.AssertExistsIf(t, false, &user_model.Redirect{LowerName: "user2-new", RedirectUserID: 2}) + unittest.AssertExistsIf(t, true, &user_model.Redirect{LowerName: "user2-new-2", RedirectUserID: 2}) + }) + + t.Run("Profile note", func(t *testing.T) { + getPrompt := func(t *testing.T) string { + req := NewRequest(t, "GET", "/user/settings") + resp := session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + + return htmlDoc.Find("input[name='name'] + .help").Text() + } + + t.Run("No cooldown", func(t *testing.T) { + defer test.MockVariableValue(&setting.Service.UsernameCooldownPeriod, 0)() + defer tests.PrintCurrentTest(t)() + + assert.Contains(t, getPrompt(t), "The old username will redirect until someone claims it.") + }) + + t.Run("With cooldown", func(t *testing.T) { + defer test.MockVariableValue(&setting.Service.UsernameCooldownPeriod, 8)() + defer tests.PrintCurrentTest(t)() + + assert.Contains(t, getPrompt(t), "The old username will be available to everyone after a cooldown period of 8 days, you can still reclaim the old username during the cooldown period.") + }) + }) + + t.Run("Org settings note", func(t *testing.T) { + getPrompt := func(t *testing.T) string { + req := NewRequest(t, "GET", "/org/org3/settings") + resp := session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + + return htmlDoc.Find("#org_name + .help").Text() + } + + t.Run("No cooldown", func(t *testing.T) { + defer test.MockVariableValue(&setting.Service.UsernameCooldownPeriod, 0)() + defer tests.PrintCurrentTest(t)() + + assert.Contains(t, getPrompt(t), "The old name will redirect until it is claimed.") + }) + + t.Run("With cooldown", func(t *testing.T) { + defer test.MockVariableValue(&setting.Service.UsernameCooldownPeriod, 8)() + defer tests.PrintCurrentTest(t)() + + assert.Contains(t, getPrompt(t), "The old organization name will be available to everyone after a cooldown period of 8 days, you can still reclaim the old name during the cooldown period.") + }) + }) +} + +// NOTE: This is a unit test but written in the integration test to ensure this runs on all databases. +func TestLimitUserRedirects(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + _, err := db.GetEngine(db.DefaultContext).NoAutoTime().Insert(&user_model.Redirect{RedirectUserID: 1, LowerName: "legacy", CreatedUnix: 0}, + &user_model.Redirect{RedirectUserID: 1, LowerName: "past", CreatedUnix: timeutil.TimeStampNow().AddDuration(-48 * time.Hour)}, + &user_model.Redirect{RedirectUserID: 1, LowerName: "recent", CreatedUnix: timeutil.TimeStampNow().AddDuration(-12 * time.Hour)}, + &user_model.Redirect{RedirectUserID: 1, LowerName: "future", CreatedUnix: timeutil.TimeStampNow().AddDuration(time.Hour)}) + require.NoError(t, err) + + require.NoError(t, user_model.LimitUserRedirects(db.DefaultContext, 1, 3)) + + unittest.AssertExistsIf(t, false, &user_model.Redirect{LowerName: "legacy"}) + unittest.AssertExistsIf(t, true, &user_model.Redirect{LowerName: "past"}) + unittest.AssertExistsIf(t, true, &user_model.Redirect{LowerName: "recent"}) + unittest.AssertExistsIf(t, true, &user_model.Redirect{LowerName: "future"}) + + require.NoError(t, user_model.LimitUserRedirects(db.DefaultContext, 1, 1)) + + unittest.AssertExistsIf(t, false, &user_model.Redirect{LowerName: "legacy"}) + unittest.AssertExistsIf(t, false, &user_model.Redirect{LowerName: "past"}) + unittest.AssertExistsIf(t, false, &user_model.Redirect{LowerName: "recent"}) + unittest.AssertExistsIf(t, true, &user_model.Redirect{LowerName: "future"}) +} + +// NOTE: This is a unit test but written in the integration test to ensure this runs on all databases. +func TestCanClaimUsername(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + + _, err := db.GetEngine(db.DefaultContext).NoAutoTime().Insert(&user_model.Redirect{RedirectUserID: 1, LowerName: "legacy", CreatedUnix: 0}, + &user_model.Redirect{RedirectUserID: 1, LowerName: "past", CreatedUnix: timeutil.TimeStampNow().AddDuration(-48 * time.Hour)}, + &user_model.Redirect{RedirectUserID: 1, LowerName: "recent", CreatedUnix: timeutil.TimeStampNow().AddDuration(-12 * time.Hour)}, + &user_model.Redirect{RedirectUserID: 1, LowerName: "future", CreatedUnix: timeutil.TimeStampNow().AddDuration(time.Hour)}, + &user_model.Redirect{RedirectUserID: 3, LowerName: "recent-org", CreatedUnix: timeutil.TimeStampNow().AddDuration(-12 * time.Hour)}) + require.NoError(t, err) + + testCase := func(t *testing.T, legacy, past, recent, future bool, doerID int64) { + t.Helper() + + ok, _, err := user_model.CanClaimUsername(db.DefaultContext, "legacy", doerID) + require.NoError(t, err) + assert.Equal(t, legacy, ok) + + ok, _, err = user_model.CanClaimUsername(db.DefaultContext, "past", doerID) + require.NoError(t, err) + assert.Equal(t, past, ok) + + ok, _, err = user_model.CanClaimUsername(db.DefaultContext, "recent", doerID) + require.NoError(t, err) + assert.Equal(t, recent, ok) + + ok, _, err = user_model.CanClaimUsername(db.DefaultContext, "future", doerID) + require.NoError(t, err) + assert.Equal(t, future, ok) + } + + t.Run("No cooldown", func(t *testing.T) { + defer test.MockVariableValue(&setting.Service.UsernameCooldownPeriod, 0)() + + testCase(t, true, true, true, true, -1) + }) + + t.Run("1 day cooldown", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + defer test.MockVariableValue(&setting.Service.UsernameCooldownPeriod, 1)() + + testCase(t, true, true, false, false, -1) + }) + + t.Run("1 week cooldown", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + defer test.MockVariableValue(&setting.Service.UsernameCooldownPeriod, 7)() + + testCase(t, true, false, false, false, -1) + + t.Run("Own username", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + defer test.MockVariableValue(&setting.Service.UsernameCooldownPeriod, 7)() + + testCase(t, true, true, true, true, 1) + }) + }) + + t.Run("Organisation", func(t *testing.T) { + defer test.MockVariableValue(&setting.Service.UsernameCooldownPeriod, 1)() + + t.Run("Not owner", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + ok, _, err := user_model.CanClaimUsername(db.DefaultContext, "recent-org", -1) + require.NoError(t, err) + assert.False(t, ok) + }) + t.Run("Owner", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + ok, _, err := user_model.CanClaimUsername(db.DefaultContext, "recent-org", 2) + require.NoError(t, err) + assert.True(t, ok) + }) + }) +} diff --git a/tests/integration/user_test.go b/tests/integration/user_test.go index d2b5f112a3..5e02f90f9e 100644 --- a/tests/integration/user_test.go +++ b/tests/integration/user_test.go @@ -15,21 +15,22 @@ import ( "testing" "time" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" - issues_model "code.gitea.io/gitea/models/issues" - repo_model "code.gitea.io/gitea/models/repo" - 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/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/modules/translation" - gitea_context "code.gitea.io/gitea/services/context" - "code.gitea.io/gitea/services/mailer" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/models/db" + issues_model "forgejo.org/models/issues" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + api "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/modules/translation" + gitea_context "forgejo.org/services/context" + "forgejo.org/services/mailer" + "forgejo.org/tests" + "github.com/PuerkitoBio/goquery" "github.com/pquerna/otp/totp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -247,6 +248,69 @@ func testExportUserGPGKeys(t *testing.T, user, expected string) { assert.Equal(t, expected, resp.Body.String()) } +func TestAccessTokenRegenerate(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + session := loginUser(t, "user1") + prevLatestTokenName, prevLatestTokenID := findLatestTokenID(t, session) + + createApplicationSettingsToken(t, session, "TestAccessToken", auth_model.AccessTokenScopeWriteUser) + oldToken := assertAccessToken(t, session) + oldTokenName, oldTokenID := findLatestTokenID(t, session) + + assert.Equal(t, "TestAccessToken", oldTokenName) + + req := NewRequestWithValues(t, "POST", "/user/settings/applications/regenerate", map[string]string{ + "_csrf": GetCSRF(t, session, "/user/settings/applications"), + "id": strconv.Itoa(oldTokenID), + }) + session.MakeRequest(t, req, http.StatusOK) + + newToken := assertAccessToken(t, session) + newTokenName, newTokenID := findLatestTokenID(t, session) + + assert.NotEqual(t, oldToken, newToken) + assert.Equal(t, oldTokenID, newTokenID) + assert.Equal(t, "TestAccessToken", newTokenName) + + req = NewRequestWithValues(t, "POST", "/user/settings/applications/delete", map[string]string{ + "_csrf": GetCSRF(t, session, "/user/settings/applications"), + "id": strconv.Itoa(newTokenID), + }) + session.MakeRequest(t, req, http.StatusOK) + + latestTokenName, latestTokenID := findLatestTokenID(t, session) + + assert.Less(t, latestTokenID, oldTokenID) + assert.Equal(t, latestTokenID, prevLatestTokenID) + assert.Equal(t, latestTokenName, prevLatestTokenName) + assert.NotEqual(t, "TestAccessToken", latestTokenName) +} + +func findLatestTokenID(t *testing.T, session *TestSession) (string, int) { + req := NewRequest(t, "GET", "/user/settings/applications") + resp := session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + latestTokenName := "" + latestTokenID := 0 + htmlDoc.Find(".delete-button").Each(func(i int, s *goquery.Selection) { + tokenID, exists := s.Attr("data-id") + + if !exists || tokenID == "" { + return + } + + id, err := strconv.Atoi(tokenID) + require.NoError(t, err) + if id > latestTokenID { + latestTokenName = s.Parent().Parent().Find(".flex-item-title").Text() + latestTokenID = id + } + }) + + return latestTokenName, latestTokenID +} + func TestGetUserRss(t *testing.T) { defer tests.PrepareTestEnv(t)() @@ -438,8 +502,16 @@ func TestUserHints(t *testing.T) { func TestUserPronouns(t *testing.T) { defer tests.PrepareTestEnv(t)() - session := loginUser(t, "user2") - token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser) + // user1 is admin, using user2 and user10 respectively instead. + // This is explicitly mentioned here because of the unconventional + // variable naming scheme. + firstUserSession := loginUser(t, "user2") + firstUserToken := getTokenForLoggedInUser(t, firstUserSession, auth_model.AccessTokenScopeWriteUser) + + // This user has the HidePronouns setting enabled. + // Check the fixture! + secondUserSession := loginUser(t, "user10") + secondUserToken := getTokenForLoggedInUser(t, secondUserSession, auth_model.AccessTokenScopeWriteUser) adminUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{IsAdmin: true}) adminSession := loginUser(t, adminUser.Name) @@ -449,8 +521,10 @@ func TestUserPronouns(t *testing.T) { t.Run("user", func(t *testing.T) { defer tests.PrintCurrentTest(t)() - req := NewRequest(t, "GET", "/api/v1/user").AddTokenAuth(token) - resp := MakeRequest(t, req, http.StatusOK) + // secondUserToken was chosen arbitrarily and should have no impact. + // See next comment. + req := NewRequest(t, "GET", "/api/v1/user").AddTokenAuth(secondUserToken) + resp := firstUserSession.MakeRequest(t, req, http.StatusOK) // We check the raw JSON, because we want to test the response, not // what it decodes into. Contents doesn't matter, we're testing the @@ -468,16 +542,22 @@ func TestUserPronouns(t *testing.T) { // what it decodes into. Contents doesn't matter, we're testing the // presence only. assert.Contains(t, resp.Body.String(), `"pronouns":`) + + req = NewRequest(t, "GET", "/api/v1/users/user10") + resp = MakeRequest(t, req, http.StatusOK) + + // Same deal here. + assert.Contains(t, resp.Body.String(), `"pronouns":`) }) t.Run("user/settings", func(t *testing.T) { defer tests.PrintCurrentTest(t)() - // Set pronouns first + // Set pronouns first for user2 pronouns := "they/them" req := NewRequestWithJSON(t, "PATCH", "/api/v1/user/settings", &api.UserSettingsOptions{ Pronouns: &pronouns, - }).AddTokenAuth(token) + }).AddTokenAuth(firstUserToken) resp := MakeRequest(t, req, http.StatusOK) // Verify the response @@ -486,7 +566,7 @@ func TestUserPronouns(t *testing.T) { assert.Equal(t, pronouns, user.Pronouns) // Verify retrieving the settings again - req = NewRequest(t, "GET", "/api/v1/user/settings").AddTokenAuth(token) + req = NewRequest(t, "GET", "/api/v1/user/settings").AddTokenAuth(firstUserToken) resp = MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &user) @@ -497,22 +577,40 @@ func TestUserPronouns(t *testing.T) { defer tests.PrintCurrentTest(t)() // Set the pronouns for user2 - pronouns := "she/her" + pronouns := "he/him" req := NewRequestWithJSON(t, "PATCH", "/api/v1/admin/users/user2", &api.EditUserOption{ Pronouns: &pronouns, }).AddTokenAuth(adminToken) resp := MakeRequest(t, req, http.StatusOK) // Verify the API response - var user *api.User - DecodeJSON(t, resp, &user) - assert.Equal(t, pronouns, user.Pronouns) + var user2 *api.User + DecodeJSON(t, resp, &user2) + assert.Equal(t, pronouns, user2.Pronouns) - // Verify via user2 too - req = NewRequest(t, "GET", "/api/v1/user").AddTokenAuth(token) + // Verify via user2 + req = NewRequest(t, "GET", "/api/v1/user").AddTokenAuth(firstUserToken) resp = MakeRequest(t, req, http.StatusOK) - DecodeJSON(t, resp, &user) - assert.Equal(t, pronouns, user.Pronouns) + DecodeJSON(t, resp, &user2) + assert.Equal(t, pronouns, user2.Pronouns) // TODO: This fails for some reason + + // Set the pronouns for user10 + pronouns = "he/him" + req = NewRequestWithJSON(t, "PATCH", "/api/v1/admin/users/user10", &api.EditUserOption{ + Pronouns: &pronouns, + }).AddTokenAuth(adminToken) + resp = MakeRequest(t, req, http.StatusOK) + + // Verify the API response + var user10 *api.User + DecodeJSON(t, resp, &user10) + assert.Equal(t, pronouns, user10.Pronouns) + + // Verify via user10 + req = NewRequest(t, "GET", "/api/v1/user").AddTokenAuth(secondUserToken) + resp = MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &user10) + assert.Equal(t, pronouns, user10.Pronouns) }) }) @@ -520,10 +618,10 @@ func TestUserPronouns(t *testing.T) { defer tests.PrintCurrentTest(t)() // Set the pronouns to a known state via the API - pronouns := "she/her" + pronouns := "they/them" req := NewRequestWithJSON(t, "PATCH", "/api/v1/user/settings", &api.UserSettingsOptions{ Pronouns: &pronouns, - }).AddTokenAuth(token) + }).AddTokenAuth(firstUserToken) MakeRequest(t, req, http.StatusOK) t.Run("profile view", func(t *testing.T) { @@ -534,14 +632,14 @@ func TestUserPronouns(t *testing.T) { htmlDoc := NewHTMLParser(t, resp.Body) userNameAndPronouns := strings.TrimSpace(htmlDoc.Find(".profile-avatar-name .username").Text()) - assert.Contains(t, userNameAndPronouns, pronouns) + assert.NotContains(t, userNameAndPronouns, pronouns) }) t.Run("settings", func(t *testing.T) { defer tests.PrintCurrentTest(t)() req := NewRequest(t, "GET", "/user/settings") - resp := session.MakeRequest(t, req, http.StatusOK) + resp := firstUserSession.MakeRequest(t, req, http.StatusOK) htmlDoc := NewHTMLParser(t, resp.Body) // Check that the field is present @@ -550,12 +648,12 @@ func TestUserPronouns(t *testing.T) { assert.Equal(t, pronouns, pronounField) // Check that updating the field works - newPronouns := "they/them" + newPronouns := "she/her" req = NewRequestWithValues(t, "POST", "/user/settings", map[string]string{ - "_csrf": GetCSRF(t, session, "/user/settings"), + "_csrf": GetCSRF(t, firstUserSession, "/user/settings"), "pronouns": newPronouns, }) - session.MakeRequest(t, req, http.StatusSeeOther) + firstUserSession.MakeRequest(t, req, http.StatusSeeOther) user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user2"}) assert.Equal(t, newPronouns, user2.Pronouns) @@ -886,11 +984,27 @@ func TestUserActivate(t *testing.T) { assert.False(t, authToken.IsExpired()) assert.EqualValues(t, authToken.HashedValidator, auth_model.HashValidator(rawValidator)) - req = NewRequest(t, "POST", "/user/activate?code="+code) - session.MakeRequest(t, req, http.StatusOK) + t.Run("No password", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() - unittest.AssertNotExistsBean(t, &auth_model.AuthorizationToken{ID: authToken.ID}) - unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "doesnotexist", IsActive: true}) + req = NewRequest(t, "POST", "/user/activate?code="+code) + session.MakeRequest(t, req, http.StatusOK) + + unittest.AssertExistsIf(t, true, &auth_model.AuthorizationToken{ID: authToken.ID}) + unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "doesnotexist"}, "is_active = false") + }) + + t.Run("With password", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req = NewRequestWithValues(t, "POST", "/user/activate?code="+code, map[string]string{ + "password": "examplePassword!1", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + unittest.AssertExistsIf(t, false, &auth_model.AuthorizationToken{ID: authToken.ID}) + unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "doesnotexist"}, "is_active = true") + }) } func TestUserPasswordReset(t *testing.T) { diff --git a/tests/integration/version_test.go b/tests/integration/version_test.go index 144471adb2..9db586ee97 100644 --- a/tests/integration/version_test.go +++ b/tests/integration/version_test.go @@ -7,12 +7,12 @@ import ( "net/http" "testing" - auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/test" - "code.gitea.io/gitea/routers" - "code.gitea.io/gitea/tests" + auth_model "forgejo.org/models/auth" + "forgejo.org/modules/setting" + "forgejo.org/modules/structs" + "forgejo.org/modules/test" + "forgejo.org/routers" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/view_test.go b/tests/integration/view_test.go index ff2f2bdfd0..80371b84ce 100644 --- a/tests/integration/view_test.go +++ b/tests/integration/view_test.go @@ -10,13 +10,13 @@ import ( "strings" "testing" - 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/setting" - "code.gitea.io/gitea/modules/test" - files_service "code.gitea.io/gitea/services/repository/files" - "code.gitea.io/gitea/tests" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + files_service "forgejo.org/services/repository/files" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -131,7 +131,7 @@ func TestAmbiguousCharacterDetection(t *testing.T) { }) } -func TestInHistoryButton(t *testing.T) { +func TestCommitListActions(t *testing.T) { onGiteaRun(t, func(t *testing.T, u *url.URL) { user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) session := loginUser(t, user2.Name) @@ -164,6 +164,7 @@ func TestInHistoryButton(t *testing.T) { htmlDoc.AssertElement(t, fmt.Sprintf(".commit-list a[href^='/%s/src/commit/']", repo.FullName()), false) }) + fileDiffSelector := fmt.Sprintf(".commit-list a[href='/%s/commit/%s?files=test.sh']", repo.FullName(), commitID) t.Run("Commit list", func(t *testing.T) { defer tests.PrintCurrentTest(t)() @@ -172,6 +173,7 @@ func TestInHistoryButton(t *testing.T) { htmlDoc := NewHTMLParser(t, resp.Body) htmlDoc.AssertElement(t, fmt.Sprintf(".commit-list a[href='/%s/src/commit/%s']", repo.FullName(), commitID), true) + htmlDoc.AssertElement(t, fileDiffSelector, false) }) t.Run("File history", func(t *testing.T) { @@ -182,6 +184,7 @@ func TestInHistoryButton(t *testing.T) { htmlDoc := NewHTMLParser(t, resp.Body) htmlDoc.AssertElement(t, fmt.Sprintf(".commit-list a[href='/%s/src/commit/%s/test.sh']", repo.FullName(), commitID), true) + htmlDoc.AssertElement(t, fileDiffSelector, true) }) }) } diff --git a/tests/integration/webfinger_test.go b/tests/integration/webfinger_test.go index 18f509aca9..053528d919 100644 --- a/tests/integration/webfinger_test.go +++ b/tests/integration/webfinger_test.go @@ -9,10 +9,10 @@ import ( "net/url" "testing" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/tests" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/setting" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) diff --git a/tests/integration/webhook_test.go b/tests/integration/webhook_test.go index 60d4d48d7c..6d92a16dd8 100644 --- a/tests/integration/webhook_test.go +++ b/tests/integration/webhook_test.go @@ -8,17 +8,17 @@ import ( "net/url" "testing" - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - webhook_model "code.gitea.io/gitea/models/webhook" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/json" - webhook_module "code.gitea.io/gitea/modules/webhook" - "code.gitea.io/gitea/services/release" - "code.gitea.io/gitea/tests" + "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + webhook_model "forgejo.org/models/webhook" + "forgejo.org/modules/git" + "forgejo.org/modules/gitrepo" + "forgejo.org/modules/json" + webhook_module "forgejo.org/modules/webhook" + "forgejo.org/services/release" + "forgejo.org/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/tests/integration/wiki_test.go b/tests/integration/wiki_test.go index 30170086d2..3e4761b9bd 100644 --- a/tests/integration/wiki_test.go +++ b/tests/integration/wiki_test.go @@ -4,7 +4,6 @@ package integration import ( - "context" "fmt" "net/http" "net/url" @@ -13,9 +12,9 @@ import ( "strings" "testing" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/util" - "code.gitea.io/gitea/tests" + "forgejo.org/modules/git" + "forgejo.org/modules/util" + "forgejo.org/tests" "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" @@ -42,7 +41,7 @@ func TestRepoCloneWiki(t *testing.T) { u, _ = url.Parse(r) u.User = url.UserPassword("user2", userPassword) t.Run("Clone", func(t *testing.T) { - require.NoError(t, git.CloneWithArgs(context.Background(), git.AllowLFSFiltersArgs(), u.String(), dstPath, git.CloneRepoOptions{})) + require.NoError(t, git.CloneWithArgs(t.Context(), git.AllowLFSFiltersArgs(), u.String(), dstPath, git.CloneRepoOptions{})) assertFileEqual(t, filepath.Join(dstPath, "Home.md"), []byte("# Home page\n\nThis is the home page!\n")) assertFileExist(t, filepath.Join(dstPath, "Page-With-Image.md")) assertFileExist(t, filepath.Join(dstPath, "Page-With-Spaced-Name.md")) diff --git a/tests/integration/xss_test.go b/tests/integration/xss_test.go index 6ac5b062f2..94cbeaf331 100644 --- a/tests/integration/xss_test.go +++ b/tests/integration/xss_test.go @@ -8,10 +8,10 @@ import ( "net/http" "testing" - issues_model "code.gitea.io/gitea/models/issues" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/tests" + issues_model "forgejo.org/models/issues" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/tests" "github.com/stretchr/testify/assert" ) @@ -68,7 +68,7 @@ func TestXSSWikiLastCommitInfo(t *testing.T) { } func TestXSSReviewDismissed(t *testing.T) { - defer tests.AddFixtures("tests/integration/fixtures/TestXSSReviewDismissed/")() + defer unittest.OverrideFixtures("tests/integration/fixtures/TestXSSReviewDismissed")() defer tests.PrepareTestEnv(t)() review := unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 1000}) diff --git a/tests/test_utils.go b/tests/test_utils.go index 6e9374db25..6c7eb16b21 100644 --- a/tests/test_utils.go +++ b/tests/test_utils.go @@ -18,27 +18,27 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" - packages_model "code.gitea.io/gitea/models/packages" - repo_model "code.gitea.io/gitea/models/repo" - 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/base" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/graceful" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/optional" - "code.gitea.io/gitea/modules/process" - repo_module "code.gitea.io/gitea/modules/repository" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/storage" - "code.gitea.io/gitea/modules/testlogger" - "code.gitea.io/gitea/modules/util" - "code.gitea.io/gitea/routers" - repo_service "code.gitea.io/gitea/services/repository" - files_service "code.gitea.io/gitea/services/repository/files" - wiki_service "code.gitea.io/gitea/services/wiki" + "forgejo.org/models/db" + packages_model "forgejo.org/models/packages" + repo_model "forgejo.org/models/repo" + unit_model "forgejo.org/models/unit" + "forgejo.org/models/unittest" + user_model "forgejo.org/models/user" + "forgejo.org/modules/base" + "forgejo.org/modules/git" + "forgejo.org/modules/graceful" + "forgejo.org/modules/log" + "forgejo.org/modules/optional" + "forgejo.org/modules/process" + repo_module "forgejo.org/modules/repository" + "forgejo.org/modules/setting" + "forgejo.org/modules/storage" + "forgejo.org/modules/testlogger" + "forgejo.org/modules/util" + "forgejo.org/routers" + repo_service "forgejo.org/services/repository" + files_service "forgejo.org/services/repository/files" + wiki_service "forgejo.org/services/wiki" "github.com/google/uuid" "github.com/stretchr/testify/assert" @@ -68,9 +68,6 @@ func InitTest(requireGitea bool) { setting.CustomPath = filepath.Join(setting.AppWorkPath, "custom") if requireGitea { giteaBinary := "gitea" - if setting.IsWindows { - giteaBinary += ".exe" - } setting.AppPath = path.Join(giteaRoot, giteaBinary) if _, err := os.Stat(setting.AppPath); err != nil { exitf("Could not find gitea binary at %s", setting.AppPath) @@ -269,9 +266,7 @@ func cancelProcesses(t testing.TB, delay time.Duration) { } func PrepareGitRepoDirectory(t testing.TB) { - var err error - setting.RepoRootPath, err = os.MkdirTemp(t.TempDir(), "forgejo-repo-rooth") - require.NoError(t, err) + setting.RepoRootPath = t.TempDir() require.NoError(t, unittest.CopyDir(preparedDir, setting.RepoRootPath)) } @@ -344,16 +339,6 @@ func Printf(format string, args ...any) { testlogger.Printf(format, args...) } -func AddFixtures(dirs ...string) func() { - return unittest.OverrideFixtures( - unittest.FixturesOptions{ - Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"), - Base: setting.AppWorkPath, - Dirs: dirs, - }, - ) -} - type DeclarativeRepoOptions struct { Name optional.Option[string] EnabledUnits optional.Option[[]unit_model.Type] diff --git a/tools/migrate_locales.sh b/tools/migrate_locales.sh new file mode 100755 index 0000000000..f02fe702cc --- /dev/null +++ b/tools/migrate_locales.sh @@ -0,0 +1,145 @@ +#!/bin/bash + +# Copyright 2024 The Forgejo Authors. All rights reserved. +# SPDX-License-Identifier: MIT + +if [ -z "$1" ] || [ -z "$2" ] +then + echo "USAGE: $0 section key [key1 [keyN]]" + exit 1 +fi + +if ! [ -d ../options/locale_next ] +then + echo 'Call this script from the `tools` directory.' + exit 1 +fi + +destsection="$1" +keyJSON="$destsection.$2" +key1="" +keyN="" +if [ -n "$3" ] +then + key1="$3" +else + key1="$2" +fi +if [ -n "$4" ] +then + keyN="$4" +fi + +cd ../options/locale + +# Migrate the string in one file. +function process() { + file="$1" + exec 3<$file + + val1="" + valN="" + cursection="" + line1=0 + lineN=0 + lineNumber=0 + + # Parse the file + while read -u 3 line + do + ((++lineNumber)) + if [[ $line =~ ^\[[-._a-zA-Z0-9]+\]$ ]] + then + cursection="${line#[}" + cursection="${cursection%]}" + elif [ "$cursection" = "$destsection" ] + then + key="${line%%=*}" + value="${line#*=}" + key="$(echo $key)" # Trim leading/trailing whitespace + value="$(echo $value)" + + if [ "$key" = "$key1" ] + then + val1="$value" + line1=$lineNumber + fi + if [ -n "$keyN" ] && [ "$key" = "$keyN" ] + then + valN="$value" + lineN=$lineNumber + fi + + if [ -n "$val1" ] && ( [ -n "$valN" ] || [ -z "$keyN" ] ) + then + # Found all desired strings + break + fi + fi + done + + if [ -n "$val1" ] || [ -n "$valN" ] + then + localename="${file#locale_}" + localename="${localename%.ini}" + localename="${localename%-*}" + + if [ "$file" = "locale_en-US.ini" ] + then + # Delete migrated string from source file + if [ $line1 -gt 0 ] && [ $lineN -gt 0 ] && [ $lineN -ne $line1 ] + then + sed -i "${line1}d;${lineN}d" "$file" + elif [ $line1 -gt 0 ] + then + sed -i "${line1}d" "$file" + elif [ $lineN -gt 0 ] + then + sed -i "${lineN}d" "$file" + fi + fi + + # Write JSON + jsonfile="../locale_next/${file/.ini/.json}" + + pluralform="other" + oneform="one" + case $localename in + "be" | "bs" | "cnr" | "csb" | "hr" | "lt" | "pl" | "ru" | "sr" | "szl" | "uk" | "wen") + # These languages have no "other" form and use "many" instead. + pluralform="many" + ;; + "ace" | "ay" | "bm" | "bo" | "cdo" | "cpx" | "crh" | "dz" | "gan" | "hak" | "hnj" | "hsn" | "id" | "ig" | "ii" | "ja" | "jbo" | "jv" | "kde" | "kea" | "km" | "ko" | "kos" | "lkt" | "lo" | "lzh" | "ms" | "my" | "nan" | "nqo" | "osa" | "sah" | "ses" | "sg" | "son" | "su" | "th" | "tlh" | "to" | "tok" | "tpi" | "tt" | "vi" | "wo" | "wuu" | "yo" | "yue" | "zh") + # These languages have no singular form. + oneform="" + ;; + *) + ;; + esac + + content="" + if [ -z "$keyN" ] + then + content="$(jq --arg val "$val1" ".$keyJSON = \$val" < "$jsonfile")" + else + object='{}' + if [ -n "$val1" ] && [ -n "$oneform" ] + then + object=$(jq --arg val "$val1" ".$oneform = \$val" <<< "$object") + fi + if [ -n "$valN" ] + then + object=$(jq --arg val "$valN" ".$pluralform = \$val" <<< "$object") + fi + content="$(jq --argjson val "$object" ".$keyJSON = \$val" < "$jsonfile")" + fi + jq . <<< "$content" > "$jsonfile" + fi +} + +for file in *.ini +do + process "$file" & +done +wait + diff --git a/web_src/css/base.css b/web_src/css/base.css index dd761a1b75..ad6e8a2a24 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -948,7 +948,15 @@ img.ui.avatar, @media (max-width: 767.98px) { .ui.pagination.menu .item:not(.active,.navigation), .ui.pagination.menu .item.navigation span.navigation_label { - display: none; + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; } } @@ -1050,6 +1058,7 @@ overflow-menu .overflow-menu-items { overflow-menu .overflow-menu-items .item { margin-bottom: 0 !important; /* reset fomantic's margin, because the active menu has special bottom border */ + height: 100%; } overflow-menu .ui.label { diff --git a/web_src/css/dashboard.css b/web_src/css/dashboard.css index 4bb9fa38bf..3a1fc34ed3 100644 --- a/web_src/css/dashboard.css +++ b/web_src/css/dashboard.css @@ -79,3 +79,7 @@ .dashboard .secondary-nav .ui.dropdown { max-width: 100%; } + +.dashboard .help { + color: var(--color-secondary-dark-8); +} diff --git a/web_src/css/features/gitgraph.css b/web_src/css/features/gitgraph.css index 4da871da61..726ac7e9e2 100644 --- a/web_src/css/features/gitgraph.css +++ b/web_src/css/features/gitgraph.css @@ -23,6 +23,18 @@ #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) { @@ -34,15 +46,10 @@ #git-graph-heading-left { margin-bottom: 1rem; } - - h2, - #flow-select-refs-dropdown { - max-width: 100%; - } } #git-graph-container #flow-select-refs-dropdown { - min-width: 250px; + flex-wrap: wrap; } #git-graph-container #flow-select-refs-dropdown .ui.label { diff --git a/web_src/css/home.css b/web_src/css/home.css index 22f1a2dc98..84dd793612 100644 --- a/web_src/css/home.css +++ b/web_src/css/home.css @@ -70,7 +70,7 @@ .page-footer .right-links > a { border-left: 1px solid var(--color-secondary-dark-1); padding-left: 8px; - margin-left: 5px; + margin-left: 8px; } .page-footer .ui.dropdown.language .menu { diff --git a/web_src/css/index.css b/web_src/css/index.css index 49ceb2c8ce..12830299cf 100644 --- a/web_src/css/index.css +++ b/web_src/css/index.css @@ -17,6 +17,7 @@ @import "./modules/checkbox.css"; @import "./modules/modal.css"; +@import "./modules/switch.css"; @import "./modules/select.css"; @import "./modules/tippy.css"; @import "./modules/breadcrumb.css"; diff --git a/web_src/css/modules/switch.css b/web_src/css/modules/switch.css new file mode 100644 index 0000000000..7780155787 --- /dev/null +++ b/web_src/css/modules/switch.css @@ -0,0 +1,35 @@ +.switch { + display: grid; + grid-auto-flow: column; + height: fit-content; + align-items: center; + align-self: center; + background: var(--color-menu); + border: 1px solid var(--color-input-border); + border-radius: var(--border-radius); +} + +.switch .item { + display: flex; + gap: 0.5rem; + align-items: center; + padding: .5em 1.125em; + color: var(--color-text); + border-radius: var(--border-radius); + text-wrap: nowrap; +} + +.switch .active.item { + background: var(--color-active); + outline: 1px solid var(--color-input-border); +} + +@media (pointer: coarse) { + .switch .item { + padding: .75em 1.125em; + } +} + +.switch button.item { + background: transparent; +} diff --git a/web_src/css/repo.css b/web_src/css/repo.css index 651c69c703..a2982b3eb3 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -153,7 +153,9 @@ border-radius: 0 var(--border-radius) var(--border-radius) 0 !important; } -.repository .clone-panel .dropdown .menu { +/* Dropdown alignment */ +.repository .clone-panel .dropdown .menu, +.repository .folder-actions .dropdown .menu { right: 0 !important; left: auto !important; } @@ -758,7 +760,7 @@ td .commit-summary { .repository.view.issue .comment-list .timeline-item, .repository.view.issue .comment-list .timeline-item-group { - padding: 16px 0; + padding: 0.65rem 0; } .repository.view.issue .comment-list .timeline-item-group .timeline-item { @@ -841,6 +843,18 @@ td .commit-summary { margin-right: 0.25em; } +.repository.view.issue .comment-list .timeline-item .aggregated-actions .badge { + width: 20px; + height: 20px; + margin-top: 5px; + padding: 12px; +} + +.repository.view.issue .comment-list .timeline-item .aggregated-actions .badge .svg { + width: 20px; + height: 20px; +} + .singular-commit { display: flex; align-items: center; @@ -891,15 +905,18 @@ td .commit-summary { background: var(--color-orange-badge-hover-bg) !important; } -.repository.view.issue .comment-list .timeline-item .comparebox { - line-height: 32px; - vertical-align: middle; +@media (min-width: 768px) { + .repository.view.issue .comment-list .timeline-item .forced-push { + display: grid; + grid-template-columns: 1fr auto; + column-gap: 1rem; + } } -.repository.view.issue .comment-list .timeline-item .comparebox .compare.label { +.repository.view.issue .comment-list .timeline-item .compare.label { font-size: 1rem; - margin: 0; border: 1px solid var(--color-light-border); + height: fit-content; } @media (max-width: 767.98px) { @@ -1140,6 +1157,19 @@ td .commit-summary { text-align: center; } +.branch-tag-tab { + padding: 0 10px 10px; +} + +.branch-tag-item { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0 10px; + border: 1px solid transparent; + border-bottom: none; +} + .repository.compare.pull .comment.form .content::before, .repository.compare.pull .comment.form .content::after { right: 100%; @@ -1710,26 +1740,6 @@ td .commit-summary { max-width: initial; /* remove fomantic over 100% width */ } -.repository .diff-stats { - clear: both; - margin-bottom: 5px; - max-height: 200px; - height: fit-content; - overflow: auto; - padding-left: 0; -} - -.repository .diff-stats li { - list-style: none; - padding-bottom: 4px; - margin-bottom: 4px; - padding-left: 6px; -} - -.repository .diff-stats li + li { - border-top: 1px solid var(--color-secondary); -} - .repository .repo-search-result { padding-top: 10px; padding-bottom: 10px; @@ -1840,10 +1850,6 @@ details.repo-search-result summary::marker { color: var(--color-success-text); } -.repository .ui.attached.isSigned.isVerified.message .pull-right { - color: var(--color-text); -} - .repository .ui.attached.isSigned.isVerified.message .ui.text { color: var(--color-success-text); } @@ -2047,13 +2053,22 @@ details.repo-search-result summary::marker { font-weight: var(--font-weight-medium); } -.repository .repository-summary .segment.language-stats { +.repository .repository-summary #language-stats-bar { display: flex; gap: 2px; padding: 0; height: 10px; white-space: nowrap; - border-radius: 0 0 3px 3px !important; + border-top-left-radius: 0 !important; + border-top-right-radius: 0 !important; + overflow: hidden; +} + +.size-overview .segment:has(> .bar) { + display: flex; + height: 10px; + padding: 0; + border-radius: 3px; overflow: hidden; } @@ -2272,7 +2287,7 @@ details.repo-search-result summary::marker { } .timeline .ui.comment-header { - padding: 0.5rem 1rem; + padding: 0.25rem 0.75rem; } .comment-header::before, @@ -2426,6 +2441,11 @@ 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; } @@ -2902,7 +2922,7 @@ tbody.commit-list { .commit-status-header { /* reset the default ".ui.attached.header" styles, to use the outer border */ border: none !important; - /* add a bottom border to make sure the there is always a divider between the header and list when the list is scrolling */ + /* add a bottom border to make sure there is always a divider between the header and list when the list is scrolling */ border-bottom: 1px solid var(--color-secondary) !important; /* use negative margin to avoid the newly added border conflict with the list's top border */ margin: 0 0 -1px !important; diff --git a/web_src/css/repo/issue-list.css b/web_src/css/repo/issue-list.css index 9143b01384..07ae5a5683 100644 --- a/web_src/css/repo/issue-list.css +++ b/web_src/css/repo/issue-list.css @@ -2,7 +2,7 @@ display: flex; flex-wrap: wrap-reverse; justify-content: space-between; - align-items: flex-start; + align-items: center; gap: 1rem; margin-top: 1rem; } diff --git a/web_src/css/shared/milestone.css b/web_src/css/shared/milestone.css index 91e6b5e387..8578a09b5b 100644 --- a/web_src/css/shared/milestone.css +++ b/web_src/css/shared/milestone.css @@ -29,6 +29,13 @@ justify-content: space-between; } +.milestone-header h3 { + display: flex; + align-items: center; + margin: 0; + gap: 0.5rem; +} + .milestone-toolbar { padding-top: 5px; display: flex; diff --git a/web_src/css/themes/theme-forgejo-dark.css b/web_src/css/themes/theme-forgejo-dark.css index bc321f38a8..c9c538502d 100644 --- a/web_src/css/themes/theme-forgejo-dark.css +++ b/web_src/css/themes/theme-forgejo-dark.css @@ -326,8 +326,8 @@ i.grey.icon.icon.icon.icon { .ui.ui.ui.basic.primary.label { color: var(--color-text-dark) !important; } -.ui.basic.yellow.label.pending-label { - background: var(--color-light) !important; +.ui.yellow.label.pending-label { + color: var(--color-warning-text) !important; } ::selection { background: var(--steel-100) !important; diff --git a/web_src/css/themes/theme-forgejo-light.css b/web_src/css/themes/theme-forgejo-light.css index c86ea53314..a5e4ffe050 100644 --- a/web_src/css/themes/theme-forgejo-light.css +++ b/web_src/css/themes/theme-forgejo-light.css @@ -314,10 +314,9 @@ .ui.ui.ui.basic.primary.label { color: var(--color-text-dark) !important; } -.ui.basic.yellow.label.pending-label { +.ui.yellow.label.pending-label { background: var(--color-warning-bg) !important; - color: var(--color-warning-text) !important; - border-color: var(--color-yellow-light) !important; + color: var(--color-text-dark) !important; } ::selection { background: var(--steel-450) !important; diff --git a/web_src/fomantic/build/semantic.js b/web_src/fomantic/build/semantic.js index affd6a4bd0..fb68705c08 100644 --- a/web_src/fomantic/build/semantic.js +++ b/web_src/fomantic/build/semantic.js @@ -344,7 +344,7 @@ $.api = $.fn.api = function(parameters) { cancelled: function() { return (module.cancelled || false); }, - succesful: function() { // codespell-ignore + succesful: function() { // codespell:ignore module.verbose('This behavior will be deleted due to typo. Use "was successful" instead.'); return module.was.successful(); }, diff --git a/web_src/fomantic/package-lock.json b/web_src/fomantic/package-lock.json index 7e0317629a..f3fb7fc8a8 100644 --- a/web_src/fomantic/package-lock.json +++ b/web_src/fomantic/package-lock.json @@ -132,17 +132,17 @@ } }, "node_modules/@octokit/core": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.2.tgz", - "integrity": "sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.4.tgz", + "integrity": "sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==", "license": "MIT", "peer": true, "dependencies": { "@octokit/auth-token": "^5.0.0", - "@octokit/graphql": "^8.0.0", - "@octokit/request": "^9.0.0", - "@octokit/request-error": "^6.0.1", - "@octokit/types": "^13.0.0", + "@octokit/graphql": "^8.1.2", + "@octokit/request": "^9.2.1", + "@octokit/request-error": "^6.1.7", + "@octokit/types": "^13.6.2", "before-after-hook": "^3.0.2", "universal-user-agent": "^7.0.0" }, @@ -151,9 +151,9 @@ } }, "node_modules/@octokit/core/node_modules/@octokit/auth-token": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.1.tgz", - "integrity": "sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", + "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==", "license": "MIT", "peer": true, "engines": { @@ -161,13 +161,13 @@ } }, "node_modules/@octokit/core/node_modules/@octokit/endpoint": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.1.tgz", - "integrity": "sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==", + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz", + "integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==", "license": "MIT", "peer": true, "dependencies": { - "@octokit/types": "^13.0.0", + "@octokit/types": "^13.6.2", "universal-user-agent": "^7.0.2" }, "engines": { @@ -175,22 +175,23 @@ } }, "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", - "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", "license": "MIT", "peer": true }, "node_modules/@octokit/core/node_modules/@octokit/request": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.3.tgz", - "integrity": "sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz", + "integrity": "sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==", "license": "MIT", "peer": true, "dependencies": { - "@octokit/endpoint": "^10.0.0", - "@octokit/request-error": "^6.0.1", - "@octokit/types": "^13.1.0", + "@octokit/endpoint": "^10.1.3", + "@octokit/request-error": "^6.1.7", + "@octokit/types": "^13.6.2", + "fast-content-type-parse": "^2.0.0", "universal-user-agent": "^7.0.2" }, "engines": { @@ -198,26 +199,26 @@ } }, "node_modules/@octokit/core/node_modules/@octokit/request-error": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.5.tgz", - "integrity": "sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz", + "integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==", "license": "MIT", "peer": true, "dependencies": { - "@octokit/types": "^13.0.0" + "@octokit/types": "^13.6.2" }, "engines": { "node": ">= 18" } }, "node_modules/@octokit/core/node_modules/@octokit/types": { - "version": "13.6.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.6.2.tgz", - "integrity": "sha512-WpbZfZUcZU77DrSW4wbsSgTPfKcp286q3ItaIgvSbBpZJlu6mnYXAkjZz6LVZPXkEvLIM8McanyZejKTYUHipA==", + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", "license": "MIT", "peer": true, "dependencies": { - "@octokit/openapi-types": "^22.2.0" + "@octokit/openapi-types": "^24.2.0" } }, "node_modules/@octokit/core/node_modules/before-after-hook": { @@ -252,14 +253,14 @@ "license": "ISC" }, "node_modules/@octokit/graphql": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.1.1.tgz", - "integrity": "sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.1.tgz", + "integrity": "sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw==", "license": "MIT", "peer": true, "dependencies": { - "@octokit/request": "^9.0.0", - "@octokit/types": "^13.0.0", + "@octokit/request": "^9.2.2", + "@octokit/types": "^13.8.0", "universal-user-agent": "^7.0.0" }, "engines": { @@ -267,13 +268,13 @@ } }, "node_modules/@octokit/graphql/node_modules/@octokit/endpoint": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.1.tgz", - "integrity": "sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==", + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz", + "integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==", "license": "MIT", "peer": true, "dependencies": { - "@octokit/types": "^13.0.0", + "@octokit/types": "^13.6.2", "universal-user-agent": "^7.0.2" }, "engines": { @@ -281,22 +282,23 @@ } }, "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", - "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", "license": "MIT", "peer": true }, "node_modules/@octokit/graphql/node_modules/@octokit/request": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.3.tgz", - "integrity": "sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz", + "integrity": "sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==", "license": "MIT", "peer": true, "dependencies": { - "@octokit/endpoint": "^10.0.0", - "@octokit/request-error": "^6.0.1", - "@octokit/types": "^13.1.0", + "@octokit/endpoint": "^10.1.3", + "@octokit/request-error": "^6.1.7", + "@octokit/types": "^13.6.2", + "fast-content-type-parse": "^2.0.0", "universal-user-agent": "^7.0.2" }, "engines": { @@ -304,26 +306,26 @@ } }, "node_modules/@octokit/graphql/node_modules/@octokit/request-error": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.5.tgz", - "integrity": "sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz", + "integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==", "license": "MIT", "peer": true, "dependencies": { - "@octokit/types": "^13.0.0" + "@octokit/types": "^13.6.2" }, "engines": { "node": ">= 18" } }, "node_modules/@octokit/graphql/node_modules/@octokit/types": { - "version": "13.6.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.6.2.tgz", - "integrity": "sha512-WpbZfZUcZU77DrSW4wbsSgTPfKcp286q3ItaIgvSbBpZJlu6mnYXAkjZz6LVZPXkEvLIM8McanyZejKTYUHipA==", + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", "license": "MIT", "peer": true, "dependencies": { - "@octokit/openapi-types": "^22.2.0" + "@octokit/openapi-types": "^24.2.0" } }, "node_modules/@octokit/graphql/node_modules/universal-user-agent": { @@ -492,9 +494,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "version": "22.13.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.11.tgz", + "integrity": "sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g==", "license": "MIT", "dependencies": { "undici-types": "~6.20.0" @@ -1115,9 +1117,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", - "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "funding": [ { "type": "opencollective", @@ -1209,9 +1211,9 @@ } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -1222,13 +1224,13 @@ } }, "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -1247,9 +1249,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001690", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", - "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", + "version": "1.0.30001707", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz", + "integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==", "funding": [ { "type": "opencollective", @@ -1991,9 +1993,9 @@ } }, "node_modules/editorconfig/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -2003,9 +2005,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.75", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.75.tgz", - "integrity": "sha512-Lf3++DumRE/QmweGjU+ZcKqQ+3bKkU/qjaKYhIJKEOhgIO9Xs6IiAQFkfFoj+RhgDk4LUeNsLo6plExHqSyu6Q==", + "version": "1.5.123", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.123.tgz", + "integrity": "sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -2064,9 +2066,9 @@ } }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -2330,6 +2332,23 @@ "node": ">= 0.10" } }, + "node_modules/fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "peer": true + }, "node_modules/fast-levenshtein": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", @@ -2532,12 +2551,12 @@ } }, "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -2713,21 +2732,21 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", - "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "dunder-proto": "^1.0.0", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "math-intrinsics": "^1.0.0" + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -2742,6 +2761,19 @@ "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", "license": "ISC" }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -4220,6 +4252,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", "integrity": "sha512-0B4Y53I0OgHUJkt+7RmlDFWKjVAI/YUpWNiL9GQz5ORDr4ttgfQGo+phBWKFLJbBdtOwgMuUkdOHOnPg45jKmQ==", + "deprecated": "This package is deprecated. Use https://socket.dev/npm/package/eta instead.", "license": "MIT", "dependencies": { "lodash._basecopy": "^3.0.0", @@ -4965,16 +4998,16 @@ "license": "MIT" }, "node_modules/js-beautify": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.1.tgz", - "integrity": "sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz", + "integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==", "license": "MIT", "dependencies": { "config-chain": "^1.1.13", "editorconfig": "^1.0.4", - "glob": "^10.3.3", + "glob": "^10.4.2", "js-cookie": "^3.0.5", - "nopt": "^7.2.0" + "nopt": "^7.2.1" }, "bin": { "css-beautify": "js/bin/css-beautify.js", @@ -5321,6 +5354,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", "integrity": "sha512-GhrVeweiTD6uTmmn5hV/lzgCQhccwReIVRLHp7LT4SopOjqEZ5BbX8b5WWEtAKasjmy8hR7ZPwsYlxRCku5odg==", + "deprecated": "This package is deprecated. Use structuredClone instead.", "license": "MIT" }, "node_modules/lodash.defaults": { @@ -5352,6 +5386,7 @@ "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", "license": "MIT" }, "node_modules/lodash.isarguments": { @@ -5402,6 +5437,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", + "deprecated": "This package is deprecated. Use destructuring assignment syntax instead.", "license": "MIT" }, "node_modules/lodash.restparam": { @@ -5420,6 +5456,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "deprecated": "This package is deprecated. Use https://socket.dev/npm/package/eta instead.", "license": "MIT", "dependencies": { "lodash._reinterpolate": "^3.0.0", @@ -5813,9 +5850,9 @@ "license": "ISC" }, "node_modules/nan": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", - "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz", + "integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==", "license": "MIT", "optional": true }, @@ -7472,9 +7509,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", "license": "CC0-1.0" }, "node_modules/split-string": { @@ -8287,9 +8324,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "funding": [ { "type": "opencollective", @@ -8307,7 +8344,7 @@ "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" diff --git a/web_src/js/components/ActionRunStatus.vue b/web_src/js/components/ActionRunStatus.vue index eb7f780fbe..db380f0038 100644 --- a/web_src/js/components/ActionRunStatus.vue +++ b/web_src/js/components/ActionRunStatus.vue @@ -29,12 +29,12 @@ export default { diff --git a/web_src/js/components/DashboardRepoList.vue b/web_src/js/components/DashboardRepoList.vue index 007891a39f..4b48376088 100644 --- a/web_src/js/components/DashboardRepoList.vue +++ b/web_src/js/components/DashboardRepoList.vue @@ -1,5 +1,5 @@ - diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue index 136ad3693d..75afd708ef 100644 --- a/web_src/js/components/RepoActionView.vue +++ b/web_src/js/components/RepoActionView.vue @@ -30,7 +30,6 @@ const sfc = { intervalID: null, currentJobStepsStates: [], artifacts: [], - onHoverRerunIndex: -1, menuVisible: false, isFullScreen: false, timeVisible: { @@ -263,7 +262,7 @@ const sfc = { try { this.loading = true; - // Since no async operations occured since fetching myLoadingLogCursors, we can be sure that we have the most + // Since no async operations occurred since fetching myLoadingLogCursors, we can be sure that we have the most // recent needed log cursors, so we can reset needLoadingWithLogCursors -- it could be stale if exceptions // occurred in previous load attempts. this.needLoadingWithLogCursors = null; @@ -457,13 +456,13 @@ export function initRepositoryActionView() {
- +
{{ job.name }}
- + {{ job.duration }}
diff --git a/web_src/js/components/RepoBranchTagSelector.vue b/web_src/js/components/RepoBranchTagSelector.vue index bfba2037cc..881c7c09ea 100644 --- a/web_src/js/components/RepoBranchTagSelector.vue +++ b/web_src/js/components/RepoBranchTagSelector.vue @@ -54,12 +54,12 @@ const sfc = { if (this.viewType === 'tree') { this.isViewTree = true; this.refNameText = this.commitIdShort; - } else if (this.viewType === 'tag') { - this.isViewTag = true; - this.refNameText = this.tagName; - } else { + } else if (this.viewType === 'branch') { this.isViewBranch = true; this.refNameText = this.branchName; + } else { + this.isViewTag = true; + this.refNameText = this.tagName; } document.body.addEventListener('click', (event) => { @@ -252,11 +252,12 @@ export default sfc; // activate IDE's Vue plugin - +