pull:初次提交
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import { randomName } from '@n8n/backend-test-utils';
|
||||
import { Container } from '@n8n/di';
|
||||
|
||||
import { NODE_PACKAGE_PREFIX } from '@/constants';
|
||||
import { InstalledNodesRepository } from '@/modules/community-packages/installed-nodes.repository';
|
||||
import { InstalledPackages } from '@/modules/community-packages/installed-packages.entity';
|
||||
import { InstalledPackagesRepository } from '@/modules/community-packages/installed-packages.repository';
|
||||
|
||||
import { COMMUNITY_NODE_VERSION, COMMUNITY_PACKAGE_VERSION } from '../constants';
|
||||
|
||||
export const mockPackageName = () => NODE_PACKAGE_PREFIX + randomName();
|
||||
|
||||
export const mockPackage = () =>
|
||||
Container.get(InstalledPackagesRepository).create({
|
||||
packageName: mockPackageName(),
|
||||
installedVersion: COMMUNITY_PACKAGE_VERSION.CURRENT,
|
||||
installedNodes: [],
|
||||
});
|
||||
|
||||
export const mockNode = (packageName: string) => {
|
||||
const nodeName = randomName();
|
||||
|
||||
return Container.get(InstalledNodesRepository).create({
|
||||
name: nodeName,
|
||||
type: `${packageName}.${nodeName}`,
|
||||
latestVersion: COMMUNITY_NODE_VERSION.CURRENT,
|
||||
package: { packageName },
|
||||
});
|
||||
};
|
||||
|
||||
export const emptyPackage = async () => {
|
||||
const installedPackage = new InstalledPackages();
|
||||
installedPackage.installedNodes = [];
|
||||
return installedPackage;
|
||||
};
|
||||
|
||||
export function mockPackagePair(): InstalledPackages[] {
|
||||
const pkgA = mockPackage();
|
||||
const nodeA = mockNode(pkgA.packageName);
|
||||
pkgA.installedNodes = [nodeA];
|
||||
|
||||
const pkgB = mockPackage();
|
||||
const nodeB1 = mockNode(pkgB.packageName);
|
||||
const nodeB2 = mockNode(pkgB.packageName);
|
||||
pkgB.installedNodes = [nodeB1, nodeB2];
|
||||
|
||||
return [pkgA, pkgB];
|
||||
}
|
||||
207
n8n-n8n-1.109.2/packages/cli/test/integration/shared/utils/index.ts
Executable file
207
n8n-n8n-1.109.2/packages/cli/test/integration/shared/utils/index.ts
Executable file
@@ -0,0 +1,207 @@
|
||||
import { mockInstance } from '@n8n/backend-test-utils';
|
||||
import { SettingsRepository, WorkflowEntity } from '@n8n/db';
|
||||
import { Container } from '@n8n/di';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import {
|
||||
BinaryDataConfig,
|
||||
BinaryDataService,
|
||||
InstanceSettings,
|
||||
UnrecognizedNodeTypeError,
|
||||
type DirectoryLoader,
|
||||
} from 'n8n-core';
|
||||
import { Ftp } from 'n8n-nodes-base/credentials/Ftp.credentials';
|
||||
import { GithubApi } from 'n8n-nodes-base/credentials/GithubApi.credentials';
|
||||
import { Cron } from 'n8n-nodes-base/nodes/Cron/Cron.node';
|
||||
import { FormTrigger } from 'n8n-nodes-base/nodes/Form/FormTrigger.node';
|
||||
import { ScheduleTrigger } from 'n8n-nodes-base/nodes/Schedule/ScheduleTrigger.node';
|
||||
import { Set } from 'n8n-nodes-base/nodes/Set/Set.node';
|
||||
import { Start } from 'n8n-nodes-base/nodes/Start/Start.node';
|
||||
import type { INodeTypeData, INode } from 'n8n-workflow';
|
||||
import type request from 'supertest';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import config from '@/config';
|
||||
import { AUTH_COOKIE_NAME } from '@/constants';
|
||||
import { ExecutionService } from '@/executions/execution.service';
|
||||
import { LoadNodesAndCredentials } from '@/load-nodes-and-credentials';
|
||||
import { Push } from '@/push';
|
||||
|
||||
export { setupTestServer } from './test-server';
|
||||
|
||||
// ----------------------------------
|
||||
// initializers
|
||||
// ----------------------------------
|
||||
|
||||
/**
|
||||
* Initialize node types.
|
||||
*/
|
||||
export async function initActiveWorkflowManager() {
|
||||
mockInstance(BinaryDataConfig);
|
||||
mockInstance(InstanceSettings, {
|
||||
isMultiMain: false,
|
||||
});
|
||||
|
||||
mockInstance(Push);
|
||||
mockInstance(ExecutionService);
|
||||
const { ActiveWorkflowManager } = await import('@/active-workflow-manager');
|
||||
const activeWorkflowManager = Container.get(ActiveWorkflowManager);
|
||||
await activeWorkflowManager.init();
|
||||
return activeWorkflowManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize node types.
|
||||
*/
|
||||
export async function initCredentialsTypes(): Promise<void> {
|
||||
Container.get(LoadNodesAndCredentials).loaded.credentials = {
|
||||
githubApi: {
|
||||
type: new GithubApi(),
|
||||
sourcePath: '',
|
||||
},
|
||||
ftp: {
|
||||
type: new Ftp(),
|
||||
sourcePath: '',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize node types.
|
||||
*/
|
||||
export async function initNodeTypes(customNodes?: INodeTypeData) {
|
||||
const defaultNodes: INodeTypeData = {
|
||||
'n8n-nodes-base.start': {
|
||||
type: new Start(),
|
||||
sourcePath: '',
|
||||
},
|
||||
'n8n-nodes-base.cron': {
|
||||
type: new Cron(),
|
||||
sourcePath: '',
|
||||
},
|
||||
'n8n-nodes-base.set': {
|
||||
type: new Set(),
|
||||
sourcePath: '',
|
||||
},
|
||||
'n8n-nodes-base.scheduleTrigger': {
|
||||
type: new ScheduleTrigger(),
|
||||
sourcePath: '',
|
||||
},
|
||||
'n8n-nodes-base.formTrigger': {
|
||||
type: new FormTrigger(),
|
||||
sourcePath: '',
|
||||
},
|
||||
};
|
||||
|
||||
ScheduleTrigger.prototype.trigger = async () => ({});
|
||||
const nodes = customNodes ?? defaultNodes;
|
||||
const loader = mock<DirectoryLoader>();
|
||||
loader.getNode.mockImplementation((nodeType) => {
|
||||
const node = nodes[`n8n-nodes-base.${nodeType}`];
|
||||
if (!node) throw new UnrecognizedNodeTypeError('n8n-nodes-base', nodeType);
|
||||
return node;
|
||||
});
|
||||
|
||||
const loadNodesAndCredentials = Container.get(LoadNodesAndCredentials);
|
||||
loadNodesAndCredentials.loaders = { 'n8n-nodes-base': loader };
|
||||
loadNodesAndCredentials.loaded.nodes = nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a BinaryDataService for test runs.
|
||||
*/
|
||||
export async function initBinaryDataService(mode: 'default' | 'filesystem' = 'default') {
|
||||
const config = mock<BinaryDataConfig>({
|
||||
mode,
|
||||
availableModes: [mode],
|
||||
localStoragePath: '',
|
||||
});
|
||||
const binaryDataService = new BinaryDataService(config);
|
||||
await binaryDataService.init();
|
||||
Container.set(BinaryDataService, binaryDataService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the value (token) of the auth cookie in a response.
|
||||
*/
|
||||
export function getAuthToken(response: request.Response, authCookieName = AUTH_COOKIE_NAME) {
|
||||
const cookiesHeader = response.headers['set-cookie'];
|
||||
if (!cookiesHeader) return undefined;
|
||||
|
||||
const cookies = Array.isArray(cookiesHeader) ? cookiesHeader : [cookiesHeader];
|
||||
|
||||
const authCookie = cookies.find((c) => c.startsWith(`${authCookieName}=`));
|
||||
|
||||
if (!authCookie) return undefined;
|
||||
|
||||
const match = authCookie.match(new RegExp(`(^| )${authCookieName}=(?<token>[^;]+)`));
|
||||
|
||||
if (!match?.groups) return undefined;
|
||||
|
||||
return match.groups.token;
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
// settings
|
||||
// ----------------------------------
|
||||
|
||||
export async function isInstanceOwnerSetUp() {
|
||||
const { value } = await Container.get(SettingsRepository).findOneByOrFail({
|
||||
key: 'userManagement.isInstanceOwnerSetUp',
|
||||
});
|
||||
|
||||
return Boolean(value);
|
||||
}
|
||||
|
||||
export const setInstanceOwnerSetUp = async (value: boolean) => {
|
||||
config.set('userManagement.isInstanceOwnerSetUp', value);
|
||||
|
||||
await Container.get(SettingsRepository).update(
|
||||
{ key: 'userManagement.isInstanceOwnerSetUp' },
|
||||
{ value: JSON.stringify(value) },
|
||||
);
|
||||
};
|
||||
|
||||
// ----------------------------------
|
||||
// community nodes
|
||||
// ----------------------------------
|
||||
|
||||
export * from './community-nodes';
|
||||
|
||||
// ----------------------------------
|
||||
// workflow
|
||||
// ----------------------------------
|
||||
|
||||
export function makeWorkflow(options?: {
|
||||
withPinData: boolean;
|
||||
withCredential?: { id: string; name: string };
|
||||
}) {
|
||||
const workflow = new WorkflowEntity();
|
||||
|
||||
const node: INode = {
|
||||
id: uuid(),
|
||||
name: 'Cron',
|
||||
type: 'n8n-nodes-base.cron',
|
||||
parameters: {},
|
||||
typeVersion: 1,
|
||||
position: [740, 240],
|
||||
};
|
||||
|
||||
if (options?.withCredential) {
|
||||
node.credentials = {
|
||||
spotifyApi: options.withCredential,
|
||||
};
|
||||
}
|
||||
|
||||
workflow.name = 'My Workflow';
|
||||
workflow.active = false;
|
||||
workflow.connections = {};
|
||||
workflow.nodes = [node];
|
||||
|
||||
if (options?.withPinData) {
|
||||
workflow.pinData = MOCK_PINDATA;
|
||||
}
|
||||
|
||||
return workflow;
|
||||
}
|
||||
|
||||
export const MOCK_PINDATA = { Spotify: [{ json: { myKey: 'myValue' } }] };
|
||||
@@ -0,0 +1,33 @@
|
||||
import type { INodeTypeData } from 'n8n-workflow';
|
||||
|
||||
export function mockNodeTypesData(
|
||||
nodeNames: string[],
|
||||
options?: {
|
||||
addTrigger?: boolean;
|
||||
},
|
||||
) {
|
||||
return nodeNames.reduce<INodeTypeData>((acc, nodeName) => {
|
||||
const fullName = nodeName.indexOf('.') === -1 ? `n8n-nodes-base.${nodeName}` : nodeName;
|
||||
|
||||
return (
|
||||
(acc[fullName] = {
|
||||
sourcePath: '',
|
||||
type: {
|
||||
description: {
|
||||
displayName: nodeName,
|
||||
name: nodeName,
|
||||
group: [],
|
||||
description: '',
|
||||
version: 1,
|
||||
defaults: {},
|
||||
inputs: [],
|
||||
outputs: [],
|
||||
properties: [],
|
||||
},
|
||||
trigger: options?.addTrigger ? async () => undefined : undefined,
|
||||
},
|
||||
}),
|
||||
acc
|
||||
);
|
||||
}, {});
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { TaskRunnersConfig } from '@n8n/config';
|
||||
import { Container } from '@n8n/di';
|
||||
import request from 'supertest';
|
||||
import type TestAgent from 'supertest/lib/agent';
|
||||
|
||||
import { TaskBrokerServer } from '@/task-runners/task-broker/task-broker-server';
|
||||
|
||||
export interface TestTaskBrokerServer {
|
||||
server: TaskBrokerServer;
|
||||
agent: TestAgent;
|
||||
config: TaskRunnersConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a Task Broker Server for testing purposes. The server needs
|
||||
* to be started and stopped manually.
|
||||
*
|
||||
* @example
|
||||
* const { server, agent, config } = setupBrokerTestServer();
|
||||
*
|
||||
* beforeAll(async () => await server.start());
|
||||
* afterAll(async () => await server.stop());
|
||||
*/
|
||||
export const setupBrokerTestServer = (
|
||||
config: Partial<TaskRunnersConfig> = {},
|
||||
): TestTaskBrokerServer => {
|
||||
const runnerConfig = Container.get(TaskRunnersConfig);
|
||||
Object.assign(runnerConfig, config);
|
||||
runnerConfig.enabled = true;
|
||||
runnerConfig.port = 0; // Use any port
|
||||
|
||||
const taskBrokerServer = Container.get(TaskBrokerServer);
|
||||
const agent = request.agent(taskBrokerServer.app);
|
||||
|
||||
return {
|
||||
server: taskBrokerServer,
|
||||
agent,
|
||||
config: runnerConfig,
|
||||
};
|
||||
};
|
||||
39
n8n-n8n-1.109.2/packages/cli/test/integration/shared/utils/test-command.ts
Executable file
39
n8n-n8n-1.109.2/packages/cli/test/integration/shared/utils/test-command.ts
Executable file
@@ -0,0 +1,39 @@
|
||||
import { testDb, mockInstance } from '@n8n/backend-test-utils';
|
||||
import type { CommandClass } from '@n8n/decorators';
|
||||
import argvParser from 'yargs-parser';
|
||||
|
||||
import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus';
|
||||
import { TelemetryEventRelay } from '@/events/relays/telemetry.event-relay';
|
||||
|
||||
mockInstance(MessageEventBus);
|
||||
|
||||
export const setupTestCommand = <T extends CommandClass>(Command: T) => {
|
||||
// mock SIGINT/SIGTERM registration
|
||||
process.once = jest.fn();
|
||||
process.exit = jest.fn() as never;
|
||||
|
||||
beforeAll(async () => {
|
||||
await testDb.init();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
mockInstance(TelemetryEventRelay);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await testDb.terminate();
|
||||
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
const run = async (argv: string[] = []) => {
|
||||
const command = new Command();
|
||||
command.flags = argvParser(argv);
|
||||
await command.init?.();
|
||||
await command.run();
|
||||
return command;
|
||||
};
|
||||
|
||||
return { run };
|
||||
};
|
||||
334
n8n-n8n-1.109.2/packages/cli/test/integration/shared/utils/test-server.ts
Executable file
334
n8n-n8n-1.109.2/packages/cli/test/integration/shared/utils/test-server.ts
Executable file
@@ -0,0 +1,334 @@
|
||||
import { LicenseState, ModuleRegistry } from '@n8n/backend-common';
|
||||
import { mockInstance, mockLogger, testModules, testDb } from '@n8n/backend-test-utils';
|
||||
import { GlobalConfig } from '@n8n/config';
|
||||
import type { APIRequest, User } from '@n8n/db';
|
||||
import { Container } from '@n8n/di';
|
||||
import cookieParser from 'cookie-parser';
|
||||
import express from 'express';
|
||||
import type superagent from 'superagent';
|
||||
import request from 'supertest';
|
||||
import { URL } from 'url';
|
||||
|
||||
import { AuthService } from '@/auth/auth.service';
|
||||
import config from '@/config';
|
||||
import { AUTH_COOKIE_NAME } from '@/constants';
|
||||
import { ControllerRegistry } from '@/controller.registry';
|
||||
import { License } from '@/license';
|
||||
import { rawBodyReader, bodyParser } from '@/middlewares';
|
||||
import { PostHogClient } from '@/posthog';
|
||||
import { Push } from '@/push';
|
||||
import { Telemetry } from '@/telemetry';
|
||||
import { LicenseMocker } from '@test-integration/license';
|
||||
|
||||
import { PUBLIC_API_REST_PATH_SEGMENT, REST_PATH_SEGMENT } from '../constants';
|
||||
import type { SetupProps, TestServer } from '../types';
|
||||
|
||||
/**
|
||||
* Plugin to prefix a path segment into a request URL pathname.
|
||||
*
|
||||
* Example: http://127.0.0.1:62100/me/password → http://127.0.0.1:62100/rest/me/password
|
||||
*/
|
||||
function prefix(pathSegment: string) {
|
||||
return async function (request: superagent.SuperAgentRequest) {
|
||||
const url = new URL(request.url);
|
||||
|
||||
// enforce consistency at call sites
|
||||
if (url.pathname[0] !== '/') {
|
||||
throw new Error('Pathname must start with a forward slash');
|
||||
}
|
||||
|
||||
url.pathname = pathSegment + url.pathname;
|
||||
request.url = url.toString();
|
||||
return await request;
|
||||
};
|
||||
}
|
||||
|
||||
const browserId = 'test-browser-id';
|
||||
function createAgent(
|
||||
app: express.Application,
|
||||
options?: { auth: boolean; user?: User; noRest?: boolean },
|
||||
) {
|
||||
const agent = request.agent(app);
|
||||
|
||||
const withRestSegment = !options?.noRest;
|
||||
|
||||
if (withRestSegment) void agent.use(prefix(REST_PATH_SEGMENT));
|
||||
|
||||
if (options?.auth && options?.user) {
|
||||
const token = Container.get(AuthService).issueJWT(
|
||||
options.user,
|
||||
options.user.mfaEnabled,
|
||||
browserId,
|
||||
);
|
||||
agent.jar.setCookie(`${AUTH_COOKIE_NAME}=${token}`);
|
||||
}
|
||||
return agent;
|
||||
}
|
||||
|
||||
const userDoesNotHaveApiKey = (user: User) => {
|
||||
return !user.apiKeys || !Array.from(user.apiKeys) || user.apiKeys.length === 0;
|
||||
};
|
||||
|
||||
const publicApiAgent = (
|
||||
app: express.Application,
|
||||
{ user, apiKey, version = 1 }: { user?: User; apiKey?: string; version?: number },
|
||||
) => {
|
||||
if (user && apiKey) {
|
||||
throw new Error('Cannot provide both user and API key');
|
||||
}
|
||||
|
||||
if (user && userDoesNotHaveApiKey(user)) {
|
||||
throw new Error('User does not have an API key');
|
||||
}
|
||||
|
||||
const agentApiKey = apiKey ?? user?.apiKeys[0].apiKey;
|
||||
|
||||
const agent = request.agent(app);
|
||||
void agent.use(prefix(`${PUBLIC_API_REST_PATH_SEGMENT}/v${version}`));
|
||||
if (!user && !apiKey) return agent;
|
||||
void agent.set({ 'X-N8N-API-KEY': agentApiKey });
|
||||
return agent;
|
||||
};
|
||||
|
||||
export const setupTestServer = ({
|
||||
endpointGroups,
|
||||
enabledFeatures,
|
||||
quotas,
|
||||
modules,
|
||||
}: SetupProps): TestServer => {
|
||||
const app = express();
|
||||
app.use(rawBodyReader);
|
||||
app.use(cookieParser());
|
||||
app.set('query parser', 'extended');
|
||||
app.use((req: APIRequest, _, next) => {
|
||||
req.browserId = browserId;
|
||||
next();
|
||||
});
|
||||
|
||||
// Mock all telemetry and logging
|
||||
mockLogger();
|
||||
mockInstance(PostHogClient);
|
||||
mockInstance(Push);
|
||||
mockInstance(Telemetry);
|
||||
|
||||
const testServer: TestServer = {
|
||||
app,
|
||||
httpServer: app.listen(0),
|
||||
authAgentFor: (user: User) => createAgent(app, { auth: true, user }),
|
||||
authlessAgent: createAgent(app),
|
||||
restlessAgent: createAgent(app, { auth: false, noRest: true }),
|
||||
publicApiAgentFor: (user) => publicApiAgent(app, { user }),
|
||||
publicApiAgentWithApiKey: (apiKey) => publicApiAgent(app, { apiKey }),
|
||||
publicApiAgentWithoutApiKey: () => publicApiAgent(app, {}),
|
||||
license: new LicenseMocker(),
|
||||
};
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
beforeAll(async () => {
|
||||
if (modules) await testModules.loadModules(modules);
|
||||
await testDb.init();
|
||||
|
||||
Container.get(GlobalConfig).userManagement.jwtSecret = 'My JWT secret';
|
||||
config.set('userManagement.isInstanceOwnerSetUp', true);
|
||||
|
||||
testServer.license.mock(Container.get(License));
|
||||
testServer.license.mockLicenseState(Container.get(LicenseState));
|
||||
|
||||
if (enabledFeatures) {
|
||||
testServer.license.setDefaults({
|
||||
features: enabledFeatures,
|
||||
quotas,
|
||||
});
|
||||
}
|
||||
|
||||
if (!endpointGroups) return;
|
||||
|
||||
app.use(bodyParser);
|
||||
|
||||
const enablePublicAPI = endpointGroups?.includes('publicApi');
|
||||
if (enablePublicAPI) {
|
||||
const { loadPublicApiVersions } = await import('@/public-api');
|
||||
const { apiRouters } = await loadPublicApiVersions(PUBLIC_API_REST_PATH_SEGMENT);
|
||||
app.use(...apiRouters);
|
||||
}
|
||||
|
||||
if (endpointGroups?.includes('health')) {
|
||||
app.get('/healthz/readiness', async (_req, res) => {
|
||||
testDb.isReady()
|
||||
? res.status(200).send({ status: 'ok' })
|
||||
: res.status(503).send({ status: 'error' });
|
||||
});
|
||||
}
|
||||
if (endpointGroups.length) {
|
||||
for (const group of endpointGroups) {
|
||||
switch (group) {
|
||||
case 'annotationTags':
|
||||
await import('@/controllers/annotation-tags.controller.ee');
|
||||
break;
|
||||
|
||||
case 'credentials':
|
||||
await import('@/credentials/credentials.controller');
|
||||
break;
|
||||
|
||||
case 'workflows':
|
||||
await import('@/workflows/workflows.controller');
|
||||
break;
|
||||
|
||||
case 'executions':
|
||||
await import('@/executions/executions.controller');
|
||||
break;
|
||||
|
||||
case 'variables':
|
||||
await import('@/environments.ee/variables/variables.controller.ee');
|
||||
break;
|
||||
|
||||
case 'license':
|
||||
await import('@/license/license.controller');
|
||||
break;
|
||||
|
||||
case 'metrics': {
|
||||
const { PrometheusMetricsService } = await import(
|
||||
'@/metrics/prometheus-metrics.service'
|
||||
);
|
||||
await Container.get(PrometheusMetricsService).init(app);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'eventBus':
|
||||
await import('@/eventbus/event-bus.controller');
|
||||
break;
|
||||
|
||||
case 'auth':
|
||||
await import('@/controllers/auth.controller');
|
||||
break;
|
||||
|
||||
case 'oauth2':
|
||||
await import('@/controllers/oauth/oauth2-credential.controller');
|
||||
break;
|
||||
|
||||
case 'mfa':
|
||||
await import('@/controllers/mfa.controller');
|
||||
break;
|
||||
|
||||
case 'ldap': {
|
||||
const { LdapService } = await import('@/ldap.ee/ldap.service.ee');
|
||||
await import('@/ldap.ee/ldap.controller.ee');
|
||||
testServer.license.enable('feat:ldap');
|
||||
await Container.get(LdapService).init();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'saml': {
|
||||
const { SamlService } = await import('@/sso.ee/saml/saml.service.ee');
|
||||
await Container.get(SamlService).init();
|
||||
await import('@/sso.ee/saml/routes/saml.controller.ee');
|
||||
const { setSamlLoginEnabled } = await import('@/sso.ee/saml/saml-helpers');
|
||||
await setSamlLoginEnabled(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'sourceControl':
|
||||
await import('@/environments.ee/source-control/source-control.controller.ee');
|
||||
break;
|
||||
|
||||
case 'community-packages':
|
||||
await import('@/modules/community-packages/community-packages.controller');
|
||||
break;
|
||||
|
||||
case 'me':
|
||||
await import('@/controllers/me.controller');
|
||||
break;
|
||||
|
||||
case 'passwordReset':
|
||||
await import('@/controllers/password-reset.controller');
|
||||
break;
|
||||
|
||||
case 'owner':
|
||||
await import('@/controllers/owner.controller');
|
||||
break;
|
||||
|
||||
case 'users':
|
||||
await import('@/controllers/users.controller');
|
||||
break;
|
||||
|
||||
case 'invitations':
|
||||
await import('@/controllers/invitation.controller');
|
||||
break;
|
||||
|
||||
case 'tags':
|
||||
await import('@/controllers/tags.controller');
|
||||
break;
|
||||
|
||||
case 'workflowHistory':
|
||||
await import('@/workflows/workflow-history.ee/workflow-history.controller.ee');
|
||||
break;
|
||||
|
||||
case 'binaryData':
|
||||
await import('@/controllers/binary-data.controller');
|
||||
break;
|
||||
|
||||
case 'debug':
|
||||
await import('@/controllers/debug.controller');
|
||||
break;
|
||||
|
||||
case 'project':
|
||||
await import('@/controllers/project.controller');
|
||||
break;
|
||||
|
||||
case 'role':
|
||||
await import('@/controllers/role.controller');
|
||||
break;
|
||||
|
||||
case 'dynamic-node-parameters':
|
||||
await import('@/controllers/dynamic-node-parameters.controller');
|
||||
break;
|
||||
|
||||
case 'apiKeys':
|
||||
await import('@/controllers/api-keys.controller');
|
||||
break;
|
||||
|
||||
case 'evaluation':
|
||||
await import('@/evaluation.ee/test-runs.controller.ee');
|
||||
break;
|
||||
|
||||
case 'ai':
|
||||
await import('@/controllers/ai.controller');
|
||||
break;
|
||||
case 'folder':
|
||||
await import('@/controllers/folder.controller');
|
||||
break;
|
||||
|
||||
case 'externalSecrets':
|
||||
await import('@/modules/external-secrets.ee/external-secrets.module');
|
||||
break;
|
||||
|
||||
case 'insights':
|
||||
await import('@/modules/insights/insights.module');
|
||||
break;
|
||||
|
||||
case 'data-store':
|
||||
await import('@/modules/data-store/data-store.module');
|
||||
break;
|
||||
|
||||
case 'module-settings':
|
||||
await import('@/controllers/module-settings.controller');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await Container.get(ModuleRegistry).initModules();
|
||||
Container.get(ControllerRegistry).activate(app);
|
||||
}
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await testDb.terminate();
|
||||
testServer.httpServer.close();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
testServer.license.reset();
|
||||
});
|
||||
|
||||
return testServer;
|
||||
};
|
||||
21
n8n-n8n-1.109.2/packages/cli/test/integration/shared/utils/users.ts
Executable file
21
n8n-n8n-1.109.2/packages/cli/test/integration/shared/utils/users.ts
Executable file
@@ -0,0 +1,21 @@
|
||||
import type { User, PublicUser } from '@n8n/db';
|
||||
|
||||
export const validateUser = (user: PublicUser) => {
|
||||
expect(typeof user.id).toBe('string');
|
||||
expect(user.email).toBeDefined();
|
||||
expect(user.firstName).toBeDefined();
|
||||
expect(user.lastName).toBeDefined();
|
||||
expect(typeof user.isOwner).toBe('boolean');
|
||||
expect(user.isPending).toBe(false);
|
||||
expect(user.signInType).toBe('email');
|
||||
expect(user.settings).toBe(null);
|
||||
expect(user.personalizationAnswers).toBeNull();
|
||||
expect(user.password).toBeUndefined();
|
||||
expect(user.role).toBeDefined();
|
||||
expect(typeof (user as any).mfaEnabled).toBe('boolean');
|
||||
};
|
||||
|
||||
export type UserInvitationResult = {
|
||||
user: Pick<User, 'id' | 'email'> & { inviteAcceptUrl: string; emailSent: boolean };
|
||||
error?: string;
|
||||
};
|
||||
Reference in New Issue
Block a user