test: Ado 1296 add e2e tests (#7792)

Adds e2e tests for the template credential setup.
This commit is contained in:
Tomi Turtiainen 2023-11-27 17:18:10 +02:00 committed by GitHub
parent 847f6ac771
commit ac744d6702
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 358 additions and 9 deletions

View file

@ -0,0 +1,105 @@
import { CredentialsModal, MessageBox } from '../pages/modals';
import { TemplateCredentialSetupPage } from '../pages/template-credential-setup';
import { TemplateWorkflowPage } from '../pages/template-workflow';
import { WorkflowPage } from '../pages/workflow';
const templateWorkflowPage = new TemplateWorkflowPage();
const templateCredentialsSetupPage = new TemplateCredentialSetupPage();
const credentialsModal = new CredentialsModal();
const messageBox = new MessageBox();
const workflowPage = new WorkflowPage();
const testTemplate = templateCredentialsSetupPage.testData.simpleTemplate;
describe('Template credentials setup', () => {
beforeEach(() => {
cy.intercept('GET', `https://api.n8n.io/api/templates/workflows/${testTemplate.id}`, {
fixture: testTemplate.fixture,
});
});
it('can be opened from template workflow page', () => {
templateWorkflowPage.actions.visit(testTemplate.id);
templateCredentialsSetupPage.actions.enableFeatureFlag();
templateWorkflowPage.actions.clickUseThisWorkflowButton();
templateCredentialsSetupPage.getters
.title(`Setup 'Promote new Shopify products on Twitter and Telegram' template`)
.should('be.visible');
});
it('can be opened with a direct url', () => {
templateCredentialsSetupPage.actions.visit(testTemplate.id);
templateCredentialsSetupPage.getters
.title(`Setup 'Promote new Shopify products on Twitter and Telegram' template`)
.should('be.visible');
});
it('has all the elements on page', () => {
templateCredentialsSetupPage.actions.visit(testTemplate.id);
templateCredentialsSetupPage.getters
.title(`Setup 'Promote new Shopify products on Twitter and Telegram' template`)
.should('be.visible');
templateCredentialsSetupPage.getters
.infoCallout()
.should(
'contain.text',
'You need 1x Shopify, 1x X (Formerly Twitter) and 1x Telegram account to setup this template',
);
const expectedAppNames = ['1. Shopify', '2. X (Formerly Twitter)', '3. Telegram'];
const expectedAppDescriptions = [
'The credential you select will be used in the product created node of the workflow template.',
'The credential you select will be used in the Twitter node of the workflow template.',
'The credential you select will be used in the Telegram node of the workflow template.',
];
templateCredentialsSetupPage.getters.appCredentialSteps().each(($el, index) => {
templateCredentialsSetupPage.getters
.stepHeading($el)
.should('have.text', expectedAppNames[index]);
templateCredentialsSetupPage.getters
.stepDescription($el)
.should('have.text', expectedAppDescriptions[index]);
});
});
it('can skip template creation', () => {
templateCredentialsSetupPage.actions.visit(testTemplate.id);
templateCredentialsSetupPage.getters.skipLink().click();
workflowPage.getters.canvasNodes().should('have.length', 3);
});
it('can create credentials and workflow from the template', () => {
templateCredentialsSetupPage.actions.visit(testTemplate.id);
templateCredentialsSetupPage.getters.continueButton().should('be.disabled');
templateCredentialsSetupPage.getters.createAppCredentialsButton('Shopify').click();
credentialsModal.getters.editCredentialModal().find('input:first()').type('test');
credentialsModal.actions.save(false);
credentialsModal.actions.close();
templateCredentialsSetupPage.getters.createAppCredentialsButton('X (Formerly Twitter)').click();
credentialsModal.getters.editCredentialModal().find('input:first()').type('test');
credentialsModal.actions.save(false);
credentialsModal.actions.close();
messageBox.actions.cancel();
templateCredentialsSetupPage.getters.createAppCredentialsButton('Telegram').click();
credentialsModal.getters.editCredentialModal().find('input:first()').type('test');
credentialsModal.actions.save(false);
credentialsModal.actions.close();
cy.intercept('POST', '/rest/workflows').as('createWorkflow');
templateCredentialsSetupPage.getters.continueButton().should('be.enabled');
templateCredentialsSetupPage.getters.continueButton().click();
cy.wait('@createWorkflow');
workflowPage.getters.canvasNodes().should('have.length', 3);
});
});

View file

@ -0,0 +1,177 @@
{
"workflow": {
"id": 1205,
"name": "Promote new Shopify products on Twitter and Telegram",
"views": 478,
"recentViews": 9880,
"totalViews": 478,
"createdAt": "2021-08-24T10:40:50.007Z",
"description": "This workflow automatically promotes your new Shopify products on Twitter and Telegram. This workflow is also featured in the blog post [*6 e-commerce workflows to power up your Shopify store*](https://n8n.io/blog/no-code-ecommerce-workflow-automations/#promote-your-new-products-on-social-media).\n\n## Prerequisites\n\n- A Shopify account and [credentials](https://docs.n8n.io/integrations/credentials/shopify/)\n- A Twitter account and [credentials](https://docs.n8n.io/integrations/credentials/twitter/)\n- A Telegram account and [credentials](https://docs.n8n.io/integrations/credentials/telegram/) for the channel you want to send messages to.\n\n## Nodes\n\n- [Shopify Trigger node](https://docs.n8n.io/integrations/trigger-nodes/n8n-nodes-base.shopifytrigger/) triggers the workflow when you create a new product in Shopify.\n- [Twitter node](https://docs.n8n.io/integrations/nodes/n8n-nodes-base.twitter/) posts a tweet with the text \"Hey there, my design is now on a new product! Visit my {shop name} to get this cool {product title} (and check out more {product type})\".\n- [Telegram node](https://docs.n8n.io/integrations/nodes/n8n-nodes-base.telegram/) posts a message with the same text as above in a Telegram channel.",
"workflow": {
"nodes": [
{
"name": "Twitter",
"type": "n8n-nodes-base.twitter",
"position": [
720,
-220
],
"parameters": {
"text": "=Hey there, my design is now on a new product ✨\nVisit my {{$json[\"vendor\"]}} shop to get this cool{{$json[\"title\"]}} (and check out more {{$json[\"product_type\"]}}) 🛍️",
"additionalFields": {}
},
"credentials": {
"twitterOAuth1Api": "twitter"
},
"typeVersion": 1
},
{
"name": "Telegram",
"type": "n8n-nodes-base.telegram",
"position": [
720,
-20
],
"parameters": {
"text": "=Hey there, my design is now on a new product!\nVisit my {{$json[\"vendor\"]}} shop to get this cool{{$json[\"title\"]}} (and check out more {{$json[\"product_type\"]}})",
"chatId": "123456",
"additionalFields": {}
},
"credentials": {
"telegramApi": "telegram_habot"
},
"typeVersion": 1
},
{
"name": "product created",
"type": "n8n-nodes-base.shopifyTrigger",
"position": [
540,
-110
],
"webhookId": "2a7e0e50-8f09-4a2b-bf54-a849a6ac4fe0",
"parameters": {
"topic": "products/create"
},
"credentials": {
"shopifyApi": "shopify_nodeqa"
},
"typeVersion": 1
}
],
"connections": {
"product created": {
"main": [
[
{
"node": "Twitter",
"type": "main",
"index": 0
},
{
"node": "Telegram",
"type": "main",
"index": 0
}
]
]
}
}
},
"workflowInfo": {
"nodeCount": 3,
"nodeTypes": {
"n8n-nodes-base.twitter": {
"count": 1
},
"n8n-nodes-base.telegram": {
"count": 1
},
"n8n-nodes-base.shopifyTrigger": {
"count": 1
}
}
},
"user": {
"username": "lorenanda"
},
"nodes": [
{
"id": 49,
"icon": "file:telegram.svg",
"name": "n8n-nodes-base.telegram",
"defaults": {
"name": "Telegram"
},
"iconData": {
"type": "file",
"fileBuffer": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgNjYgNjYiIGZpbGw9IiNmZmYiIGZpbGwtcnVsZT0iZXZlbm9kZCIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjx1c2UgeGxpbms6aHJlZj0iI2EiIHg9Ii41IiB5PSIuNSIvPjxzeW1ib2wgaWQ9ImEiIG92ZXJmbG93PSJ2aXNpYmxlIj48ZyBzdHJva2U9Im5vbmUiIGZpbGwtcnVsZT0ibm9uemVybyI+PHBhdGggZD0iTTAgMzJjMCAxNy42NzMgMTQuMzI3IDMyIDMyIDMyczMyLTE0LjMyNyAzMi0zMlM0OS42NzMgMCAzMiAwIDAgMTQuMzI3IDAgMzIiIGZpbGw9IiMzN2FlZTIiLz48cGF0aCBkPSJNMjEuNjYxIDM0LjMzOGwzLjc5NyAxMC41MDhzLjQ3NS45ODMuOTgzLjk4MyA4LjA2OC03Ljg2NCA4LjA2OC03Ljg2NGw4LjQwNy0xNi4yMzctMjEuMTE5IDkuODk4eiIgZmlsbD0iI2M4ZGFlYSIvPjxwYXRoIGQ9Ik0yNi42OTUgMzcuMDM0bC0uNzI5IDcuNzQ2cy0uMzA1IDIuMzczIDIuMDY4IDBsNC42NDQtNC4yMDMiIGZpbGw9IiNhOWM2ZDgiLz48cGF0aCBkPSJNMjEuNzMgMzQuNzEybC03LjgwOS0yLjU0NXMtLjkzMi0uMzc4LS42MzMtMS4yMzdjLjA2Mi0uMTc3LjE4Ni0uMzI4LjU1OS0uNTg4IDEuNzMxLTEuMjA2IDMyLjAyOC0xMi4wOTYgMzIuMDI4LTEyLjA5NnMuODU2LS4yODggMS4zNjEtLjA5N2MuMjMxLjA4OC4zNzguMTg3LjUwMy41NDguMDQ1LjEzMi4wNzEuNDExLjA2OC42ODktLjAwMy4yMDEtLjAyNy4zODYtLjA0NS42NzgtLjE4NCAyLjk3OC01LjcwNiAyNS4xOTgtNS43MDYgMjUuMTk4cy0uMzMgMS4zLTEuNTE0IDEuMzQ1Yy0uNDMyLjAxNi0uOTU2LS4wNzEtMS41ODItLjYxLTIuMzIzLTEuOTk4LTEwLjM1Mi03LjM5NC0xMi4xMjYtOC41OGEuMzQuMzQgMCAwMS0uMTQ2LS4yMzljLS4wMjUtLjEyNS4xMDgtLjI4LjEwOC0uMjhzMTMuOTgtMTIuNDI3IDE0LjM1Mi0xMy43MzFjLjAyOS0uMTAxLS4wNzktLjE1MS0uMjI2LS4xMDctLjkyOS4zNDItMTcuMDI1IDEwLjUwNi0xOC44MDEgMTEuNjI5LS4xMDQuMDY2LS4zOTUuMDIzLS4zOTUuMDIzIi8+PC9nPjwvc3ltYm9sPjwvc3ZnPg=="
},
"categories": [
{
"id": 6,
"name": "Communication"
}
],
"displayName": "Telegram",
"typeVersion": 1
},
{
"id": 107,
"icon": "file:shopify.svg",
"name": "n8n-nodes-base.shopifyTrigger",
"defaults": {
"name": "Shopify Trigger"
},
"iconData": {
"type": "file",
"fileBuffer": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgNTggNjYiIGZpbGw9IiNmZmYiIGZpbGwtcnVsZT0iZXZlbm9kZCIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjx1c2UgeGxpbms6aHJlZj0iI2EiIHg9Ii41IiB5PSIuNSIvPjxzeW1ib2wgaWQ9ImEiIG92ZXJmbG93PSJ2aXNpYmxlIj48ZyBzdHJva2U9Im5vbmUiIGZpbGwtcnVsZT0ibm9uemVybyI+PHBhdGggZD0iTTQ5LjI1NSAxMi40ODRhLjYzMy42MzMgMCAwMC0uNTY0LS41MjdjLS4yMjUtLjAzNy01LjE3LS4zNzYtNS4xNy0uMzc2bC0zLjc3LTMuNzdjLS4zNC0uMzc2LTEuMDkyLS4yNjYtMS4zNzYtLjE4OC0uMDM3IDAtLjc1Mi4yMjUtMS45MjIuNjA1LTEuMTM3LTMuMy0zLjE1LTYuMzA2LTYuNjk2LTYuMzA2aC0uMzAzQzI4LjQzOC42MDUgMjcuMTk0IDAgMjYuMTQ0IDBjLTguMjU2LjAzNy0xMi4yIDEwLjMzMy0xMy40MzQgMTUuNTk0bC01Ljc3IDEuNzdjLTEuNzcuNTY0LTEuODM1LjYwNS0yLjA3MyAyLjI5M0wwIDU3LjE3NSAzNi40NjggNjRsMTkuNzYzLTQuMjZjMC0uMDM3LTYuOTQtNDYuODk3LTYuOTc2LTQ3LjI1NXpNMzQuNDMxIDguODZjLS45MTcuMzAzLTEuOTYzLjYwNS0zLjEuOTQ1di0uNjhhMTUuMDMgMTUuMDMgMCAwMC0uNzUyLTQuOTk5YzEuODQ4LjI4NCAzLjEgMi4zNTcgMy44NDMgNC43MzN6bS02LjA2OC00LjI5OGMuNjAzIDEuNzc4Ljg4MyAzLjY1LjgyNiA1LjUyN3YuMzRsLTYuMzc1IDEuOTYzYzEuMjQ4LTQuNjYgMy41NS02Ljk2MiA1LjU1LTcuODN6bS0yLjQ1LTIuMjkzYTEuOTQgMS45NCAwIDAxMS4wNTUuMzM5Yy0yLjY2IDEuMjM4LTUuNDcyIDQuMzY2LTYuNjc4IDEwLjYyN2wtNS4wNDUgMS41NDZDMTYuNjY4IDEwLjAzIDE5Ljk4OCAyLjI2IDI1LjkxIDIuMjZ6IiBmaWxsPSIjOTViZjQ3Ii8+PHBhdGggZD0iTTQ4LjY5MSAxMS45NTdjLS4yMjUtLjAzNy01LjE3LS4zNzYtNS4xNy0uMzc2bC0zLjc3LTMuNzdhLjc1My43NTMgMCAwMC0uNTI3LS4yMjVMMzYuNDcyIDY0bDE5Ljc2My00LjI2LTYuOTgtNDcuMjE4YS42OC42OCAwIDAwLS41NjQtLjU2NHoiIGZpbGw9IiM1ZThlM2UiLz48cGF0aCBkPSJNMjkuNzU4IDIyLjlsLTIuNDU0IDcuMjQyYTExLjM2IDExLjM2IDAgMDAtNC43NTItMS4xMzNjLTMuODQ4IDAtNC4wMzYgMi40MTItNC4wMzYgMy4wMTggMCAzLjI5OCA4LjYzNiA0LjU2NCA4LjYzNiAxMi4zMzMgMCA2LjEtMy44ODUgMTAuMDMtOS4xIDEwLjAzLTYuMjYgMC05LjQ2Ny0zLjg4NS05LjQ2Ny0zLjg4NWwxLjY2NS01LjU1czMuMjggMi44MyA2LjA3MyAyLjgzYTIuNDcgMi40NyAwIDAwMi41NjQtMi40OWMwLTQuMzQtNy4xLTQuNTI3LTcuMS0xMS42MTggMC01Ljk2MiA0LjI5OC0xMS43NyAxMi45MzQtMTEuNzcgMy4zOTQuMDUgNS4wMTggMSA1LjAxOCAxeiIvPjwvZz48L3N5bWJvbD48L3N2Zz4="
},
"categories": [
{
"id": 2,
"name": "Sales"
}
],
"displayName": "Shopify Trigger",
"typeVersion": 1
},
{
"id": 325,
"icon": "file:x.svg",
"name": "n8n-nodes-base.twitter",
"defaults": {
"name": "X"
},
"iconData": {
"type": "file",
"fileBuffer": "data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTE4LjI0NCAyLjI1aDMuMzA4bC03LjIyNyA4LjI2IDguNTAyIDExLjI0SDE2LjE3bC01LjIxNC02LjgxN0w0Ljk5IDIxLjc1SDEuNjhsNy43My04LjgzNUwxLjI1NCAyLjI1SDguMDhsNC43MTMgNi4yMzF6bS0xLjE2MSAxNy41MmgxLjgzM0w3LjA4NCA0LjEyNkg1LjExN3oiPjwvcGF0aD48L3N2Zz4K"
},
"categories": [
{
"id": 1,
"name": "Marketing & Content"
}
],
"displayName": "X (Formerly Twitter)",
"typeVersion": 2
}
],
"categories": [
{
"id": 2,
"name": "Sales"
},
{
"id": 19,
"name": "Marketing & Growth"
}
],
"image": [
{
"id": 527,
"url": "https://n8niostorageaccount.blob.core.windows.net/n8nio-strapi-blobs-prod/assets/89a078b208fe4c6181902608b1cd1332.png"
}
]
}
}

View file

@ -0,0 +1,40 @@
import { BasePage } from './base';
export type TemplateTestData = {
id: number;
fixture: string;
};
export class TemplateCredentialSetupPage extends BasePage {
testData = {
simpleTemplate: {
id: 1205,
fixture: 'Test_Template_1.json',
},
};
getters = {
continueButton: () => cy.getByTestId('continue-button'),
skipLink: () => cy.get('a:contains("Skip")'),
title: (title: string) => cy.get(`h1:contains(${title})`),
infoCallout: () => cy.getByTestId('info-callout'),
createAppCredentialsButton: (appName: string) =>
cy.get(`button:contains("Create new ${appName} credential")`),
appCredentialSteps: () => cy.getByTestId('setup-credentials-form-step'),
stepHeading: ($el: JQuery<HTMLElement>) =>
cy.wrap($el).findChildByTestId('credential-step-heading'),
stepDescription: ($el: JQuery<HTMLElement>) =>
cy.wrap($el).findChildByTestId('credential-step-description'),
};
actions = {
visit: (templateId: number) => {
cy.visit(`/templates/${templateId}/setup`);
},
enableFeatureFlag: () => {
cy.window().then((window) => {
window.localStorage.setItem('template-credentials-setup', 'true');
});
},
};
}

View file

@ -0,0 +1,19 @@
import { BasePage } from './base';
export class TemplateWorkflowPage extends BasePage {
url = '/templates';
getters = {
useTemplateButton: () => cy.get('[data-test-id="use-template-button"]'),
};
actions = {
visit: (templateId: number) => {
cy.visit(`${this.url}/${templateId}`);
},
clickUseThisWorkflowButton: () => {
this.getters.useTemplateButton().click();
},
};
}

View file

@ -4,10 +4,16 @@ export class TemplatesPage extends BasePage {
url = '/templates';
getters = {
useTemplateButton: () => cy.get('[data-testid="use-template-button"]'),
};
actions = {
openOnboardingFlow: (id: number, name: string , workflow: object) => {
openSingleTemplateView: (templateId: number) => {
cy.visit(`${this.url}/${templateId}`);
cy.waitForLoad();
},
openOnboardingFlow: (id: number, name: string, workflow: object) => {
const apiResponse = {
id,
name,
@ -41,8 +47,7 @@ export class TemplatesPage extends BasePage {
cy.visit(`/workflows/templates/${id}`);
cy.wait('@getTemplate');
cy.wait( '@getWorkflow');
}
}
cy.wait('@getWorkflow');
},
};
}

View file

@ -110,6 +110,7 @@ listenForCredentialChanges({
v-else
:label="`Create new ${props.appName} credential`"
@click="createNewCredential"
data-test-id="create-credential"
/>
</div>
</template>

View file

@ -77,16 +77,16 @@ const onCredentialDeselected = () => {
</script>
<template>
<li :class="$style.container">
<li :class="$style.container" data-test-id="setup-credentials-form-step">
<n8n-heading tag="h2" size="large">
<div v-if="nodeType" :class="$style.heading">
<div v-if="nodeType" :class="$style.heading" data-test-id="credential-step-heading">
<span :class="$style.headingOrder">{{ order }}.</span>
<span :class="$style.headingIcon"><NodeIcon :node-type="nodeType" /></span>
{{ appName }}
</div>
</n8n-heading>
<p :class="$style.description">
<p :class="$style.description" data-test-id="credential-step-description">
<i18n-t
tag="span"
keypath="templateSetup.credential.description"

View file

@ -109,7 +109,7 @@ onMounted(async () => {
<template #content>
<div :class="$style.grid">
<div :class="$style.gridContent">
<div :class="$style.notice">
<div :class="$style.notice" data-test-id="info-callout">
<AppsRequiringCredsNotice v-if="isReady" />
<n8n-loading v-else variant="p" />
</div>
@ -145,6 +145,7 @@ onMounted(async () => {
:label="$locale.baseText('templateSetup.continue.button')"
:disabled="setupTemplateStore.numCredentialsLeft > 0 || setupTemplateStore.isSaving"
@click="setupTemplateStore.createWorkflow($router)"
data-test-id="continue-button"
/>
</n8n-tooltip>
<div v-else>

View file

@ -14,6 +14,7 @@
<div :class="$style.button">
<n8n-button
v-if="template"
data-test-id="use-template-button"
:label="$locale.baseText('template.buttons.useThisWorkflowButton')"
size="large"
@click="openTemplateSetup(template.id, $event)"