build(editor): Reduce per-file module cost in the vitest suite (#38370)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Charlie Kolb 2026-09-28 07:02:43 +00:00 committed by GitHub
parent c5825bcd81
commit 5c6c581b35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 69 additions and 21 deletions

View File

@ -18,7 +18,15 @@ export const createVitestConfig = (options: InlineConfig = {}) => {
// Scoped to `nodes/` because those icons never appear in component
// snapshots (unlike the eagerly-imported `custom/` icons), and to
// `test.alias` so it never leaks into production/dev builds. See svg-stub.ts.
alias: [{ find: /^.*\/nodes\/[^/]+\.svg(\?.*)?$/, replacement: svgStub }],
alias: [
{ find: /^.*\/nodes\/[^/]+\.svg(\?.*)?$/, replacement: svgStub },
// Load `element-plus` from its single-file bundle. Its `es/` entry makes Node evaluate
// ~980 files in every test file (about 0.25 s each); the bundle has the same 432 exports.
// A bare replacement resolves from the importer, so a package without `element-plus`
// is not affected. `vue` stays external to the bundle, so there is one Vue instance.
// `patches/element-plus@2.4.3.patch` applies the same lockscreen guard to this bundle.
{ find: /^element-plus$/, replacement: 'element-plus/dist/index.full.mjs' },
],
silent: true,
globals: true,
// Restore `vi.spyOn` spies to their original implementation before each test, so

View File

@ -3,7 +3,8 @@ import 'fake-indexeddb/auto';
import 'core-js/proposals/set-methods-v2';
import englishBaseText from '@n8n/i18n/locales/en.json';
import { loadLanguage, type LocaleMessages } from '@n8n/i18n';
import { APP_MODALS_ELEMENT_ID } from '@/app/constants';
// Not the `@/app/constants` barrel: it pulls the full `@n8n/api-types` graph into every test file.
import { APP_MODALS_ELEMENT_ID } from '@/app/constants/selectors';
// Global stub for Reka UI Popover components used by N8nPopover.
// Unlike Element+ popover which always renders content regardless of visibility,

View File

@ -14,7 +14,8 @@ import {
createWorkflowDocumentId,
} from '@/app/stores/workflowDocument.store';
vi.mock('@n8n/permissions', () => ({
vi.mock('@n8n/permissions', async (importOriginal) => ({
...(await importOriginal<typeof import('@n8n/permissions')>()),
getResourcePermissions: vi.fn(() => ({
workflow: {
update: true,

View File

@ -67,7 +67,8 @@ vi.mock('@n8n/composables/useToast', () => ({
}),
}));
vi.mock('@n8n/permissions', () => ({
vi.mock('@n8n/permissions', async (importOriginal) => ({
...(await importOriginal<typeof import('@n8n/permissions')>()),
getResourcePermissions: () => ({
workflow: { update: true },
}),

View File

@ -63,7 +63,8 @@ vi.mock('@/features/integrations/sourceControl.ee/sourceControl.store', () => ({
})),
}));
vi.mock('@n8n/permissions', () => ({
vi.mock('@n8n/permissions', async (importOriginal) => ({
...(await importOriginal<typeof import('@n8n/permissions')>()),
getResourcePermissions: vi.fn((scopes: string[] = []) => ({
workflow: {
update: scopes.includes('workflow:update'),

View File

@ -2,6 +2,7 @@ import { flushPromises, mount, type VueWrapper } from '@vue/test-utils';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { AI_GATEWAY_MANAGED_TAG } from '@n8n/api-types';
import type * as permissions from '@n8n/permissions';
import type {
AgentCredentialsByProvider,
@ -93,7 +94,8 @@ vi.mock('@n8n/i18n', () => ({
}),
}));
vi.mock('@n8n/permissions', () => ({
vi.mock('@n8n/permissions', async (importOriginal) => ({
...(await importOriginal<typeof permissions>()),
getResourcePermissions: () => ({ credential: { create: canCreateCredentials.value } }),
}));

View File

@ -27,7 +27,8 @@ vi.mock('@n8n/stores/useRootStore', () => ({
useRootStore: () => ({ restApiContext: {} }),
}));
vi.mock('@n8n/permissions', () => ({
vi.mock('@n8n/permissions', async (importOriginal) => ({
...(await importOriginal<typeof import('@n8n/permissions')>()),
getResourcePermissions: () => ({ credential: { create: true } }),
}));

View File

@ -54,7 +54,8 @@ vi.mock('@n8n/stores/useRootStore', () => ({
useRootStore: () => ({ restApiContext: {} }),
}));
vi.mock('@n8n/permissions', () => ({
vi.mock('@n8n/permissions', async (importOriginal) => ({
...(await importOriginal<typeof import('@n8n/permissions')>()),
getResourcePermissions: () => ({
credential: { create: true, read: true, update: true, delete: true, share: true, move: true },
}),

View File

@ -62,7 +62,8 @@ vi.mock('@n8n/composables/useTelemetry', () => ({
}),
}));
vi.mock('@n8n/permissions', () => ({
vi.mock('@n8n/permissions', async (importOriginal) => ({
...(await importOriginal<typeof import('@n8n/permissions')>()),
getResourcePermissions: vi.fn(() => ({
workflow: {
update: true,

View File

@ -48,7 +48,8 @@ vi.mock('@/features/shared/nodeCreator/composables/useActionsGeneration', () =>
}),
}));
vi.mock('@n8n/permissions', () => ({
vi.mock('@n8n/permissions', async (importOriginal) => ({
...(await importOriginal<typeof import('@n8n/permissions')>()),
getResourcePermissions: vi.fn(),
}));

View File

@ -67,7 +67,8 @@ vi.mock('@/app/composables/useWorkflowSaving', () => ({
const mockGetResourcePermissions = vi.fn(() => ({
workflow: { share: true },
}));
vi.mock('@n8n/permissions', () => ({
vi.mock('@n8n/permissions', async (importOriginal) => ({
...(await importOriginal<typeof import('@n8n/permissions')>()),
getResourcePermissions: () => mockGetResourcePermissions(),
}));
vi.mock('@n8n/utils/event-bus', () => ({

View File

@ -1,3 +1,16 @@
diff --git a/dist/index.full.mjs b/dist/index.full.mjs
index 18aa99b6f0473e765efdb8de3a65c7f1cf42b619..47041a2a81f1130f9679082a734d59840fa5f96b 100644
--- a/dist/index.full.mjs
+++ b/dist/index.full.mjs
@@ -9274,6 +9274,8 @@ const useLockscreen = (trigger, options = {}) => {
let bodyWidth = "0";
const cleanup = () => {
setTimeout(() => {
+ // Cherry-pick from https://github.com/element-plus/element-plus/pull/18445
+ if (typeof document === "undefined") return;
removeClass(document == null ? void 0 : document.body, hiddenCls.value);
if (withoutHiddenClass && document) {
document.body.style.width = bodyWidth;
diff --git a/es/hooks/use-lockscreen/index.mjs b/es/hooks/use-lockscreen/index.mjs
--- a/es/hooks/use-lockscreen/index.mjs
+++ b/es/hooks/use-lockscreen/index.mjs

View File

@ -1063,7 +1063,7 @@ patchedDependencies:
assert@2.1.0: a73271b303dca8c10a0c9caf77d2083b52032b6a887227563bee3ce3dbf5e9d2
axios: 149e256a2a7b632497650b32816716ced972ab02a5ab00fbd8a5158a51722c49
bull@4.16.4: a4b6d56db16fe5870646929938466d6a5c668435fd1551bed6a93fffb597ba42
element-plus@2.4.3: 9547bca88969f416e6132b09a48e71a969dce25ee6669c7f1f78d51ce9b80e7c
element-plus@2.4.3: 95b9793afc4529bc887bf7dac437131975e133feb7152dce68aa4b3c9b648aff
ics: 163587ad2fa9bc787ed09cd5e958eace08b4aa8aaca651869e9434ba674e158d
imapflow@1.7.1: 9a2144a656c11ce1dbc8a0400e46e4fb575dc28be8b461e612cecf31be6f8025
lodash@4.18.1: 81ead1b07fc8efda87bd2724dbd876ab49f4a0aa03f96c3770060b2ea47d9e0b
@ -5397,7 +5397,7 @@ importers:
version: 4.17.17
element-plus:
specifier: catalog:frontend
version: 2.4.3(patch_hash=9547bca88969f416e6132b09a48e71a969dce25ee6669c7f1f78d51ce9b80e7c)(vue@3.5.26(typescript@6.0.2))
version: 2.4.3(patch_hash=95b9793afc4529bc887bf7dac437131975e133feb7152dce68aa4b3c9b648aff)(vue@3.5.26(typescript@6.0.2))
pinia:
specifier: catalog:frontend
version: 2.2.4(typescript@6.0.2)(vue@3.5.26(typescript@6.0.2))
@ -5490,7 +5490,7 @@ importers:
version: 3.0.3
element-plus:
specifier: catalog:frontend
version: 2.4.3(patch_hash=9547bca88969f416e6132b09a48e71a969dce25ee6669c7f1f78d51ce9b80e7c)(vue@3.5.26(typescript@6.0.2))
version: 2.4.3(patch_hash=95b9793afc4529bc887bf7dac437131975e133feb7152dce68aa4b3c9b648aff)(vue@3.5.26(typescript@6.0.2))
highlight.js:
specifier: catalog:frontend
version: 11.12.0
@ -6086,7 +6086,7 @@ importers:
version: link:../../../@n8n/utils
element-plus:
specifier: catalog:frontend
version: 2.4.3(patch_hash=9547bca88969f416e6132b09a48e71a969dce25ee6669c7f1f78d51ce9b80e7c)(vue@3.5.26(typescript@6.0.2))
version: 2.4.3(patch_hash=95b9793afc4529bc887bf7dac437131975e133feb7152dce68aa4b3c9b648aff)(vue@3.5.26(typescript@6.0.2))
pinia:
specifier: catalog:frontend
version: 2.2.4(typescript@6.0.2)(vue@3.5.26(typescript@6.0.2))
@ -6484,7 +6484,7 @@ importers:
version: 3.0.3
element-plus:
specifier: catalog:frontend
version: 2.4.3(patch_hash=9547bca88969f416e6132b09a48e71a969dce25ee6669c7f1f78d51ce9b80e7c)(vue@3.5.26(typescript@6.0.2))
version: 2.4.3(patch_hash=95b9793afc4529bc887bf7dac437131975e133feb7152dce68aa4b3c9b648aff)(vue@3.5.26(typescript@6.0.2))
eslint:
specifier: 'catalog:'
version: 9.29.0(jiti@2.6.1)(supports-color@8.1.1)
@ -6721,7 +6721,7 @@ importers:
version: 3.0.3
element-plus:
specifier: catalog:frontend
version: 2.4.3(patch_hash=9547bca88969f416e6132b09a48e71a969dce25ee6669c7f1f78d51ce9b80e7c)(vue@3.5.26(typescript@6.0.2))
version: 2.4.3(patch_hash=95b9793afc4529bc887bf7dac437131975e133feb7152dce68aa4b3c9b648aff)(vue@3.5.26(typescript@6.0.2))
lodash:
specifier: 4.18.1
version: 4.18.1(patch_hash=81ead1b07fc8efda87bd2724dbd876ab49f4a0aa03f96c3770060b2ea47d9e0b)
@ -29326,7 +29326,7 @@ snapshots:
mongodb: 6.21.0(@aws-sdk/credential-providers@3.808.0)(gcp-metadata@5.3.0(supports-color@8.1.1))(socks@2.8.9)
mysql2: 3.23.1(@types/node@20.19.41)
pdf-parse: 2.4.5
pg: 8.21.0(pg-native@3.8.0)
pg: 8.21.0
playwright: 1.62.1
puppeteer: 24.41.0(bufferutil@4.0.9)(supports-color@8.1.1)(typescript@7.0.2)(utf-8-validate@5.0.10)
redis: 4.6.14
@ -36829,7 +36829,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
element-plus@2.4.3(patch_hash=9547bca88969f416e6132b09a48e71a969dce25ee6669c7f1f78d51ce9b80e7c)(vue@3.5.26(typescript@6.0.2)):
element-plus@2.4.3(patch_hash=95b9793afc4529bc887bf7dac437131975e133feb7152dce68aa4b3c9b648aff)(vue@3.5.26(typescript@6.0.2)):
dependencies:
'@ctrl/tinycolor': 3.6.0
'@element-plus/icons-vue': 2.3.1(vue@3.5.26(typescript@6.0.2))
@ -41798,10 +41798,15 @@ snapshots:
libpq: 1.11.0
pg-types: 2.2.0
pg-pool@3.14.0(pg@8.21.0):
pg-pool@3.14.0(pg@8.21.0(pg-native@3.8.0)):
dependencies:
pg: 8.21.0(pg-native@3.8.0)
pg-pool@3.14.0(pg@8.21.0):
dependencies:
pg: 8.21.0
optional: true
pg-promise@11.9.1(pg-native@3.8.0):
dependencies:
assert-options: 0.8.1
@ -41826,13 +41831,24 @@ snapshots:
postgres-date: 1.0.7
postgres-interval: 1.2.0
pg@8.21.0(pg-native@3.8.0):
pg@8.21.0:
dependencies:
pg-connection-string: 2.14.0
pg-pool: 3.14.0(pg@8.21.0)
pg-protocol: 1.15.0
pg-types: 2.2.0
pgpass: 1.0.5
optionalDependencies:
pg-cloudflare: 1.4.0
optional: true
pg@8.21.0(pg-native@3.8.0):
dependencies:
pg-connection-string: 2.14.0
pg-pool: 3.14.0(pg@8.21.0(pg-native@3.8.0))
pg-protocol: 1.15.0
pg-types: 2.2.0
pgpass: 1.0.5
optionalDependencies:
pg-cloudflare: 1.4.0
pg-native: 3.8.0