mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-11 00:10:38 -05:00
115 lines
4.6 KiB
TypeScript
115 lines
4.6 KiB
TypeScript
import {test, expect} from '@playwright/test';
|
|
import {
|
|
apiAddCollaborator,
|
|
apiCreateFiles,
|
|
apiCreatePR,
|
|
apiCreateRepo,
|
|
apiCreateReview,
|
|
apiCreateUser,
|
|
apiUserHeaders,
|
|
loginUser,
|
|
randomString,
|
|
} from './utils.ts';
|
|
|
|
test('pr review flow', async ({page, request}) => {
|
|
const poster = `rv-poster-${randomString(8)}`;
|
|
const reviewer = `rv-reviewer-${randomString(8)}`;
|
|
const officialReviewer = `rv-official-${randomString(8)}`;
|
|
await Promise.all([
|
|
apiCreateUser(request, poster),
|
|
apiCreateUser(request, reviewer),
|
|
apiCreateUser(request, officialReviewer),
|
|
]);
|
|
const posterHeaders = apiUserHeaders(poster);
|
|
const repoName = `e2e-prreview-${randomString(8)}`;
|
|
await apiCreateRepo(request, {name: repoName, headers: posterHeaders});
|
|
await Promise.all([
|
|
apiAddCollaborator(
|
|
request,
|
|
poster,
|
|
repoName,
|
|
officialReviewer,
|
|
{headers: posterHeaders},
|
|
),
|
|
apiCreateFiles(
|
|
request,
|
|
poster,
|
|
repoName,
|
|
[{path: 'added.txt', content: 'new content\n'}],
|
|
{branch: 'main', newBranch: 'feat', headers: posterHeaders},
|
|
),
|
|
]);
|
|
const prIndex = await apiCreatePR(request, poster, repoName, 'feat', 'main', 'review test', {headers: posterHeaders});
|
|
const pullUrl = `/${poster}/${repoName}/pulls/${prIndex}`;
|
|
|
|
const reRequestAndApprove = async (
|
|
username: string,
|
|
approvalTooltip: string,
|
|
pendingStateClass: string,
|
|
official: boolean,
|
|
) => {
|
|
await page.goto(pullUrl);
|
|
const reviewerItem = page.locator('.issue-sidebar-combo .ui.relaxed.list > .item', {
|
|
has: page.locator(`a[href="/${username}"]`),
|
|
});
|
|
const reviewState = reviewerItem.locator('span[data-tooltip-content]');
|
|
await expect(reviewState).toHaveAttribute('data-tooltip-content', approvalTooltip);
|
|
await reviewerItem.locator('a[data-tooltip-content="Re-request review"]').click();
|
|
await expect(reviewState).toHaveAttribute('data-tooltip-content', 'Review pending');
|
|
await expect(reviewState.locator(`.octicon-dot-fill.${pendingStateClass}`)).toBeVisible();
|
|
|
|
expect(await apiCreateReview(request, poster, repoName, prIndex, {
|
|
event: 'APPROVED',
|
|
headers: apiUserHeaders(username),
|
|
})).toMatchObject({state: 'APPROVED', official});
|
|
};
|
|
|
|
// reviewer seeds an inline comment via API so the poster's UI reply exercises the reply-to-review path (#35994)
|
|
await Promise.all([
|
|
apiCreateReview(request, poster, repoName, prIndex, {
|
|
comments: [{path: 'added.txt', body: 'inline to reply to', new_position: 1}],
|
|
headers: apiUserHeaders(reviewer),
|
|
}),
|
|
apiCreateReview(request, poster, repoName, prIndex, {
|
|
event: 'APPROVED',
|
|
headers: apiUserHeaders(officialReviewer),
|
|
}),
|
|
loginUser(page, poster),
|
|
]);
|
|
|
|
await page.goto(`${pullUrl}/files`);
|
|
|
|
// diff viewer renders the added file with its header and one added-line row
|
|
const fileBox = page.locator('.diff-file-box[data-new-filename="added.txt"]');
|
|
await expect(fileBox.locator('.diff-file-header .file-link')).toHaveText('added.txt');
|
|
await expect(fileBox.locator('tr.add-code')).toHaveCount(1);
|
|
|
|
// commits tab badge reflects the single PR commit, and the diff stats header counts one changed file
|
|
const commitsTab = page.locator('.ui.pull.tabular.menu a.item', {has: page.locator('.octicon-git-commit')});
|
|
await expect(commitsTab.locator('.label')).toHaveText('1');
|
|
await expect(page.locator('.diff-detail-stats')).toContainText(/1 changed file/);
|
|
|
|
// poster replies to the reviewer's inline comment
|
|
const conversation = fileBox.locator('.conversation-holder');
|
|
await conversation.locator('.comment-form-reply').click();
|
|
const replyForm = conversation.locator('form');
|
|
await replyForm.locator('textarea[name="content"]').fill('my reply body');
|
|
await replyForm.getByRole('button', {name: 'Reply', exact: true}).click();
|
|
await expect(conversation.locator('.comment-body')).toContainText(['inline to reply to', 'my reply body']);
|
|
|
|
await page.context().clearCookies();
|
|
await loginUser(page, reviewer);
|
|
await page.goto(`${pullUrl}/files`);
|
|
await page.locator('#review-box .js-btn-review').click();
|
|
const panel = page.locator('.review-box-panel');
|
|
await panel.locator('textarea[name="content"]').fill(`First approval from ${reviewer}`);
|
|
await panel.getByRole('button', {name: 'Approve', exact: true}).click();
|
|
await expect(page.locator('.timeline-item').filter({hasText: `First approval from ${reviewer}`})).toBeVisible();
|
|
|
|
await reRequestAndApprove(reviewer, 'Uncounted approval', 'tw-text-text-light', false);
|
|
|
|
await page.context().clearCookies();
|
|
await loginUser(page, officialReviewer);
|
|
await reRequestAndApprove(officialReviewer, 'Approved', 'tw-text-yellow', true);
|
|
});
|