Files
n8n-enterprise-unlocked/cypress/e2e/6-code-node.cy.ts
OlegIvaniv 4600bb3317 fix(editor): Adjust Ask AI tracking events & pass NDV session id (no-changelog) (#7027)
Github issue / Community forum post (link here to close automatically):

---------

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2023-08-29 12:53:29 +02:00

157 lines
5.4 KiB
TypeScript

import { WorkflowPage as WorkflowPageClass } from '../pages/workflow';
import { NDV } from '../pages/ndv';
const WorkflowPage = new WorkflowPageClass();
const ndv = new NDV();
describe('Code node', () => {
describe('Code editor', () => {
beforeEach(() => {
WorkflowPage.actions.visit();
WorkflowPage.actions.addInitialNodeToCanvas('Manual');
WorkflowPage.actions.addNodeToCanvas('Code', true, true);
});
it('should show correct placeholders switching modes', () => {
cy.contains("// Loop over input items and add a new field").should('be.visible');
ndv.getters.parameterInput('mode').click();
ndv.actions.selectOptionInParameterDropdown('mode', 'Run Once for Each Item');
cy.contains("// Add a new field called 'myNewField'").should('be.visible');
ndv.getters.parameterInput('mode').click();
ndv.actions.selectOptionInParameterDropdown('mode', 'Run Once for All Items');
cy.contains("// Loop over input items and add a new field").should('be.visible');
})
it('should execute the placeholder successfully in both modes', () => {
ndv.actions.execute();
WorkflowPage.getters.successToast().contains('Node executed successfully');
ndv.getters.parameterInput('mode').click();
ndv.actions.selectOptionInParameterDropdown('mode', 'Run Once for Each Item');
ndv.actions.execute();
WorkflowPage.getters.successToast().contains('Node executed successfully');
});
})
describe('Ask AI', () => {
it('tab should display based on experiment', () => {
WorkflowPage.actions.visit();
cy.window().then((win) => {
win.featureFlags.override('011_ask_AI', 'control');
WorkflowPage.actions.addInitialNodeToCanvas('Manual');
WorkflowPage.actions.addNodeToCanvas('Code');
WorkflowPage.actions.openNode('Code');
cy.getByTestId('code-node-tab-ai').should('not.exist');
ndv.actions.close();
win.featureFlags.override('011_ask_AI', undefined);
WorkflowPage.actions.openNode('Code');
cy.getByTestId('code-node-tab-ai').should('not.exist');
})
})
describe('Enabled', () => {
beforeEach(() => {
WorkflowPage.actions.visit();
cy.window().then((win) => {
win.featureFlags.override('011_ask_AI', 'gpt3');
WorkflowPage.actions.addInitialNodeToCanvas('Manual');
WorkflowPage.actions.addNodeToCanvas('Code', true, true);
})
})
it('tab should exist if experiment selected and be selectable', () => {
cy.getByTestId('code-node-tab-ai').should('exist');
cy.get('#tab-ask-ai').click();
cy.contains('Hey AI, generate JavaScript').should('exist');
})
it('generate code button should have correct state & tooltips', () => {
cy.getByTestId('code-node-tab-ai').should('exist');
cy.get('#tab-ask-ai').click();
cy.getByTestId('ask-ai-cta').should('be.disabled');
cy.getByTestId('ask-ai-cta').realHover();
cy.getByTestId('ask-ai-cta-tooltip-no-input-data').should('exist');
ndv.actions.executePrevious();
cy.getByTestId('ask-ai-cta').realHover();
cy.getByTestId('ask-ai-cta-tooltip-no-prompt').should('exist');
cy.getByTestId('ask-ai-prompt-input')
// Type random 14 character string
.type([...Array(14)].map(() => (Math.random() * 36 | 0).toString(36)).join(''))
cy.getByTestId('ask-ai-cta').realHover();
cy.getByTestId('ask-ai-cta-tooltip-prompt-too-short').should('exist');
cy.getByTestId('ask-ai-prompt-input')
.clear()
// Type random 15 character string
.type([...Array(15)].map(() => (Math.random() * 36 | 0).toString(36)).join(''))
cy.getByTestId('ask-ai-cta').should('be.enabled');
cy.getByTestId('ask-ai-prompt-counter').should('contain.text', '15 / 600');
})
it('should send correct schema and replace code', () => {
const prompt = [...Array(20)].map(() => (Math.random() * 36 | 0).toString(36)).join('');
cy.get('#tab-ask-ai').click();
ndv.actions.executePrevious();
cy.getByTestId('ask-ai-prompt-input').type(prompt)
cy.intercept('POST', '/rest/ask-ai', {
statusCode: 200,
body: {
data: {
code: 'console.log("Hello World")'
},
}
}).as('ask-ai');
cy.getByTestId('ask-ai-cta').click();
const askAiReq = cy.wait('@ask-ai')
askAiReq.its('request.body').should('have.keys', ['question', 'model', 'context', 'n8nVersion']);
askAiReq.its('context').should('have.keys', ['schema', 'ndvSessionId', 'sessionId']);
cy.contains('Code generation completed').should('be.visible')
cy.getByTestId('code-node-tab-code').should('contain.text', 'console.log("Hello World")');
cy.get('#tab-code').should('have.class', 'is-active');
})
it('should show error based on status code', () => {
const prompt = [...Array(20)].map(() => (Math.random() * 36 | 0).toString(36)).join('');
cy.get('#tab-ask-ai').click();
ndv.actions.executePrevious();
cy.getByTestId('ask-ai-prompt-input').type(prompt)
const handledCodes = [
{ code: 400, message: 'Code generation failed due to an unknown reason' },
{ code: 413, message: 'Your workflow data is too large for AI to process' },
{ code: 429, message: 'We\'ve hit our rate limit with our AI partner' },
{ code: 500, message: 'Code generation failed due to an unknown reason' },
]
handledCodes.forEach(({ code, message }) => {
cy.intercept('POST', '/rest/ask-ai', {
statusCode: code,
status: code,
}).as('ask-ai');
cy.getByTestId('ask-ai-cta').click();
cy.contains(message).should('be.visible')
})
})
})
});
});