mirror of https://github.com/nocodb/nocodb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
7.4 KiB
216 lines
7.4 KiB
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")`).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 }: { index: number }) { |
|
await this.dashboard.grid.topbar.openDetailedTab(); |
|
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').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').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(); |
|
} |
|
}
|
|
|