mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-13 19:58:09 +00:00
UBERF-8005: Add tests to tracker projects, fix failed tests (#6454)
Signed-off-by: Rostislav Nazmeev <rostropovich@culturalcode.ru>
This commit is contained in:
parent
60444ebdab
commit
b0e523eb17
@ -13,7 +13,7 @@ export class UserProfilePage {
|
||||
selectProfile = (name: string): Locator => this.page.locator(`text=${name}`)
|
||||
leaveWorkspaceButton = (): Locator => this.page.getByRole('button', { name: 'Leave workspace' })
|
||||
leaveWorkspaceCancelButton = (): Locator => this.page.getByRole('button', { name: 'Cancel' })
|
||||
leaveWorkspaceConfirmButton = (): Locator => this.page.getByRole('button', { name: 'Ok' })
|
||||
leaveWorkspaceConfirmButton = (): Locator => this.page.getByRole('button', { name: 'Ok', exact: true })
|
||||
accountDissabledMessage = (): Locator => this.page.getByRole('heading')
|
||||
changeAccount = (): Locator => this.page.getByRole('link', { name: 'Change account' })
|
||||
settings = (): Locator => this.page.getByRole('button', { name: 'Settings' })
|
||||
|
31
tests/sanity/tests/model/tracker/all-projects-page.ts
Normal file
31
tests/sanity/tests/model/tracker/all-projects-page.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { expect, type Locator } from '@playwright/test'
|
||||
import { CommonTrackerPage } from './common-tracker-page'
|
||||
|
||||
export class AllProjectsPage extends CommonTrackerPage {
|
||||
projectTitleCells = (): Locator => this.page.locator('.antiTable-body__row .antiTable-cells__firstCell')
|
||||
|
||||
async checkProjectExistInTable (projectName: string): Promise<void> {
|
||||
await expect(this.projectTitleCells().filter({ hasText: projectName })).toBeVisible()
|
||||
}
|
||||
|
||||
async checkProjectNotExistInTable (projectName: string): Promise<void> {
|
||||
await expect(this.projectTitleCells().filter({ hasText: projectName })).toBeHidden()
|
||||
}
|
||||
|
||||
async joinProject (title: string): Promise<void> {
|
||||
const projectRow = this.page.locator('.antiTable-body__row', { has: this.page.locator(`td:has-text("${title}")`) })
|
||||
const joinButton = projectRow.locator('button:has-text("Join")')
|
||||
await joinButton.click()
|
||||
}
|
||||
|
||||
async unarchiveProject (title: string): Promise<void> {
|
||||
const projectRow = this.page.locator('.antiTable-body__row', { has: this.page.locator(`td:has-text("${title}")`) })
|
||||
await projectRow.click({ button: 'right' })
|
||||
await this.page.locator('.popup button:has-text("Unarchive")').click()
|
||||
await this.page.locator('.popup button:has-text("Ok")').click()
|
||||
}
|
||||
|
||||
async checkProjecInTableIsNotArchived (title: string): Promise<void> {
|
||||
await this.projectTitleCells().filter({ hasText: title }).filter({ hasNotText: '(archived)' }).waitFor()
|
||||
}
|
||||
}
|
@ -150,7 +150,7 @@ export class IssuesPage extends CommonTrackerPage {
|
||||
this.page.locator('[id="tracker\\:string\\:TimeSpendReportAdd"] >> text=Add time report')
|
||||
|
||||
estimationSpan = (): Locator => this.page.locator('.estimation-container >> span').first()
|
||||
okButton = (): Locator => this.page.getByRole('button', { name: 'Ok' })
|
||||
okButton = (): Locator => this.page.getByRole('button', { name: 'Ok', exact: true })
|
||||
newIssueButton = (): Locator => this.page.locator('#new-issue')
|
||||
issueNameInput = (): Locator => this.page.locator('#issue-name >> input')
|
||||
issueDescriptionInput = (): Locator => this.page.locator('#issue-description >> [contenteditable]')
|
||||
@ -159,7 +159,7 @@ export class IssuesPage extends CommonTrackerPage {
|
||||
priorityEditor = (): Locator => this.page.locator('#priority-editor')
|
||||
urgentButton = (): Locator => this.page.locator('button:has-text("Urgent")')
|
||||
assigneeEditor = (): Locator => this.page.locator('#assignee-editor')
|
||||
appleseedJohnButton = (): Locator => this.page.locator('button:has-text("Appleseed John")')
|
||||
appleseedJohnButton = (): Locator => this.page.locator('button.menu-item:has-text("Appleseed John")')
|
||||
estimationEditor = (): Locator => this.page.locator('#estimation-editor')
|
||||
dueDateButton = (): Locator => this.page.locator('button:has-text("Due date")')
|
||||
specificDay = (day: string): Locator => this.page.locator(`.date-popup-container div.day >> text=${day}`).first()
|
||||
|
@ -9,11 +9,16 @@ export class TrackerNavigationMenuPage extends CommonPage {
|
||||
this.page = page
|
||||
}
|
||||
|
||||
buttonCreateProject = (): Locator => this.page.locator('div#navGroup-tree-projects').locator('xpath=../button[1]')
|
||||
yoursProjectsMenuSelector = '#navGroup-tree-projects'
|
||||
starredProjectsMenuSelector = '#navGroup-tree-stared'
|
||||
|
||||
buttonCreateProject = (): Locator => this.page.locator(this.yoursProjectsMenuSelector).locator('xpath=../button[1]')
|
||||
buttonProjectsParent = (): Locator => this.page.locator('button.hulyNavGroup-header span')
|
||||
templateLinkForProject = (projectName: string): Locator =>
|
||||
this.page.locator(`a[href$="templates"][href*="${projectName}"]`)
|
||||
|
||||
starredProjectsInMenu = (): Locator => this.page.locator(`${this.starredProjectsMenuSelector} span`)
|
||||
|
||||
issuesLinkForProject = (projectName: string): Locator =>
|
||||
this.page
|
||||
.getByRole('button', { name: projectName, exact: true })
|
||||
@ -49,6 +54,22 @@ export class TrackerNavigationMenuPage extends CommonPage {
|
||||
await expect(this.buttonProjectsParent().filter({ hasText: projectName })).toHaveCount(1)
|
||||
}
|
||||
|
||||
async checkProjectStarred (projectName: string): Promise<void> {
|
||||
await expect(this.starredProjectsInMenu().filter({ hasText: projectName })).toHaveCount(1)
|
||||
}
|
||||
|
||||
async checkProjectWillBeRemovedFromYours (projectName: string): Promise<void> {
|
||||
await this.page.waitForSelector(`${this.yoursProjectsMenuSelector} span:has-text("${projectName}")`, {
|
||||
state: 'detached'
|
||||
})
|
||||
}
|
||||
|
||||
async checkProjectWillBeRemovedFromStarred (projectName: string): Promise<void> {
|
||||
await this.page.waitForSelector(`${this.starredProjectsMenuSelector} span:has-text("${projectName}")`, {
|
||||
state: 'detached'
|
||||
})
|
||||
}
|
||||
|
||||
async checkProjectNotExist (projectName: string): Promise<void> {
|
||||
await expect(this.buttonProjectsParent().filter({ hasText: projectName })).toHaveCount(0)
|
||||
}
|
||||
@ -75,6 +96,16 @@ export class TrackerNavigationMenuPage extends CommonPage {
|
||||
await this.selectFromDropdown(this.page, action)
|
||||
}
|
||||
|
||||
async makeActionWithStarredProject (projectName: string, action: string): Promise<void> {
|
||||
await this.starredProjectsInMenu().filter({ hasText: projectName }).hover()
|
||||
await this.starredProjectsInMenu()
|
||||
.filter({ hasText: projectName })
|
||||
.locator('xpath=../..')
|
||||
.locator('div[class*="tools"] button')
|
||||
.click()
|
||||
await this.selectFromDropdown(this.page, action)
|
||||
}
|
||||
|
||||
async openMilestonesForProject (projectName: string): Promise<void> {
|
||||
await this.milestonesLinkForProject(projectName).click()
|
||||
}
|
||||
@ -96,4 +127,8 @@ export class TrackerNavigationMenuPage extends CommonPage {
|
||||
await expect(this.milestone()).toBeVisible()
|
||||
await expect(this.templates()).toBeVisible()
|
||||
}
|
||||
|
||||
async openAllProjects (): Promise<void> {
|
||||
await this.allProjects().click()
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ export async function prepareNewIssueStep (page: Page, issue: NewIssue): Promise
|
||||
}
|
||||
|
||||
export async function prepareNewIssueWithOpenStep (page: Page, issue: NewIssue): Promise<string> {
|
||||
return await test.step('Prepare document', async () => {
|
||||
return await test.step('Prepare Issue', async () => {
|
||||
const issuesPage = new IssuesPage(page)
|
||||
await issuesPage.linkSidebarAll().click()
|
||||
await issuesPage.clickModelSelectorAll()
|
||||
|
@ -174,6 +174,8 @@ test.describe('Tracker issue tests', () => {
|
||||
await issuesDetailsPage.checkIssue({
|
||||
...moveIssue
|
||||
})
|
||||
|
||||
await trackerNavigationMenuPage.openIssuesForProject('Default')
|
||||
// TODO need to return back after bug with activity fixed
|
||||
// await issuesDetailsPage.checkActivityExist('changed project in')
|
||||
// await issuesDetailsPage.checkActivityExist('changed number in')
|
||||
@ -221,9 +223,11 @@ test.describe('Tracker issue tests', () => {
|
||||
|
||||
test('Delete an issue', async ({ page }) => {
|
||||
const deleteIssue: NewIssue = {
|
||||
title: 'Issue for deletion',
|
||||
title: `Issue-to-delete-${generateId()}`,
|
||||
description: 'Description Issue for deletion'
|
||||
}
|
||||
await prepareNewIssueWithOpenStep(page, deleteIssue)
|
||||
await issuesPage.navigateToIssues()
|
||||
await issuesPage.clickModelSelectorAll()
|
||||
await issuesPage.searchIssueByName(deleteIssue.title)
|
||||
await issuesPage.openIssueByName(deleteIssue.title)
|
||||
|
@ -4,6 +4,8 @@ import { TrackerNavigationMenuPage } from '../model/tracker/tracker-navigation-m
|
||||
import { NewProjectPage } from '../model/tracker/new-project-page'
|
||||
import { NewProject } from '../model/tracker/types'
|
||||
import { EditProjectPage } from '../model/tracker/edit-project-page'
|
||||
import { AllProjectsPage } from '../model/tracker/all-projects-page'
|
||||
import { generateProjectId } from './tracker.utils'
|
||||
|
||||
test.use({
|
||||
storageState: PlatformSetting
|
||||
@ -13,76 +15,189 @@ test.describe('Tracker Projects tests', () => {
|
||||
let trackerNavigationMenuPage: TrackerNavigationMenuPage
|
||||
let newProjectPage: NewProjectPage
|
||||
let editProjectPage: EditProjectPage
|
||||
let allProjectsPage: AllProjectsPage
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
trackerNavigationMenuPage = new TrackerNavigationMenuPage(page)
|
||||
newProjectPage = new NewProjectPage(page)
|
||||
editProjectPage = new EditProjectPage(page)
|
||||
allProjectsPage = new AllProjectsPage(page)
|
||||
await (await page.goto(`${PlatformURI}/workbench/sanity-ws`))?.finished()
|
||||
})
|
||||
|
||||
test('Create project', async () => {
|
||||
test('User can create project', async () => {
|
||||
const projectId = generateProjectId()
|
||||
const newProjectData: NewProject = {
|
||||
title: 'TestProject',
|
||||
identifier: 'QWERT',
|
||||
description: 'Test Project description',
|
||||
title: `NewProject-${projectId}`,
|
||||
identifier: projectId,
|
||||
description: 'New Project description',
|
||||
private: true,
|
||||
defaultAssigneeForIssues: 'Dirak Kainin',
|
||||
defaultIssueStatus: 'In Progress'
|
||||
}
|
||||
|
||||
await trackerNavigationMenuPage.checkProjectNotExist(newProjectData.title)
|
||||
await trackerNavigationMenuPage.pressCreateProjectButton()
|
||||
await newProjectPage.createNewProject(newProjectData)
|
||||
await trackerNavigationMenuPage.checkProjectExist(newProjectData.title)
|
||||
await trackerNavigationMenuPage.openProject(newProjectData.title)
|
||||
await test.step('User create project', async () => {
|
||||
await trackerNavigationMenuPage.checkProjectNotExist(newProjectData.title)
|
||||
await trackerNavigationMenuPage.pressCreateProjectButton()
|
||||
await newProjectPage.createNewProject(newProjectData)
|
||||
})
|
||||
|
||||
await test.step('User see project in menu', async () => {
|
||||
await trackerNavigationMenuPage.checkProjectExist(newProjectData.title)
|
||||
})
|
||||
|
||||
await test.step('User see project in all projects table', async () => {
|
||||
await trackerNavigationMenuPage.openAllProjects()
|
||||
await allProjectsPage.checkProjectExistInTable(newProjectData.title)
|
||||
})
|
||||
|
||||
await test.step('User can open created project', async () => {
|
||||
await trackerNavigationMenuPage.openProject(newProjectData.title)
|
||||
})
|
||||
})
|
||||
|
||||
test('Edit project', async () => {
|
||||
test('User can edit project', async () => {
|
||||
const projectId = generateProjectId()
|
||||
|
||||
const editProjectData: NewProject = {
|
||||
title: 'EditProject',
|
||||
identifier: 'EDIT',
|
||||
title: `EditProject-${projectId}`,
|
||||
identifier: projectId,
|
||||
description: 'Edit Project description',
|
||||
private: true,
|
||||
defaultAssigneeForIssues: 'Dirak Kainin',
|
||||
defaultIssueStatus: 'In Progress'
|
||||
}
|
||||
const updateProjectData: NewProject = {
|
||||
title: 'UpdateProject',
|
||||
identifier: 'EDIT',
|
||||
title: `UpdateProject-${projectId}`,
|
||||
identifier: projectId,
|
||||
description: 'Updated Project description',
|
||||
private: true,
|
||||
defaultAssigneeForIssues: 'Chen Rosamund',
|
||||
defaultIssueStatus: 'Done'
|
||||
}
|
||||
|
||||
await trackerNavigationMenuPage.checkProjectNotExist(editProjectData.title)
|
||||
await trackerNavigationMenuPage.pressCreateProjectButton()
|
||||
await newProjectPage.createNewProject(editProjectData)
|
||||
await trackerNavigationMenuPage.checkProjectExist(editProjectData.title)
|
||||
await trackerNavigationMenuPage.makeActionWithProject(editProjectData.title, 'Edit project')
|
||||
await editProjectPage.checkProject(editProjectData)
|
||||
await editProjectPage.updateProject(updateProjectData)
|
||||
await trackerNavigationMenuPage.makeActionWithProject(updateProjectData.title, 'Edit project')
|
||||
await editProjectPage.checkProject(updateProjectData)
|
||||
await test.step('User prepare project', async () => {
|
||||
await trackerNavigationMenuPage.checkProjectNotExist(editProjectData.title)
|
||||
await trackerNavigationMenuPage.pressCreateProjectButton()
|
||||
await newProjectPage.createNewProject(editProjectData)
|
||||
await trackerNavigationMenuPage.checkProjectExist(editProjectData.title)
|
||||
})
|
||||
|
||||
await test.step('User edit project', async () => {
|
||||
await trackerNavigationMenuPage.makeActionWithProject(editProjectData.title, 'Edit project')
|
||||
await editProjectPage.checkProject(editProjectData)
|
||||
await editProjectPage.updateProject(updateProjectData)
|
||||
await trackerNavigationMenuPage.makeActionWithProject(updateProjectData.title, 'Edit project')
|
||||
await editProjectPage.checkProject(updateProjectData)
|
||||
await editProjectPage.buttonSaveProject().click()
|
||||
})
|
||||
})
|
||||
|
||||
test('Archive Project', async ({ page }) => {
|
||||
test('User can archive and unarchive Project', async ({ page }) => {
|
||||
const projectId = generateProjectId()
|
||||
|
||||
const archiveProjectData: NewProject = {
|
||||
title: 'PROJECT_ARCHIVE',
|
||||
identifier: 'ARCH',
|
||||
title: `ArchiveProject-${projectId}`,
|
||||
identifier: projectId,
|
||||
description: 'Archive Project description',
|
||||
private: true,
|
||||
defaultAssigneeForIssues: 'Dirak Kainin',
|
||||
defaultIssueStatus: 'In Progress'
|
||||
}
|
||||
|
||||
await trackerNavigationMenuPage.checkProjectNotExist(archiveProjectData.title)
|
||||
await trackerNavigationMenuPage.pressCreateProjectButton()
|
||||
await newProjectPage.createNewProject(archiveProjectData)
|
||||
await trackerNavigationMenuPage.checkProjectExist(archiveProjectData.title)
|
||||
await trackerNavigationMenuPage.makeActionWithProject(archiveProjectData.title, 'Archive')
|
||||
await trackerNavigationMenuPage.pressYesForPopup(page)
|
||||
await trackerNavigationMenuPage.checkProjectNotExist(archiveProjectData.title)
|
||||
await test.step('User prepare project', async () => {
|
||||
await trackerNavigationMenuPage.checkProjectNotExist(archiveProjectData.title)
|
||||
await trackerNavigationMenuPage.pressCreateProjectButton()
|
||||
await newProjectPage.createNewProject(archiveProjectData)
|
||||
})
|
||||
|
||||
await test.step('User archive project', async () => {
|
||||
await trackerNavigationMenuPage.checkProjectExist(archiveProjectData.title)
|
||||
await trackerNavigationMenuPage.makeActionWithProject(archiveProjectData.title, 'Archive')
|
||||
await trackerNavigationMenuPage.pressYesForPopup(page)
|
||||
await trackerNavigationMenuPage.checkProjectNotExist(archiveProjectData.title)
|
||||
await trackerNavigationMenuPage.openAllProjects()
|
||||
await allProjectsPage.checkProjectExistInTable(`${archiveProjectData.title} (archived)`)
|
||||
})
|
||||
|
||||
await test.step('User unarchive project', async () => {
|
||||
await allProjectsPage.unarchiveProject(archiveProjectData.title)
|
||||
await allProjectsPage.checkProjecInTableIsNotArchived(`${archiveProjectData.title}`)
|
||||
await trackerNavigationMenuPage.checkProjectExist(archiveProjectData.title)
|
||||
})
|
||||
|
||||
await test.step('Finally archive project again', async () => {
|
||||
await trackerNavigationMenuPage.makeActionWithProject(archiveProjectData.title, 'Archive')
|
||||
await trackerNavigationMenuPage.pressYesForPopup(page)
|
||||
await trackerNavigationMenuPage.checkProjectNotExist(archiveProjectData.title)
|
||||
})
|
||||
})
|
||||
|
||||
test('Star and Unstar Project', async () => {
|
||||
const projectId = generateProjectId()
|
||||
|
||||
const projectToStarData: NewProject = {
|
||||
title: `ProjectToStar-${projectId}`,
|
||||
identifier: projectId,
|
||||
description: 'Starred Project description',
|
||||
private: true,
|
||||
defaultAssigneeForIssues: 'Dirak Kainin',
|
||||
defaultIssueStatus: 'In Progress'
|
||||
}
|
||||
|
||||
await test.step('User prepare project', async () => {
|
||||
await trackerNavigationMenuPage.checkProjectNotExist(projectToStarData.title)
|
||||
await trackerNavigationMenuPage.pressCreateProjectButton()
|
||||
await newProjectPage.createNewProject(projectToStarData)
|
||||
await trackerNavigationMenuPage.checkProjectExist(projectToStarData.title)
|
||||
})
|
||||
|
||||
await test.step('User star project', async () => {
|
||||
await trackerNavigationMenuPage.makeActionWithProject(projectToStarData.title, 'Star')
|
||||
await trackerNavigationMenuPage.checkProjectStarred(projectToStarData.title)
|
||||
await trackerNavigationMenuPage.checkProjectWillBeRemovedFromYours(projectToStarData.title)
|
||||
})
|
||||
|
||||
await test.step('User unstar project', async () => {
|
||||
await trackerNavigationMenuPage.makeActionWithStarredProject(projectToStarData.title, 'Unstar')
|
||||
await trackerNavigationMenuPage.checkProjectExist(projectToStarData.title)
|
||||
await trackerNavigationMenuPage.checkProjectWillBeRemovedFromStarred(projectToStarData.title)
|
||||
})
|
||||
})
|
||||
|
||||
test('Leave and Join Project', async () => {
|
||||
const projectId = generateProjectId()
|
||||
|
||||
const projectToLeaveData: NewProject = {
|
||||
title: `ProjectToLeave-${projectId}`,
|
||||
identifier: projectId,
|
||||
description: 'Project to leave description',
|
||||
private: true,
|
||||
defaultAssigneeForIssues: 'Appleseed John',
|
||||
defaultIssueStatus: 'In Progress'
|
||||
}
|
||||
|
||||
await test.step('User prepare project', async () => {
|
||||
await trackerNavigationMenuPage.checkProjectNotExist(projectToLeaveData.title)
|
||||
await trackerNavigationMenuPage.pressCreateProjectButton()
|
||||
await newProjectPage.createNewProject(projectToLeaveData)
|
||||
await trackerNavigationMenuPage.checkProjectExist(projectToLeaveData.title)
|
||||
})
|
||||
|
||||
await test.step('User leave project', async () => {
|
||||
await trackerNavigationMenuPage.makeActionWithProject(projectToLeaveData.title, 'Leave')
|
||||
await trackerNavigationMenuPage.checkProjectWillBeRemovedFromYours(projectToLeaveData.title)
|
||||
})
|
||||
|
||||
await test.step('User join project', async () => {
|
||||
await trackerNavigationMenuPage.openAllProjects()
|
||||
await allProjectsPage.checkProjectExistInTable(projectToLeaveData.title)
|
||||
await allProjectsPage.joinProject(projectToLeaveData.title)
|
||||
await trackerNavigationMenuPage.checkProjectExist(projectToLeaveData.title)
|
||||
})
|
||||
})
|
||||
|
||||
test.afterEach(async () => {
|
||||
await trackerNavigationMenuPage.openIssuesForProject('Default')
|
||||
})
|
||||
})
|
||||
|
@ -253,6 +253,16 @@ export async function toTime (value: number): Promise<string> {
|
||||
].join(' ')
|
||||
}
|
||||
export const getIssueName = (postfix: string = generateId()): string => `issue-${postfix}`
|
||||
|
||||
/**
|
||||
* Return random capitalized string like "AFJKD"
|
||||
*
|
||||
* @returns string
|
||||
*/
|
||||
export function generateProjectId (size: number = 5): string {
|
||||
return Array.from({ length: size }, () => String.fromCharCode(65 + Math.floor(Math.random() * 26))).join('')
|
||||
}
|
||||
|
||||
export async function performPanelTest (page: Page, statuses: string[], panel: string, mode: string): Promise<void> {
|
||||
const locator = page.locator('.list-container')
|
||||
const excluded = DEFAULT_STATUSES.filter((status) => !statuses.includes(status))
|
||||
|
Loading…
Reference in New Issue
Block a user