import { expect, Locator } from '@playwright/test'; import BasePage from '../../Base'; import { DashboardPage } from '..'; import { ToolbarPage } from '../common/Toolbar'; import { getTextExcludeIconText } from '../../../tests/utils/general'; import { TopbarPage } from '../common/Topbar'; export class WebhookFormPage extends BasePage { readonly dashboard: DashboardPage; readonly topbar: TopbarPage; readonly toolbar: ToolbarPage; readonly addNewButton: Locator; readonly saveButton: Locator; readonly testButton: Locator; constructor(dashboard: DashboardPage) { super(dashboard.rootPage); this.dashboard = dashboard; this.toolbar = dashboard.grid.toolbar; this.topbar = dashboard.grid.topbar; this.addNewButton = this.dashboard.get().locator('.nc-btn-create-webhook'); this.saveButton = this.get().locator('button:has-text("Save")'); this.testButton = this.get().locator('button:has-text("Test Webhook")'); } get() { return this.dashboard.get().locator(`.nc-view-sidebar-webhook`); } async create({ title, event, url = 'http://localhost:9090/hook' }: { title: string; event: string; url?: string }) { await this.dashboard.grid.topbar.openDetailedTab(); await this.dashboard.details.clickWebhooksTab(); await this.dashboard.details.clickAddWebhook(); await this.get().waitFor({ state: 'visible' }); await this.configureHeader({ key: 'Content-Type', value: 'application/json', }); await this.configureWebhook({ title, event, url }); await this.save(); await this.close(); } async configureWebhook({ title, event, url }: { title?: string; event?: string; url?: string }) { if (title) { await this.get().locator(`.nc-text-field-hook-title`).fill(title); } if (event) { await this.get().locator(`.nc-text-field-hook-event`).click(); const modal = this.rootPage.locator(`.nc-dropdown-webhook-event`); await modal.locator(`.ant-select-item:has-text("${event}")`).click(); } if (url) { await this.get().locator(`.nc-text-field-hook-url-path`).fill(url); } } async addCondition({ column, operator, value, save, }: { column: string; operator: string; value: string; save: boolean; }) { await this.get().locator(`.nc-check-box-hook-condition`).click(); const modal = this.get().locator(`.menu-filter-dropdown`).last(); await modal.locator(`button:has-text("Add Filter")`).first().click(); await modal.locator('.nc-filter-field-select').waitFor({ state: 'visible', timeout: 4000 }); await modal.locator('.nc-filter-field-select').click(); const modalField = this.dashboard.rootPage.locator('.nc-dropdown-toolbar-field-list:visible'); await modalField.locator(`.ant-select-item:has-text("${column}")`).click(); await modal.locator('.nc-filter-operation-select').click(); const modalOp = this.dashboard.rootPage.locator('.nc-dropdown-filter-comp-op:visible'); await modalOp.locator(`.ant-select-item:has-text("${operator}")`).click(); if (operator != 'is null' && operator != 'is not null') { await modal.locator('.nc-filter-value-select > input').fill(value); } if (save) { await this.save(); await this.close(); } } async deleteCondition(p: { save: boolean }) { await this.get().locator(`.nc-filter-item-remove-btn`).click(); if (p.save) { await this.save(); await this.close(); } } async save() { const saveAction = async () => await this.saveButton.click(); await this.waitForResponse({ uiAction: saveAction, requestUrlPathToMatch: '/hooks', httpMethodsToMatch: ['POST', 'PATCH'], }); await this.verifyToast({ message: 'Webhook details updated successfully' }); } async test() { await this.testButton.click(); await this.verifyToast({ message: 'Webhook tested successfully' }); } async delete({ index, wfr = true }: { index: number; wfr?: boolean }) { await this.dashboard.grid.topbar.openDetailedTab({ waitForResponse: wfr }); await this.dashboard.details.clickWebhooksTab(); await this.dashboard.details.webhook.deleteHook({ index }); await this.rootPage.locator('div.ant-modal.active').locator('button:has-text("Delete")').click(); } async close() { // type esc key await this.get().press('Escape'); await this.dashboard.grid.topbar.openDataTab(); } async open({ index }: { index: number }) { await this.dashboard.grid.topbar.openDetailedTab(); await this.dashboard.details.clickWebhooksTab(); await (await this.dashboard.details.webhook.getItem({ index })).click(); await this.get().waitFor({ state: 'visible' }); } async openForm({ index }: { index: number }) { await this.dashboard.get().locator(`.nc-hook`).nth(index).click(); } async click({ index }: { index: number }) { await this.dashboard.get().locator(`.nc-hook`).nth(index).click(); } async configureHeader({ key, value }: { key: string; value: string }) { // hardcode "Content-type: application/json" await this.get().locator(`.ant-tabs-tab-btn:has-text("Headers")`).click(); await this.rootPage.waitForTimeout(500); await this.get().locator('.nc-input-hook-header-key input').click(); await this.rootPage.waitForTimeout(500); // kludge, as the dropdown is not visible even after scroll into view await this.rootPage.locator('.nc-input-hook-header-key input').pressSequentially(key); await this.rootPage .locator('.ant-select-dropdown:visible') .locator(`.ant-select-item:has-text("${key}")`) .scrollIntoViewIfNeeded(); await this.rootPage .locator('.ant-select-dropdown:visible') .locator(`.ant-select-item:has-text("${key}")`) .click({ force: true }); await this.get().locator('.nc-input-hook-header-value').clear(); await this.get().locator('.nc-input-hook-header-value').type(value); await this.get().press('Enter'); // find out if the checkbox is already checked const isChecked = await this.get() .locator('.nc-hook-header-tab-checkbox') .locator('input.ant-checkbox-input') .isChecked(); if (!isChecked) await this.get().locator('.nc-hook-header-tab-checkbox').locator('input.ant-checkbox-input').click(); } async verifyForm({ title, hookEvent, url, notificationType, urlMethod, condition, }: { title: string; hookEvent: string; url: string; notificationType: string; urlMethod: string; condition: boolean; }) { await expect.poll(async () => await this.get().locator('input.nc-text-field-hook-title').inputValue()).toBe(title); await expect(this.get().locator('.nc-text-field-hook-event >> .ant-select-selection-item')).toHaveText(hookEvent); const locator = this.get().locator('.nc-select-hook-notification-type >> .ant-select-selection-item'); const text = await getTextExcludeIconText(locator); expect(text).toBe(notificationType); await expect(this.get().locator('.nc-select-hook-url-method >> .ant-select-selection-item')).toHaveText(urlMethod); await expect.poll(async () => await this.get().locator('input.nc-text-field-hook-url-path').inputValue()).toBe(url); const conditionCheckbox = this.get().locator('label.nc-check-box-hook-condition >> input[type="checkbox"]'); if (condition) { await expect(conditionCheckbox).toBeChecked(); } else { await expect(conditionCheckbox).not.toBeChecked(); } } async goBackFromForm() { await this.get().locator('svg.nc-icon-hook-navigate-left').click(); } }