mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-16 21:19:43 +02:00
fix(core): Isolate instance settings writes (no-changelog) (#39118)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
parent
30b3226101
commit
898480070f
|
|
@ -45,6 +45,9 @@ throw new UnexpectedError('message', { extra: { context } });
|
|||
**Testing:**
|
||||
- Vitest (unit), Playwright (E2E)
|
||||
- Mock external dependencies
|
||||
- Keep filesystem tests in a test-owned temporary directory
|
||||
- Set `N8N_USER_FOLDER` before importing settings code
|
||||
- Trace branches activated by mocks and isolate every reachable mutation
|
||||
- Work from package directory: `pushd packages/cli && pnpm test`
|
||||
|
||||
**Database:**
|
||||
|
|
|
|||
|
|
@ -73,6 +73,12 @@ Write a regression test that:
|
|||
- Asserts the CORRECT behavior (test will fail on current code)
|
||||
- Also includes a "happy path" test to prove the setup works
|
||||
|
||||
Complete the test safety gate in `/AGENTS.md` before you run the test:
|
||||
- Trace side effects from imports, constructors, hooks, and mocked branches
|
||||
- Keep filesystem access in a test-owned temporary directory
|
||||
- Set `N8N_USER_FOLDER` before importing modules that resolve it
|
||||
- When a mock changes a state check, inspect and isolate the branch that it activates
|
||||
|
||||
## Step 8: Run and Score
|
||||
|
||||
Run the test from the package directory (e.g., `cd packages/nodes-base && pnpm test <file>`).
|
||||
|
|
|
|||
11
AGENTS.md
11
AGENTS.md
|
|
@ -342,6 +342,17 @@ Testing rules:
|
|||
- Run tests and `pnpm typecheck` from the owning package.
|
||||
- Confirm unit test cases with the user before you write them.
|
||||
- Mock external dependencies. Use `nock` for HTTP services.
|
||||
- Trace side effects from imports, constructors, hooks, and mocked branches before
|
||||
you run a new or changed test.
|
||||
- Do not let tests read from or write to the developer's home directory,
|
||||
`~/.n8n`, or other user-owned locations.
|
||||
- Use a test-owned temporary directory for filesystem tests. Set
|
||||
+ `N8N_USER_FOLDER` before you import modules that resolve it. n8n writes to `${N8N_USER_FOLDER}/.n8n`, so expect the `.n8n` subfolder there.
|
||||
- When a mock changes a state check such as `existsSync()`, inspect the branch
|
||||
that it activates. Mock every reachable filesystem mutation unless filesystem
|
||||
behavior is under test.
|
||||
- Run tests that can initialize n8n settings with an isolated
|
||||
`N8N_USER_FOLDER` first. Clean up only paths that the test created.
|
||||
- Reuse immutable hoisted `mock<T>(...)` fixtures. Do not replace typed entity mocks with `as unknown as T`.
|
||||
- Use `createVitestConfigWithDecorators` for Vitest packages that use `@n8n/di` decorators.
|
||||
- Check for unused computed properties after you change a Pinia store.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ vi.mock('node:fs', async (importActual) => ({
|
|||
...(await importActual()),
|
||||
existsSync: vi.fn().mockReturnValue(false),
|
||||
renameSync: vi.fn(),
|
||||
writeFileSync: vi.fn(),
|
||||
}));
|
||||
|
||||
import { DirectedGraph } from '../partial-execution-utils';
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ vi.mock('node:fs', async (importActual) => ({
|
|||
...(await importActual()),
|
||||
existsSync: vi.fn().mockReturnValue(false),
|
||||
renameSync: vi.fn(),
|
||||
writeFileSync: vi.fn(),
|
||||
}));
|
||||
|
||||
const nodeTypes = Helpers.NodeTypes();
|
||||
|
|
|
|||
|
|
@ -1 +1,23 @@
|
|||
import { mkdtempSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
|
||||
import 'reflect-metadata';
|
||||
|
||||
const originalUserFolder = process.env.N8N_USER_FOLDER;
|
||||
const testUserFolder = mkdtempSync(join(tmpdir(), 'n8n-core-test-'));
|
||||
|
||||
process.env.N8N_USER_FOLDER = testUserFolder;
|
||||
|
||||
afterAll(() => {
|
||||
if (originalUserFolder === undefined) {
|
||||
delete process.env.N8N_USER_FOLDER;
|
||||
} else {
|
||||
process.env.N8N_USER_FOLDER = originalUserFolder;
|
||||
}
|
||||
|
||||
rmSync(testUserFolder, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
// Best-effort cleanup for runs interrupted before afterAll executes (SIGINT/worker kill).
|
||||
process.on('exit', () => rmSync(testUserFolder, { recursive: true, force: true }));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user