const { test } = require('node:test'); const assert = require('node:assert'); function withMockFetch(mockFetch, fn) { const original = global.fetch; global.fetch = mockFetch; return fn().finally(() => { global.fetch = original; }); } test('listFolders calls /projects/{projectId}/folders with the API key header', async () => { process.env.N8N_BASE_URL = 'https://n8n.test'; process.env.N8N_API_KEY = 'test-key'; delete require.cache[require.resolve('../src/n8nClient')]; const { listFolders } = require('../src/n8nClient'); await withMockFetch(async (url, options) => { const parsed = new URL(url); assert.strictEqual(parsed.pathname, '/api/v1/projects/proj-1/folders'); assert.strictEqual(options.headers['X-N8N-API-KEY'], 'test-key'); return { ok: true, json: async () => ({ data: [{ id: 'f1', name: 'フォルダA', parentFolderId: null }] }) }; }, async () => { const folders = await listFolders('proj-1'); assert.deepStrictEqual(folders, [{ id: 'f1', name: 'フォルダA', parentFolderId: null }]); }); }); test('listWorkflows calls /workflows and returns the data array', async () => { process.env.N8N_BASE_URL = 'https://n8n.test'; process.env.N8N_API_KEY = 'test-key'; delete require.cache[require.resolve('../src/n8nClient')]; const { listWorkflows } = require('../src/n8nClient'); await withMockFetch(async (url) => { const parsed = new URL(url); assert.strictEqual(parsed.pathname, '/api/v1/workflows'); return { ok: true, json: async () => ({ data: [{ id: 'w1', name: 'ワークフローA', active: true, parentFolder: null }] }), }; }, async () => { const workflows = await listWorkflows(); assert.deepStrictEqual(workflows, [{ id: 'w1', name: 'ワークフローA', active: true, parentFolder: null }]); }); }); test('listExecutions passes workflowId and status as query params', async () => { process.env.N8N_BASE_URL = 'https://n8n.test'; process.env.N8N_API_KEY = 'test-key'; delete require.cache[require.resolve('../src/n8nClient')]; const { listExecutions } = require('../src/n8nClient'); await withMockFetch(async (url) => { const parsed = new URL(url); assert.strictEqual(parsed.pathname, '/api/v1/executions'); assert.strictEqual(parsed.searchParams.get('workflowId'), 'w1'); assert.strictEqual(parsed.searchParams.get('status'), 'error'); assert.strictEqual(parsed.searchParams.get('limit'), '20'); return { ok: true, json: async () => ({ data: [{ id: 'e1', status: 'error' }] }) }; }, async () => { const executions = await listExecutions('w1', { status: 'error', limit: 20 }); assert.deepStrictEqual(executions, [{ id: 'e1', status: 'error' }]); }); }); test('listExecutions omits status param when not given', async () => { process.env.N8N_BASE_URL = 'https://n8n.test'; process.env.N8N_API_KEY = 'test-key'; delete require.cache[require.resolve('../src/n8nClient')]; const { listExecutions } = require('../src/n8nClient'); await withMockFetch(async (url) => { const parsed = new URL(url); assert.strictEqual(parsed.searchParams.has('status'), false); return { ok: true, json: async () => ({ data: [] }) }; }, async () => { await listExecutions('w1', { limit: 20 }); }); }); test('getExecution requests includeData=true when asked and returns the execution', async () => { process.env.N8N_BASE_URL = 'https://n8n.test'; process.env.N8N_API_KEY = 'test-key'; delete require.cache[require.resolve('../src/n8nClient')]; const { getExecution } = require('../src/n8nClient'); await withMockFetch(async (url) => { const parsed = new URL(url); assert.strictEqual(parsed.pathname, '/api/v1/executions/e1'); assert.strictEqual(parsed.searchParams.get('includeData'), 'true'); return { ok: true, json: async () => ({ id: 'e1', status: 'success', data: {} }) }; }, async () => { const execution = await getExecution('e1', true); assert.deepStrictEqual(execution, { id: 'e1', status: 'success', data: {} }); }); }); test('n8n client throws when the response is not ok', async () => { process.env.N8N_BASE_URL = 'https://n8n.test'; process.env.N8N_API_KEY = 'test-key'; delete require.cache[require.resolve('../src/n8nClient')]; const { listWorkflows } = require('../src/n8nClient'); await withMockFetch(async () => ({ ok: false, status: 401 }), async () => { await assert.rejects(() => listWorkflows(), /401/); }); });