mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-10-10 19:32:02 +00:00
refactor and add e2e js tests
This commit is contained in:
parent
922cd52f1b
commit
1d0cff2368
7 changed files with 139 additions and 67 deletions
|
@ -82,6 +82,15 @@ type Issue struct {
|
||||||
PinOrder int `json:"pin_order"`
|
PinOrder int `json:"pin_order"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IssueSuggestion struct {
|
||||||
|
Index int64 `json:"number"`
|
||||||
|
State StateType `json:"state"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
IsPr bool `json:"is_pr"`
|
||||||
|
HasMerged bool `json:"merged"`
|
||||||
|
IsWorkInProgress bool `json:"draft"`
|
||||||
|
}
|
||||||
|
|
||||||
// CreateIssueOption options to create one issue
|
// CreateIssueOption options to create one issue
|
||||||
type CreateIssueOption struct {
|
type CreateIssueOption struct {
|
||||||
// required:true
|
// required:true
|
||||||
|
|
|
@ -24,9 +24,9 @@ func IssueSuggestions(ctx *context.Context) {
|
||||||
isPull = optional.Some(false)
|
isPull = optional.Some(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
suggestions, err := issue_service.GetSuggestion(ctx, ctx.Repo.Repository, isPull)
|
suggestions, err := issue_service.GetSuggestions(ctx, ctx.Repo.Repository, isPull)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetSuggestion", err)
|
ctx.ServerError("GetSuggestions", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
|
||||||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package issue
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"forgejo.org/models/db"
|
|
||||||
repo_model "forgejo.org/models/repo"
|
|
||||||
"forgejo.org/models/unittest"
|
|
||||||
"forgejo.org/modules/optional"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Suggestion(t *testing.T) {
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
isPull optional.Option[bool]
|
|
||||||
expectedIndexes []int64
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "All",
|
|
||||||
expectedIndexes: []int64{5, 1, 4, 2, 3},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
|
||||||
t.Run(testCase.name, func(t *testing.T) {
|
|
||||||
issues, err := GetSuggestion(db.DefaultContext, repo1, testCase.isPull)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
issueIndexes := make([]int64, 0, len(issues))
|
|
||||||
for _, issue := range issues {
|
|
||||||
issueIndexes = append(issueIndexes, issue.Index)
|
|
||||||
}
|
|
||||||
assert.Equal(t, testCase.expectedIndexes, issueIndexes)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"forgejo.org/modules/structs"
|
"forgejo.org/modules/structs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetSuggestion(ctx context.Context, repo *repo_model.Repository, isPull optional.Option[bool]) ([]*structs.Issue, error) {
|
func GetSuggestions(ctx context.Context, repo *repo_model.Repository, isPull optional.Option[bool]) ([]*structs.IssueSuggestion, error) {
|
||||||
var issues issues_model.IssueList
|
var issues issues_model.IssueList
|
||||||
var err error
|
var err error
|
||||||
pageSize := 1000
|
pageSize := 1000
|
||||||
|
@ -26,20 +26,18 @@ func GetSuggestion(ctx context.Context, repo *repo_model.Repository, isPull opti
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
suggestions := make([]*structs.Issue, 0, len(issues))
|
suggestions := make([]*structs.IssueSuggestion, 0, len(issues))
|
||||||
for _, issue := range issues {
|
for _, issue := range issues {
|
||||||
suggestion := &structs.Issue{
|
suggestion := &structs.IssueSuggestion{
|
||||||
ID: issue.ID,
|
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Title: issue.Title,
|
Title: issue.Title,
|
||||||
State: issue.State(),
|
State: issue.State(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if issue.IsPull && issue.PullRequest != nil {
|
if issue.IsPull && issue.PullRequest != nil {
|
||||||
suggestion.PullRequest = &structs.PullRequestMeta{
|
suggestion.IsPr = true
|
||||||
HasMerged: issue.PullRequest.HasMerged,
|
suggestion.HasMerged = issue.PullRequest.HasMerged
|
||||||
IsWorkInProgress: issue.PullRequest.IsWorkInProgress(ctx),
|
suggestion.IsWorkInProgress = issue.PullRequest.IsWorkInProgress(ctx)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
suggestions = append(suggestions, suggestion)
|
suggestions = append(suggestions, suggestion)
|
||||||
}
|
}
|
84
services/issue/suggestions_test.go
Normal file
84
services/issue/suggestions_test.go
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||||
|
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package issue
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"forgejo.org/models/db"
|
||||||
|
repo_model "forgejo.org/models/repo"
|
||||||
|
"forgejo.org/models/unittest"
|
||||||
|
"forgejo.org/modules/optional"
|
||||||
|
"forgejo.org/modules/structs"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Suggestions(t *testing.T) {
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
isPull optional.Option[bool]
|
||||||
|
expectedSuggestion []*structs.IssueSuggestion
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "All",
|
||||||
|
expectedSuggestion: []*structs.IssueSuggestion{
|
||||||
|
{
|
||||||
|
Index: 5,
|
||||||
|
State: "open",
|
||||||
|
Title: "pull5",
|
||||||
|
IsPr: true,
|
||||||
|
HasMerged: false,
|
||||||
|
IsWorkInProgress: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 1,
|
||||||
|
State: "open",
|
||||||
|
Title: "issue1",
|
||||||
|
IsPr: false,
|
||||||
|
HasMerged: false,
|
||||||
|
IsWorkInProgress: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 4,
|
||||||
|
State: "closed",
|
||||||
|
Title: "issue5",
|
||||||
|
IsPr: false,
|
||||||
|
HasMerged: false,
|
||||||
|
IsWorkInProgress: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 2,
|
||||||
|
State: "open",
|
||||||
|
Title: "issue2",
|
||||||
|
IsPr: true,
|
||||||
|
HasMerged: true,
|
||||||
|
IsWorkInProgress: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 3,
|
||||||
|
State: "open",
|
||||||
|
Title: "issue3",
|
||||||
|
IsPr: true,
|
||||||
|
HasMerged: false,
|
||||||
|
IsWorkInProgress: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
|
suggestion, err := GetSuggestions(db.DefaultContext, repo1, testCase.isPull)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, testCase.expectedSuggestion, suggestion)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -413,8 +413,14 @@ test('text expander has higher prio then prefix continuation', async ({page}) =>
|
||||||
await textarea.press('Enter');
|
await textarea.press('Enter');
|
||||||
await expect(textarea).toHaveValue(`* first\n* 😸\n* @user2 `);
|
await expect(textarea).toHaveValue(`* first\n* 😸\n* @user2 `);
|
||||||
|
|
||||||
|
// Test issue completion
|
||||||
await textarea.press('Enter');
|
await textarea.press('Enter');
|
||||||
await expect(textarea).toHaveValue(`* first\n* 😸\n* @user2 \n* `);
|
await textarea.pressSequentially('#pull');
|
||||||
|
await textarea.press('Enter');
|
||||||
|
await expect(textarea).toHaveValue(`* first\n* 😸\n* @user2 \n* #5 `);
|
||||||
|
|
||||||
|
await textarea.press('Enter');
|
||||||
|
await expect(textarea).toHaveValue(`* first\n* 😸\n* @user2 \n* #5 \n* `);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Combo Markdown: preview mode switch', async ({page}) => {
|
test('Combo Markdown: preview mode switch', async ({page}) => {
|
||||||
|
@ -456,3 +462,28 @@ test('Combo Markdown: preview mode switch', async ({page}) => {
|
||||||
await expect(previewPanel).toBeHidden();
|
await expect(previewPanel).toBeHidden();
|
||||||
await save_visual(page);
|
await save_visual(page);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('issue suggestions', async ({page}) => {
|
||||||
|
const response = await page.goto('/user2/repo1/issues/1');
|
||||||
|
expect(response?.status()).toBe(200);
|
||||||
|
|
||||||
|
const textarea = page.locator('#comment-form textarea[name=content]');
|
||||||
|
|
||||||
|
await textarea.focus();
|
||||||
|
await textarea.pressSequentially('#');
|
||||||
|
|
||||||
|
const suggestionList = page.locator('#comment-form .suggestions');
|
||||||
|
await expect(suggestionList).toBeVisible();
|
||||||
|
|
||||||
|
const expectedSuggestions = [
|
||||||
|
{ number: '5', label: 'pull5' },
|
||||||
|
{ number: '4', label: 'issue5' },
|
||||||
|
{ number: '3', label: 'issue3' },
|
||||||
|
{ number: '2', label: 'issue2' },
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const suggestion of expectedSuggestions) {
|
||||||
|
const entry = suggestionList.locator(`li:has-text("${suggestion.number}") >> text="${suggestion.label}"`);
|
||||||
|
await expect(entry).toBeVisible();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
|
@ -2,13 +2,13 @@ import {GET} from '../modules/fetch.js';
|
||||||
import {parseIssueHref, parseRepoOwnerPathInfo} from '../utils.js';
|
import {parseIssueHref, parseRepoOwnerPathInfo} from '../utils.js';
|
||||||
|
|
||||||
export function getIssueIcon(issue) {
|
export function getIssueIcon(issue) {
|
||||||
if (issue.pull_request) {
|
if (issue.is_pr) {
|
||||||
if (issue.state === 'open') {
|
if (issue.state === 'open') {
|
||||||
if (issue.pull_request.draft === true) {
|
if (issue.draft === true) {
|
||||||
return 'octicon-git-pull-request-draft'; // WIP PR
|
return 'octicon-git-pull-request-draft'; // WIP PR
|
||||||
}
|
}
|
||||||
return 'octicon-git-pull-request'; // Open PR
|
return 'octicon-git-pull-request'; // Open PR
|
||||||
} else if (issue.pull_request.merged === true) {
|
} else if (issue.merged === true) {
|
||||||
return 'octicon-git-merge'; // Merged PR
|
return 'octicon-git-merge'; // Merged PR
|
||||||
}
|
}
|
||||||
return 'octicon-git-pull-request'; // Closed PR
|
return 'octicon-git-pull-request'; // Closed PR
|
||||||
|
@ -19,10 +19,10 @@ export function getIssueIcon(issue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getIssueColor(issue) {
|
export function getIssueColor(issue) {
|
||||||
if (issue.pull_request) {
|
if (issue.is_pr) {
|
||||||
if (issue.pull_request.draft === true) {
|
if (issue.draft === true) {
|
||||||
return 'grey'; // WIP PR
|
return 'grey'; // WIP PR
|
||||||
} else if (issue.pull_request.merged === true) {
|
} else if (issue.merged === true) {
|
||||||
return 'purple'; // Merged PR
|
return 'purple'; // Merged PR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,9 +44,6 @@ export async function fetchIssueSuggestions() {
|
||||||
issuePathInfo.repoName = repoOwnerPathInfo.repoName;
|
issuePathInfo.repoName = repoOwnerPathInfo.repoName;
|
||||||
// then no issuePathInfo.indexString here, it is only used to exclude the current issue when "matchIssue"
|
// then no issuePathInfo.indexString here, it is only used to exclude the current issue when "matchIssue"
|
||||||
}
|
}
|
||||||
if (!issuePathInfo.ownerName) {
|
|
||||||
throw new Error('unexpected');
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await GET(`${window.config.appSubUrl}/${issuePathInfo.ownerName}/${issuePathInfo.repoName}/issues/suggestions`);
|
const res = await GET(`${window.config.appSubUrl}/${issuePathInfo.ownerName}/${issuePathInfo.repoName}/issues/suggestions`);
|
||||||
const issues = await res.json();
|
const issues = await res.json();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue