mirror of
https://github.com/n8n-io/n8n.git
synced 2026-06-01 09:17:08 +02:00
test(editor): Prevent jsdom XHR leaks causing Node-22 shard-2 flake (#30732)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
04a31cdfd2
commit
b136dd3de1
|
|
@ -34,9 +34,10 @@ export function setupServer() {
|
|||
// Handle undefined endpoints
|
||||
server.post('/rest/:any', async () => ({}));
|
||||
|
||||
// Reset for everything else
|
||||
server.namespace = '';
|
||||
server.passthrough();
|
||||
// Intentionally no `server.passthrough()` here: in tests we never want
|
||||
// mirage to fall through to the real network. Unmatched requests return
|
||||
// mirage's default 404 in-memory.
|
||||
|
||||
if (server.logging) {
|
||||
console.log('Mirage database');
|
||||
|
|
|
|||
|
|
@ -413,3 +413,20 @@ Object.defineProperty(window, 'speechSynthesis', {
|
|||
});
|
||||
|
||||
loadLanguage('en', englishBaseText as unknown as LocaleMessages);
|
||||
|
||||
// Block jsdom XHRs from making real network requests in tests. Unmocked store
|
||||
// actions used to fire real /rest/* calls; on Node 22 the resulting dual-stack
|
||||
// DNS AggregateError emits via socketErrorListener AFTER the test has finished,
|
||||
// and vitest 4 promotes that to a test-run failure (~22% miss rate on shard 2).
|
||||
// Short-circuiting send() means any unmocked request fails synchronously during
|
||||
// the test instead of racing teardown.
|
||||
XMLHttpRequest.prototype.send = function (this: XMLHttpRequest) {
|
||||
Object.defineProperty(this, 'readyState', { value: 4, configurable: true });
|
||||
Object.defineProperty(this, 'status', { value: 0, configurable: true });
|
||||
Object.defineProperty(this, 'statusText', { value: '', configurable: true });
|
||||
queueMicrotask(() => {
|
||||
this.dispatchEvent(new Event('readystatechange'));
|
||||
this.dispatchEvent(new Event('error'));
|
||||
this.dispatchEvent(new Event('loadend'));
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ describe('WorkflowSettingsVue', () => {
|
|||
// Mock specific store actions that tests assert on
|
||||
workflowsStore.updateWorkflow = vi.fn();
|
||||
workflowsListStore.fetchWorkflow = vi.fn();
|
||||
// Component calls this on mount; avoid a real XHR with stubActions: false.
|
||||
settingsStore.getTimezones = vi.fn().mockResolvedValue({});
|
||||
|
||||
// Create document store on the main pinia (same one the component uses).
|
||||
// With stubActions: false, setSettings and getSettingsSnapshot work normally.
|
||||
|
|
|
|||
|
|
@ -87,6 +87,19 @@ vi.mock('vue-router', async (importOriginal) => ({
|
|||
}),
|
||||
}));
|
||||
|
||||
vi.mock('@/app/api/workflows', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@/app/api/workflows')>();
|
||||
return {
|
||||
...actual,
|
||||
getNewWorkflow: vi.fn().mockResolvedValue({ name: 'New Workflow', settings: {} }),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock('@n8n/rest-api-client/api/workflowHistory', () => ({
|
||||
getWorkflowHistory: vi.fn().mockResolvedValue([]),
|
||||
getWorkflowVersion: vi.fn().mockResolvedValue({ workflow: { nodes: [], connections: {} } }),
|
||||
}));
|
||||
|
||||
import { useCanvasOperations } from '@/app/composables/useCanvasOperations';
|
||||
import * as workflowHelpersModule from '@/app/composables/useWorkflowHelpers';
|
||||
import { GRID_SIZE, PUSH_NODES_OFFSET } from '@/app/utils/nodeViewUtils';
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ import { sourceControlEventBus } from '@/features/integrations/sourceControl.ee/
|
|||
|
||||
vi.mock('@/app/composables/useToast');
|
||||
vi.mock('vue-router');
|
||||
vi.mock('@/app/api/workflow-dependencies', () => ({
|
||||
getResourceDependencyCounts: vi.fn().mockResolvedValue({}),
|
||||
getResourceDependencies: vi.fn().mockResolvedValue({}),
|
||||
}));
|
||||
vi.mock('@/app/composables/useDocumentTitle', () => ({
|
||||
useDocumentTitle: vi.fn(() => ({
|
||||
set: vi.fn(),
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@ vi.mock('@/features/collaboration/projects/composables/useProjectPages', () => (
|
|||
}),
|
||||
}));
|
||||
|
||||
vi.mock('@/app/api/workflow-dependencies', () => ({
|
||||
getResourceDependencyCounts: vi.fn().mockResolvedValue({}),
|
||||
getResourceDependencies: vi.fn().mockResolvedValue({}),
|
||||
}));
|
||||
|
||||
vi.mock('@n8n/i18n', async (importOriginal) => {
|
||||
const actual = await importOriginal();
|
||||
const actualObj = typeof actual === 'object' && actual !== null ? actual : {};
|
||||
|
|
|
|||
|
|
@ -186,6 +186,8 @@ describe('NodeCredentials', () => {
|
|||
renderComponent = createComponentRenderer(NodeCredentials, defaultRenderOptions);
|
||||
|
||||
credentialsStore = mockedStore(useCredentialsStore);
|
||||
// Component triggers this on mount; avoid a real XHR with stubActions: false.
|
||||
credentialsStore.fetchAllCredentials = vi.fn().mockResolvedValue([]);
|
||||
ndvStore = mockedStore(useNDVStore);
|
||||
uiStore = mockedStore(useUIStore);
|
||||
projectsStore = mockedStore(useProjectsStore);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@ vi.mock('@/features/collaboration/projects/projects.api', () => ({
|
|||
getProject: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('@/app/api/workflow-dependencies', () => ({
|
||||
getResourceDependencyCounts: vi.fn().mockResolvedValue({}),
|
||||
getResourceDependencies: vi.fn().mockResolvedValue({}),
|
||||
}));
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user