diff --git a/apps/meteor/client/views/modal/uikit/ModalBlock.tsx b/apps/meteor/client/views/modal/uikit/ModalBlock.tsx index a39a0f063ecfb..ff102f00e773e 100644 --- a/apps/meteor/client/views/modal/uikit/ModalBlock.tsx +++ b/apps/meteor/client/views/modal/uikit/ModalBlock.tsx @@ -175,10 +175,10 @@ const ModalBlock = ({ view, errors, onSubmit, onClose, onCancel }: ModalBlockPar return ( - + {view.showIcon ? : null} - {modalParser.text(view.title, UiKit.BlockContext.NONE, 0)} + {modalParser.text(view.title, UiKit.BlockContext.NONE, 0)} diff --git a/apps/meteor/tests/e2e/apps/apps-modal.spec.ts b/apps/meteor/tests/e2e/apps/apps-modal.spec.ts index 638096a66ad89..b4f1b4fb3068b 100644 --- a/apps/meteor/tests/e2e/apps/apps-modal.spec.ts +++ b/apps/meteor/tests/e2e/apps/apps-modal.spec.ts @@ -3,7 +3,7 @@ import type { Page } from '@playwright/test'; import { IS_EE } from '../config/constants'; import { Users } from '../fixtures/userStates'; import { HomeChannel } from '../page-objects'; -import { Modal } from '../page-objects/modal'; +import { AppsModal } from '../page-objects/fragments/apps-modal'; import { expect, test } from '../utils/test'; test.use({ storageState: Users.user1.state }); @@ -11,7 +11,7 @@ test.use({ storageState: Users.user1.state }); test.describe.serial('Apps > Modal', () => { test.skip(!IS_EE, 'Premium Only'); let poHomeChannel: HomeChannel; - let poModal: Modal; + let poModal: AppsModal; let page: Page; @@ -19,7 +19,7 @@ test.describe.serial('Apps > Modal', () => { page = await browser.newPage(); poHomeChannel = new HomeChannel(page); - poModal = new Modal(page); + poModal = new AppsModal(page); await page.goto('/home'); await poHomeChannel.sidenav.openChat('general'); @@ -29,23 +29,17 @@ test.describe.serial('Apps > Modal', () => { await page.close(); }); - test('expect allow user open app modal', async () => { + test('should allow user open app modal', async () => { await poHomeChannel.content.dispatchSlashCommand('/modal'); - await expect(poModal.btnModalSubmit).toBeVisible(); + await poModal.waitForDisplay(); }); - test('expect validation error message appears in app modal', async () => { - await expect(poModal.textInput).toBeVisible(); - - await poModal.btnModalSubmit.click(); - + test('should display validation error message in app modal', async () => { + await poModal.btnSubmit.click(); await expect(poModal.textInputErrorMessage).toBeVisible(); }); - test("expect validation error message don't appears in app modal", async () => { - await poModal.textInput.fill('something'); - await poModal.btnModalSubmit.click(); - - await expect(poModal.textInputErrorMessage).not.toBeVisible(); + test('should not display validation error message in app modal', async () => { + await poModal.submit('something'); }); }); diff --git a/apps/meteor/tests/e2e/page-objects/fragments/apps-modal.ts b/apps/meteor/tests/e2e/page-objects/fragments/apps-modal.ts new file mode 100644 index 0000000000000..a68a1f1f586a9 --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/apps-modal.ts @@ -0,0 +1,29 @@ +import type { Locator, Page } from 'playwright-core'; + +import { Modal } from './modal'; + +export class AppsModal extends Modal { + protected readonly page: Page; + + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Modal Example' })); + } + + get textInput(): Locator { + return this.root.locator('[name="modal_input"]'); + } + + get textInputErrorMessage(): Locator { + return this.root.getByText('Validation failed'); + } + + get btnSubmit(): Locator { + return this.root.getByRole('button', { name: 'Submit' }); + } + + async submit(inputText: string) { + await this.textInput.fill(inputText); + await this.btnSubmit.click(); + await this.waitForDismissal(); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/edit-status-modal.ts b/apps/meteor/tests/e2e/page-objects/fragments/edit-status-modal.ts new file mode 100644 index 0000000000000..6d7eda04176a3 --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/edit-status-modal.ts @@ -0,0 +1,20 @@ +import type { Page } from 'playwright-core'; + +import { Modal } from './modal'; + +export class EditStatusModal extends Modal { + protected readonly page: Page; + + constructor(page: Page) { + super(page.getByRole('dialog', { name: 'Edit Status' })); + } + + private get statusMessageInput() { + return this.root.getByRole('textbox', { name: 'Status message' }); + } + + async changeStatusMessage(statusMessage: string): Promise { + await this.statusMessageInput.fill(statusMessage); + await this.save(); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/modal.ts b/apps/meteor/tests/e2e/page-objects/fragments/modal.ts index 007dfd5cb3c3a..9952db8203a58 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/modal.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/modal.ts @@ -5,7 +5,20 @@ import { expect } from '../../utils/test'; export abstract class Modal { constructor(protected root: Locator) {} + waitForDisplay() { + return expect(this.root).toBeVisible(); + } + waitForDismissal() { return expect(this.root).not.toBeVisible(); } + + private get btnSave() { + return this.root.getByRole('button', { name: 'Save' }); + } + + async save() { + await this.btnSave.click(); + await this.waitForDismissal(); + } } diff --git a/apps/meteor/tests/e2e/page-objects/index.ts b/apps/meteor/tests/e2e/page-objects/index.ts index b7edff294fc7f..b4f2213e94339 100644 --- a/apps/meteor/tests/e2e/page-objects/index.ts +++ b/apps/meteor/tests/e2e/page-objects/index.ts @@ -20,6 +20,5 @@ export * from './omnichannel-settings'; export * from './omnichannel-business-hours'; export * from './omnichannel-tags'; export * from './utils'; -export * from './modal'; export * from './marketplace'; export * from './toastBar'; diff --git a/apps/meteor/tests/e2e/page-objects/modal.ts b/apps/meteor/tests/e2e/page-objects/modal.ts deleted file mode 100644 index 79afc067efd24..0000000000000 --- a/apps/meteor/tests/e2e/page-objects/modal.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { Locator, Page } from '@playwright/test'; - -/** - * TODO: merge this class with the Modal class in fragments/modal.ts - */ -export class Modal { - protected readonly page: Page; - - constructor(page: Page) { - this.page = page; - } - - getModalByName(name: string): Locator { - return this.page.getByRole('dialog', { name }); - } - - get textInput(): Locator { - return this.page.locator('[name="modal_input"]'); - } - - get textInputErrorMessage(): Locator { - return this.page.getByText('Validation failed'); - } - - get btnModalSubmit(): Locator { - return this.page.locator('role=button[name="Submit"]'); - } -} diff --git a/apps/meteor/tests/e2e/presence.spec.ts b/apps/meteor/tests/e2e/presence.spec.ts index 61a8efb771460..30b6b3627a4bc 100644 --- a/apps/meteor/tests/e2e/presence.spec.ts +++ b/apps/meteor/tests/e2e/presence.spec.ts @@ -1,7 +1,7 @@ import { DEFAULT_USER_CREDENTIALS, IS_EE } from './config/constants'; import { Users } from './fixtures/userStates'; import { Registration, HomeChannel } from './page-objects'; -import { Modal } from './page-objects/modal'; +import { EditStatusModal } from './page-objects/fragments/edit-status-modal'; import { setSettingValueById } from './utils/setSettingValueById'; import { test, expect } from './utils/test'; @@ -48,12 +48,11 @@ test.describe.serial('Presence', () => { const user1Page = await browser.newPage({ storageState: Users.user1.state }); await user1Page.goto('/home'); const user1Channel = new HomeChannel(user1Page); - const user1Modal = new Modal(user1Page); + const user1Modal = new EditStatusModal(user1Page); await user1Channel.sidenav.btnUserProfileMenu.click(); await user1Channel.sidenav.getUserProfileMenuOption('Custom Status').click(); - await user1Modal.getModalByName('Edit Status').getByRole('textbox', { name: 'Status message' }).fill('new status'); - await user1Modal.getModalByName('Edit Status').getByRole('button', { name: 'Save' }).click(); + await user1Modal.changeStatusMessage('new status'); await user1Page.close(); });