Fix unstable tests (#11052)

* Fix unstable tests

Signed-off-by: Artyom Savchenko <armisav@gmail.com>

* Fix tests

Signed-off-by: Artyom Savchenko <armisav@gmail.com>

* Fix tests

Signed-off-by: Artyom Savchenko <armisav@gmail.com>

* Fix date formatting

Signed-off-by: Artyom Savchenko <armisav@gmail.com>

---------

Signed-off-by: Artyom Savchenko <armisav@gmail.com>
This commit is contained in:
Artyom Savchenko
2026-09-30 13:16:18 +02:00
committed by GitHub
parent 798280391c
commit e4fd72b36a
6 changed files with 42 additions and 10 deletions
@@ -160,11 +160,20 @@ export function getFormattedDate (value: number | null, options?: Intl.DateTimeF
}
export function formatDate (date: Date, showYear: boolean): string {
const locale = new Intl.NumberFormat().resolvedOptions().locale
// Intl.DateTimeFormat.format throws RangeError for an invalid date, which breaks rendering
// of the whole component tree, so never let it propagate.
if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
return ''
}
const options: Intl.DateTimeFormatOptions = showYear
? { year: 'numeric', month: 'short', day: 'numeric' }
: { month: 'short', day: 'numeric' }
return new Intl.DateTimeFormat(locale, options).format(date)
try {
const locale = new Intl.NumberFormat().resolvedOptions().locale
return new Intl.DateTimeFormat(locale, options).format(date)
} catch (err: any) {
return date.toLocaleDateString('default', options)
}
}
export const getTimeZoneName = (
@@ -96,7 +96,12 @@
void validate($themeStore.language)
}
$: if ($themeStore.language != null && $themeStore.language !== '') {
// Re-validate only when the language actually changes (to re-translate validation messages).
// Theme updates with the same language (e.g. after plugin strings are loaded) must not
// reset the status, otherwise an action error (like wrong credentials) could be wiped out.
let validatedLanguage: string | undefined
$: if ($themeStore.language != null && $themeStore.language !== '' && $themeStore.language !== validatedLanguage) {
validatedLanguage = $themeStore.language
void validate($themeStore.language)
}
@@ -67,11 +67,11 @@ export class CommonRecruitingPage extends CalendarPage {
readonly chenRosamundPopupButton = (): Locator => this.page.locator('.popup button:has-text("Chen Rosamund")')
async clickOnTitle (): Promise<void> {
await this.title().click()
await this.newReviewTitle().click()
}
async fillTitle (title: string): Promise<void> {
await this.title().fill(title)
await this.newReviewTitle().fill(title)
}
async clickAppleseedJohn (): Promise<void> {
@@ -90,13 +90,16 @@ export class CommonRecruitingPage extends CalendarPage {
await this.talentButton().click()
}
async createApplication (): Promise<void> {
async createReview (): Promise<void> {
await this.createButton().click()
await this.page.waitForSelector('form.antiCard', { state: 'detached' })
await this.page.reload({ waitUntil: 'domcontentloaded' })
}
async selectReviewItem (reviewId: string): Promise<void> {
await this.reviewItemLink(reviewId).first().click()
const link = this.reviewItemLink(reviewId).first()
await expect(link).toBeVisible()
await Promise.all([this.page.waitForURL(/\/recruit\/RVE-/), link.click()])
}
async clickTwoMembers (): Promise<void> {
@@ -136,6 +139,7 @@ export class CommonRecruitingPage extends CalendarPage {
await this.newReviewTitle().fill(title)
await this.newReviewDescription().fill(description)
await this.submitNewReview().click()
await this.submitNewReview().waitFor({ state: 'hidden' })
}
async deleteEntity (): Promise<void> {
@@ -11,6 +11,8 @@ export class RecruitingPage {
talentsNavElement = (): Locator => this.page.locator('.antiPanel-navigator').locator('text=Talents')
reviews = (): Locator => this.page.locator('.antiPanel-navigator').locator('text=Reviews')
reviewButton = (): Locator => this.page.getByRole('button', { name: 'Review', exact: true })
reviewForm = (): Locator => this.page.locator('form[id="recruit:string:CreateReviewParams"]')
reviewsTotal = (): Locator => this.page.getByText(/^Total: \d+$/)
frontendEngineerOption = (): Locator => this.page.locator('td:has-text("Frontend Engineer")')
searchOrRunCommandInput = (): Locator => this.page.locator('[placeholder="Search\\ or\\ run\\ a\\ command\\.\\.\\."]')
@@ -44,10 +46,12 @@ export class RecruitingPage {
async clickOnReviews (): Promise<void> {
await this.reviews().click()
await expect(this.reviewsTotal()).toBeVisible()
}
async clickOnReviewButton (): Promise<void> {
await this.reviewButton().click()
await expect(this.reviewForm()).toBeVisible()
}
async clickTalentsNavElement (): Promise<void> {
@@ -33,8 +33,18 @@ export class TalentDetailsPage extends CommonRecruitingPage {
readonly titleAndSourceTalent = (title: string): Locator => this.page.locator('button > span', { hasText: title })
async addSkill (skillTag: string, skillDescription: string): Promise<void> {
await this.buttonAddSkill().click()
await this.pressCreateButtonSelectPopup(this.page)
const tagTitle = this.tagsStringAddTagForm('title')
await expect(async () => {
if (!(await tagTitle.isVisible())) {
if (!(await this.selectPopupAddButton().isVisible())) {
await this.buttonAddSkill().click({ timeout: 3000 })
}
await this.selectPopupAddButton().click({ timeout: 3000 })
}
await expect(tagTitle).toBeVisible({ timeout: 3000 })
await this.page.waitForTimeout(300)
await expect(tagTitle).toBeVisible({ timeout: 1000 })
}).toPass({ timeout: 20000 })
await this.addNewTagPopup(this.page, skillTag, skillDescription)
await this.pressShowAllButtonSelectPopup(this.page)
@@ -30,7 +30,7 @@ test.describe('review tests', () => {
await commonRecruitingPage.clickTalent()
// Click button:has-text("Chen Rosamund")
await commonRecruitingPage.clickChenRosamund()
await commonRecruitingPage.createApplication()
await commonRecruitingPage.createReview()
await commonRecruitingPage.selectReviewItem(reviewId)
await commonRecruitingPage.clickTwoMembers()
await commonRecruitingPage.clickAppleseedJohn()