test: add simple webhook flow test

This commit is contained in:
Jakub P.
2024-08-20 19:17:08 +02:00
parent 98e4b843ea
commit 2c21b7762c
6 changed files with 149 additions and 7 deletions

View File

@@ -1,4 +1,6 @@
const { AuthenticatedPage } = require('./authenticated-page');
const { expect } = require('@playwright/test');
const axios = require('axios');
export class FlowEditorPage extends AuthenticatedPage {
screenshotPath = '/flow-editor';
@@ -9,17 +11,74 @@ export class FlowEditorPage extends AuthenticatedPage {
constructor(page) {
super(page);
this.page = page;
this.appAutocomplete = this.page.getByTestId('choose-app-autocomplete');
this.eventAutocomplete = this.page.getByTestId('choose-event-autocomplete');
this.continueButton = this.page.getByTestId('flow-substep-continue-button');
this.testAndContinueButton = this.page.getByText('Test & Continue');
this.connectionAutocomplete = this.page.getByTestId(
'choose-connection-autocomplete'
);
this.testOuput = this.page.getByTestId('flow-test-substep-output');
this.testOutput = this.page.getByTestId('flow-test-substep-output');
this.hasNoOutput = this.page.getByTestId('flow-test-substep-no-output');
this.unpublishFlowButton = this.page.getByTestId('unpublish-flow-button');
this.publishFlowButton = this.page.getByTestId('publish-flow-button');
this.infoSnackbar = this.page.getByTestId('flow-cannot-edit-info-snackbar');
this.trigger = this.page.getByLabel('Trigger on weekends?');
this.stepCircularLoader = this.page.getByTestId('step-circular-loader');
this.flowName = this.page.getByTestId('editableTypography');
this.flowNameInput = this.page
.getByTestId('editableTypographyInput')
.locator('input');
}
async createWebhookTrigger(workSynchronously) {
await this.appAutocomplete.click();
await this.page.getByRole('option', { name: 'Webhook' }).click();
await expect(this.eventAutocomplete).toBeVisible();
await this.eventAutocomplete.click();
await this.page.getByRole('option', { name: 'Catch raw webhook' }).click();
await this.continueButton.click();
await this.page
.getByTestId('parameters.workSynchronously-autocomplete')
.click();
await this.page
.getByRole('option', { name: workSynchronously ? 'Yes' : 'No' })
.click();
await this.continueButton.click();
const webhookUrl = this.page.locator('input[name="webhookUrl"]');
if (workSynchronously) {
await expect(webhookUrl).toHaveValue(/sync/);
} else {
await expect(webhookUrl).not.toHaveValue(/sync/);
}
const triggerResponse = await axios.get(await webhookUrl.inputValue());
await expect(triggerResponse.status).toBe(204);
await expect(this.testOutput).not.toBeVisible();
await this.testAndContinueButton.click();
await expect(this.testOutput).toBeVisible();
await expect(this.hasNoOutput).not.toBeVisible();
await this.continueButton.click();
return await webhookUrl.inputValue();
}
async chooseAppAndEvent(appName, eventName) {
await this.appAutocomplete.click();
await this.page.getByRole('option', { name: appName }).click();
await expect(this.eventAutocomplete).toBeVisible();
await this.eventAutocomplete.click();
await this.page.getByRole('option', { name: eventName }).click();
await this.continueButton.click();
}
async testAndContinue() {
await this.continueButton.last().click();
await expect(this.testOutput).toBeVisible();
await this.continueButton.click();
}
}

View File

@@ -0,0 +1,82 @@
const { test, expect } = require('../../fixtures/index');
const axios = require('axios');
test.describe('Webhook flow', () => {
test.beforeEach(async ({ page }) => {
await page.getByTestId('create-flow-button').click();
await page.waitForURL(
/\/editor\/[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}/
);
await expect(page.getByTestId('flow-step')).toHaveCount(2);
});
test('Create a new flow with a sync Webhook step then a Webhook step', async ({
flowEditorPage,
page,
}) => {
await flowEditorPage.flowName.click();
await flowEditorPage.flowNameInput.fill('syncWebhook');
const syncWebhookUrl = await flowEditorPage.createWebhookTrigger(true);
await flowEditorPage.chooseAppAndEvent('Webhook', 'Respond with');
await expect(flowEditorPage.continueButton.last()).not.toBeEnabled();
await page
.getByTestId('parameters.statusCode-power-input')
.locator('[contenteditable]')
.fill('200');
await flowEditorPage.clickAway();
await expect(flowEditorPage.continueButton.last()).not.toBeEnabled();
await page
.getByTestId('parameters.body-power-input')
.locator('[contenteditable]')
.fill('response from webhook');
await flowEditorPage.clickAway();
await expect(flowEditorPage.continueButton).toBeEnabled();
await flowEditorPage.continueButton.click();
await flowEditorPage.testAndContinue();
await flowEditorPage.publishFlowButton.click();
const response = await axios.get(syncWebhookUrl);
await expect(response.status).toBe(200);
await expect(response.data).toBe('response from webhook');
});
test('Create a new flow with an async Webhook step then a Webhook step', async ({
flowEditorPage,
page,
}) => {
await flowEditorPage.flowName.click();
await flowEditorPage.flowNameInput.fill('asyncWebhook');
const asyncWebhookUrl = await flowEditorPage.createWebhookTrigger(false);
await flowEditorPage.chooseAppAndEvent('Webhook', 'Respond with');
await expect(flowEditorPage.continueButton.last()).not.toBeEnabled();
await page
.getByTestId('parameters.statusCode-power-input')
.locator('[contenteditable]')
.fill('200');
await flowEditorPage.clickAway();
await expect(flowEditorPage.continueButton.last()).not.toBeEnabled();
await page
.getByTestId('parameters.body-power-input')
.locator('[contenteditable]')
.fill('response from webhook');
await flowEditorPage.clickAway();
await expect(flowEditorPage.continueButton).toBeEnabled();
await flowEditorPage.continueButton.click();
await flowEditorPage.testAndContinue();
await flowEditorPage.publishFlowButton.click();
const response = await axios.get(asyncWebhookUrl);
await expect(response.status).toBe(204);
await expect(response.data).toBe('');
});
});

View File

@@ -2,7 +2,6 @@ const { test, expect } = require('../../fixtures/index');
test('Ensure creating a new flow works', async ({ page }) => {
await page.getByTestId('create-flow-button').click();
await expect(page).toHaveURL(/\/editor\/create/);
await expect(page).toHaveURL(
/\/editor\/[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}/
);
@@ -69,9 +68,9 @@ test(
await test.step('test trigger', async () => {
await test.step('show sample output', async () => {
await expect(flowEditorPage.testOuput).not.toBeVisible();
await expect(flowEditorPage.testOutput).not.toBeVisible();
await flowEditorPage.continueButton.click();
await expect(flowEditorPage.testOuput).toBeVisible();
await expect(flowEditorPage.testOutput).toBeVisible();
await flowEditorPage.screenshot({
path: 'Scheduler trigger test output.png',
});
@@ -143,12 +142,12 @@ test(
await test.step('test trigger substep', async () => {
await test.step('show sample output', async () => {
await expect(flowEditorPage.testOuput).not.toBeVisible();
await expect(flowEditorPage.testOutput).not.toBeVisible();
await page
.getByTestId('flow-substep-continue-button')
.first()
.click();
await expect(flowEditorPage.testOuput).toBeVisible();
await expect(flowEditorPage.testOutput).toBeVisible();
await flowEditorPage.screenshot({
path: 'Ntfy action test output.png',
});

View File

@@ -41,6 +41,7 @@ function EditableTypography(props) {
if (editing) {
component = (
<TextField
data-test="editableTypographyInput"
onClick={handleTextFieldClick}
onKeyDown={handleTextFieldKeyDown}
onBlur={handleTextFieldBlur}

View File

@@ -101,6 +101,7 @@ export default function EditorLayout() {
{!isFlowLoading && (
<EditableTypography
data-test="editableTypography"
variant="body1"
onConfirm={onFlowNameUpdate}
noWrap

View File

@@ -118,7 +118,7 @@ function TestSubstep(props) {
)}
{hasNoOutput && (
<Alert severity="warning" sx={{ mb: 1, width: '100%' }}>
<Alert data-test="flow-test-substep-no-output" severity="warning" sx={{ mb: 1, width: '100%' }}>
<AlertTitle sx={{ fontWeight: 700 }}>
{formatMessage('flowEditor.noTestDataTitle')}
</AlertTitle>