Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Recruiting filtering tests + fix old test of Issues list #6764

Open
wants to merge 21 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d8e5426
Add filling all social link to new talent
kakRostropovich Sep 27, 2024
a96d3d9
Refactor of Tracker filter tests, add filter tests to talents
kakRostropovich Sep 27, 2024
71a24be
Merge branch 'develop' into add-recruiting-tests
kakRostropovich Sep 27, 2024
528b83b
Add talents filter tests, refactor issues filters tests
kakRostropovich Sep 29, 2024
99f5c3d
Update and add new vacancies filter tests
kakRostropovich Sep 29, 2024
5aca54c
Merge branch 'develop' into add-recruiting-tests
kakRostropovich Sep 29, 2024
e464a8d
Remove unstable checkings
kakRostropovich Sep 29, 2024
7f787d3
Merge branch 'add-recruiting-tests' of github.com:hcengineering/platf…
kakRostropovich Sep 29, 2024
deabcdd
Update CreatedBy and ModifiedBy filter tests
kakRostropovich Sep 29, 2024
7cd99a5
Merge branch 'develop' into add-recruiting-tests
kakRostropovich Sep 30, 2024
e762510
Remove only
kakRostropovich Sep 30, 2024
aecd1a7
Add Review tests
kakRostropovich Sep 30, 2024
437ac61
Merge branch 'add-recruiting-tests' of github.com:hcengineering/platf…
kakRostropovich Oct 1, 2024
a744a76
Add Review Deleting test
kakRostropovich Oct 1, 2024
d7f56ea
Merge branch 'add-recruiting-tests' of github.com:hcengineering/platf…
kakRostropovich Oct 1, 2024
beea02c
Merge branch 'develop' into add-recruiting-tests
kakRostropovich Oct 2, 2024
1a563d7
Fix of a review editing test
kakRostropovich Oct 2, 2024
6438ccc
Merge branch 'develop' into add-recruiting-tests
kakRostropovich Oct 2, 2024
f26f8b1
Fix bugs in filtering tests
kakRostropovich Oct 2, 2024
8a3a13d
Fix unstable dragging test
kakRostropovich Oct 2, 2024
483a01d
Improve Talents locator to fix flaky actions tests
kakRostropovich Oct 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions tests/sanity/tests/model/common-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ export class CommonPage {
menuPopupItemButton = (itemText: string): Locator =>
this.page.locator('div.selectPopup button.menu-item', { hasText: itemText })

buttonFilter = (): Locator => this.page.getByRole('button', { name: 'Filter' })
buttonFilter = (): Locator => this.page.locator('.hulyHeader-container button:has-text("Filter")')
inputFilterTitle = (): Locator => this.page.locator('div.selectPopup input[placeholder="Title"]')
inputFilterSource = (): Locator => this.page.locator('div.selectPopup input[placeholder="Source"]')
inputFilterName = (): Locator => this.page.locator('div.selectPopup input[placeholder="Name"]')
inputFilter = (name: string): Locator => this.page.locator(`div.selectPopup input[placeholder="${name}"]`)
inputSearch = (): Locator => this.page.locator('div.selectPopup input[placeholder="Search..."]')
buttonFilterApply = (): Locator => this.page.locator('div.selectPopup button[type="button"]', { hasText: 'Apply' })
buttonClearFilters = (): Locator => this.page.locator('button > span', { hasText: 'Clear filters' })
Expand Down Expand Up @@ -227,22 +229,32 @@ export class CommonPage {
case 'Labels':
await this.selectFromDropdown(this.page, filterSecondLevel)
break
case 'Location':
await this.inputFilter(filter).fill(filterSecondLevel)
await this.buttonFilterApply().click()
break
case 'Skills':
await this.inputSearch().fill(filterSecondLevel)
await this.selectFromDropdown(this.page, filterSecondLevel)
await this.page.keyboard.press('Escape')
break
case 'Source':
await this.inputFilterSource().fill(filterSecondLevel)
await this.buttonFilterApply().click()
break
default:
await this.selectPopupMenu(filterSecondLevel).click()
}
}
}

async filterOppositeCondition (filter: string, conditionBefore: string, conditionAfter: string): Promise<void> {
async filterOppositeCondition (filter: string, conditionBefore: string, conditionAfter?: string): Promise<void> {
const filterSection = this.selectFilterSection(filter)
await filterSection.locator('button', { hasText: conditionBefore }).isVisible()
await filterSection.locator('button[data-id="btnCondition"]').click()
await this.page.locator('div.selectPopup button.menu-item', { hasText: conditionAfter }).click()
if (typeof conditionAfter === 'string') {
await filterSection.locator('button[data-id="btnCondition"]').click()
await this.page.locator('div.selectPopup button.menu-item', { hasText: conditionAfter }).click()
}
}

async checkFilter (filter: string, filterSecondLevel?: string, filterThirdLevel?: string): Promise<void> {
Expand All @@ -255,6 +267,24 @@ export class CommonPage {
}
}

async checkFilterWithInitials (filter: string, filterSecondLevel?: string, filterThirdLevel?: string): Promise<void> {
await expect(this.filterButton(1)).toHaveText(filter)
if (filterSecondLevel !== undefined) {
await expect(this.filterButton(2)).toContainText(filterSecondLevel)
}
if (filterThirdLevel !== undefined) {
const avatarWrapper = this.filterButton(3).locator(`[data-name="${filterThirdLevel}"]`)

const content = avatarWrapper.evaluate((elem) => {
const computedStyle = window.getComputedStyle(elem, '::after')
return computedStyle.getPropertyValue('content')
})

// Pseudoelement returns content "\"AJ\"
expect(await content).toEqual(JSON.stringify(filterThirdLevel))
}
}

async updateFilterDimension (
filterSecondLevel: string,
dateStart?: string,
Expand Down
2 changes: 1 addition & 1 deletion tests/sanity/tests/model/planning/planning-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export class PlanningPage extends CalendarPage {
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.move(boundingBox.x + 10, size === 'bottom' ? boundingBox.y + 5 : boundingBox.y - 8)
await this.page.mouse.up()
}
}).toPass(retryOptions)
Expand Down
19 changes: 17 additions & 2 deletions tests/sanity/tests/model/recruiting/common-recruiting-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ export class CommonRecruitingPage extends CalendarPage {
readonly buttonContactLinkedIn = (): Locator =>
this.page.locator('div[class^="popupPanel-body"] div.horizontal button[id="contact:string:LinkedIn"]')

readonly buttonContactGithub = (): Locator =>
this.page.locator('div[class^="popupPanel-body"] div.horizontal button[id="contact:string:GitHub"]')

readonly newTalentFirstName = (): Locator =>
this.page.locator('div.popup form[id="recruit:string:CreateTalent"] input[placeholder="First name"]')

Expand Down Expand Up @@ -63,6 +66,7 @@ export class CommonRecruitingPage extends CalendarPage {
readonly reviewItemLink = (reviewId: string): Locator => this.page.locator(`tr:has-text('${reviewId}') td a`)
readonly twoMembersButton = (): Locator => this.page.locator('button:has-text("2 members")')
readonly chenRosamundPopupButton = (): Locator => this.page.locator('.popup button:has-text("Chen Rosamund")')
readonly buttonClearFilters = (): Locator => this.page.locator('button > span', { hasText: 'Clear filters' })

async clickOnTitle (): Promise<void> {
await this.title().click()
Expand Down Expand Up @@ -93,6 +97,11 @@ export class CommonRecruitingPage extends CalendarPage {
await this.page.waitForSelector('form.antiCard', { state: 'detached' })
}

async confirmCreateReview (): Promise<void> {
await this.createButton().click()
await this.page.waitForSelector('form.antiCard', { state: 'detached' })
}

async selectReviewItem (reviewId: string): Promise<void> {
await this.reviewItemLink(reviewId).first().click()
}
Expand Down Expand Up @@ -142,14 +151,14 @@ export class CommonRecruitingPage extends CalendarPage {
await this.pressYesDeletePopup(this.page)
}

async addSocialLinks (link: string, linkDescription: string): Promise<void> {
async openAddSocialLinksPopup (link: string, linkDescription: string): Promise<void> {
await this.buttonAddSocialLinks().click()
await this.selectFromDropdown(this.page, link)
await this.fillToDropdown(this.page, linkDescription)
}

async addSocialLink (social: SocialLink): Promise<void> {
await this.addSocialLinks(social.type, social.value)
await this.openAddSocialLinksPopup(social.type, social.value)
}

async checkSocialLinks (link: string, value: string): Promise<void> {
Expand All @@ -172,6 +181,12 @@ export class CommonRecruitingPage extends CalendarPage {
await expect(this.inputSocialValue()).toHaveValue(value)
await this.buttonSocialSave().click()
break
case 'Github':
await expect(this.buttonContactGithub()).toBeVisible()
await this.buttonContactGithub().click()
await expect(this.inputSocialValue()).toHaveValue(value)
await this.buttonSocialSave().click()
break
default:
throw new Error(`Unknown case ${link}`)
}
Expand Down
12 changes: 1 addition & 11 deletions tests/sanity/tests/model/recruiting/recruiting-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ export class RecruitingPage {
}

recruitApplication = (): Locator => this.page.locator('[id="app-recruit\\:string\\:RecruitApplication"]')
talentsNavElement = (): Locator => this.page.locator('text=Talents')
reviews = (): Locator => this.page.locator('text=Reviews')
reviewButton = (): Locator => this.page.getByRole('button', { name: 'Review', exact: true })
talentsNavElement = (): Locator => this.page.locator('.antiPanel-navigator').locator('text=Talents')

frontendEngineerOption = (): Locator => this.page.locator('td:has-text("Frontend Engineer")')
searchOrRunCommandInput = (): Locator => this.page.locator('[placeholder="Search\\ or\\ run\\ a\\ command\\.\\.\\."]')
Expand Down Expand Up @@ -42,14 +40,6 @@ export class RecruitingPage {
await this.recruitApplication().click()
}

async clickOnReviews (): Promise<void> {
await this.reviews().click()
}

async clickOnReviewButton (): Promise<void> {
await this.reviewButton().click()
}

async clickTalentsNavElement (): Promise<void> {
await this.talentsNavElement().click()
}
Expand Down
159 changes: 159 additions & 0 deletions tests/sanity/tests/model/recruiting/reviews-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import { expect, type Locator, type Page } from '@playwright/test'
import { CommonRecruitingPage } from './common-recruiting-page'
import { generateId } from '@hcengineering/core'
import { NewReview, TalentName } from './types'

export class ReviewsPage extends CommonRecruitingPage {
readonly page: Page

constructor (page: Page) {
super(page)
this.page = page
}

readonly buttonReviews = (): Locator => this.page.locator('.antiPanel-navigator').locator('text=Reviews')
readonly buttonNewReview = (): Locator => this.page.getByRole('button', { name: 'Review', exact: true })
readonly buttonPopupTalentByName = (talent: TalentName): Locator =>
this.page.locator(`button:has-text("${talent.lastName} ${talent.firstName}")`)

readonly inputVerdict = (): Locator => this.page.locator('input[placeholder="Verdict"]')
readonly buttonInputLocation = (): Locator => this.page.locator('span.labelOnPanel:has-text("Location") + div button')
readonly editorDescription = (description: string): Locator => this.page.locator(`.tiptap:has-text("${description}")`)
readonly buttonMenuDelete = (): Locator => this.page.locator('button.ap-menuItem span', { hasText: 'Delete' })

async checkReviewExist (reviewName: string): Promise<void> {
await expect(this.page.locator('tr', { hasText: reviewName })).toHaveCount(1)
}

async checkReviewNotExist (reviewName: string): Promise<void> {
await expect(this.page.locator('tr', { hasText: reviewName })).toHaveCount(0)
}

async deleteReview (reviewName: string): Promise<void> {
await this.openReviews()
await this.page.locator('tr', { hasText: reviewName }).click({ button: 'right' })
await this.buttonMenuDelete().click()
await this.pressYesForPopup(this.page)
}

async addDescription (oldDescription: string, newDescription: string): Promise<void> {
await this.editorDescription(oldDescription).fill(newDescription)
}

async addLocation (location: string): Promise<void> {
await this.buttonInputLocation().first().click()
await this.fillToSelectPopup(this.page, location)
}

async openReviews (): Promise<void> {
await this.buttonReviews().click()
}

async enterTalent (talent: TalentName): Promise<void> {
await this.clickTalent()
await this.buttonPopupTalentByName(talent).click()
}

async clickOnReviewButton (): Promise<void> {
await this.buttonNewReview().click()
}

async checkIfHeaderOfReviewHasTalentName (talent: TalentName): Promise<void> {
await expect(
this.page.locator(`.hulyHeader-titleGroup:has-text("${talent.lastName} ${talent.firstName}")`)
).toBeVisible()
}

// TODO: need to improve locator
async updateTitle (newTitle: string): Promise<void> {
const input = this.page.locator('[placeholder="Type text..."]')
await input.click()
await input.fill(newTitle)
}

async updateTalent (newTalent: TalentName): Promise<void> {
await this.clickTalent()
await this.buttonPopupTalentByName(newTalent).click()
}

async enterVerdict (verdict: string): Promise<void> {
await this.inputVerdict().click()
await this.inputVerdict().clear()
await this.inputVerdict().fill(verdict)
}

async enterLocation (location: string): Promise<void> {
const input = this.page.locator('[placeholder="Location"]')
await input.click()
await input.fill(location)
}

async enterDescription (description: string): Promise<void> {
const input = this.page.locator('[data-placeholder="Add description"]')
await input.click()
await input.fill(description)
}

async createReview ({ title, talent, location, description }: NewReview): Promise<string> {
if (typeof title !== 'string') title = `Review ${generateId()}`
await this.openReviews()
await this.buttonNewReview().click()

await this.clickOnTitle()
await this.fillTitle(title)
await this.enterTalent(talent)

if (typeof location === 'string') {
await this.enterLocation(location)
}

if (typeof description === 'string') {
await this.enterDescription(description)
}

await this.confirmCreateReview()
return title
}

async openAndCheckReview ({ title, talent, location, verdict, description }: NewReview): Promise<void> {
if (typeof title !== 'string') title = `Review ${generateId()}`
await this.openReviews()
await this.selectReviewItem(title)

await this.checkIfHeaderOfReviewHasTalentName(talent)

if (typeof location === 'string') {
await expect(this.page.locator(`text=${location}`).first()).toBeVisible()
}

if (typeof description === 'string') {
await expect(this.page.locator(`text=${description}`).first()).toBeVisible()
}

if (typeof verdict === 'string') {
await expect(this.inputVerdict()).toHaveValue(verdict)
}
}

async openAndUpdateReview (oldData: NewReview, newData: NewReview): Promise<void> {
await this.openReviews()
await this.selectReviewItem(oldData.title)

if (typeof newData.title === 'string') {
await this.updateTitle(newData.title)
await this.page.keyboard.press('Enter')
}

if (typeof newData.location === 'string') {
await this.addLocation(newData.location)
}

if (typeof oldData.description === 'string' && typeof newData.description === 'string') {
await this.addDescription(oldData.description, newData.description)
}

if (typeof newData.verdict === 'string') {
await this.enterVerdict(newData.verdict)
}
}
}
34 changes: 30 additions & 4 deletions tests/sanity/tests/model/recruiting/talents-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,25 @@ export class TalentsPage extends CommonRecruitingPage {

recruitApplicationButton = (): Locator => this.page.locator('[id="app-recruit\\:string\\:RecruitApplication"]')

talentsTab = (): Locator => this.page.locator('text=Talents')
talentsTab = (): Locator => this.page.locator('.antiPanel-navigator').locator('text=Talents')
newTalentButton = (): Locator => this.page.locator('button:has-text("New Talent")')
addSocialLinksButton = (): Locator => this.page.locator('[id="presentation\\:string\\:AddSocialLinks"]')

emailSelectorButton = (): Locator => this.page.locator('.antiPopup').locator('text=Email')
confirmEmailButton = (): Locator => this.page.locator('#channel-ok.antiButton')
twitterSelectorButton = (): Locator => this.page.locator('.antiPopup').locator('text=Twitter')
linkedInSelectorButton = (): Locator => this.page.locator('.antiPopup').locator('text=LinkedIn')
githubSelectorButton = (): Locator => this.page.locator('.antiPopup').locator('text=GitHub')
facebookSelectorButton = (): Locator => this.page.locator('.antiPopup').locator('text=Facebook')
homePageSelectorButton = (): Locator => this.page.locator('.antiPopup').locator('text="Home page"')
whatsAppSelectorButton = (): Locator => this.page.locator('.antiPopup').locator('text=WhatsApp')
skypeAppSelectorButton = (): Locator => this.page.locator('.antiPopup').locator('text=Skype')
profileAppSelectorButton = (): Locator => this.page.locator('.antiPopup').locator('text=Profile')
telegramAppSelectorButton = (): Locator => this.page.locator('.antiPopup').locator('text=Telegram')

buttonSocialLinkMenuItem = (title: string): Locator =>
this.page.locator('.antiPopup').locator(`button:has-text("${title}")`)

confirmSocialLinkButton = (): Locator => this.page.locator('#channel-ok.antiButton')
createTalentButton = (): Locator => this.page.locator('.antiCard button:has-text("Create")')
popupPanel = (): Locator => this.page.locator('.popupPanel')
talentsLink = (): Locator => this.page.locator('text=Talents')
Expand Down Expand Up @@ -150,21 +164,29 @@ export class TalentsPage extends CommonRecruitingPage {
await input.fill(location)
}

async addSocialLinks (): Promise<void> {
async openAddSocialLinksPopup (): Promise<void> {
await this.addSocialLinksButton().click()
}

async selectEmail (): Promise<void> {
await this.emailSelectorButton().click()
}

async enterSocialInfo (name: string, value: string): Promise<void> {
await this.addSocialLinksButton().click()
await this.buttonSocialLinkMenuItem(name).click()
const input = this.page.locator('.popup .editor-container input')
await input.fill(value)
await this.confirmSocialLinkButton().click()
}

async enterEmail (email: string): Promise<void> {
const input = this.page.locator('[placeholder="john\\.appleseed@apple\\.com"]')
await input.fill(email)
}

async confirmEmail (): Promise<void> {
await this.confirmEmailButton().click()
await this.confirmSocialLinkButton().click()
}

async createTalent (): Promise<void> {
Expand Down Expand Up @@ -207,6 +229,10 @@ export class TalentsPage extends CommonRecruitingPage {
.click()
}

async checkTalentExist (talentName: TalentName): Promise<void> {
await expect(this.page.locator('tr', { hasText: `${talentName.lastName} ${talentName.firstName}` })).toHaveCount(1)
}

async checkTalentNotExist (talentName: TalentName): Promise<void> {
await expect(this.page.locator('tr', { hasText: `${talentName.lastName} ${talentName.firstName}` })).toHaveCount(0)
}
Expand Down
Loading
Loading