TSK-473: Added tracker layout sanity tests (#2452)

Signed-off-by: Anton Brechka <anton.brechka@xored.com>
This commit is contained in:
mrsadman99 2022-12-21 13:00:44 +07:00 committed by GitHub
parent 9c78dc8c9c
commit 4f842eaa8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 361 additions and 120 deletions

View File

@ -0,0 +1,169 @@
import { test, expect, Page } from '@playwright/test'
import {
checkIssueFromList,
createIssue,
createProject,
createSprint,
DEFAULT_STATUSES,
DEFAULT_USER,
IssueProps,
navigate,
PRIORITIES,
setViewGroup,
setViewOrder,
ViewletSelectors
} from './tracker.utils'
import { generateId, PlatformSetting } from './utils'
test.use({
storageState: PlatformSetting
})
const getIssueName = (postfix: string = generateId(5)): string => `issue-${postfix}`
async function createIssues (page: Page, projects?: string[], sprints?: string[]): Promise<IssueProps[]> {
const issuesProps = []
for (let index = 0; index < 5; index++) {
const shiftedIndex = 4 - index
const issueProps = {
name: getIssueName(`layout-${shiftedIndex}`),
status: DEFAULT_STATUSES[shiftedIndex],
assignee: shiftedIndex % 2 === 0 ? DEFAULT_USER : 'Chen Rosamund',
priority: PRIORITIES[shiftedIndex],
project: projects !== undefined ? projects[index % projects.length] : undefined,
sprint: sprints !== undefined ? sprints[index % sprints.length] : undefined
}
issuesProps.push(issueProps)
await createIssue(page, issueProps)
}
return issuesProps
}
async function createProjects (page: Page): Promise<string[]> {
const projects = []
for (let index = 0; index < 5; index++) {
const prjId = `project-${generateId()}-${index}`
projects.push(prjId)
await createProject(page, prjId)
}
return projects
}
async function createSprints (page: Page): Promise<string[]> {
const sprints = []
for (let index = 0; index < 5; index++) {
const sprintId = `sprint-${generateId()}-${index}`
sprints.push(sprintId)
await createSprint(page, sprintId)
}
return sprints
}
async function initIssues (page: Page): Promise<IssueProps[]> {
const projects = await createProjects(page)
const sprints = await createSprints(page)
const issuesProps = await createIssues(page, projects, sprints)
await page.click('text="Issues"')
return issuesProps
}
test.describe('tracker layout tests', () => {
test.beforeEach(async ({ page }) => {
test.setTimeout(60000)
await navigate(page)
issuesProps = await initIssues(page)
})
let issuesProps: IssueProps[] = []
const orders = ['Status', 'Last updated', 'Priority'] as const
const groups = ['Status', 'Assignee', 'Priority', 'Project', 'Sprint', 'No grouping'] as const
const groupsLabels: { [key in typeof groups[number]]?: string[] } = {
Status: DEFAULT_STATUSES,
Assignee: [DEFAULT_USER, 'Chen Rosamund'],
Priority: PRIORITIES,
'No grouping': ['No grouping']
}
for (const group of groups) {
test(`issues-${group.toLowerCase()}-grouping-layout`, async ({ page }) => {
const locator = page.locator('.issueslist-container')
await setViewGroup(page, group)
let groupLabels: any[]
if (group === 'Sprint') {
groupLabels = issuesProps.map((props) => props.sprint)
} else if (group === 'Project') {
groupLabels = issuesProps.map((props) => props.project)
} else {
groupLabels = groupsLabels[group] ?? []
}
const issueNames = issuesProps.map((props) => props.name)
await page.click(ViewletSelectors.Table)
await expect(locator).toContainText(groupLabels)
for (const issueName of issueNames) {
await checkIssueFromList(page, issueName)
}
})
}
for (const order of orders) {
test(`issues-${order.toLowerCase()}-ordering-layout`, async ({ page }) => {
const locator = page.locator('.panel-container')
let orderedIssueNames: string[]
if (order === 'Priority') {
orderedIssueNames = issuesProps
.sort((propsLeft, propsRight) => {
if (propsLeft.priority === undefined || propsRight.priority === undefined) {
return -1
}
if (propsLeft.priority === propsRight.priority) {
return 0
} else if (
PRIORITIES.findIndex((p) => p === propsLeft.priority) -
PRIORITIES.findIndex((p) => p === propsRight.priority) >
0
) {
return 1
}
return -1
})
.map((p) => p.name)
} else if (order === 'Status') {
orderedIssueNames = issuesProps
.sort((propsLeft, propsRight) => {
if (propsLeft.status !== undefined && propsRight.status !== undefined) {
if (propsLeft.status === propsRight.status) {
return 0
} else if (
DEFAULT_STATUSES.findIndex((s) => s === propsLeft.status) -
DEFAULT_STATUSES.findIndex((s) => s === propsRight.status) >
0
) {
return 1
}
}
return -1
})
.map((p) => p.name)
} else {
orderedIssueNames = issuesProps.map((props) => props.name).reverse()
}
await setViewOrder(page, order)
await page.click(ViewletSelectors.Board)
await expect(locator).toContainText(orderedIssueNames)
})
}
})

View File

@ -1,4 +1,5 @@
import { expect, test } from '@playwright/test'
import { navigate } from './tracker.utils'
import { generateId, PlatformSetting, PlatformURI } from './utils'
test.use({
@ -13,6 +14,7 @@ test.describe('project tests', () => {
test('create-project-issue', async ({ page }) => {
await page.click('[id="app-tracker\\:string\\:TrackerApplication"]')
await navigate(page)
// Click text=Projects
await page.click('text=Projects')
await expect(page).toHaveURL(

View File

@ -1,130 +1,32 @@
import { test, expect, Page } from '@playwright/test'
import { generateId, PlatformSetting, PlatformURI } from './utils'
import { test, expect } from '@playwright/test'
import {
checkIssue,
createIssue,
createLabel,
createSubissue,
DEFAULT_STATUSES,
DEFAULT_USER,
navigate,
openIssue,
ViewletSelectors
} from './tracker.utils'
import { generateId, PlatformSetting } from './utils'
test.use({
storageState: PlatformSetting
})
async function navigate (page: Page): Promise<void> {
await page.goto(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/sanity-ws`)
await page.click('[id="app-tracker\\:string\\:TrackerApplication"]')
await expect(page).toHaveURL(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/sanity-ws/tracker`)
}
interface IssueProps {
name: string
description?: string
status?: string
labels?: string[]
priority?: string
assignee?: string
}
async function fillIssueForm (
page: Page,
{ name, description, status, assignee, labels, priority }: IssueProps
): Promise<void> {
await page.fill('[placeholder="Issue\\ title"]', name)
if (description !== undefined) {
await page.fill('.ProseMirror', description)
}
if (status !== undefined) {
await page.click('#status-editor')
await page.click(`.menu-item:has-text("${status}")`)
}
if (priority !== undefined) {
await page.click('button:has-text("No priority")')
await page.click(`.selectPopup button:has-text("${priority}")`)
}
if (labels !== undefined) {
await page.click('.button:has-text("Labels")')
for (const label of labels) {
await page.click(`.selectPopup button:has-text("${label}") >> nth=0`)
}
await page.keyboard.press('Escape')
}
if (assignee !== undefined) {
await page.click('.button:has-text("Assignee")')
await page.click(`.selectPopup button:has-text("${assignee}")`)
}
}
async function createIssue (page: Page, props: IssueProps): Promise<void> {
await page.waitForSelector('span:has-text("Default")')
await page.click('button:has-text("New issue")')
await fillIssueForm(page, props)
await page.click('button:has-text("Save issue")')
await page.waitForSelector('form.antiCard', { state: 'detached' })
}
async function createSubissue (page: Page, props: IssueProps): Promise<void> {
await page.click('button:has-text("Add sub-issue")')
await fillIssueForm(page, props)
await page.click('button:has-text("Save")')
}
interface LabelProps {
label: string
}
async function createLabel (page: Page, { label }: LabelProps): Promise<void> {
await page.click('button:has-text("New issue")')
await page.click('button:has-text("Labels")')
await page.click('.buttons-group >> button >> nth=-1')
await page.fill('[id="tags:string:AddTag"] >> input >> nth=0', label)
await page.click('[id="tags:string:AddTag"] >> button:has-text("Create")')
await page.waitForSelector('form.antiCard[id="tags:string:AddTag"]', { state: 'detached' })
await page.keyboard.press('Escape')
await page.waitForTimeout(100)
await page.keyboard.press('Escape')
}
async function checkIssue (
page: Page,
{ name, description, status, assignee, labels, priority }: IssueProps
): Promise<void> {
if (name !== undefined) {
await expect(page.locator('.popupPanel')).toContainText(name)
}
if (description !== undefined) {
await expect(page.locator('.popupPanel')).toContainText(description)
}
const asideLocator = page.locator('.popupPanel-body__aside')
if (status !== undefined) {
await expect(asideLocator).toContainText(status)
}
if (labels !== undefined) {
await expect(asideLocator).toContainText(labels)
}
if (priority !== undefined) {
await expect(asideLocator).toContainText(priority)
}
if (assignee !== undefined) {
await expect(asideLocator).toContainText(assignee)
}
}
async function openIssue (page: Page, name: string): Promise<void> {
await page.click(`.antiList__row:has-text("${name}") .issuePresenterRoot`)
}
const defaultStatuses = ['Backlog', 'Todo', 'In Progress', 'Done', 'Canceled']
const defaultUser = 'Appleseed John'
enum viewletSelectors {
Table = '.tablist-container >> div.button:nth-child(1)',
Board = '.tablist-container >> div.button:nth-child(2)'
}
test('create-issue-and-sub-issue', async ({ page }) => {
const props = {
name: getIssueName(),
description: 'description',
labels: ['label', 'another-label'],
status: defaultStatuses[0],
status: DEFAULT_STATUSES[0],
priority: 'Urgent',
assignee: defaultUser
assignee: DEFAULT_USER
}
await navigate(page)
for (const label of props.labels) {
await createLabel(page, { label })
await createLabel(page, label)
}
await createIssue(page, props)
await page.click('text="Issues"')
@ -140,22 +42,22 @@ const getIssueName = (postfix: string = generateId(5)): string => `issue-${postf
test('issues-status-display', async ({ page }) => {
const panelStatusMap = new Map([
['Issues', defaultStatuses],
['Issues', DEFAULT_STATUSES],
['Active', ['Todo', 'In Progress']],
['Backlog', ['Backlog']]
])
const locator = page.locator('.issueslist-container')
await navigate(page)
for (const status of defaultStatuses) {
for (const status of DEFAULT_STATUSES) {
await createIssue(page, { name: getIssueName(status), status })
}
for (const [panel, statuses] of panelStatusMap) {
const excluded = defaultStatuses.filter((status) => !statuses.includes(status))
const excluded = DEFAULT_STATUSES.filter((status) => !statuses.includes(status))
await page.locator(`text="${panel}"`).click()
await page.click(viewletSelectors.Table)
await page.click(ViewletSelectors.Table)
await expect(locator).toContainText(statuses)
if (excluded.length > 0) await expect(locator).not.toContainText(excluded)
await page.click(viewletSelectors.Board)
await page.click(ViewletSelectors.Board)
if (excluded.length > 0) await expect(locator).not.toContainText(excluded)
for (const status of statuses) {
await expect(page.locator(`.panel-container:has-text("${status}")`)).toContainText(getIssueName(status))
@ -166,7 +68,7 @@ test('issues-status-display', async ({ page }) => {
test('save-view-options', async ({ page }) => {
const panels = ['Issues', 'Active', 'Backlog']
await navigate(page)
for (const viewletSelector of [viewletSelectors.Board, viewletSelectors.Table]) {
for (const viewletSelector of [ViewletSelectors.Board, ViewletSelectors.Table]) {
for (const panel of panels) {
await page.click(`text="${panel}"`)
await page.click(viewletSelector)

View File

@ -0,0 +1,168 @@
import { Page, expect } from '@playwright/test'
import { PlatformURI } from './utils'
export interface IssueProps {
name: string
description?: string
status?: string
labels?: string[]
priority?: string
assignee?: string
project?: string
sprint?: string
}
export enum ViewletSelectors {
Table = '.tablist-container >> div.button:nth-child(1)',
Board = '.tablist-container >> div.button:nth-child(2)'
}
export const PRIORITIES = ['No priority', 'Urgent', 'High', 'Medium', 'Low']
export const DEFAULT_STATUSES = ['Backlog', 'Todo', 'In Progress', 'Done', 'Canceled']
export const DEFAULT_USER = 'Appleseed John'
export async function navigate (page: Page): Promise<void> {
await page.goto(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/sanity-ws`)
await page.click('[id="app-tracker\\:string\\:TrackerApplication"]')
await expect(page).toHaveURL(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/sanity-ws/tracker`)
}
export async function setViewGroup (page: Page, groupName: string): Promise<void> {
await page.click('button:has-text("View")')
await page.click('.antiCard >> button >> nth=0')
await page.click(`.menu-item:has-text("${groupName}")`)
await expect(page.locator('.antiCard >> button >> nth=0')).toContainText(groupName)
await page.keyboard.press('Escape')
}
export async function setViewOrder (page: Page, orderName: string): Promise<void> {
await page.click('button:has-text("View")')
await page.click('.antiCard >> button >> nth=1')
await page.click(`.menu-item:has-text("${orderName}")`)
await expect(page.locator('.antiCard >> button >> nth=1')).toContainText(orderName)
await page.keyboard.press('Escape')
}
export async function fillIssueForm (page: Page, props: IssueProps): Promise<void> {
const { name, description, status, assignee, labels, priority, project, sprint } = props
await page.fill('[placeholder="Issue\\ title"]', name)
if (description !== undefined) {
await page.fill('.ProseMirror', description)
}
if (status !== undefined) {
await page.click('#status-editor')
await page.click(`.menu-item:has-text("${status}")`)
}
if (priority !== undefined) {
await page.click('button:has-text("No priority")')
await page.click(`.selectPopup button:has-text("${priority}")`)
}
if (labels !== undefined) {
await page.click('.button:has-text("Labels")')
for (const label of labels) {
await page.click(`.selectPopup button:has-text("${label}") >> nth=0`)
}
await page.keyboard.press('Escape')
}
if (assignee !== undefined) {
await page.click('.button:has-text("Assignee")')
await page.click(`.selectPopup button:has-text("${assignee}")`)
}
if (project !== undefined) {
await page.click('form button:has-text("Project")')
await page.click(`.selectPopup button:has-text("${project}")`)
}
if (sprint !== undefined) {
await page.click('.button:has-text("No Sprint")')
await page.click(`.selectPopup button:has-text("${sprint}")`)
}
}
export async function createIssue (page: Page, props: IssueProps): Promise<void> {
await page.waitForSelector('span:has-text("Default")')
await page.click('button:has-text("New issue")')
await fillIssueForm(page, props)
await page.click('button:has-text("Save issue")')
await page.waitForSelector('form.antiCard', { state: 'detached' })
}
export async function createProject (page: Page, projectName: string): Promise<void> {
await page.click('text=Projects')
await expect(page).toHaveURL(
`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/sanity-ws/tracker/tracker%3Ateam%3ADefaultTeam/projects`
)
await page.click('button:has-text("Project")')
await page.click('[placeholder="Project\\ name"]')
await page.fill('[placeholder="Project\\ name"]', projectName)
await page.click('button:has-text("Create project")')
}
export async function createSprint (page: Page, sprintName: string): Promise<void> {
await page.click('text=Sprints')
await expect(page).toHaveURL(
`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/sanity-ws/tracker/tracker%3Ateam%3ADefaultTeam/sprints`
)
await page.click('button:has-text("Sprint")')
await page.click('[placeholder="Sprint\\ name"]')
await page.fill('[placeholder="Sprint\\ name"]', sprintName)
await page.click('button:has-text("Create")')
}
export async function createSubissue (page: Page, props: IssueProps): Promise<void> {
await page.click('button:has-text("Add sub-issue")')
await fillIssueForm(page, props)
await page.click('button:has-text("Save")')
}
export async function createLabel (page: Page, label: string): Promise<void> {
await page.click('button:has-text("New issue")')
await page.click('button:has-text("Labels")')
await page.click('.buttons-group >> button >> nth=-1')
await page.fill('[id="tags:string:AddTag"] >> input >> nth=0', label)
await page.click('[id="tags:string:AddTag"] >> button:has-text("Create")')
await page.waitForSelector('form.antiCard[id="tags:string:AddTag"]', { state: 'detached' })
await page.keyboard.press('Escape')
await page.waitForTimeout(100)
await page.keyboard.press('Escape')
}
export async function checkIssue (page: Page, props: IssueProps): Promise<void> {
const { name, description, status, assignee, labels, priority, project, sprint } = props
if (name !== undefined) {
await expect(page.locator('.popupPanel')).toContainText(name)
}
if (description !== undefined) {
await expect(page.locator('.popupPanel')).toContainText(description)
}
const asideLocator = page.locator('.popupPanel-body__aside')
if (status !== undefined) {
await expect(asideLocator).toContainText(status)
}
if (labels !== undefined) {
await expect(asideLocator).toContainText(labels)
}
if (priority !== undefined) {
await expect(asideLocator).toContainText(priority)
}
if (assignee !== undefined) {
await expect(asideLocator).toContainText(assignee)
}
if (project !== undefined) {
await expect(asideLocator).toContainText(project)
}
if (sprint !== undefined) {
await expect(asideLocator).toContainText(sprint)
}
}
export async function checkIssueFromList (page: Page, issueName: string): Promise<void> {
await page.click(ViewletSelectors.Board)
await expect(page.locator(`.panel-container:has-text("${issueName}")`)).toContainText(issueName)
}
export async function openIssue (page: Page, name: string): Promise<void> {
await page.click(`.antiList__row:has-text("${name}") .issuePresenterRoot`)
}