New planner tests (#6728)

Signed-off-by: Rostislav Nazmeev <rostropovich@culturalcode.ru>
This commit is contained in:
Rostislav Nazmeev 2024-09-30 07:35:52 +02:00 committed by GitHub
parent 40a524ddb7
commit 64d5ceab0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 284 additions and 5 deletions

View File

@ -33,6 +33,8 @@ export class PlanningPage extends CalendarPage {
readonly buttonPopupVisibleToEveryone = (): Locator => readonly buttonPopupVisibleToEveryone = (): Locator =>
this.popup().getByRole('button', { name: 'Visible to everyone' }) this.popup().getByRole('button', { name: 'Visible to everyone' })
readonly buttonCreateRelatedIssue = (): Locator => this.page.locator('.popup button:has-text("New related issue")')
readonly buttonPopupOnlyVisibleToYou = (): Locator => readonly buttonPopupOnlyVisibleToYou = (): Locator =>
this.popup().getByRole('button', { name: 'Only visible to you' }) this.popup().getByRole('button', { name: 'Only visible to you' })
@ -91,6 +93,15 @@ export class PlanningPage extends CalendarPage {
readonly checkboxToDoInToDos = (hasText: string): Locator => readonly checkboxToDoInToDos = (hasText: string): Locator =>
this.toDoInToDos(hasText).locator('div.hulyToDoLine-checkbox') this.toDoInToDos(hasText).locator('div.hulyToDoLine-checkbox')
readonly buttonTagByName = (tagName: string): Locator =>
this.page.locator(`#navGroup-tags button:has-text("${tagName}")`)
readonly labelToDoReference = (toDoName: string): Locator =>
this.page
.locator('button.hulyToDoLine-container div[class$="overflow-label"]', { hasText: toDoName })
.locator('xpath=..')
.locator('button.reference')
async dragToCalendar (title: string, column: number, time: string, addHalf: boolean = false): Promise<void> { async dragToCalendar (title: string, column: number, time: string, addHalf: boolean = false): Promise<void> {
await this.toDosContainer().getByRole('button', { name: title }).hover() await this.toDosContainer().getByRole('button', { name: title }).hover()
@ -106,6 +117,27 @@ export class PlanningPage extends CalendarPage {
}).toPass(retryOptions) }).toPass(retryOptions)
} }
async moveToDoBorderByMouse (
title: string,
column: number,
targetTime: string,
size: 'top' | 'bottom'
): Promise<void> {
await this.page
.locator(`.calendar-element:has-text("${title}") .calendar-element-${size === 'top' ? 'start' : 'end'}`)
.hover()
await expect(async () => {
await this.page.mouse.down()
const boundingBox = await this.selectTimeCell(targetTime, column).boundingBox()
expect(boundingBox).toBeTruthy()
if (boundingBox != null) {
await this.page.mouse.move(boundingBox.x + 10, size === 'bottom' ? boundingBox.y - 8 : boundingBox.y + 5)
await this.page.mouse.up()
}
}).toPass(retryOptions)
}
async checkInSchedule (title: string): Promise<void> { async checkInSchedule (title: string): Promise<void> {
await expect(this.eventInSchedule(title)).toBeVisible() await expect(this.eventInSchedule(title)).toBeVisible()
} }
@ -245,6 +277,12 @@ export class PlanningPage extends CalendarPage {
await expect(this.page.locator(`button.hulyToDoLine-container:has-text("${toDoName}")`)).toHaveCount(1) await expect(this.page.locator(`button.hulyToDoLine-container:has-text("${toDoName}")`)).toHaveCount(1)
} }
async checkToDoExistAndShowDuration (toDoName: string, duration: string): Promise<void> {
await expect(
this.page.locator(`button.hulyToDoLine-container:has-text("${toDoName}"):has-text("${duration}")`)
).toHaveCount(1)
}
async checkToDo (data: NewToDo): Promise<void> { async checkToDo (data: NewToDo): Promise<void> {
await expect(this.textPanelToDoTitle()).toHaveValue(data.title) await expect(this.textPanelToDoTitle()).toHaveValue(data.title)
if (data.description != null) { if (data.description != null) {
@ -293,6 +331,24 @@ export class PlanningPage extends CalendarPage {
.click() .click()
} }
async openReferenceToDoByName (toDoName: string): Promise<void> {
await this.labelToDoReference(toDoName).click()
}
async getReferenceNameToDoByName (toDoName: string): Promise<null | string> {
return await this.labelToDoReference(toDoName).textContent()
}
async checkIfReferenceIsOpen (toDoName: string): Promise<void> {
const referenceName = await this.getReferenceNameToDoByName(toDoName)
await this.openReferenceToDoByName(toDoName)
await expect(this.page.locator(`.popupPanel .hulyHeader-row:has-text("${referenceName}")`)).toBeVisible()
}
async clickButtonTagByName (tagName: string): Promise<void> {
await this.buttonTagByName(tagName).click()
}
async checkToDoExistInCalendar (toDoName: string, count: number): Promise<void> { async checkToDoExistInCalendar (toDoName: string, count: number): Promise<void> {
await expect( await expect(
this.page.locator('div.calendar-element > div.event-container >> div[class*="label"]', { hasText: toDoName }) this.page.locator('div.calendar-element > div.event-container >> div[class*="label"]', { hasText: toDoName })

View File

@ -69,6 +69,11 @@ export class IssuesDetailsPage extends CommonTrackerPage {
return this.popup().locator(this.page.getByRole('button', { name: nameDr })) return this.popup().locator(this.page.getByRole('button', { name: nameDr }))
} }
readonly rowDecriptionToDo = (hasText: string): Locator => this.page.locator('div.tiptap div.todo-item', { hasText })
readonly assigneeToDo = (hasText: string): Locator => this.rowDecriptionToDo(hasText).locator('div.assignee')
readonly checkboxToDo = (hasText: string): Locator => this.rowDecriptionToDo(hasText).locator('input.chBox')
readonly slashActionItemsPopup = (): Locator => this.page.locator('.selectPopup')
async clickCloseIssueButton (): Promise<void> { async clickCloseIssueButton (): Promise<void> {
await this.buttonCloseIssue().click() await this.buttonCloseIssue().click()
} }
@ -230,4 +235,10 @@ export class IssuesDetailsPage extends CommonTrackerPage {
async checkIfButtonCbuttonCreatedByHaveTextCreatedBy (createdBy: string): Promise<void> { async checkIfButtonCbuttonCreatedByHaveTextCreatedBy (createdBy: string): Promise<void> {
await expect(this.buttonCreatedBy()).toHaveText(createdBy) await expect(this.buttonCreatedBy()).toHaveText(createdBy)
} }
async assignToDo (user: string, text: string): Promise<void> {
await this.rowDecriptionToDo(text).hover()
await this.assigneeToDo(text).click()
await this.selectListItem(user)
}
} }

View File

@ -1,4 +1,4 @@
import { test } from '@playwright/test' import { expect, test } from '@playwright/test'
import { import {
generateId, generateId,
PlatformSetting, PlatformSetting,
@ -21,6 +21,8 @@ import { SidebarPage } from '../model/sidebar-page'
import { TeamPage } from '../model/team-page' import { TeamPage } from '../model/team-page'
import { SelectWorkspacePage } from '../model/select-workspace-page' import { SelectWorkspacePage } from '../model/select-workspace-page'
import { ChannelPage } from '../model/channel-page' import { ChannelPage } from '../model/channel-page'
import { IssuesPage } from '../model/tracker/issues-page'
import { NewIssue } from '../model/tracker/types'
test.use({ test.use({
storageState: PlatformSetting storageState: PlatformSetting
@ -31,7 +33,7 @@ test.describe('Planning ToDo tests', () => {
await (await page.goto(`${PlatformURI}/workbench/sanity-ws/time`))?.finished() await (await page.goto(`${PlatformURI}/workbench/sanity-ws/time`))?.finished()
}) })
test('Add several slots for the same day', async ({ browser, page }) => { test('Add several slots for the same day', async ({ page }) => {
const dateEnd = new Date() const dateEnd = new Date()
const toDoSeveralSlots: NewToDo = { const toDoSeveralSlots: NewToDo = {
title: 'Add several slots for the same day', title: 'Add several slots for the same day',
@ -74,6 +76,27 @@ test.describe('Planning ToDo tests', () => {
} }
await planningPage.clickButtonCardClose() await planningPage.clickButtonCardClose()
await test.step('User is able to create Related Issue for Action Item', async () => {
const issuesPage = new IssuesPage(page)
const leftMenuPage = new LeftSideMenuPage(page)
const relatedIssueData: NewIssue = {
title: `ToDo Related Issue ${generateId()}`,
description: 'Description',
projectName: 'Default'
}
await planningPage.eventInSchedule(toDoSeveralSlots.title).first().click({ button: 'right' })
await planningPage.buttonCreateRelatedIssue().click()
await issuesPage.fillNewIssueForm(relatedIssueData)
await issuesPage.clickButtonCreateIssue()
await leftMenuPage.clickTracker()
await issuesPage.clickLinkSidebarAll()
await issuesPage.searchIssueByName(relatedIssueData.title)
await (await page.goto(`${PlatformURI}/workbench/sanity-ws/time`))?.finished()
})
await planningPage.checkToDoExistInCalendar(toDoSeveralSlots.title, 2) await planningPage.checkToDoExistInCalendar(toDoSeveralSlots.title, 2)
}) })
@ -192,6 +215,7 @@ test.describe('Planning ToDo tests', () => {
const titleV = `Visible ToDo ${generateId()}` const titleV = `Visible ToDo ${generateId()}`
const titleI = `Inisible ToDo ${generateId()}` const titleI = `Inisible ToDo ${generateId()}`
const time = getTimeForPlanner() const time = getTimeForPlanner()
const time2 = getTimeForPlanner(1)
const leftSideMenuPage: LeftSideMenuPage = new LeftSideMenuPage(page) const leftSideMenuPage: LeftSideMenuPage = new LeftSideMenuPage(page)
const loginPage: LoginPage = new LoginPage(page) const loginPage: LoginPage = new LoginPage(page)
@ -217,6 +241,11 @@ test.describe('Planning ToDo tests', () => {
await planningPage.buttonPopupVisibleToEveryone().click() await planningPage.buttonPopupVisibleToEveryone().click()
await planningPage.buttonPopupSave().click() await planningPage.buttonPopupSave().click()
await test.step('User is able to create multiple by dragging slots to the same Action Item', async () => {
await planningPage.dragToCalendar(titleV, 3, time2)
await planningPage.checkToDoExistInCalendar(titleV, 2)
})
await planningPage.selectInputToDo().fill(titleI) await planningPage.selectInputToDo().fill(titleI)
await planningPage.selectInputToDo().press('Enter') await planningPage.selectInputToDo().press('Enter')
await planningPage.dragToCalendar(titleI, 2, time, true) await planningPage.dragToCalendar(titleI, 2, time, true)
@ -262,7 +291,98 @@ test.describe('Planning ToDo tests', () => {
}) })
}) })
test('User is able to open Planner in Sidebar', async ({ browser, page, request }) => { test.only('ToDo labels are exist in Tag list', async ({ page }) => {
const planningPage = new PlanningPage(page)
const planningNavigationMenuPage = new PlanningNavigationMenuPage(page)
const toDoWithLabel: NewToDo = {
title: `ToDo with label-${generateId()}`,
description: 'Description for ToDo with label',
duedate: 'today',
priority: 'Medium',
visible: 'FreeBusy',
labels: `TAG-${generateId()}`,
createLabel: true
}
const toDoWithoutLabel: NewToDo = {
title: `ToDo without label-${generateId()}`,
description: 'Description for ToDo without label',
duedate: 'today',
priority: 'Medium',
visible: 'FreeBusy'
}
await test.step('Prepare ToDo with label', async () => {
await planningNavigationMenuPage.clickOnButtonToDoAll()
await planningPage.createNewToDo(toDoWithLabel)
await planningPage.openToDoByName(toDoWithLabel.title)
await planningPage.updateToDo(toDoWithLabel)
await planningPage.clickButtonCardClose()
})
await test.step('Prepare ToDo without label', async () => {
await planningNavigationMenuPage.clickOnButtonToDoAll()
await planningPage.createNewToDo(toDoWithoutLabel)
})
await test.step('Labels are added to tag list', async () => {
await planningPage.checkToDoExist(toDoWithLabel.title)
await planningPage.checkToDoExist(toDoWithoutLabel.title)
if (typeof toDoWithLabel.labels === 'string') {
await expect(planningPage.buttonTagByName(toDoWithLabel.labels)).toBeVisible()
}
})
await test.step('Click to the tag and filter todos', async () => {
if (typeof toDoWithLabel.labels === 'string') {
await planningPage.clickButtonTagByName(toDoWithLabel.labels)
await planningPage.checkToDoExist(toDoWithLabel.title)
await planningPage.checkToDoNotExist(toDoWithoutLabel.title)
}
})
})
test('Change ToDo start and end times by dragging', async ({ page }) => {
const planningPage = new PlanningPage(page)
const planningNavigationMenuPage = new PlanningNavigationMenuPage(page)
const dateEnd = new Date()
const toDoWithLabel: NewToDo = {
title: `ToDo to change duration-${generateId()}`,
description: 'Description for ToDo to change duration',
slots: [
{
dateStart: 'today',
timeStart: '1400',
dateEnd: {
day: dateEnd.getDate().toString(),
month: (dateEnd.getMonth() + 1).toString(),
year: dateEnd.getFullYear().toString()
},
timeEnd: '1500'
}
]
}
await test.step('Prepare ToDo', async () => {
await planningNavigationMenuPage.clickOnButtonToDoAll()
await planningPage.createNewToDo(toDoWithLabel)
})
await test.step('Resize ToDo', async () => {
await planningPage.moveToDoBorderByMouse(toDoWithLabel.title, 1, '4pm', 'bottom')
await planningPage.moveToDoBorderByMouse(toDoWithLabel.title, 1, '1pm', 'top')
})
await test.step('Check time changes', async () => {
await planningNavigationMenuPage.clickOnButtonToDoAll()
await planningPage.checkToDoExistAndShowDuration(toDoWithLabel.title, '3h')
})
})
test('User is able to open Planner in Sidebar', async ({ page }) => {
const leftMenuPage = new LeftSideMenuPage(page) const leftMenuPage = new LeftSideMenuPage(page)
const channelPage = new ChannelPage(page) const channelPage = new ChannelPage(page)

View File

@ -3,6 +3,11 @@ import { generateId, PlatformSetting, PlatformURI } from '../utils'
import { PlanningPage } from '../model/planning/planning-page' import { PlanningPage } from '../model/planning/planning-page'
import { NewToDo } from '../model/planning/types' import { NewToDo } from '../model/planning/types'
import { PlanningNavigationMenuPage } from '../model/planning/planning-navigation-menu-page' import { PlanningNavigationMenuPage } from '../model/planning/planning-navigation-menu-page'
import { IssuesPage } from '../model/tracker/issues-page'
import { IssuesDetailsPage } from '../model/tracker/issues-details-page'
import { LeftSideMenuPage } from '../model/left-side-menu-page'
import { DocumentsPage } from '../model/documents/documents-page'
import { DocumentContentPage } from '../model/documents/document-content-page'
test.use({ test.use({
storageState: PlatformSetting storageState: PlatformSetting
@ -11,6 +16,12 @@ test.use({
const retryOptions = { intervals: [1000, 1500, 2500], timeout: 60000 } const retryOptions = { intervals: [1000, 1500, 2500], timeout: 60000 }
test.describe('Planning ToDo tests', () => { test.describe('Planning ToDo tests', () => {
let issuesPage: IssuesPage
let issuesDetailsPage: IssuesDetailsPage
let leftSideMenuPage: LeftSideMenuPage
let documentsPage: DocumentsPage
let documentContentPage: DocumentContentPage
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
await (await page.goto(`${PlatformURI}/workbench/sanity-ws/time`))?.finished() await (await page.goto(`${PlatformURI}/workbench/sanity-ws/time`))?.finished()
}) })
@ -109,7 +120,7 @@ test.describe('Planning ToDo tests', () => {
}) })
}) })
test('Delete ToDo', async ({ page }) => { test('Delete a ToDo', async ({ page }) => {
const deleteToDo: NewToDo = { const deleteToDo: NewToDo = {
title: 'ToDo For delete' title: 'ToDo For delete'
} }
@ -151,4 +162,76 @@ test.describe('Planning ToDo tests', () => {
await planningPage.checkToDoExist(newToDoPlanned.title) await planningPage.checkToDoExist(newToDoPlanned.title)
await planningPage.checkToDoExist(newToDoUnPlanned.title) await planningPage.checkToDoExist(newToDoUnPlanned.title)
}) })
test('Show ActionItem in Planner from Issue description', async ({ page }) => {
issuesPage = new IssuesPage(page)
issuesDetailsPage = new IssuesDetailsPage(page)
leftSideMenuPage = new LeftSideMenuPage(page)
const planningNavigationMenuPage = new PlanningNavigationMenuPage(page)
const planningPage = new PlanningPage(page)
const toDoName = `ToDo from issue ${generateId()}`
const newIssue = {
title: `Issue with ToDos ${generateId()}`,
description: '',
projectName: 'Default'
}
await test.step('Prepare Issue and add ActionItems to that', async () => {
await leftSideMenuPage.clickTracker()
await issuesPage.clickNewIssue()
await issuesPage.fillNewIssueForm(newIssue)
await issuesPage.clickButtonCreateIssue()
await issuesPage.clickLinkSidebarAll()
await issuesPage.openIssueByName(newIssue.title)
await issuesDetailsPage.editIssue({ assignee: 'Appleseed John', status: 'ToDo' })
await issuesDetailsPage.addToDescription('/')
await issuesDetailsPage.slashActionItemsPopup().getByText('Action item').click()
await issuesPage.page.keyboard.type(toDoName)
await issuesPage.page.keyboard.press('Escape')
await issuesDetailsPage.assignToDo('Appleseed John', toDoName)
})
await test.step('Check ToDo in Planner', async () => {
await leftSideMenuPage.clickPlanner()
await planningNavigationMenuPage.clickOnButtonToDoAll()
await planningPage.checkToDoExist(toDoName)
await planningPage.checkIfReferenceIsOpen(toDoName)
})
})
test('Show ActionItem in Planner from Document', async ({ page }) => {
documentsPage = new DocumentsPage(page)
documentContentPage = new DocumentContentPage(page)
leftSideMenuPage = new LeftSideMenuPage(page)
const planningNavigationMenuPage = new PlanningNavigationMenuPage(page)
const planningPage = new PlanningPage(page)
const toDoName = `ToDo from document ${generateId()}`
const newDocument = {
title: `Document with ToDos ${generateId()}`,
space: 'Default'
}
await test.step('Prepare Document and add ActionItems to that', async () => {
await leftSideMenuPage.clickDocuments()
await documentsPage.buttonCreateDocument().click()
await documentsPage.createDocument(newDocument)
await documentsPage.openDocument(newDocument.title)
await documentContentPage.addContentToTheNewLine('/')
await documentContentPage.slashActionItemsPopup().getByText('Action item').click()
await documentContentPage.page.keyboard.type(toDoName)
await documentContentPage.page.keyboard.press('Escape')
await documentContentPage.assignToDo('Appleseed John', toDoName)
})
await test.step('Check ToDo in Planner', async () => {
await leftSideMenuPage.clickPlanner()
await planningNavigationMenuPage.clickOnButtonToDoAll()
await planningPage.checkToDoExist(toDoName)
await planningPage.checkIfReferenceIsOpen(toDoName)
})
})
}) })

View File

@ -36,8 +36,17 @@ export function generateTestData (): TestData {
} }
} }
export function getTimeForPlanner (): string { export function getTimeForPlanner (plusHours?: number): string {
let hour = new Date().getHours() let hour = new Date().getHours()
if (typeof plusHours === 'number') hour += plusHours
const ampm = hour < 13 ? 'am' : 'pm'
hour = hour < 1 ? 1 : hour >= 11 && hour < 13 ? 11 : hour >= 22 ? 10 : hour > 12 ? hour - 12 : hour
return `${hour}${ampm}`
}
export function getNextHourTimeForPlanner (): string {
let hour = new Date().getHours() + 1
const ampm = hour < 13 ? 'am' : 'pm' const ampm = hour < 13 ? 'am' : 'pm'
hour = hour < 1 ? 1 : hour >= 11 && hour < 13 ? 11 : hour >= 22 ? 10 : hour > 12 ? hour - 12 : hour hour = hour < 1 ? 1 : hour >= 11 && hour < 13 ? 11 : hour >= 22 ? 10 : hour > 12 ? hour - 12 : hour