2024-09-11 22:34:33 +02:00
// @watch start
// templates/repo/issue/view_content/**
// web_src/css/repo/issue-**
// web_src/js/features/repo-issue**
// @watch end
2024-11-15 01:41:55 +01:00
/* eslint playwright/expect-expect: ["error", { "assertFunctionNames": ["check_wip"] }] */
import { expect , type Page } from '@playwright/test' ;
2024-12-07 18:38:06 +01:00
import { test , save_visual , login_user , login } from './utils_e2e.ts' ;
2024-07-05 07:03:45 +02:00
test . beforeAll ( async ( { browser } , workerInfo ) = > {
await login_user ( browser , workerInfo , 'user2' ) ;
} ) ;
2024-11-12 21:07:09 +01:00
test . describe ( 'Pull: Toggle WIP' , ( ) = > {
const prTitle = 'pull5' ;
2024-11-15 01:41:55 +01:00
async function toggle_wip_to ( { page } , should : boolean ) {
2024-11-12 21:07:09 +01:00
await page . waitForLoadState ( 'domcontentloaded' ) ;
if ( should ) {
await page . getByText ( 'Still in progress?' ) . click ( ) ;
} else {
await page . getByText ( 'Ready for review?' ) . click ( ) ;
}
2024-07-05 07:03:45 +02:00
}
2024-11-15 01:41:55 +01:00
async function check_wip ( { page } , is : boolean ) {
2024-11-12 21:07:09 +01:00
const elemTitle = 'h1' ;
const stateLabel = '.issue-state-label' ;
await page . waitForLoadState ( 'domcontentloaded' ) ;
await expect ( page . locator ( elemTitle ) ) . toContainText ( prTitle ) ;
await expect ( page . locator ( elemTitle ) ) . toContainText ( '#5' ) ;
if ( is ) {
await expect ( page . locator ( elemTitle ) ) . toContainText ( 'WIP' ) ;
await expect ( page . locator ( stateLabel ) ) . toContainText ( 'Draft' ) ;
} else {
await expect ( page . locator ( elemTitle ) ) . not . toContainText ( 'WIP' ) ;
await expect ( page . locator ( stateLabel ) ) . toContainText ( 'Open' ) ;
}
}
test . beforeEach ( async ( { browser } , workerInfo ) = > {
const page = await login ( { browser } , workerInfo ) ;
const response = await page . goto ( '/user2/repo1/pulls/5' ) ;
expect ( response ? . status ( ) ) . toBe ( 200 ) ; // Status OK
// ensure original title
await page . locator ( '#issue-title-edit-show' ) . click ( ) ;
await page . locator ( '#issue-title-editor input' ) . fill ( prTitle ) ;
await page . getByText ( 'Save' ) . click ( ) ;
await check_wip ( { page } , false ) ;
} ) ;
test ( 'simple toggle' , async ( { browser } , workerInfo ) = > {
test . skip ( workerInfo . project . name === 'Mobile Safari' , 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636' ) ;
const page = await login ( { browser } , workerInfo ) ;
await page . goto ( '/user2/repo1/pulls/5' ) ;
// toggle to WIP
await toggle_wip_to ( { page } , true ) ;
await check_wip ( { page } , true ) ;
// remove WIP
await toggle_wip_to ( { page } , false ) ;
await check_wip ( { page } , false ) ;
} ) ;
test ( 'manual edit' , async ( { browser } , workerInfo ) = > {
test . skip ( workerInfo . project . name === 'Mobile Safari' , 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636' ) ;
const page = await login ( { browser } , workerInfo ) ;
await page . goto ( '/user2/repo1/pulls/5' ) ;
// manually edit title to another prefix
await page . locator ( '#issue-title-edit-show' ) . click ( ) ;
await page . locator ( '#issue-title-editor input' ) . fill ( ` [WIP] ${ prTitle } ` ) ;
await page . getByText ( 'Save' ) . click ( ) ;
await check_wip ( { page } , true ) ;
// remove again
await toggle_wip_to ( { page } , false ) ;
await check_wip ( { page } , false ) ;
} ) ;
test ( 'maximum title length' , async ( { browser } , workerInfo ) = > {
test . skip ( workerInfo . project . name === 'Mobile Safari' , 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636' ) ;
const page = await login ( { browser } , workerInfo ) ;
await page . goto ( '/user2/repo1/pulls/5' ) ;
// check maximum title length is handled gracefully
const maxLenStr = prTitle + 'a' . repeat ( 240 ) ;
await page . locator ( '#issue-title-edit-show' ) . click ( ) ;
await page . locator ( '#issue-title-editor input' ) . fill ( maxLenStr ) ;
await page . getByText ( 'Save' ) . click ( ) ;
await expect ( page . locator ( 'h1' ) ) . toContainText ( maxLenStr ) ;
await check_wip ( { page } , false ) ;
await toggle_wip_to ( { page } , true ) ;
await check_wip ( { page } , true ) ;
await expect ( page . locator ( 'h1' ) ) . toContainText ( maxLenStr ) ;
await toggle_wip_to ( { page } , false ) ;
await check_wip ( { page } , false ) ;
await expect ( page . locator ( 'h1' ) ) . toContainText ( maxLenStr ) ;
} ) ;
2024-07-05 07:03:45 +02:00
} ) ;
test ( 'Issue: Labels' , async ( { browser } , workerInfo ) = > {
test . skip ( workerInfo . project . name === 'Mobile Safari' , 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636' ) ;
2024-11-12 21:07:09 +01:00
2024-11-15 01:41:55 +01:00
async function submitLabels ( { page } : { page : Page } ) {
2024-11-12 21:07:09 +01:00
const submitted = page . waitForResponse ( '/user2/repo1/issues/labels' ) ;
await page . locator ( 'textarea' ) . first ( ) . click ( ) ; // close via unrelated element
await submitted ;
await page . waitForLoadState ( ) ;
}
2024-07-05 07:03:45 +02:00
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' ) ;
2024-10-23 16:22:25 +02:00
expect ( response ? . status ( ) ) . toBe ( 200 ) ;
2024-11-12 21:07:09 +01:00
// restore initial state
await page . locator ( '.select-label' ) . click ( ) ;
const responsePromise = page . waitForResponse ( '/user2/repo1/issues/labels' ) ;
await page . getByText ( 'Clear labels' ) . click ( ) ;
await responsePromise ;
await expect ( labelList . filter ( { hasText : 'label1' } ) ) . toBeHidden ( ) ;
2024-07-22 20:03:32 +02:00
await expect ( labelList . filter ( { hasText : 'label2' } ) ) . toBeHidden ( ) ;
2024-11-12 21:07:09 +01:00
// add both labels
2024-07-05 07:03:45 +02:00
await page . locator ( '.select-label' ) . click ( ) ;
// label search could be tested this way:
// await page.locator('.select-label input').fill('label2');
await page . locator ( '.select-label .item' ) . filter ( { hasText : 'label2' } ) . click ( ) ;
2024-11-12 21:07:09 +01:00
await page . locator ( '.select-label .item' ) . filter ( { hasText : 'label1' } ) . click ( ) ;
await submitLabels ( { page } ) ;
2024-07-05 07:03:45 +02:00
await expect ( labelList . filter ( { hasText : 'label2' } ) ) . toBeVisible ( ) ;
2024-11-12 21:07:09 +01:00
await expect ( labelList . filter ( { hasText : 'label1' } ) ) . toBeVisible ( ) ;
// test removing label2 again
// due to a race condition, the page could still be "reloading",
// closing the dropdown after it was clicked.
// Retry the interaction as a group
// also see https://playwright.dev/docs/test-assertions#expecttopass
await expect ( async ( ) = > {
await page . locator ( '.select-label' ) . click ( ) ;
await page . locator ( '.select-label .item' ) . filter ( { hasText : 'label2' } ) . click ( ) ;
} ) . toPass ( ) ;
await submitLabels ( { page } ) ;
2024-07-22 20:03:32 +02:00
await expect ( labelList . filter ( { hasText : 'label2' } ) ) . toBeHidden ( ) ;
2024-07-05 07:03:45 +02:00
await expect ( labelList . filter ( { hasText : 'label1' } ) ) . toBeVisible ( ) ;
} ) ;
2024-07-17 04:25:35 +02:00
2024-10-08 10:39:52 +02:00
test ( 'Issue: Assignees' , async ( { browser } , workerInfo ) = > {
test . skip ( workerInfo . project . name === 'Mobile Safari' , 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636' ) ;
const page = await login ( { browser } , workerInfo ) ;
// select label list in sidebar only
const assigneesList = page . locator ( '.issue-content-right .assignees.list .selected .item a' ) ;
const response = await page . goto ( '/org3/repo3/issues/1' ) ;
2024-10-23 16:22:25 +02:00
expect ( response ? . status ( ) ) . toBe ( 200 ) ;
2024-10-08 10:39:52 +02:00
// Clear all assignees
await page . locator ( '.select-assignees-modify.dropdown' ) . click ( ) ;
await page . locator ( '.select-assignees-modify.dropdown .no-select.item' ) . click ( ) ;
await expect ( assigneesList . filter ( { hasText : 'user2' } ) ) . toBeHidden ( ) ;
await expect ( assigneesList . filter ( { hasText : 'user4' } ) ) . toBeHidden ( ) ;
await expect ( page . locator ( '.ui.assignees.list .item.no-select' ) ) . toBeVisible ( ) ;
2024-10-09 14:12:46 +02:00
await expect ( page . locator ( '.select-assign-me' ) ) . toBeVisible ( ) ;
2024-10-08 10:39:52 +02:00
// Assign other user (with searchbox)
await page . locator ( '.select-assignees-modify.dropdown' ) . click ( ) ;
await page . type ( '.select-assignees-modify .menu .search input' , 'user4' ) ;
await expect ( page . locator ( '.select-assignees-modify .menu .item' ) . filter ( { hasText : 'user2' } ) ) . toBeHidden ( ) ;
await expect ( page . locator ( '.select-assignees-modify .menu .item' ) . filter ( { hasText : 'user4' } ) ) . toBeVisible ( ) ;
await page . locator ( '.select-assignees-modify .menu .item' ) . filter ( { hasText : 'user4' } ) . click ( ) ;
await page . locator ( '.select-assignees-modify.dropdown' ) . click ( ) ;
await expect ( assigneesList . filter ( { hasText : 'user4' } ) ) . toBeVisible ( ) ;
// remove user4
await page . locator ( '.select-assignees-modify.dropdown' ) . click ( ) ;
await page . locator ( '.select-assignees-modify .menu .item' ) . filter ( { hasText : 'user4' } ) . click ( ) ;
await page . locator ( '.select-assignees-modify.dropdown' ) . click ( ) ;
await expect ( page . locator ( '.ui.assignees.list .item.no-select' ) ) . toBeVisible ( ) ;
await expect ( assigneesList . filter ( { hasText : 'user4' } ) ) . toBeHidden ( ) ;
// Test assign me
await page . locator ( '.ui.assignees .select-assign-me' ) . click ( ) ;
await expect ( assigneesList . filter ( { hasText : 'user2' } ) ) . toBeVisible ( ) ;
await expect ( page . locator ( '.ui.assignees.list .item.no-select' ) ) . toBeHidden ( ) ;
} ) ;
test ( 'New Issue: Assignees' , async ( { browser } , workerInfo ) = > {
test . skip ( workerInfo . project . name === 'Mobile Safari' , 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636' ) ;
const page = await login ( { browser } , workerInfo ) ;
// select label list in sidebar only
const assigneesList = page . locator ( '.issue-content-right .assignees.list .selected .item' ) ;
const response = await page . goto ( '/org3/repo3/issues/new' ) ;
2024-10-23 16:22:25 +02:00
expect ( response ? . status ( ) ) . toBe ( 200 ) ;
2024-10-08 10:39:52 +02:00
// preconditions
await expect ( page . locator ( '.ui.assignees.list .item.no-select' ) ) . toBeVisible ( ) ;
await expect ( assigneesList . filter ( { hasText : 'user2' } ) ) . toBeHidden ( ) ;
await expect ( assigneesList . filter ( { hasText : 'user4' } ) ) . toBeHidden ( ) ;
// Assign other user (with searchbox)
await page . locator ( '.select-assignees.dropdown' ) . click ( ) ;
2024-11-15 01:41:55 +01:00
await page . fill ( '.select-assignees .menu .search input' , 'user4' ) ;
2024-10-08 10:39:52 +02:00
await expect ( page . locator ( '.select-assignees .menu .item' ) . filter ( { hasText : 'user2' } ) ) . toBeHidden ( ) ;
await expect ( page . locator ( '.select-assignees .menu .item' ) . filter ( { hasText : 'user4' } ) ) . toBeVisible ( ) ;
await page . locator ( '.select-assignees .menu .item' ) . filter ( { hasText : 'user4' } ) . click ( ) ;
await page . locator ( '.select-assignees.dropdown' ) . click ( ) ;
await expect ( assigneesList . filter ( { hasText : 'user4' } ) ) . toBeVisible ( ) ;
2024-12-07 18:38:06 +01:00
await save_visual ( page ) ;
2024-10-08 10:39:52 +02:00
// remove user4
await page . locator ( '.select-assignees.dropdown' ) . click ( ) ;
await page . locator ( '.select-assignees .menu .item' ) . filter ( { hasText : 'user4' } ) . click ( ) ;
await page . locator ( '.select-assignees.dropdown' ) . click ( ) ;
await expect ( page . locator ( '.ui.assignees.list .item.no-select' ) ) . toBeVisible ( ) ;
await expect ( assigneesList . filter ( { hasText : 'user4' } ) ) . toBeHidden ( ) ;
// Test assign me
await page . locator ( '.ui.assignees .select-assign-me' ) . click ( ) ;
await expect ( assigneesList . filter ( { hasText : 'user2' } ) ) . toBeVisible ( ) ;
await expect ( page . locator ( '.ui.assignees.list .item.no-select' ) ) . toBeHidden ( ) ;
await page . locator ( '.select-assignees.dropdown' ) . click ( ) ;
await page . fill ( '.select-assignees .menu .search input' , '' ) ;
await page . locator ( '.select-assignees.dropdown .no-select.item' ) . click ( ) ;
2024-10-09 14:12:46 +02:00
await expect ( page . locator ( '.select-assign-me' ) ) . toBeVisible ( ) ;
2024-12-07 18:38:06 +01:00
await save_visual ( page ) ;
2024-10-08 10:39:52 +02:00
} ) ;
2024-07-17 04:25:35 +02:00
test ( 'Issue: Milestone' , async ( { browser } , workerInfo ) = > {
test . skip ( workerInfo . project . name === 'Mobile Safari' , 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636' ) ;
const page = await login ( { browser } , workerInfo ) ;
const response = await page . goto ( '/user2/repo1/issues/1' ) ;
2024-10-23 16:22:25 +02:00
expect ( response ? . status ( ) ) . toBe ( 200 ) ;
2024-07-17 04:25:35 +02:00
const selectedMilestone = page . locator ( '.issue-content-right .select-milestone.list' ) ;
const milestoneDropdown = page . locator ( '.issue-content-right .select-milestone.dropdown' ) ;
await expect ( selectedMilestone ) . toContainText ( 'No milestone' ) ;
// Add milestone.
await milestoneDropdown . click ( ) ;
await page . getByRole ( 'option' , { name : 'milestone1' } ) . click ( ) ;
await expect ( selectedMilestone ) . toContainText ( 'milestone1' ) ;
await expect ( page . locator ( '.timeline-item.event' ) . last ( ) ) . toContainText ( 'user2 added this to the milestone1 milestone' ) ;
// Clear milestone.
await milestoneDropdown . click ( ) ;
await page . getByText ( 'Clear milestone' , { exact : true } ) . click ( ) ;
await expect ( selectedMilestone ) . toContainText ( 'No milestone' ) ;
await expect ( page . locator ( '.timeline-item.event' ) . last ( ) ) . toContainText ( 'user2 removed this from the milestone1 milestone' ) ;
} ) ;
2024-08-30 14:53:40 +02:00
test ( 'New Issue: Milestone' , async ( { browser } , workerInfo ) = > {
test . skip ( workerInfo . project . name === 'Mobile Safari' , 'Unable to get tests working on Safari Mobile, see https://codeberg.org/forgejo/forgejo/pulls/3445#issuecomment-1789636' ) ;
const page = await login ( { browser } , workerInfo ) ;
const response = await page . goto ( '/user2/repo1/issues/new' ) ;
2024-10-23 16:22:25 +02:00
expect ( response ? . status ( ) ) . toBe ( 200 ) ;
2024-08-30 14:53:40 +02:00
const selectedMilestone = page . locator ( '.issue-content-right .select-milestone.list' ) ;
const milestoneDropdown = page . locator ( '.issue-content-right .select-milestone.dropdown' ) ;
await expect ( selectedMilestone ) . toContainText ( 'No milestone' ) ;
2024-12-07 18:38:06 +01:00
await save_visual ( page ) ;
2024-08-30 14:53:40 +02:00
// Add milestone.
await milestoneDropdown . click ( ) ;
await page . getByRole ( 'option' , { name : 'milestone1' } ) . click ( ) ;
await expect ( selectedMilestone ) . toContainText ( 'milestone1' ) ;
2024-12-07 18:38:06 +01:00
await save_visual ( page ) ;
2024-08-30 14:53:40 +02:00
// Clear milestone.
await milestoneDropdown . click ( ) ;
await page . getByText ( 'Clear milestone' , { exact : true } ) . click ( ) ;
await expect ( selectedMilestone ) . toContainText ( 'No milestone' ) ;
2024-12-07 18:38:06 +01:00
await save_visual ( page ) ;
2024-08-30 14:53:40 +02:00
} ) ;