// playwright-dev-page.ts import { expect, Locator } from '@playwright/test'; import BasePage from '../../Base'; import { DashboardPage } from '..'; import { ToolbarPage } from '../common/Toolbar'; // import clipboard from "clipboardy"; export class WebhookFormPage extends BasePage { readonly dashboard: DashboardPage; 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.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-drawer-webhook-body`); } // todo: Removing opening webhook drawer logic as it belongs to `Toolbar` page async create({ title, event, url = 'http://localhost:9090/hook' }: { title: string; event: string; url?: string }) { await this.toolbar.clickActions(); await this.toolbar.actions.click('Webhooks'); await this.addNewButton.click(); 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 = await this.get().locator(`.menu-filter-dropdown`).last(); // todo: All delays are for api calls that filter does, which rerenders await this.rootPage.waitForTimeout(1000); await modal.locator(`button:has-text("Add Filter")`).click(); await this.rootPage.waitForTimeout(1500); await modal.locator('.nc-filter-field-select').click(); const modalField = await this.dashboard.rootPage.locator('.nc-dropdown-toolbar-field-list:visible'); await modalField.locator(`.ant-select-item:has-text("${column}")`).click(); await this.rootPage.waitForTimeout(1500); await modal.locator('.nc-filter-operation-select').click(); const modalOp = await this.dashboard.rootPage.locator('.nc-dropdown-filter-comp-op:visible'); await modalOp.locator(`.ant-select-item:has-text("${operator}")`).click(); await this.rootPage.waitForTimeout(1500); if (operator != 'is null' && operator != 'is not null') { await modal.locator('input.nc-filter-value-select').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 = 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 }: { index: number }) { await this.toolbar.clickActions(); await this.toolbar.actions.click('Webhooks'); await this.get().locator(`.nc-hook-delete-icon`).nth(index).click(); await this.verifyToast({ message: 'Hook deleted successfully' }); // click escape to close the drawer await this.get().press('Escape'); } async close() { // type esc key await this.get().press('Escape'); } async open({ index }: { index: number }) { await this.toolbar.clickActions(); await this.toolbar.actions.click('Webhooks'); await this.dashboard.get().locator(`.nc-hook`).nth(index).click(); } 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.get().locator('.nc-input-hook-header-key >> input').fill(key); await this.rootPage.locator(`.ant-select-item:has-text("${key}")`).click(); await this.get().locator('.nc-input-hook-header-value').type(value); await this.get().press('Enter'); 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); await expect(this.get().locator('.nc-select-hook-notification-type >> .ant-select-selection-item')).toHaveText( 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(); } }