diff --git a/tests/sanity-ws/000009/_migrations-1710692874573-0.snp.gz b/tests/sanity-ws/000009/_migrations-1710692874573-0.snp.gz new file mode 100644 index 0000000000..4e4e1d3cc9 Binary files /dev/null and b/tests/sanity-ws/000009/_migrations-1710692874573-0.snp.gz differ diff --git a/tests/sanity-ws/000009/_migrations-data-1710692874573-1.tar.gz b/tests/sanity-ws/000009/_migrations-data-1710692874573-1.tar.gz new file mode 100644 index 0000000000..0e888d7658 Binary files /dev/null and b/tests/sanity-ws/000009/_migrations-data-1710692874573-1.tar.gz differ diff --git a/tests/sanity-ws/000009/activity-1710692874573-0.snp.gz b/tests/sanity-ws/000009/activity-1710692874573-0.snp.gz new file mode 100644 index 0000000000..6d57e3be09 Binary files /dev/null and b/tests/sanity-ws/000009/activity-1710692874573-0.snp.gz differ diff --git a/tests/sanity-ws/000009/doc-index-state-1710692874573-0.snp.gz b/tests/sanity-ws/000009/doc-index-state-1710692874573-0.snp.gz new file mode 100644 index 0000000000..83efd39854 Binary files /dev/null and b/tests/sanity-ws/000009/doc-index-state-1710692874573-0.snp.gz differ diff --git a/tests/sanity-ws/000009/doc-index-state-data-1710692874573-1.tar.gz b/tests/sanity-ws/000009/doc-index-state-data-1710692874573-1.tar.gz new file mode 100644 index 0000000000..3e975885ea Binary files /dev/null and b/tests/sanity-ws/000009/doc-index-state-data-1710692874573-1.tar.gz differ diff --git a/tests/sanity-ws/000009/fulltext-blob-1710692874573-0.snp.gz b/tests/sanity-ws/000009/fulltext-blob-1710692874573-0.snp.gz new file mode 100644 index 0000000000..c26a4c96c9 Binary files /dev/null and b/tests/sanity-ws/000009/fulltext-blob-1710692874573-0.snp.gz differ diff --git a/tests/sanity-ws/000009/fulltext-blob-data-1710692874573-1.tar.gz b/tests/sanity-ws/000009/fulltext-blob-data-1710692874573-1.tar.gz new file mode 100644 index 0000000000..b08eaeb12b Binary files /dev/null and b/tests/sanity-ws/000009/fulltext-blob-data-1710692874573-1.tar.gz differ diff --git a/tests/sanity-ws/000009/space-1710692874573-0.snp.gz b/tests/sanity-ws/000009/space-1710692874573-0.snp.gz new file mode 100644 index 0000000000..9ca827a129 Binary files /dev/null and b/tests/sanity-ws/000009/space-1710692874573-0.snp.gz differ diff --git a/tests/sanity-ws/000009/space-data-1710692874573-1.tar.gz b/tests/sanity-ws/000009/space-data-1710692874573-1.tar.gz new file mode 100644 index 0000000000..92e30d5a3c Binary files /dev/null and b/tests/sanity-ws/000009/space-data-1710692874573-1.tar.gz differ diff --git a/tests/sanity-ws/000009/tags-1710692874573-0.snp.gz b/tests/sanity-ws/000009/tags-1710692874573-0.snp.gz new file mode 100644 index 0000000000..0e67af2fa3 Binary files /dev/null and b/tests/sanity-ws/000009/tags-1710692874573-0.snp.gz differ diff --git a/tests/sanity-ws/000009/tags-data-1710692874573-1.tar.gz b/tests/sanity-ws/000009/tags-data-1710692874573-1.tar.gz new file mode 100644 index 0000000000..1b9625e77a Binary files /dev/null and b/tests/sanity-ws/000009/tags-data-1710692874573-1.tar.gz differ diff --git a/tests/sanity-ws/000009/task-1710692874573-0.snp.gz b/tests/sanity-ws/000009/task-1710692874573-0.snp.gz new file mode 100644 index 0000000000..1bbd869ce0 Binary files /dev/null and b/tests/sanity-ws/000009/task-1710692874573-0.snp.gz differ diff --git a/tests/sanity-ws/000009/task-data-1710692874573-1.tar.gz b/tests/sanity-ws/000009/task-data-1710692874573-1.tar.gz new file mode 100644 index 0000000000..13e1dbda23 Binary files /dev/null and b/tests/sanity-ws/000009/task-data-1710692874573-1.tar.gz differ diff --git a/tests/sanity-ws/000009/time-1710692874573-0.snp.gz b/tests/sanity-ws/000009/time-1710692874573-0.snp.gz new file mode 100644 index 0000000000..3c78be2be5 Binary files /dev/null and b/tests/sanity-ws/000009/time-1710692874573-0.snp.gz differ diff --git a/tests/sanity-ws/000009/time-data-1710692874573-1.tar.gz b/tests/sanity-ws/000009/time-data-1710692874573-1.tar.gz new file mode 100644 index 0000000000..94644eeca6 Binary files /dev/null and b/tests/sanity-ws/000009/time-data-1710692874573-1.tar.gz differ diff --git a/tests/sanity-ws/000009/tx-1710692874573-0.snp.gz b/tests/sanity-ws/000009/tx-1710692874573-0.snp.gz new file mode 100644 index 0000000000..0a57f63cc0 Binary files /dev/null and b/tests/sanity-ws/000009/tx-1710692874573-0.snp.gz differ diff --git a/tests/sanity-ws/000009/tx-data-1710692874573-1.tar.gz b/tests/sanity-ws/000009/tx-data-1710692874573-1.tar.gz new file mode 100644 index 0000000000..abee7ea244 Binary files /dev/null and b/tests/sanity-ws/000009/tx-data-1710692874573-1.tar.gz differ diff --git a/tests/sanity-ws/backup.json.gz b/tests/sanity-ws/backup.json.gz index ae03dc659f..3c3c76d060 100644 Binary files a/tests/sanity-ws/backup.json.gz and b/tests/sanity-ws/backup.json.gz differ diff --git a/tests/sanity/tests/model/calendar-page.ts b/tests/sanity/tests/model/calendar-page.ts index 0fc6095ebf..316965a64d 100644 --- a/tests/sanity/tests/model/calendar-page.ts +++ b/tests/sanity/tests/model/calendar-page.ts @@ -8,6 +8,11 @@ export class CalendarPage extends CommonPage { readonly inputTargetDateMonth: Locator readonly inputTargetDateYear: Locator readonly buttonTargetDateSave: Locator + readonly inputPopupDateDay: Locator + readonly inputPopupDateMonth: Locator + readonly inputPopupDateYear: Locator + readonly inputPopupTime: Locator + readonly inputPopupDateSave: Locator constructor (page: Page) { super() @@ -17,6 +22,11 @@ export class CalendarPage extends CommonPage { this.inputTargetDateMonth = page.locator('div.date-popup-container div.datetime-input span.digit:nth-child(3)') this.inputTargetDateYear = page.locator('div.date-popup-container div.datetime-input span.digit:nth-child(5)') this.buttonTargetDateSave = page.locator('div.date-popup-container div.footer button') + this.inputPopupDateDay = page.locator('div[class*="date-popup"] div.datetime-input span.digit:first-child') + this.inputPopupDateMonth = page.locator('div[class*="date-popup"] div.datetime-input span.digit:nth-child(3)') + this.inputPopupDateYear = page.locator('div[class*="date-popup"] div.datetime-input span.digit:nth-child(5)') + this.inputPopupTime = page.locator('div[class*="date-popup"] div.datetime-input span.digit:nth-child(7)') + this.inputPopupDateSave = page.locator('div[class*="date-popup"] div.footer button') } async fillDatePopup (day: string, month: string, year: string): Promise { @@ -31,4 +41,18 @@ export class CalendarPage extends CommonPage { await expect(this.inputTargetDateDay).toBeVisible() await this.page.locator('div.popup div.shift-container div.btn span', { hasText: inDays }).click() } + + async fillSelectDatePopup (day: string, month: string, year: string, time: string): Promise { + await this.inputPopupDateDay.click() + await this.inputPopupDateDay.pressSequentially(day) + await this.inputPopupDateMonth.click() + await this.inputPopupDateMonth.pressSequentially(month) + await this.inputPopupDateYear.click() + await this.inputPopupDateYear.pressSequentially(year) + + await this.inputPopupTime.click() + await this.inputPopupTime.pressSequentially(time) + + await this.inputPopupDateSave.click() + } } diff --git a/tests/sanity/tests/model/common-page.ts b/tests/sanity/tests/model/common-page.ts index e02f67a7c2..be43250965 100644 --- a/tests/sanity/tests/model/common-page.ts +++ b/tests/sanity/tests/model/common-page.ts @@ -96,7 +96,19 @@ export class CommonPage { await page.locator('form.mentionPoup div.list-item span.name', { hasText: mentionName }).click() } + async selectListItem (page: Page, name: string): Promise { + await page.locator('div.selectPopup div.list-item', { hasText: name }).click({ delay: 100 }) + } + + async selectPopupItem (page: Page, name: string): Promise { + await page.locator('div.hulyPopup-container button.hulyPopup-row', { hasText: name }).click({ delay: 100 }) + } + async closePopup (page: Page): Promise { await page.locator('div.popup button[id="card-close"]').click() } + + async checkPopupItem (page: Page, itemText: string): Promise { + await expect(page.locator('div.selectPopup button.menu-item', { hasText: itemText })).toBeVisible() + } } diff --git a/tests/sanity/tests/model/planning/planning-navigation-menu-page.ts b/tests/sanity/tests/model/planning/planning-navigation-menu-page.ts new file mode 100644 index 0000000000..f5667b8a68 --- /dev/null +++ b/tests/sanity/tests/model/planning/planning-navigation-menu-page.ts @@ -0,0 +1,21 @@ +import { type Locator, type Page } from '@playwright/test' + +export class PlanningNavigationMenuPage { + readonly page: Page + readonly buttonToDoAll: Locator + readonly buttonToDoUnplanned: Locator + readonly buttonToDoPlanned: Locator + + constructor (page: Page) { + this.page = page + this.buttonToDoAll = page.locator('button[class*="hulyNavItem-container"] span[class*="hulyNavItem-label"]', { + hasText: 'All' + }) + this.buttonToDoUnplanned = page.locator('button[class*="hulyNavItem-container"] span[class*="hulyNavItem-label"]', { + hasText: 'Unplanned' + }) + this.buttonToDoPlanned = page.locator( + 'button[class*="hulyNavItem-container"] span[class*="hulyNavItem-label"]:text-is("Planned")' + ) + } +} diff --git a/tests/sanity/tests/model/planning/planning-page.ts b/tests/sanity/tests/model/planning/planning-page.ts new file mode 100644 index 0000000000..67860c6538 --- /dev/null +++ b/tests/sanity/tests/model/planning/planning-page.ts @@ -0,0 +1,272 @@ +import { type Locator, type Page, expect } from '@playwright/test' +import { NewToDo, Slot } from './types' +import { CalendarPage } from '../calendar-page' + +export class PlanningPage extends CalendarPage { + readonly page: Page + readonly pageHeader: Locator + readonly buttonCreateNewToDo: Locator + readonly inputPopupCreateTitle: Locator + readonly inputPopupCreateDescription: Locator + readonly inputPanelCreateDescription: Locator + readonly buttonPopupCreateDueDate: Locator + readonly buttonPanelCreateDueDate: Locator + readonly buttonPopupCreatePriority: Locator + readonly buttonPanelCreatePriority: Locator + readonly buttonPopupCreateVisible: Locator + readonly buttonPanelCreateVisible: Locator + readonly buttonPopupCreateAddLabel: Locator + readonly buttonPanelCreateAddLabel: Locator + readonly buttonPopupCreateAddSlot: Locator + readonly buttonPanelCreateAddSlot: Locator + readonly buttonCalendarToday: Locator + readonly buttonCreateToDo: Locator + readonly inputCreateToDoTitle: Locator + readonly buttonCardClose: Locator + readonly textPanelToDoTitle: Locator + readonly textPanelToDoDescription: Locator + readonly textPanelDueDate: Locator + readonly textPanelPriority: Locator + readonly textPanelVisible: Locator + readonly buttonPanelLabelFirst: Locator + readonly buttonMenuDelete: Locator + readonly buttonPopupSelectDateNextMonth: Locator + + constructor (page: Page) { + super(page) + this.page = page + this.pageHeader = page.locator('div[class*="navigator"] div[class*="header"]', { hasText: 'Planning' }) + this.buttonCreateNewToDo = page.locator('div[class*="toDos-container"] button.button') + this.inputPopupCreateTitle = page.locator('div.popup input') + this.inputPopupCreateDescription = page.locator('div.popup div.tiptap') + this.inputPanelCreateDescription = page.locator('div.hulyModal-container div.tiptap') + this.buttonPopupCreateDueDate = page.locator('div.popup button.antiButton', { hasText: 'Due date' }) + this.buttonPanelCreateDueDate = page.locator('div.hulyModal-container button.antiButton', { hasText: 'Due date' }) + this.buttonPopupCreatePriority = page.locator('div.popup button#priorityButton') + this.buttonPanelCreatePriority = page.locator('div.hulyModal-container button#priorityButton') + this.buttonPopupCreateVisible = page.locator('div.popup button.type-button.menu', { hasText: 'visible' }) + this.buttonPanelCreateVisible = page.locator('div.hulyModal-container button.type-button.menu', { + hasText: 'visible' + }) + this.buttonPopupCreateAddLabel = page.locator('div.popup button.antiButton', { hasText: 'Add label' }) + this.buttonPanelCreateAddLabel = page.locator('.hulyHeader-titleGroup > button:nth-child(2)') + this.buttonPopupCreateAddSlot = page.locator('div.popup button.antiButton', { hasText: 'Add Slot' }) + this.buttonPanelCreateAddSlot = page.locator('div.hulyModal-container button.antiButton', { hasText: 'Add Slot' }) + this.buttonCalendarToday = page.locator('div.popup div.calendar button.day.today') + this.buttonCreateToDo = page.locator('div.popup button.antiButton', { hasText: 'Add ToDo' }) + this.inputCreateToDoTitle = page.locator('div.toDos-container input[placeholder="Add todo, press Enter to save"]') + this.buttonCardClose = page.locator( + '.hulyModal-container > .hulyHeader-container > .hulyHeader-buttonsGroup > .font-medium-14' + ) + this.textPanelToDoTitle = page.locator( + 'div.hulyModal-container div.top-content label.editbox-wrapper.ghost.large input' + ) + this.textPanelToDoDescription = page.locator('div.hulyModal-container div.top-content div.tiptap > p') + this.textPanelDueDate = page.locator( + 'div.hulyModal-container div.slots-content div.flex-row-top.justify-between div.flex-row-center button.antiButton:first-child div[slot="content"]' + ) + this.textPanelPriority = page.locator('div.hulyModal-container button#priorityButton svg') + this.textPanelVisible = page.locator( + 'div.hulyModal-container div.hulyHeader-titleGroup > button:nth-child(3) > span' + ) + this.buttonPanelLabelFirst = page.locator('div.hulyModal-container div.hulyHeader-titleGroup > button:nth-child(2)') + this.buttonMenuDelete = page.locator('button.ap-menuItem span', { hasText: 'Delete' }) + this.buttonPopupSelectDateNextMonth = page.locator('div.popup div.header > div:last-child > button:last-child') + } + + async createNewToDoFromInput (title: string): Promise { + await this.inputCreateToDoTitle.fill(title) + await this.page.keyboard.press('Enter') + } + + async createNewToDo (data: NewToDo): Promise { + await this.buttonCreateNewToDo.click() + + await this.inputPopupCreateTitle.fill(data.title) + await this.updateToDo(data, true) + + await this.buttonCreateToDo.click() + } + + async updateToDo (data: NewToDo, popup: boolean = false): Promise { + if (data.description != null) { + await (popup + ? this.inputPopupCreateDescription.fill(data.description) + : this.inputPanelCreateDescription.fill(data.description)) + } + if (data.duedate != null) { + await (popup ? this.buttonPopupCreateDueDate.click() : this.buttonPanelCreateDueDate.click()) + if (data.duedate === 'today') { + await this.buttonDatePopupToday.click() + } else { + await this.selectMenuItem(this.page, data.duedate) + } + } + if (data.priority != null) { + await (popup ? this.buttonPopupCreatePriority.click() : this.buttonPanelCreatePriority.click()) + await this.selectListItem(this.page, data.priority) + } + if (data.visible != null) { + await (popup ? this.buttonPopupCreateVisible.click() : this.buttonPanelCreateVisible.click()) + await this.selectPopupItem(this.page, data.visible) + } + if (data.labels != null && data.createLabel != null) { + await (popup ? this.buttonPopupCreateAddLabel.click() : this.buttonPanelCreateAddLabel.click()) + if (data.createLabel) { + await this.pressCreateButtonSelectPopup(this.page) + await this.addNewTagPopup(this.page, data.labels, 'Tag from createNewIssue') + } + await this.checkFromDropdownWithSearch(this.page, data.labels) + await (popup ? this.buttonPopupCreateAddLabel.press('Escape') : this.buttonPanelCreateAddLabel.press('Escape')) + } + if (data.slots != null) { + let index = 0 + for (const slot of data.slots) { + await (popup + ? this.buttonPopupCreateAddSlot.click({ force: true }) + : this.buttonPanelCreateAddSlot.click({ force: true })) + await this.setTimeSlot(index, slot, popup) + index++ + } + } + } + + public async setTimeSlot (rowNumber: number, slot: Slot, popup: boolean = false): Promise { + const p = popup + ? 'div.popup div.horizontalBox div.flex-row-center' + : 'div.hulyModal-container div.slots-content div.horizontalBox div.flex-row-center' + const row = this.page.locator(p).nth(rowNumber) + + // dateStart + await row.locator('div.dateEditor-container:nth-child(2) button:first-child').click() + if (slot.dateStart === 'today') { + await this.buttonCalendarToday.click() + } else { + if (slot.dateStart === '1') { + await this.buttonPopupSelectDateNextMonth.click() + } + await this.page + .locator('div.popup div.calendar button.day') + .filter({ has: this.page.locator(`text="${slot.dateStart}"`) }) + .click() + } + // timeStart + const hours = slot.timeStart.substring(0, 2) + const minutes = slot.timeStart.substring(2, slot.timeStart.length) + await row + .locator('div.dateEditor-container:nth-child(2) button:last-child span.digit:first-child') + .click({ delay: 200 }) + await row + .locator('div.dateEditor-container:nth-child(2) button:last-child span.digit:first-child') + .pressSequentially(hours, { delay: 100 }) + await row + .locator('div.dateEditor-container:nth-child(2) button:last-child span.digit:last-child') + .click({ delay: 200 }) + await row + .locator('div.dateEditor-container:nth-child(2) button:last-child span.digit:last-child') + .pressSequentially(minutes, { delay: 100 }) + + // dateEnd + timeEnd + await row.locator('div.dateEditor-container:nth-child(4) button').click() + await this.fillSelectDatePopup(slot.dateEnd.day, slot.dateEnd.month, slot.dateEnd.year, slot.timeEnd) + } + + private async checkTimeSlot (rowNumber: number, slot: Slot, popup: boolean = false): Promise { + const p = popup + ? 'div.popup div.horizontalBox div.flex-row-center' + : 'div.hulyModal-container div.slots-content div.horizontalBox div.flex-row-center' + const row = this.page.locator(p).nth(rowNumber) + // timeStart + await expect(row.locator('div.dateEditor-container:nth-child(2) button:last-child div.datetime-input')).toHaveText( + slot.timeStart + ) + // timeEnd + await expect(row.locator('div.dateEditor-container:nth-child(4) button > div:first-child')).toHaveText(slot.timeEnd) + } + + async openToDoByName (toDoName: string): Promise { + await this.page.locator('button.hulyToDoLine-container div[class$="overflow-label"]', { hasText: toDoName }).click() + } + + async checkToDoNotExist (toDoName: string): Promise { + await expect( + this.page.locator('button.hulyToDoLine-container div[class$="overflow-label"]', { hasText: toDoName }) + ).toHaveCount(0) + } + + async checkToDoExist (toDoName: string): Promise { + await expect( + this.page.locator('button.hulyToDoLine-container div[class$="overflow-label"]', { hasText: toDoName }) + ).toHaveCount(1) + } + + async checkToDo (data: NewToDo): Promise { + await expect(this.textPanelToDoTitle).toHaveValue(data.title) + if (data.description != null) { + await expect(this.textPanelToDoDescription).toHaveText(data.description) + } + if (data.duedate != null) { + await expect(this.textPanelDueDate).toHaveText(data.duedate) + } + if (data.priority != null) { + const classAttribute = await this.textPanelPriority.getAttribute('class') + expect(classAttribute).toContain(data.priority) + } + if (data.visible != null) { + await expect(this.textPanelVisible).toHaveText(data.visible) + } + if (data.labels != null) { + await this.buttonPanelLabelFirst.click() + await this.checkPopupItem(this.page, data.labels) + await this.buttonPanelLabelFirst.click({ force: true }) + } + if (data.slots != null) { + let index = 0 + for (const slot of data.slots) { + await this.checkTimeSlot(index, slot) + index++ + } + } + } + + async deleteToDoByName (toDoName: string): Promise { + await this.page.locator('button.hulyToDoLine-container div[class$="overflow-label"]', { hasText: toDoName }).hover() + await this.page + .locator('button.hulyToDoLine-container div[class$="overflow-label"]', { hasText: toDoName }) + .locator('xpath=..') + .locator('div.flex-row-center button.hulyToDoLine-dragbox') + .click({ button: 'right' }) + await this.buttonMenuDelete.click() + await this.pressYesDeletePopup(this.page) + } + + async selectToDoByName (toDoName: string): Promise { + await this.page + .locator('button.hulyToDoLine-container div[class$="overflow-label"]', { hasText: toDoName }) + .locator('xpath=..') + .locator('div.flex-row-center div.hulyToDoLine-checkbox > label') + .click() + } + + async checkToDoExistInCalendar (toDoName: string, count: number): Promise { + await expect( + this.page.locator('div.calendar-element > div.event-container >> div[class*="label"]', { hasText: toDoName }) + ).toHaveCount(count) + } + + public async deleteTimeSlot (rowNumber: number): Promise { + const row = this.page.locator('div.hulyModal-container div.slots-content div.horizontalBox div.tool').nth(rowNumber) + await row.locator('xpath=..').hover() + await row.locator('button').click() + await expect(row.locator('button')).toBeHidden() + await this.pressYesDeletePopup(this.page) + } + + public async checkTimeSlotEndDate (rowNumber: number, dateEnd: string): Promise { + const row = this.page + .locator('div.hulyModal-container div.slots-content div.horizontalBox div.flex-row-center') + .nth(rowNumber) + // dateEnd + await expect(row.locator('div.dateEditor-container:nth-child(2) button:first-child')).toContainText(dateEnd) + } +} diff --git a/tests/sanity/tests/model/planning/types.ts b/tests/sanity/tests/model/planning/types.ts new file mode 100644 index 0000000000..4a7056e85a --- /dev/null +++ b/tests/sanity/tests/model/planning/types.ts @@ -0,0 +1,23 @@ +export interface NewToDo { + title: string + description?: string + duedate?: string + priority?: string + visible?: string + createLabel?: boolean + labels?: string + slots?: Slot[] +} + +export interface Slot { + dateStart: string + timeStart: string + dateEnd: Date + timeEnd: string +} + +export interface Date { + day: string + month: string + year: string +} diff --git a/tests/sanity/tests/planning/plan.spec.ts b/tests/sanity/tests/planning/plan.spec.ts new file mode 100644 index 0000000000..278cf8285c --- /dev/null +++ b/tests/sanity/tests/planning/plan.spec.ts @@ -0,0 +1,162 @@ +import { test } from '@playwright/test' +import { PlatformSetting, PlatformURI } from '../utils' +import { PlanningPage } from '../model/planning/planning-page' +import { NewToDo } from '../model/planning/types' +import { PlanningNavigationMenuPage } from '../model/planning/planning-navigation-menu-page' + +test.use({ + storageState: PlatformSetting +}) + +test.describe('Planning ToDo tests', () => { + test.beforeEach(async ({ page }) => { + await (await page.goto(`${PlatformURI}/workbench/sanity-ws/time`))?.finished() + }) + + test('Add several slots for the same day', async ({ browser, page }) => { + const dateEnd = new Date() + const toDoSeveralSlots: NewToDo = { + title: 'Add several slots for the same day', + slots: [ + { + dateStart: 'today', + timeStart: '1000', + dateEnd: { + day: dateEnd.getDate().toString(), + month: (dateEnd.getMonth() + 1).toString(), + year: dateEnd.getFullYear().toString() + }, + timeEnd: '1400' + }, + { + dateStart: 'today', + timeStart: '1500', + dateEnd: { + day: dateEnd.getDate().toString(), + month: (dateEnd.getMonth() + 1).toString(), + year: dateEnd.getFullYear().toString() + }, + timeEnd: '1800' + } + ] + } + + const planningPage = new PlanningPage(page) + const planningNavigationMenuPage = new PlanningNavigationMenuPage(page) + await planningNavigationMenuPage.buttonToDoAll.click() + + await planningPage.checkToDoExist(toDoSeveralSlots.title) + await planningPage.openToDoByName(toDoSeveralSlots.title) + + if (toDoSeveralSlots.slots != null) { + await planningPage.buttonPanelCreateAddSlot.click({ force: true }) + await planningPage.setTimeSlot(0, toDoSeveralSlots.slots[0]) + await planningPage.buttonPanelCreateAddSlot.click({ force: true }) + await planningPage.setTimeSlot(1, toDoSeveralSlots.slots[1]) + } + await planningPage.buttonCardClose.click() + + await planningPage.checkToDoExistInCalendar(toDoSeveralSlots.title, 2) + }) + + test('Delete and add a new time slot', async ({ page }) => { + const dateEnd = new Date() + const deleteTimeSlot: NewToDo = { + title: 'Delete and add a new time slot', + slots: [ + { + dateStart: 'today', + timeStart: '0900', + dateEnd: { + day: dateEnd.getDate().toString(), + month: (dateEnd.getMonth() + 1).toString(), + year: dateEnd.getFullYear().toString() + }, + timeEnd: '1800' + } + ] + } + const planningNavigationMenuPage = new PlanningNavigationMenuPage(page) + await planningNavigationMenuPage.buttonToDoAll.click() + + const planningPage = new PlanningPage(page) + await planningPage.checkToDoExist(deleteTimeSlot.title) + await planningPage.openToDoByName(deleteTimeSlot.title) + + if (deleteTimeSlot.slots != null) { + await planningPage.buttonPanelCreateAddSlot.click({ force: true }) + await planningPage.setTimeSlot(0, deleteTimeSlot.slots[0]) + } + await planningPage.buttonCardClose.click() + await planningPage.checkToDoExistInCalendar(deleteTimeSlot.title, 1) + + // delete time slot + await planningPage.openToDoByName(deleteTimeSlot.title) + await planningPage.deleteTimeSlot(0) + await planningPage.buttonCardClose.click() + await planningPage.checkToDoExistInCalendar(deleteTimeSlot.title, 0) + + // add a new time slot + // TODO delete after fix UBERF-4273 + await page.reload() + await planningNavigationMenuPage.buttonToDoAll.click() + + await planningPage.openToDoByName(deleteTimeSlot.title) + if (deleteTimeSlot.slots != null) { + await planningPage.buttonPanelCreateAddSlot.click({ force: true }) + await planningPage.setTimeSlot(0, deleteTimeSlot.slots[0]) + } + await planningPage.buttonCardClose.click() + }) + + test('Plan work for several days', async ({ page }) => { + const dateEndToday = new Date() + const dateEndTomorrow = new Date() + dateEndTomorrow.setDate(dateEndTomorrow.getDate() + 1) + + const toDoSeveralSlots: NewToDo = { + title: 'Plan work for several days', + slots: [ + { + dateStart: 'today', + timeStart: '1000', + dateEnd: { + day: dateEndToday.getDate().toString(), + month: (dateEndToday.getMonth() + 1).toString(), + year: dateEndToday.getFullYear().toString() + }, + timeEnd: '1400' + }, + { + dateStart: `${dateEndTomorrow.getDate().toString()}`, + timeStart: '1000', + dateEnd: { + day: dateEndTomorrow.getDate().toString(), + month: (dateEndTomorrow.getMonth() + 1).toString(), + year: dateEndTomorrow.getFullYear().toString() + }, + timeEnd: '1400' + } + ] + } + + const planningPage = new PlanningPage(page) + const planningNavigationMenuPage = new PlanningNavigationMenuPage(page) + await planningNavigationMenuPage.buttonToDoAll.click() + + await planningPage.checkToDoExist(toDoSeveralSlots.title) + await planningPage.openToDoByName(toDoSeveralSlots.title) + if (toDoSeveralSlots.slots != null) { + await planningPage.buttonPanelCreateAddSlot.click({ force: true }) + await planningPage.setTimeSlot(0, toDoSeveralSlots.slots[0]) + await planningPage.buttonPanelCreateAddSlot.click({ force: true }) + await planningPage.setTimeSlot(1, toDoSeveralSlots.slots[1]) + } + await planningPage.buttonCardClose.click() + + await planningNavigationMenuPage.buttonToDoAll.click() + await planningPage.openToDoByName(toDoSeveralSlots.title) + await planningPage.checkTimeSlotEndDate(0, dateEndToday.getDate().toString()) + await planningPage.checkTimeSlotEndDate(1, dateEndTomorrow.getDate().toString()) + }) +}) diff --git a/tests/sanity/tests/planning/todos.spec.ts b/tests/sanity/tests/planning/todos.spec.ts new file mode 100644 index 0000000000..8b61916be2 --- /dev/null +++ b/tests/sanity/tests/planning/todos.spec.ts @@ -0,0 +1,146 @@ +import { test } from '@playwright/test' +import { generateId, PlatformSetting, PlatformURI } from '../utils' +import { PlanningPage } from '../model/planning/planning-page' +import { NewToDo } from '../model/planning/types' +import { PlanningNavigationMenuPage } from '../model/planning/planning-navigation-menu-page' + +test.use({ + storageState: PlatformSetting +}) + +test.describe('Planning ToDo tests', () => { + test.beforeEach(async ({ page }) => { + await (await page.goto(`${PlatformURI}/workbench/sanity-ws/time`))?.finished() + }) + + test('New ToDo', async ({ page }) => { + const dateEnd = new Date() + dateEnd.setDate(dateEnd.getDate() + 1) + + const newToDo: NewToDo = { + title: `ToDo with all parameters-${generateId()}`, + description: 'Created todo with all parameters and attachments description', + duedate: 'today', + priority: 'High Priority', + visible: 'Visible to everyone', + createLabel: true, + labels: `CREATE-TODO-${generateId()}`, + slots: [ + { + dateStart: 'today', + timeStart: '1130', + dateEnd: { + day: dateEnd.getDate().toString(), + month: (dateEnd.getMonth() + 1).toString(), + year: dateEnd.getFullYear().toString() + }, + timeEnd: '1830' + } + ] + } + + const planningPage = new PlanningPage(page) + await planningPage.createNewToDo(newToDo) + + const planningNavigationMenuPage = new PlanningNavigationMenuPage(page) + await planningNavigationMenuPage.buttonToDoAll.click() + + await planningPage.checkToDoExist(newToDo.title) + await planningPage.openToDoByName(newToDo.title) + }) + + test('Edit a ToDo', async ({ page }) => { + const dateEnd = new Date() + const editToDo: NewToDo = { + title: 'ToDo For Edit', + description: 'For Edit todo', + duedate: 'today', + priority: 'Medium Priority', + visible: 'FreeBusy', + createLabel: true, + labels: `EDIT-TODO-${generateId()}`, + slots: [ + { + dateStart: 'today', + timeStart: '1530', + dateEnd: { + day: dateEnd.getDate().toString(), + month: (dateEnd.getMonth() + 1).toString(), + year: dateEnd.getFullYear().toString() + }, + timeEnd: '1830' + } + ] + } + + const planningNavigationMenuPage = new PlanningNavigationMenuPage(page) + await planningNavigationMenuPage.buttonToDoAll.click() + + const planningPage = new PlanningPage(page) + await planningPage.openToDoByName(editToDo.title) + await planningPage.updateToDo(editToDo) + await planningPage.buttonCardClose.click() + + await planningPage.openToDoByName(editToDo.title) + await planningPage.checkToDo({ + ...editToDo, + priority: 'medium', + duedate: `${dateEnd.getMonth() + 1}/${dateEnd.getDate()}/${dateEnd.getFullYear()}`, + slots: [ + { + dateStart: '', + timeStart: '15 : 30', + dateEnd: { + day: dateEnd.getDate().toString(), + month: (dateEnd.getMonth() + 1).toString(), + year: dateEnd.getFullYear().toString() + }, + timeEnd: '18 : 30' + } + ] + }) + }) + + test('Delete ToDo', async ({ page }) => { + const deleteToDo: NewToDo = { + title: 'ToDo For delete' + } + + const planningNavigationMenuPage = new PlanningNavigationMenuPage(page) + await planningNavigationMenuPage.buttonToDoAll.click() + + const planningPage = new PlanningPage(page) + await planningPage.deleteToDoByName(deleteToDo.title) + await planningPage.checkToDoNotExist(deleteToDo.title) + }) + + test.skip('Unplanned / Planned ToDo', async ({ page }) => { + const newToDoPlanned: NewToDo = { + title: 'ToDo Planned' + } + const newToDoUnPlanned: NewToDo = { + title: 'ToDo UnPlanned' + } + + const planningPage = new PlanningPage(page) + + const planningNavigationMenuPage = new PlanningNavigationMenuPage(page) + await planningNavigationMenuPage.buttonToDoAll.click() + await planningPage.checkToDoExist(newToDoPlanned.title) + await planningPage.checkToDoExist(newToDoUnPlanned.title) + + await planningNavigationMenuPage.buttonToDoUnplanned.click() + await planningPage.selectToDoByName(newToDoPlanned.title) + + await planningPage.checkToDoNotExist(newToDoPlanned.title) + await planningPage.checkToDoExist(newToDoUnPlanned.title) + + await planningNavigationMenuPage.buttonToDoPlanned.click() + await planningPage.checkToDoNotExist(newToDoUnPlanned.title) + await planningPage.checkToDoExist(newToDoPlanned.title) + + await planningNavigationMenuPage.buttonToDoAll.click() + await planningPage.checkToDoExist(newToDoPlanned.title) + await planningPage.checkToDoExist(newToDoUnPlanned.title) + }) +})