test: add delete flow tests
This commit is contained in:
204
packages/e2e-tests/tests/flow/create-flow.spec.js
Normal file
204
packages/e2e-tests/tests/flow/create-flow.spec.js
Normal file
@@ -0,0 +1,204 @@
|
||||
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\/[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}/
|
||||
);
|
||||
});
|
||||
|
||||
test(
|
||||
'Create a new flow with a Scheduler step then an Ntfy step',
|
||||
async ({ flowEditorPage, page }) => {
|
||||
await test.step('create flow', async () => {
|
||||
await test.step('navigate to new flow page', async () => {
|
||||
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 test.step('has two steps by default', async () => {
|
||||
await expect(page.getByTestId('flow-step')).toHaveCount(2);
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('setup Scheduler trigger', async () => {
|
||||
await test.step('choose app and event substep', async () => {
|
||||
await test.step('choose application', async () => {
|
||||
await flowEditorPage.appAutocomplete.click();
|
||||
await page
|
||||
.getByRole('option', { name: 'Scheduler' })
|
||||
.click();
|
||||
});
|
||||
|
||||
await test.step('choose and event', async () => {
|
||||
await expect(flowEditorPage.eventAutocomplete).toBeVisible();
|
||||
await flowEditorPage.eventAutocomplete.click();
|
||||
await page
|
||||
.getByRole('option', { name: 'Every hour' })
|
||||
.click();
|
||||
});
|
||||
|
||||
await test.step('continue to next step', async () => {
|
||||
await flowEditorPage.continueButton.click();
|
||||
});
|
||||
|
||||
await test.step('collapses the substep', async () => {
|
||||
await expect(flowEditorPage.appAutocomplete).not.toBeVisible();
|
||||
await expect(flowEditorPage.eventAutocomplete).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('set up a trigger', async () => {
|
||||
await test.step('choose "yes" in "trigger on weekends?"', async () => {
|
||||
await expect(flowEditorPage.trigger).toBeVisible();
|
||||
await flowEditorPage.trigger.click();
|
||||
await page.getByRole('option', { name: 'Yes' }).click();
|
||||
});
|
||||
|
||||
await test.step('continue to next step', async () => {
|
||||
await flowEditorPage.continueButton.click();
|
||||
});
|
||||
|
||||
await test.step('collapses the substep', async () => {
|
||||
await expect(flowEditorPage.trigger).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('test trigger', async () => {
|
||||
await test.step('show sample output', async () => {
|
||||
await expect(flowEditorPage.testOutput).not.toBeVisible();
|
||||
await flowEditorPage.continueButton.click();
|
||||
await expect(flowEditorPage.testOutput).toBeVisible();
|
||||
await flowEditorPage.screenshot({
|
||||
path: 'Scheduler trigger test output.png',
|
||||
});
|
||||
await flowEditorPage.continueButton.click();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('arrange Ntfy action', async () => {
|
||||
await test.step('choose app and event substep', async () => {
|
||||
await test.step('choose application', async () => {
|
||||
await flowEditorPage.appAutocomplete.click();
|
||||
await page.getByRole('option', { name: 'Ntfy' }).click();
|
||||
});
|
||||
|
||||
await test.step('choose an event', async () => {
|
||||
await expect(flowEditorPage.eventAutocomplete).toBeVisible();
|
||||
await flowEditorPage.eventAutocomplete.click();
|
||||
await page
|
||||
.getByRole('option', { name: 'Send message' })
|
||||
.click();
|
||||
});
|
||||
|
||||
await test.step('continue to next step', async () => {
|
||||
await flowEditorPage.continueButton.click();
|
||||
});
|
||||
|
||||
await test.step('collapses the substep', async () => {
|
||||
await expect(flowEditorPage.appAutocomplete).not.toBeVisible();
|
||||
await expect(flowEditorPage.eventAutocomplete).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('choose connection substep', async () => {
|
||||
await test.step('choose connection list item', async () => {
|
||||
await flowEditorPage.connectionAutocomplete.click();
|
||||
await page.getByRole('option').first().click();
|
||||
});
|
||||
|
||||
await test.step('continue to next step', async () => {
|
||||
await flowEditorPage.continueButton.click();
|
||||
});
|
||||
|
||||
await test.step('collapses the substep', async () => {
|
||||
await expect(flowEditorPage.connectionAutocomplete).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('set up action substep', async () => {
|
||||
await test.step('fill topic and message body', async () => {
|
||||
await page
|
||||
.getByTestId('parameters.topic-power-input')
|
||||
.locator('[contenteditable]')
|
||||
.fill('Topic');
|
||||
await page
|
||||
.getByTestId('parameters.message-power-input')
|
||||
.locator('[contenteditable]')
|
||||
.fill('Message body');
|
||||
});
|
||||
|
||||
await test.step('continue to next step', async () => {
|
||||
await flowEditorPage.continueButton.click();
|
||||
});
|
||||
|
||||
await test.step('collapses the substep', async () => {
|
||||
await expect(flowEditorPage.connectionAutocomplete).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('test trigger substep', async () => {
|
||||
await test.step('show sample output', async () => {
|
||||
await expect(flowEditorPage.testOutput).not.toBeVisible();
|
||||
await page
|
||||
.getByTestId('flow-substep-continue-button')
|
||||
.first()
|
||||
.click();
|
||||
await expect(flowEditorPage.testOutput).toBeVisible();
|
||||
await flowEditorPage.screenshot({
|
||||
path: 'Ntfy action test output.png',
|
||||
});
|
||||
await flowEditorPage.continueButton.click();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('publish and unpublish', async () => {
|
||||
await test.step('publish flow', async () => {
|
||||
await expect(flowEditorPage.unpublishFlowButton).not.toBeVisible();
|
||||
await expect(flowEditorPage.publishFlowButton).toBeVisible();
|
||||
await flowEditorPage.publishFlowButton.click();
|
||||
await expect(flowEditorPage.publishFlowButton).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('shows read-only sticky snackbar', async () => {
|
||||
await expect(flowEditorPage.infoSnackbar).toBeVisible();
|
||||
await flowEditorPage.screenshot({
|
||||
path: 'Published flow.png',
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('unpublish from snackbar', async () => {
|
||||
await page
|
||||
.getByTestId('unpublish-flow-from-snackbar')
|
||||
.click();
|
||||
await expect(flowEditorPage.infoSnackbar).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('publish once again', async () => {
|
||||
await expect(flowEditorPage.publishFlowButton).toBeVisible();
|
||||
await flowEditorPage.publishFlowButton.click();
|
||||
await expect(flowEditorPage.publishFlowButton).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('unpublish from layout top bar', async () => {
|
||||
await expect(flowEditorPage.unpublishFlowButton).toBeVisible();
|
||||
await flowEditorPage.unpublishFlowButton.click();
|
||||
await expect(flowEditorPage.unpublishFlowButton).not.toBeVisible();
|
||||
await flowEditorPage.screenshot({
|
||||
path: 'Unpublished flow.png',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('in layout', async () => {
|
||||
await test.step('can go back to flows page', async () => {
|
||||
await page.getByTestId('editor-go-back-button').click();
|
||||
await expect(page).toHaveURL('/flows');
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
213
packages/e2e-tests/tests/flow/delete-flow.spec.js
Normal file
213
packages/e2e-tests/tests/flow/delete-flow.spec.js
Normal file
@@ -0,0 +1,213 @@
|
||||
const { test, expect } = require('../../fixtures/index');
|
||||
const { expectNoDelayedJobForFlow } = require('../../helpers/bullmq-helper');
|
||||
const {
|
||||
createFlow,
|
||||
updateFlowName,
|
||||
updateFlowStep,
|
||||
testStep,
|
||||
publishFlow,
|
||||
} = require('../../helpers/flow-api-helper');
|
||||
|
||||
let tokenJsonResponse;
|
||||
|
||||
test.beforeAll(async ({ request }) => {
|
||||
const tokenResponse = await request.post(
|
||||
`http://localhost:${process.env.PORT}/api/v1/access-tokens`,
|
||||
{
|
||||
data: {
|
||||
email: process.env.LOGIN_EMAIL,
|
||||
password: process.env.LOGIN_PASSWORD,
|
||||
},
|
||||
}
|
||||
);
|
||||
await expect(tokenResponse.status()).toBe(200);
|
||||
tokenJsonResponse = await tokenResponse.json();
|
||||
});
|
||||
|
||||
test('Empty flow can be deleted', async ({ page, request, flowsPage }) => {
|
||||
const flow = await createFlow(request, tokenJsonResponse.data.token);
|
||||
const flowId = flow.data.id;
|
||||
await updateFlowName(request, tokenJsonResponse.data.token, flowId);
|
||||
|
||||
await page.reload();
|
||||
|
||||
await flowsPage.deleteFlow(flowId);
|
||||
});
|
||||
|
||||
test('Completed webhook flow can be deleted', async ({
|
||||
page,
|
||||
request,
|
||||
flowsPage,
|
||||
}) => {
|
||||
const flow = await createFlow(request, tokenJsonResponse.data.token);
|
||||
const flowId = flow.data.id;
|
||||
const flowSteps = flow.data.steps;
|
||||
await updateFlowName(request, tokenJsonResponse.data.token, flowId);
|
||||
|
||||
const triggerStepId = flowSteps.find((step) => step.type === 'trigger').id;
|
||||
const actionStepId = flowSteps.find((step) => step.type === 'action').id;
|
||||
|
||||
const triggerStep = await updateFlowStep(
|
||||
request,
|
||||
tokenJsonResponse.data.token,
|
||||
triggerStepId,
|
||||
{
|
||||
appKey: 'webhook',
|
||||
key: 'catchRawWebhook',
|
||||
parameters: {
|
||||
workSynchronously: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
await testStep(request, tokenJsonResponse.data.token, triggerStepId);
|
||||
|
||||
await updateFlowStep(request, tokenJsonResponse.data.token, actionStepId, {
|
||||
appKey: 'webhook',
|
||||
key: 'respondWith',
|
||||
parameters: {
|
||||
statusCode: '200',
|
||||
body: 'ok',
|
||||
headers: [
|
||||
{
|
||||
key: '',
|
||||
value: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
await testStep(request, tokenJsonResponse.data.token, actionStepId);
|
||||
|
||||
await page.reload();
|
||||
|
||||
await flowsPage.deleteFlow(flowId);
|
||||
const triggerWebhookResponse = await request.get(triggerStep.data.webhookUrl);
|
||||
await expect(triggerWebhookResponse.status()).toBe(404);
|
||||
});
|
||||
|
||||
test('Completed poll flow can be deleted', async ({
|
||||
page,
|
||||
request,
|
||||
flowsPage,
|
||||
}) => {
|
||||
const flow = await createFlow(request, tokenJsonResponse.data.token);
|
||||
const flowId = flow.data.id;
|
||||
const flowSteps = flow.data.steps;
|
||||
await updateFlowName(request, tokenJsonResponse.data.token, flowId);
|
||||
|
||||
const triggerStepId = flowSteps.find((step) => step.type === 'trigger').id;
|
||||
const actionStepId = flowSteps.find((step) => step.type === 'action').id;
|
||||
|
||||
await updateFlowStep(request, tokenJsonResponse.data.token, triggerStepId, {
|
||||
appKey: 'rss',
|
||||
key: 'newItemsInFeed',
|
||||
parameters: { feedUrl: 'https://feeds.bbci.co.uk/news/rss.xml' },
|
||||
});
|
||||
await testStep(request, tokenJsonResponse.data.token, triggerStepId);
|
||||
|
||||
await updateFlowStep(request, tokenJsonResponse.data.token, actionStepId, {
|
||||
appKey: 'datastore',
|
||||
key: 'setValue',
|
||||
parameters: {
|
||||
key: 'newsTitle',
|
||||
value: '{{step.' + triggerStepId + '.title}}',
|
||||
},
|
||||
});
|
||||
await testStep(request, tokenJsonResponse.data.token, actionStepId);
|
||||
|
||||
await page.reload();
|
||||
|
||||
await flowsPage.deleteFlow(flowId);
|
||||
|
||||
await expectNoDelayedJobForFlow(request, flowId);
|
||||
});
|
||||
|
||||
test('Published webhook flow can be deleted', async ({
|
||||
page,
|
||||
request,
|
||||
flowsPage,
|
||||
}) => {
|
||||
const flow = await createFlow(request, tokenJsonResponse.data.token);
|
||||
const flowId = flow.data.id;
|
||||
const flowSteps = flow.data.steps;
|
||||
await updateFlowName(request, tokenJsonResponse.data.token, flowId);
|
||||
|
||||
const triggerStepId = flowSteps.find((step) => step.type === 'trigger').id;
|
||||
const actionStepId = flowSteps.find((step) => step.type === 'action').id;
|
||||
|
||||
const triggerStep = await updateFlowStep(
|
||||
request,
|
||||
tokenJsonResponse.data.token,
|
||||
triggerStepId,
|
||||
{
|
||||
appKey: 'webhook',
|
||||
key: 'catchRawWebhook',
|
||||
parameters: {
|
||||
workSynchronously: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
await testStep(request, tokenJsonResponse.data.token, triggerStepId);
|
||||
|
||||
await updateFlowStep(request, tokenJsonResponse.data.token, actionStepId, {
|
||||
appKey: 'webhook',
|
||||
key: 'respondWith',
|
||||
parameters: {
|
||||
statusCode: '200',
|
||||
body: 'ok',
|
||||
headers: [
|
||||
{
|
||||
key: '',
|
||||
value: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
await testStep(request, tokenJsonResponse.data.token, actionStepId);
|
||||
|
||||
await publishFlow(request, tokenJsonResponse.data.token, flowId);
|
||||
|
||||
await page.reload();
|
||||
|
||||
await flowsPage.deleteFlow(flowId);
|
||||
const triggerWebhookResponse = await request.get(triggerStep.data.webhookUrl);
|
||||
await expect(triggerWebhookResponse.status()).toBe(404);
|
||||
});
|
||||
|
||||
test('Published poll flow can be deleted', async ({
|
||||
page,
|
||||
request,
|
||||
flowsPage,
|
||||
}) => {
|
||||
const flow = await createFlow(request, tokenJsonResponse.data.token);
|
||||
const flowId = flow.data.id;
|
||||
const flowSteps = flow.data.steps;
|
||||
await updateFlowName(request, tokenJsonResponse.data.token, flowId);
|
||||
|
||||
const triggerStepId = flowSteps.find((step) => step.type === 'trigger').id;
|
||||
const actionStepId = flowSteps.find((step) => step.type === 'action').id;
|
||||
|
||||
await updateFlowStep(request, tokenJsonResponse.data.token, triggerStepId, {
|
||||
appKey: 'rss',
|
||||
key: 'newItemsInFeed',
|
||||
parameters: { feedUrl: 'https://feeds.bbci.co.uk/news/rss.xml' },
|
||||
});
|
||||
await testStep(request, tokenJsonResponse.data.token, triggerStepId);
|
||||
|
||||
await updateFlowStep(request, tokenJsonResponse.data.token, actionStepId, {
|
||||
appKey: 'datastore',
|
||||
key: 'setValue',
|
||||
parameters: {
|
||||
key: 'newsTitle',
|
||||
value: '{{step.' + triggerStepId + '.title}}',
|
||||
},
|
||||
});
|
||||
await testStep(request, tokenJsonResponse.data.token, actionStepId);
|
||||
|
||||
await publishFlow(request, tokenJsonResponse.data.token, flowId);
|
||||
|
||||
await page.reload();
|
||||
|
||||
await flowsPage.deleteFlow(flowId);
|
||||
|
||||
await expectNoDelayedJobForFlow(request, flowId);
|
||||
});
|
Reference in New Issue
Block a user