first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,280 @@
|
||||
import type { TestRequirements } from '../Types';
|
||||
|
||||
// #region Mock AI Responses
|
||||
|
||||
export const simpleAssistantResponse = {
|
||||
sessionId: '1',
|
||||
messages: [
|
||||
{
|
||||
role: 'assistant',
|
||||
type: 'message',
|
||||
text: 'Hey, this is an assistant message',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const codeDiffSuggestionResponse = {
|
||||
sessionId: '1',
|
||||
messages: [
|
||||
{
|
||||
role: 'assistant',
|
||||
type: 'message',
|
||||
text: 'Hi there! Here is my top solution to fix the error in your **Code** node 👇',
|
||||
},
|
||||
{
|
||||
role: 'assistant',
|
||||
type: 'code-diff',
|
||||
description:
|
||||
"Fix the syntax error by changing '1asd' to a valid value. In this case, it seems like '1' was intended.",
|
||||
suggestionId: '1',
|
||||
codeDiff:
|
||||
'@@ -2,2 +2,2 @@\\n item.json.myNewField = 1asd;\\n+ item.json.myNewField = 1;\\n',
|
||||
quickReplies: [
|
||||
{
|
||||
text: 'Give me another solution',
|
||||
type: 'new-suggestion',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const applyCodeDiffResponse = {
|
||||
data: {
|
||||
sessionId:
|
||||
'f9130bd7-c078-4862-a38a-369b27b0ff20-e96eb9f7-d581-4684-b6a9-fd3dfe9fe1fb-emTezIGat7bQsDdtIlbti',
|
||||
parameters: {
|
||||
jsCode:
|
||||
"// Loop over input items and add a new field called 'myNewField' to the JSON of each one\\nfor (export const item of $input.all()) {\\n item.json.myNewField = 1;\\n}\\n\\nreturn $input.all();",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const nodeExecutionSucceededResponse = {
|
||||
sessionId: '1',
|
||||
messages: [
|
||||
{
|
||||
role: 'assistant',
|
||||
type: 'message',
|
||||
text: '**Code** node ran successfully, did my solution help resolve your issue?',
|
||||
quickReplies: [
|
||||
{
|
||||
text: 'Yes, thanks',
|
||||
type: 'all-good',
|
||||
isFeedback: true,
|
||||
},
|
||||
{
|
||||
text: 'No, I am still stuck',
|
||||
type: 'still-stuck',
|
||||
isFeedback: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const codeSnippetAssistantResponse = {
|
||||
sessionId:
|
||||
'f1d19ed5-0d55-4bad-b49a-f0c56bd6f76f-705b5dbf-12d4-4805-87a3-1e5b3c716d29-W1JgVNrpfitpSNF9rAjB4',
|
||||
messages: [
|
||||
{
|
||||
role: 'assistant',
|
||||
type: 'message',
|
||||
text: 'To use expressions in n8n, follow these steps:\\n\\n1. Hover over the parameter where you want to use an expression.\\n2. Select **Expressions** in the **Fixed/Expression** toggle.\\n3. Write your expression in the parameter, or select **Open expression editor** to open the expressions editor. You can browse the available data in the **Variable selector**. All expressions have the format `{{ your expression here }}`.\\n\\n### Example: Get data from webhook body\\n\\nIf your webhook data looks like this:\\n\\n```json\\n[\\n {\\n \\"headers\\": {\\n \\"host\\": \\"n8n.instance.address\\",\\n ...\\n },\\n \\"params\\": {},\\n \\"query\\": {},\\n \\"body\\": {\\n \\"name\\": \\"Jim\\",\\n \\"age\\": 30,\\n \\"city\\": \\"New York\\"\\n }\\n }\\n]\\n```\\n\\nYou can use the following expression to get the value of `city`:\\n\\n```js\\n{{$json.body.city}}\\n```\\n\\nThis expression accesses the incoming JSON-formatted data using n8n\'s custom `$json` variable and finds the value of `city` (in this example, \\"New York\\").',
|
||||
codeSnippet: '{{$json.body.city}}',
|
||||
},
|
||||
{
|
||||
role: 'assistant',
|
||||
type: 'message',
|
||||
text: 'Did this answer solve your question?',
|
||||
quickReplies: [
|
||||
{
|
||||
text: 'Yes, thanks',
|
||||
type: 'all-good',
|
||||
isFeedback: true,
|
||||
},
|
||||
{
|
||||
text: 'No, I am still stuck',
|
||||
type: 'still-stuck',
|
||||
isFeedback: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Test Requirements for different scenarios
|
||||
|
||||
export const aiDisabledRequirements: TestRequirements = {
|
||||
config: {
|
||||
settings: {
|
||||
aiAssistant: { enabled: false, setup: false },
|
||||
},
|
||||
features: { aiAssistant: false },
|
||||
},
|
||||
};
|
||||
|
||||
export const aiEnabledRequirements: TestRequirements = {
|
||||
config: {
|
||||
settings: {
|
||||
aiAssistant: { enabled: true, setup: true },
|
||||
},
|
||||
features: { aiAssistant: true, setup: true },
|
||||
},
|
||||
};
|
||||
|
||||
export const aiEnabledWithWorkflowRequirements: TestRequirements = {
|
||||
config: {
|
||||
settings: {
|
||||
aiAssistant: { enabled: true, setup: true },
|
||||
},
|
||||
features: { aiAssistant: true, setup: true },
|
||||
},
|
||||
workflow: {
|
||||
'ai_assistant_test_workflow.json': 'AI_Assistant_Test_Workflow',
|
||||
},
|
||||
intercepts: {
|
||||
aiChat: {
|
||||
url: '**/rest/ai/chat',
|
||||
response: simpleAssistantResponse,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const aiEnabledWithQuickRepliesRequirements: TestRequirements = {
|
||||
config: {
|
||||
settings: {
|
||||
aiAssistant: { enabled: true, setup: true },
|
||||
},
|
||||
features: { aiAssistant: true },
|
||||
},
|
||||
workflow: {
|
||||
'ai_assistant_test_workflow.json': 'AI_Assistant_Test_Workflow',
|
||||
},
|
||||
intercepts: {
|
||||
aiChat: {
|
||||
url: '**/rest/ai/chat',
|
||||
response: {
|
||||
sessionId: '1',
|
||||
messages: [
|
||||
{
|
||||
role: 'assistant',
|
||||
type: 'message',
|
||||
text: 'Hey, this is an assistant message',
|
||||
quickReplies: [
|
||||
{
|
||||
text: "Sure, let's do it",
|
||||
type: 'yes',
|
||||
},
|
||||
{
|
||||
text: "Nah, doesn't sound good",
|
||||
type: 'no',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const aiEnabledWithEndSessionRequirements: TestRequirements = {
|
||||
config: {
|
||||
settings: {
|
||||
aiAssistant: { enabled: true, setup: true },
|
||||
},
|
||||
features: { aiAssistant: true },
|
||||
},
|
||||
workflow: {
|
||||
'ai_assistant_test_workflow.json': 'AI_Assistant_Test_Workflow',
|
||||
},
|
||||
intercepts: {
|
||||
aiChat: {
|
||||
url: '**/rest/ai/chat',
|
||||
response: {
|
||||
sessionId: '1',
|
||||
messages: [
|
||||
{
|
||||
role: 'assistant',
|
||||
type: 'message',
|
||||
title: 'Glad to Help',
|
||||
text: "I'm glad I could help. If you have any more questions or need further assistance with your n8n workflows, feel free to ask!",
|
||||
},
|
||||
{
|
||||
role: 'assistant',
|
||||
type: 'event',
|
||||
eventName: 'end-session',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const aiEnabledWorkflowBaseRequirements: TestRequirements = {
|
||||
config: {
|
||||
settings: {
|
||||
aiAssistant: { enabled: true, setup: true },
|
||||
},
|
||||
features: { aiAssistant: true, setup: true },
|
||||
},
|
||||
workflow: {
|
||||
'ai_assistant_test_workflow.json': 'AI_Assistant_Test_Workflow',
|
||||
},
|
||||
};
|
||||
|
||||
export const aiEnabledWithCodeDiffRequirements: TestRequirements = {
|
||||
...aiEnabledWorkflowBaseRequirements,
|
||||
intercepts: {
|
||||
aiChat: {
|
||||
url: '**/rest/ai/chat',
|
||||
response: codeDiffSuggestionResponse,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const aiEnabledWithSimpleChatRequirements: TestRequirements = {
|
||||
config: {
|
||||
settings: {
|
||||
aiAssistant: { enabled: true, setup: true },
|
||||
},
|
||||
features: { aiAssistant: true, setup: true },
|
||||
},
|
||||
intercepts: {
|
||||
aiChat: {
|
||||
url: '**/rest/ai/chat',
|
||||
response: simpleAssistantResponse,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const aiEnabledWithCodeSnippetRequirements: TestRequirements = {
|
||||
config: {
|
||||
settings: {
|
||||
aiAssistant: { enabled: true, setup: true },
|
||||
},
|
||||
features: { aiAssistant: true, setup: true },
|
||||
},
|
||||
intercepts: {
|
||||
aiChat: {
|
||||
url: '**/rest/ai/chat',
|
||||
response: codeSnippetAssistantResponse,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const aiEnabledWithHttpWorkflowRequirements: TestRequirements = {
|
||||
config: {
|
||||
settings: {
|
||||
aiAssistant: { enabled: true, setup: true },
|
||||
},
|
||||
features: { aiAssistant: true, setup: true },
|
||||
},
|
||||
workflow: {
|
||||
'Simple_workflow_with_http_node.json': 'Simple HTTP Workflow',
|
||||
},
|
||||
};
|
||||
|
||||
// #endregion
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { TestRequirements } from '../Types';
|
||||
|
||||
/**
|
||||
* Requirements for enabling the AI workflow builder feature.
|
||||
* These tests use the real Anthropic API for workflow generation,
|
||||
* requiring N8N_AI_ANTHROPIC_KEY to be set in the environment.
|
||||
*/
|
||||
export const workflowBuilderEnabledRequirements: TestRequirements = {
|
||||
config: {
|
||||
settings: {
|
||||
aiAssistant: { enabled: true, setup: true },
|
||||
aiBuilder: { enabled: true, setup: true },
|
||||
},
|
||||
features: {
|
||||
aiAssistant: true,
|
||||
aiBuilder: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
export const BACKEND_BASE_URL = 'http://localhost:5678';
|
||||
export const N8N_AUTH_COOKIE = 'n8n-auth';
|
||||
|
||||
export const DEFAULT_USER_PASSWORD = 'PlaywrightTest123';
|
||||
|
||||
export const MANUAL_TRIGGER_NODE_NAME = 'Manual Trigger';
|
||||
export const MANUAL_TRIGGER_NODE_DISPLAY_NAME = 'When clicking ‘Execute workflow’';
|
||||
export const MANUAL_CHAT_TRIGGER_NODE_NAME = 'Chat';
|
||||
export const CHAT_TRIGGER_NODE_DISPLAY_NAME = 'When chat message received';
|
||||
export const SCHEDULE_TRIGGER_NODE_NAME = 'Schedule Trigger';
|
||||
export const CODE_NODE_NAME = 'Code';
|
||||
export const CODE_NODE_DISPLAY_NAME = 'Code in JavaScript';
|
||||
export const SET_NODE_NAME = 'Set';
|
||||
export const EDIT_FIELDS_SET_NODE_NAME = 'Edit Fields (Set)';
|
||||
export const LOOP_OVER_ITEMS_NODE_NAME = 'Loop Over Items';
|
||||
export const IF_NODE_NAME = 'If';
|
||||
export const MERGE_NODE_NAME = 'Merge';
|
||||
export const SWITCH_NODE_NAME = 'Switch';
|
||||
export const GMAIL_NODE_NAME = 'Gmail';
|
||||
export const TRELLO_NODE_NAME = 'Trello';
|
||||
export const NOTION_NODE_NAME = 'Notion';
|
||||
export const PIPEDRIVE_NODE_NAME = 'Pipedrive';
|
||||
export const HTTP_REQUEST_NODE_NAME = 'HTTP Request';
|
||||
export const AGENT_NODE_NAME = 'AI Agent';
|
||||
export const BASIC_LLM_CHAIN_NODE_NAME = 'Basic LLM Chain';
|
||||
export const AI_MEMORY_WINDOW_BUFFER_MEMORY_NODE_NAME = 'Simple Memory';
|
||||
export const AI_TOOL_CALCULATOR_NODE_NAME = 'Calculator';
|
||||
export const AI_TOOL_CODE_NODE_NAME = 'Code Tool';
|
||||
export const AI_TOOL_WIKIPEDIA_NODE_NAME = 'Wikipedia';
|
||||
export const AI_TOOL_HTTP_NODE_NAME = 'HTTP Request Tool';
|
||||
export const AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME = 'OpenAI Chat Model';
|
||||
export const AI_MEMORY_POSTGRES_NODE_NAME = 'Postgres Chat Memory';
|
||||
export const AI_MEMORY_REDIS_CHAT_NODE_NAME = 'Redis Chat Memory';
|
||||
export const AI_OUTPUT_PARSER_AUTO_FIXING_NODE_NAME = 'Auto-fixing Output Parser';
|
||||
export const WEBHOOK_NODE_NAME = 'Webhook';
|
||||
export const EXECUTE_WORKFLOW_NODE_NAME = 'Execute Workflow';
|
||||
export const NO_OPERATION_NODE_NAME = 'No Operation, do nothing';
|
||||
export const HACKER_NEWS_NODE_NAME = 'Hacker News';
|
||||
|
||||
export const NEW_GOOGLE_ACCOUNT_NAME = 'Gmail account';
|
||||
export const NEW_TRELLO_ACCOUNT_NAME = 'Trello account';
|
||||
export const NEW_NOTION_ACCOUNT_NAME = 'Notion account';
|
||||
export const NEW_QUERY_AUTH_ACCOUNT_NAME = 'Query Auth account';
|
||||
export const E2E_TEST_NODE_NAME = 'E2E Test';
|
||||
|
||||
export const TOOL_SUBCATEGORY = 'Action in an app';
|
||||
export const HITL_TOOL_SUBCATEGORY = 'Human review';
|
||||
|
||||
export const ROUTES = {
|
||||
NEW_WORKFLOW_PAGE: '/workflow/new',
|
||||
};
|
||||
@@ -0,0 +1,123 @@
|
||||
import type { BrowserContext, Route } from '@playwright/test';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import merge from 'lodash/merge';
|
||||
|
||||
const contextSettings = new Map<BrowserContext, Partial<Record<string, unknown>>>();
|
||||
|
||||
export function setContextSettings(
|
||||
context: BrowserContext,
|
||||
settings: Partial<Record<string, unknown>>,
|
||||
) {
|
||||
contextSettings.set(context, settings);
|
||||
}
|
||||
|
||||
export function getContextSettings(context: BrowserContext) {
|
||||
return contextSettings.get(context);
|
||||
}
|
||||
|
||||
export async function setupDefaultInterceptors(target: BrowserContext) {
|
||||
// Global /rest/settings intercept - always active like Cypress
|
||||
// TODO: Remove this as a global and move it per test
|
||||
await target.route('**/rest/settings', async (route: Route) => {
|
||||
try {
|
||||
const originalResponse = await route.fetch();
|
||||
const originalJson = await originalResponse.json();
|
||||
|
||||
// Get settings stored for this specific context
|
||||
const testSettings = getContextSettings(target);
|
||||
|
||||
// Deep merge test settings with backend settings (like Cypress)
|
||||
const modifiedData = {
|
||||
data:
|
||||
testSettings && Object.keys(testSettings).length > 0
|
||||
? merge(cloneDeep(originalJson.data), testSettings)
|
||||
: originalJson.data,
|
||||
};
|
||||
|
||||
await route.fulfill({
|
||||
status: originalResponse.status(),
|
||||
headers: originalResponse.headers(),
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify(modifiedData),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error in /rest/settings intercept:', error);
|
||||
await route.continue();
|
||||
}
|
||||
});
|
||||
|
||||
// POST /rest/credentials/test
|
||||
await target.route('**/rest/credentials/test', async (route: Route) => {
|
||||
if (route.request().method() === 'POST') {
|
||||
await route.fulfill({
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ data: { status: 'success', message: 'Tested successfully' } }),
|
||||
});
|
||||
} else {
|
||||
await route.continue();
|
||||
}
|
||||
});
|
||||
|
||||
// POST /rest/license/renew
|
||||
await target.route('**/rest/license/renew', async (route: Route) => {
|
||||
if (route.request().method() === 'POST') {
|
||||
await route.fulfill({
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
data: {
|
||||
usage: { activeWorkflowTriggers: { limit: -1, value: 0, warningThreshold: 0.8 } },
|
||||
license: { planId: '', planName: 'Community' },
|
||||
},
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
await route.continue();
|
||||
}
|
||||
});
|
||||
|
||||
// Pathname /api/health
|
||||
await target.route(
|
||||
(url) => url.pathname.endsWith('/api/health'),
|
||||
async (route: Route) => {
|
||||
await route.fulfill({
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ status: 'OK' }),
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// Pathname /api/versions/*
|
||||
await target.route(
|
||||
(url) => url.pathname.startsWith('/api/versions/'),
|
||||
async (route: Route) => {
|
||||
await route.fulfill({
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify([
|
||||
{
|
||||
name: '1.45.1',
|
||||
createdAt: '2023-08-18T11:53:12.857Z',
|
||||
hasSecurityIssue: null,
|
||||
hasSecurityFix: null,
|
||||
securityIssueFixVersion: null,
|
||||
hasBreakingChange: null,
|
||||
documentationUrl: 'https://docs.n8n.io/release-notes/#n8n131',
|
||||
nodes: [],
|
||||
description: 'Includes <strong>bug fixes</strong>',
|
||||
},
|
||||
{
|
||||
name: '1.0.5',
|
||||
createdAt: '2023-07-24T10:54:56.097Z',
|
||||
hasSecurityIssue: false,
|
||||
hasSecurityFix: null,
|
||||
securityIssueFixVersion: null,
|
||||
hasBreakingChange: true,
|
||||
documentationUrl: 'https://docs.n8n.io/release-notes/#n8n104',
|
||||
nodes: [],
|
||||
description:
|
||||
'Includes <strong>core functionality</strong> and <strong>bug fixes</strong>',
|
||||
},
|
||||
]),
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import { DEFAULT_USER_PASSWORD } from './constants';
|
||||
|
||||
export interface UserCredentials {
|
||||
email: string;
|
||||
password: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
mfaEnabled?: boolean;
|
||||
mfaSecret?: string;
|
||||
mfaRecoveryCodes?: string[];
|
||||
}
|
||||
|
||||
// Simple name generators
|
||||
const FIRST_NAMES = [
|
||||
'Alex',
|
||||
'Jordan',
|
||||
'Taylor',
|
||||
'Morgan',
|
||||
'Casey',
|
||||
'Riley',
|
||||
'Avery',
|
||||
'Quinn',
|
||||
'Sam',
|
||||
'Drew',
|
||||
'Blake',
|
||||
'Sage',
|
||||
'River',
|
||||
'Rowan',
|
||||
'Skylar',
|
||||
'Emery',
|
||||
];
|
||||
|
||||
const LAST_NAMES = [
|
||||
'Smith',
|
||||
'Johnson',
|
||||
'Williams',
|
||||
'Brown',
|
||||
'Jones',
|
||||
'Garcia',
|
||||
'Miller',
|
||||
'Davis',
|
||||
'Rodriguez',
|
||||
'Martinez',
|
||||
'Hernandez',
|
||||
'Lopez',
|
||||
'Gonzalez',
|
||||
'Wilson',
|
||||
'Anderson',
|
||||
'Thomas',
|
||||
];
|
||||
|
||||
const getRandomName = (names: string[]): string => {
|
||||
return names[Math.floor(Math.random() * names.length)];
|
||||
};
|
||||
|
||||
const randFirstName = (): string => getRandomName(FIRST_NAMES);
|
||||
const randLastName = (): string => getRandomName(LAST_NAMES);
|
||||
|
||||
export const INSTANCE_OWNER_CREDENTIALS: UserCredentials = {
|
||||
email: 'nathan@n8n.io',
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: randFirstName(),
|
||||
lastName: randLastName(),
|
||||
mfaEnabled: false,
|
||||
mfaSecret: 'KVKFKRCPNZQUYMLXOVYDSQKJKZDTSRLD',
|
||||
mfaRecoveryCodes: ['d04ea17f-e8b2-4afa-a9aa-57a2c735b30e'],
|
||||
};
|
||||
|
||||
export const INSTANCE_ADMIN_CREDENTIALS: UserCredentials = {
|
||||
email: 'admin@n8n.io',
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: randFirstName(),
|
||||
lastName: randLastName(),
|
||||
};
|
||||
|
||||
export const INSTANCE_MEMBER_CREDENTIALS: UserCredentials[] = [
|
||||
{
|
||||
email: 'member@n8n.io',
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: randFirstName(),
|
||||
lastName: randLastName(),
|
||||
},
|
||||
{
|
||||
email: 'member2@n8n.io',
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: randFirstName(),
|
||||
lastName: randLastName(),
|
||||
},
|
||||
];
|
||||
|
||||
export const INSTANCE_CHAT_CREDENTIALS: UserCredentials = {
|
||||
email: 'chat@n8n.io',
|
||||
password: DEFAULT_USER_PASSWORD,
|
||||
firstName: randFirstName(),
|
||||
lastName: randLastName(),
|
||||
};
|
||||
Reference in New Issue
Block a user