From 03ff2eda4e34b23a940bd90f2a82834bca21aaf0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 08:15:37 +0000 Subject: [PATCH 1/4] Initial plan From 518c13f10db3dbee7b9cebd42062ca4f7afed5a2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 08:19:44 +0000 Subject: [PATCH 2/4] fix: update sveltekit adapter tests to use dispatch() catch-all pattern The sveltekit adapter implementation uses dispatcher.dispatch() for the catch-all route (meta, data, etc.), but the test mocks were using the old handleMetadata/handleData methods that no longer exist in the code path. Updated the mock to include dispatch and aligned test assertions with the unified catch-all pattern used by all other adapters (hono, etc.). Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> Agent-Logs-Url: https://github.com/objectstack-ai/spec/sessions/d30145f6-3528-4e58-baf1-5011e72f43c4 --- .../adapters/sveltekit/src/sveltekit.test.ts | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/packages/adapters/sveltekit/src/sveltekit.test.ts b/packages/adapters/sveltekit/src/sveltekit.test.ts index 21d228820..086e2ddb6 100644 --- a/packages/adapters/sveltekit/src/sveltekit.test.ts +++ b/packages/adapters/sveltekit/src/sveltekit.test.ts @@ -7,9 +7,8 @@ const mockDispatcher = { getDiscoveryInfo: vi.fn().mockReturnValue({ version: '1.0', endpoints: [] }), handleAuth: vi.fn().mockResolvedValue({ handled: true, response: { body: { ok: true }, status: 200 } }), handleGraphQL: vi.fn().mockResolvedValue({ data: {} }), - handleMetadata: vi.fn().mockResolvedValue({ handled: true, response: { body: { objects: [] }, status: 200 } }), - handleData: vi.fn().mockResolvedValue({ handled: true, response: { body: { records: [] }, status: 200 } }), handleStorage: vi.fn().mockResolvedValue({ handled: true, response: { body: {}, status: 200 } }), + dispatch: vi.fn().mockResolvedValue({ handled: true, response: { body: { success: true }, status: 200 } }), }; vi.mock('@objectstack/runtime', () => { @@ -167,27 +166,29 @@ describe('createRequestHandler', () => { }); describe('Metadata', () => { - it('GET /api/meta/objects calls handleMetadata', async () => { + it('GET /api/meta/objects delegates to dispatch()', async () => { const event = makeEvent('http://localhost/api/meta/objects'); const res = await handler(event); expect(res.status).toBe(200); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( - '/objects', + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( + 'GET', + '/meta/objects', + undefined, + expect.any(Object), expect.objectContaining({ request: expect.anything() }), - 'GET', undefined, ); }); }); describe('Data', () => { - it('GET /api/data/account calls handleData', async () => { + it('GET /api/data/account delegates to dispatch()', async () => { const event = makeEvent('http://localhost/api/data/account'); const res = await handler(event); expect(res.status).toBe(200); - const json = await res.json(); - expect(json.records).toBeDefined(); - expect(mockDispatcher.handleData).toHaveBeenCalledWith( - '/account', 'GET', {}, + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( + 'GET', + '/data/account', + undefined, expect.any(Object), expect.objectContaining({ request: expect.anything() }), ); @@ -198,15 +199,17 @@ describe('createRequestHandler', () => { const event = makeEvent('http://localhost/api/data/account', 'POST', body); const res = await handler(event); expect(res.status).toBe(200); - expect(mockDispatcher.handleData).toHaveBeenCalledWith( - '/account', 'POST', body, + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( + 'POST', + '/data/account', + body, expect.any(Object), expect.objectContaining({ request: expect.anything() }), ); }); it('returns 404 when not handled', async () => { - mockDispatcher.handleData.mockResolvedValueOnce({ handled: false }); + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: false }); const event = makeEvent('http://localhost/api/data/missing'); const res = await handler(event); expect(res.status).toBe(404); @@ -227,13 +230,14 @@ describe('createRequestHandler', () => { describe('Error handling', () => { it('returns 404 for unknown routes', async () => { + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: false }); const event = makeEvent('http://localhost/api/unknown'); const res = await handler(event); expect(res.status).toBe(404); }); it('returns 500 on generic error', async () => { - mockDispatcher.handleData.mockRejectedValueOnce(new Error()); + mockDispatcher.dispatch.mockRejectedValueOnce(new Error()); const event = makeEvent('http://localhost/api/data/account'); const res = await handler(event); expect(res.status).toBe(500); @@ -242,7 +246,7 @@ describe('createRequestHandler', () => { describe('toResponse', () => { it('handles redirect result', async () => { - mockDispatcher.handleData.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, result: { type: 'redirect', url: 'https://example.com' }, }); @@ -253,7 +257,7 @@ describe('createRequestHandler', () => { }); it('handles generic result objects', async () => { - mockDispatcher.handleData.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, result: { foo: 'bar' }, }); From 9d2db914c534bb3076a968347b7f90c601361c77 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 08:21:56 +0000 Subject: [PATCH 3/4] docs: update CHANGELOG with sveltekit adapter test fix Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> Agent-Logs-Url: https://github.com/objectstack-ai/spec/sessions/d30145f6-3528-4e58-baf1-5011e72f43c4 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3172c003a..854488a3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 remains lazy (cold-start only) via `ensureApp()` / `ensureKernel()` in `_kernel.ts`. ### Fixed +- **SvelteKit adapter test failures** — Updated test mock to include `dispatch()` method and + aligned Metadata, Data, Error handling, and toResponse test assertions with the unified + catch-all dispatch pattern used by the implementation and all other adapters (e.g. Hono). + Removed obsolete `handleMetadata`/`handleData` references from the mock. - **Vercel serverless 404 fix** — The previous `api/[...path].ts` path-normalisation fix is now superseded by the Hono adapter migration above. The new `api/index.ts` entrypoint combined with Vercel rewrites (`/api/*` → `/api`) eliminates the routing ambiguity that caused 404s. From e57dd7ee10610d6bb306e362f480b7d96545a323 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 09:07:49 +0000 Subject: [PATCH 4/4] Changes before error encountered Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> Agent-Logs-Url: https://github.com/objectstack-ai/spec/sessions/b4107236-dbb5-4f8e-8fda-054f241adfe7 --- packages/adapters/express/src/express.test.ts | 3 +- packages/adapters/fastify/src/fastify.test.ts | 22 ++-- .../adapters/nestjs/src/__mocks__/runtime.ts | 1 + .../adapters/nestjs/src/metadata-api.test.ts | 106 ++++++++++-------- packages/adapters/nestjs/src/nestjs.test.ts | 18 +-- .../adapters/nextjs/src/metadata-api.test.ts | 71 ++++++------ packages/adapters/nextjs/src/nextjs.test.ts | 55 ++++----- packages/adapters/nuxt/src/nuxt.test.ts | 23 ++-- 8 files changed, 158 insertions(+), 141 deletions(-) diff --git a/packages/adapters/express/src/express.test.ts b/packages/adapters/express/src/express.test.ts index e1a981d10..0fc86574d 100644 --- a/packages/adapters/express/src/express.test.ts +++ b/packages/adapters/express/src/express.test.ts @@ -7,9 +7,8 @@ const mockDispatcher = { getDiscoveryInfo: vi.fn().mockReturnValue({ version: '1.0', endpoints: [] }), handleAuth: vi.fn().mockResolvedValue({ handled: true, response: { body: { ok: true }, status: 200 } }), handleGraphQL: vi.fn().mockResolvedValue({ data: {} }), - handleMetadata: vi.fn().mockResolvedValue({ handled: true, response: { body: { objects: [] }, status: 200 } }), - handleData: vi.fn().mockResolvedValue({ handled: true, response: { body: { records: [] }, status: 200 } }), handleStorage: vi.fn().mockResolvedValue({ handled: true, response: { body: {}, status: 200 } }), + dispatch: vi.fn().mockResolvedValue({ handled: true, response: { body: { success: true }, status: 200 } }), }; vi.mock('@objectstack/runtime', () => { diff --git a/packages/adapters/fastify/src/fastify.test.ts b/packages/adapters/fastify/src/fastify.test.ts index 43f80ac0f..3032fb0b9 100644 --- a/packages/adapters/fastify/src/fastify.test.ts +++ b/packages/adapters/fastify/src/fastify.test.ts @@ -7,9 +7,8 @@ const mockDispatcher = { getDiscoveryInfo: vi.fn().mockReturnValue({ version: '1.0', endpoints: [] }), handleAuth: vi.fn().mockResolvedValue({ handled: true, response: { body: { ok: true }, status: 200 } }), handleGraphQL: vi.fn().mockResolvedValue({ data: {} }), - handleMetadata: vi.fn().mockResolvedValue({ handled: true, response: { body: { objects: [] }, status: 200 } }), - handleData: vi.fn().mockResolvedValue({ handled: true, response: { body: { records: [] }, status: 200 } }), handleStorage: vi.fn().mockResolvedValue({ handled: true, response: { body: {}, status: 200 } }), + dispatch: vi.fn().mockResolvedValue({ handled: true, response: { body: { success: true }, status: 200 } }), }; vi.mock('@objectstack/runtime', () => { @@ -91,13 +90,12 @@ describe('objectStackPlugin', () => { const res = await app.inject({ method: 'GET', url: '/api/meta/objects' }); expect(res.statusCode).toBe(200); - const json = JSON.parse(res.payload); - expect(json.objects).toBeDefined(); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( - '/objects', - expect.objectContaining({ request: expect.anything() }), + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'GET', + '/meta/objects', undefined, + expect.any(Object), + expect.objectContaining({ request: expect.anything() }), ); }); @@ -108,12 +106,10 @@ describe('objectStackPlugin', () => { const res = await app.inject({ method: 'GET', url: '/api/data/account' }); expect(res.statusCode).toBe(200); - const json = JSON.parse(res.payload); - expect(json.records).toBeDefined(); - expect(mockDispatcher.handleData).toHaveBeenCalledWith( - '/account', + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'GET', - {}, + '/data/account', + undefined, expect.any(Object), expect.objectContaining({ request: expect.anything() }), ); @@ -148,7 +144,7 @@ describe('objectStackPlugin', () => { }); it('returns error on exception', async () => { - mockDispatcher.handleData.mockRejectedValueOnce( + mockDispatcher.dispatch.mockRejectedValueOnce( Object.assign(new Error('Forbidden'), { statusCode: 403 }), ); const app = Fastify(); diff --git a/packages/adapters/nestjs/src/__mocks__/runtime.ts b/packages/adapters/nestjs/src/__mocks__/runtime.ts index aa91068dc..3b6d884d3 100644 --- a/packages/adapters/nestjs/src/__mocks__/runtime.ts +++ b/packages/adapters/nestjs/src/__mocks__/runtime.ts @@ -8,6 +8,7 @@ export class HttpDispatcher { handleMetadata = vi.fn().mockResolvedValue({ handled: true, response: { status: 200, body: [] } }); handleData = vi.fn().mockResolvedValue({ handled: true, response: { status: 200, body: [] } }); handleStorage = vi.fn().mockResolvedValue({ handled: true, response: { status: 200, body: {} } }); + dispatch = vi.fn().mockResolvedValue({ handled: true, response: { status: 200, body: { success: true } } }); constructor(_kernel: any) {} } diff --git a/packages/adapters/nestjs/src/metadata-api.test.ts b/packages/adapters/nestjs/src/metadata-api.test.ts index cb333c6df..ce1440c2a 100644 --- a/packages/adapters/nestjs/src/metadata-api.test.ts +++ b/packages/adapters/nestjs/src/metadata-api.test.ts @@ -80,8 +80,8 @@ describe('NestJS Metadata API Integration Tests', () => { describe('CRUD Operations', () => { describe('GET /api/meta/objects — List all objects', () => { - it('dispatches to handleMetadata with correct path', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + it('dispatches to dispatch with correct path', async () => { + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { @@ -100,18 +100,19 @@ describe('NestJS Metadata API Integration Tests', () => { expect(res._status).toBe(200); expect(res._body.data).toHaveLength(2); - expect(service.dispatcher.handleMetadata).toHaveBeenCalledWith( - '/objects', - { request: req }, + expect(service.dispatcher.dispatch).toHaveBeenCalledWith( 'GET', + '/meta/objects', + undefined, undefined, + { request: req }, ); }); }); describe('GET /api/meta/objects/account — Get single object', () => { it('dispatches with item-level path', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { @@ -126,11 +127,12 @@ describe('NestJS Metadata API Integration Tests', () => { await controller.metadata(req, res, undefined); expect(res._body.data.name).toBe('account'); - expect(service.dispatcher.handleMetadata).toHaveBeenCalledWith( - '/objects/account', - { request: req }, + expect(service.dispatcher.dispatch).toHaveBeenCalledWith( 'GET', + '/meta/objects/account', + undefined, undefined, + { request: req }, ); }); }); @@ -139,7 +141,7 @@ describe('NestJS Metadata API Integration Tests', () => { it('dispatches POST with body', async () => { const body = { type: 'object', name: 'project_task', data: { label: 'Task' } }; - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { success: true }, status: 201 }, }); @@ -148,11 +150,12 @@ describe('NestJS Metadata API Integration Tests', () => { await controller.metadata(req, res, body); expect(res._status).toBe(201); - expect(service.dispatcher.handleMetadata).toHaveBeenCalledWith( - '/objects', - { request: req }, + expect(service.dispatcher.dispatch).toHaveBeenCalledWith( 'POST', + '/meta/objects', body, + undefined, + { request: req }, ); }); }); @@ -161,7 +164,7 @@ describe('NestJS Metadata API Integration Tests', () => { it('dispatches PUT with body', async () => { const body = { label: 'Updated Account' }; - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { success: true }, status: 200 }, }); @@ -175,7 +178,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('DELETE /api/meta/objects/old_entity — Delete metadata', () => { it('dispatches DELETE', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { type: 'object', name: 'old_entity' } }, @@ -194,33 +197,36 @@ describe('NestJS Metadata API Integration Tests', () => { it('dispatches for views', async () => { const req = { params: {}, url: '/api/meta/views', method: 'GET' }; await controller.metadata(req, res, undefined); - expect(service.dispatcher.handleMetadata).toHaveBeenCalledWith( - '/views', - { request: req }, + expect(service.dispatcher.dispatch).toHaveBeenCalledWith( 'GET', + '/meta/views', + undefined, undefined, + { request: req }, ); }); it('dispatches for flows', async () => { const req = { params: {}, url: '/api/meta/flows', method: 'GET' }; await controller.metadata(req, res, undefined); - expect(service.dispatcher.handleMetadata).toHaveBeenCalledWith( - '/flows', - { request: req }, + expect(service.dispatcher.dispatch).toHaveBeenCalledWith( 'GET', + '/meta/flows', + undefined, undefined, + { request: req }, ); }); it('dispatches for agents', async () => { const req = { params: {}, url: '/api/meta/agents', method: 'GET' }; await controller.metadata(req, res, undefined); - expect(service.dispatcher.handleMetadata).toHaveBeenCalledWith( - '/agents', - { request: req }, + expect(service.dispatcher.dispatch).toHaveBeenCalledWith( 'GET', + '/meta/agents', + undefined, undefined, + { request: req }, ); }); }); @@ -240,7 +246,7 @@ describe('NestJS Metadata API Integration Tests', () => { pageSize: 25, }; - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { @@ -279,7 +285,7 @@ describe('NestJS Metadata API Integration Tests', () => { ], }; - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { total: 2, succeeded: 2, failed: 0 } }, @@ -300,7 +306,7 @@ describe('NestJS Metadata API Integration Tests', () => { items: [{ type: 'object', name: 'old' }], }; - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { total: 1, succeeded: 1, failed: 0 } }, @@ -317,7 +323,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('Bulk with partial failures', () => { it('returns error details', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { @@ -357,7 +363,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('Overlay / Customization', () => { describe('GET /api/meta/objects/account/overlay — Get overlay', () => { it('dispatches overlay retrieval', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { @@ -389,7 +395,7 @@ describe('NestJS Metadata API Integration Tests', () => { patch: { fields: { status: { label: 'Custom' } } }, }; - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { success: true }, status: 200 }, }); @@ -403,7 +409,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('GET /api/meta/objects/account/effective — Get effective', () => { it('dispatches effective metadata retrieval', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { @@ -429,7 +435,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('Import / Export', () => { describe('POST /api/meta/export — Export metadata', () => { it('dispatches export request', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { version: '1.0', objects: {} } }, @@ -447,7 +453,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('POST /api/meta/import — Import metadata', () => { it('dispatches import request', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { total: 3, imported: 3, skipped: 0, failed: 0 } }, @@ -465,7 +471,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('POST /api/meta/import — Dry run', () => { it('returns preview without saving', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { total: 2, imported: 0, skipped: 0, failed: 0 } }, @@ -489,7 +495,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('Validation', () => { describe('POST /api/meta/validate — Validate metadata', () => { it('dispatches validation for valid payload', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { valid: true } }, @@ -505,7 +511,7 @@ describe('NestJS Metadata API Integration Tests', () => { }); it('returns errors for invalid metadata', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { @@ -536,7 +542,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('Type Registry', () => { describe('GET /api/meta/types — List types', () => { it('returns all types', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: ['object', 'view', 'flow', 'agent'] }, @@ -554,7 +560,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('GET /api/meta/types/object — Get type info', () => { it('returns type metadata', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { @@ -587,7 +593,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('Dependency Tracking', () => { describe('GET /api/meta/objects/account/dependencies', () => { it('returns dependencies', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { @@ -614,7 +620,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('GET /api/meta/objects/account/dependents', () => { it('returns dependents', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { body: { @@ -642,7 +648,7 @@ describe('NestJS Metadata API Integration Tests', () => { describe('Error Handling', () => { it('returns 404 when metadata not found', async () => { - (service.dispatcher.handleMetadata as any).mockResolvedValueOnce({ handled: false }); + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: false }); const req = { params: {}, url: '/api/meta/objects/nonexistent', method: 'GET' }; await controller.metadata(req, res, undefined); @@ -652,7 +658,7 @@ describe('NestJS Metadata API Integration Tests', () => { }); it('returns 500 on dispatcher exception', async () => { - (service.dispatcher.handleMetadata as any).mockRejectedValueOnce(new Error('Internal error')); + (service.dispatcher.dispatch as any).mockRejectedValueOnce(new Error('Internal error')); const req = { params: {}, url: '/api/meta/objects', method: 'GET' }; await controller.metadata(req, res, undefined); @@ -662,7 +668,7 @@ describe('NestJS Metadata API Integration Tests', () => { }); it('returns custom status code from error', async () => { - (service.dispatcher.handleMetadata as any).mockRejectedValueOnce( + (service.dispatcher.dispatch as any).mockRejectedValueOnce( Object.assign(new Error('Forbidden'), { statusCode: 403 }), ); @@ -682,11 +688,12 @@ describe('NestJS Metadata API Integration Tests', () => { const req = { params: {}, url: '/api/meta/objects/account/fields/name', method: 'GET' }; await controller.metadata(req, res, undefined); - expect(service.dispatcher.handleMetadata).toHaveBeenCalledWith( - '/objects/account/fields/name', - { request: req }, + expect(service.dispatcher.dispatch).toHaveBeenCalledWith( 'GET', + '/meta/objects/account/fields/name', + undefined, undefined, + { request: req }, ); }); @@ -694,11 +701,12 @@ describe('NestJS Metadata API Integration Tests', () => { const req = { params: {}, url: '/api/meta/objects?scope=platform', method: 'GET' }; await controller.metadata(req, res, undefined); - expect(service.dispatcher.handleMetadata).toHaveBeenCalledWith( - '/objects', - { request: req }, + expect(service.dispatcher.dispatch).toHaveBeenCalledWith( 'GET', + '/meta/objects', + undefined, undefined, + { request: req }, ); }); }); diff --git a/packages/adapters/nestjs/src/nestjs.test.ts b/packages/adapters/nestjs/src/nestjs.test.ts index 6cbe8794a..99763c44a 100644 --- a/packages/adapters/nestjs/src/nestjs.test.ts +++ b/packages/adapters/nestjs/src/nestjs.test.ts @@ -294,26 +294,26 @@ describe('ObjectStackController', () => { }); describe('metadata()', () => { - it('dispatches to handleMetadata with extracted path', async () => { + it('dispatches to dispatch with extracted path', async () => { const req = { params: { 0: '' }, url: '/api/meta/objects', method: 'GET' }; await controller.metadata(req, res, undefined); - expect(service.dispatcher.handleMetadata).toHaveBeenCalledWith( - '/objects', { request: req }, 'GET', undefined, + expect(service.dispatcher.dispatch).toHaveBeenCalledWith( + 'GET', '/meta/objects', undefined, undefined, { request: req }, ); }); }); describe('data()', () => { - it('dispatches to handleData with extracted path', async () => { + it('dispatches to dispatch with extracted path', async () => { const req = { params: { 0: '' }, url: '/api/data/account', method: 'GET' }; const query = { limit: '10' }; await controller.data(req, res, {}, query); - expect(service.dispatcher.handleData).toHaveBeenCalledWith( - '/account', 'GET', {}, query, { request: req }, + expect(service.dispatcher.dispatch).toHaveBeenCalledWith( + 'GET', '/data/account', {}, query, { request: req }, ); }); }); @@ -342,7 +342,7 @@ describe('ObjectStackController', () => { }); it('sets custom headers from response', async () => { - (service.dispatcher.handleData as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, response: { status: 201, body: { id: 1 }, headers: { 'X-Custom': 'yes' } }, }); @@ -386,7 +386,7 @@ describe('ObjectStackController', () => { }); it('handles generic result objects with 200 status', async () => { - (service.dispatcher.handleData as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, result: { foo: 'bar' }, }); @@ -400,7 +400,7 @@ describe('ObjectStackController', () => { it('handles Response-like objects', async () => { const mockHeaders = new Map([['content-type', 'text/plain']]); - (service.dispatcher.handleData as any).mockResolvedValueOnce({ + (service.dispatcher.dispatch as any).mockResolvedValueOnce({ handled: true, result: { status: 203, diff --git a/packages/adapters/nextjs/src/metadata-api.test.ts b/packages/adapters/nextjs/src/metadata-api.test.ts index 6a38efbf3..c1379bfbe 100644 --- a/packages/adapters/nextjs/src/metadata-api.test.ts +++ b/packages/adapters/nextjs/src/metadata-api.test.ts @@ -19,6 +19,7 @@ const mockDispatcher = { handleMetadata: vi.fn().mockResolvedValue({ handled: true, response: { body: { success: true }, status: 200 } }), handleData: vi.fn().mockResolvedValue({ handled: true, response: { body: { records: [] }, status: 200 } }), handleStorage: vi.fn().mockResolvedValue({ handled: true, response: { body: {}, status: 200 } }), + dispatch: vi.fn().mockResolvedValue({ handled: true, response: { body: { success: true }, status: 200 } }), }; vi.mock('@objectstack/runtime', () => { @@ -106,8 +107,8 @@ describe('Next.js Metadata API Integration Tests', () => { describe('CRUD Operations', () => { describe('GET meta/objects — List all objects', () => { - it('dispatches to handleMetadata with correct path', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + it('dispatches to dispatch with correct path', async () => { + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { @@ -125,7 +126,7 @@ describe('Next.js Metadata API Integration Tests', () => { const res = await handler(req, { params: { objectstack: ['meta', 'objects'] } }); expect(res.status).toBe(200); expect(res.body.data).toHaveLength(2); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'objects', expect.objectContaining({ request: expect.anything() }), 'GET', @@ -135,8 +136,8 @@ describe('Next.js Metadata API Integration Tests', () => { }); describe('GET meta/objects/account — Get single object', () => { - it('dispatches to handleMetadata with item-level path', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + it('dispatches to dispatch with item-level path', async () => { + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { @@ -151,7 +152,7 @@ describe('Next.js Metadata API Integration Tests', () => { const res = await handler(req, { params: { objectstack: ['meta', 'objects', 'account'] } }); expect(res.status).toBe(200); expect(res.body.data.name).toBe('account'); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'objects/account', expect.objectContaining({ request: expect.anything() }), 'GET', @@ -168,7 +169,7 @@ describe('Next.js Metadata API Integration Tests', () => { data: { label: 'Project Task', fields: {} }, }; - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { success: true }, status: 201 }, }); @@ -176,7 +177,7 @@ describe('Next.js Metadata API Integration Tests', () => { const req = makeReq('http://localhost/api/meta/objects', 'POST', body); const res = await handler(req, { params: { objectstack: ['meta', 'objects'] } }); expect(res.status).toBe(201); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'objects', expect.objectContaining({ request: expect.anything() }), 'POST', @@ -189,7 +190,7 @@ describe('Next.js Metadata API Integration Tests', () => { it('dispatches PUT with JSON body', async () => { const body = { label: 'Updated Account' }; - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { success: true }, status: 200 }, }); @@ -197,7 +198,7 @@ describe('Next.js Metadata API Integration Tests', () => { const req = makeReq('http://localhost/api/meta/objects/account', 'PUT', body); const res = await handler(req, { params: { objectstack: ['meta', 'objects', 'account'] } }); expect(res.status).toBe(200); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'objects/account', expect.objectContaining({ request: expect.anything() }), 'PUT', @@ -207,8 +208,8 @@ describe('Next.js Metadata API Integration Tests', () => { }); describe('DELETE meta/objects/old_entity — Delete metadata', () => { - it('dispatches DELETE to handleMetadata', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + it('dispatches DELETE to dispatch', async () => { + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { type: 'object', name: 'old_entity' } }, @@ -227,7 +228,7 @@ describe('Next.js Metadata API Integration Tests', () => { it('dispatches for views', async () => { const req = makeReq('http://localhost/api/meta/views'); await handler(req, { params: { objectstack: ['meta', 'views'] } }); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'views', expect.objectContaining({ request: expect.anything() }), 'GET', @@ -238,7 +239,7 @@ describe('Next.js Metadata API Integration Tests', () => { it('dispatches for flows', async () => { const req = makeReq('http://localhost/api/meta/flows'); await handler(req, { params: { objectstack: ['meta', 'flows'] } }); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'flows', expect.objectContaining({ request: expect.anything() }), 'GET', @@ -249,7 +250,7 @@ describe('Next.js Metadata API Integration Tests', () => { it('dispatches for agents', async () => { const req = makeReq('http://localhost/api/meta/agents'); await handler(req, { params: { objectstack: ['meta', 'agents'] } }); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'agents', expect.objectContaining({ request: expect.anything() }), 'GET', @@ -273,7 +274,7 @@ describe('Next.js Metadata API Integration Tests', () => { pageSize: 25, }; - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { @@ -305,7 +306,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('Bulk Operations', () => { describe('POST meta/bulk/register — Bulk register', () => { it('dispatches bulk register', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { total: 2, succeeded: 2, failed: 0 } }, @@ -328,7 +329,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('POST meta/bulk/unregister — Bulk unregister', () => { it('dispatches bulk unregister', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { total: 2, succeeded: 2, failed: 0 } }, @@ -348,7 +349,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('Bulk operation with partial failures', () => { it('returns error details', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { @@ -387,7 +388,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('Overlay / Customization', () => { describe('GET meta/objects/account/overlay — Get overlay', () => { it('dispatches overlay retrieval', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { @@ -413,7 +414,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('PUT meta/objects/account/overlay — Save overlay', () => { it('dispatches overlay save', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { success: true }, status: 200 }, }); @@ -431,7 +432,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('GET meta/objects/account/effective — Get effective metadata', () => { it('dispatches effective metadata retrieval', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { @@ -457,7 +458,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('Import / Export', () => { describe('POST meta/export — Export metadata', () => { it('dispatches export request', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { version: '1.0', objects: {} } }, @@ -474,7 +475,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('POST meta/import — Import metadata', () => { it('dispatches import request', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { total: 3, imported: 3, skipped: 0, failed: 0 } }, @@ -500,7 +501,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('Validation', () => { describe('POST meta/validate — Validate metadata', () => { it('dispatches validation', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: { valid: true } }, @@ -515,7 +516,7 @@ describe('Next.js Metadata API Integration Tests', () => { }); it('returns errors for invalid metadata', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { @@ -544,7 +545,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('Type Registry', () => { describe('GET meta/types — List types', () => { it('returns all registered types', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { success: true, data: ['object', 'view', 'flow', 'agent'] }, @@ -561,7 +562,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('GET meta/types/object — Get type info', () => { it('returns type metadata', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { @@ -593,7 +594,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('Dependency Tracking', () => { describe('GET meta/objects/account/dependencies — Get dependencies', () => { it('returns dependencies', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { @@ -619,7 +620,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('GET meta/objects/account/dependents — Get dependents', () => { it('returns dependents', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, response: { body: { @@ -647,7 +648,7 @@ describe('Next.js Metadata API Integration Tests', () => { describe('Error Handling', () => { it('returns 404 when metadata not found', async () => { - mockDispatcher.handleMetadata.mockResolvedValueOnce({ handled: false }); + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: false }); const req = makeReq('http://localhost/api/meta/objects/nonexistent'); const res = await handler(req, { params: { objectstack: ['meta', 'objects', 'nonexistent'] } }); @@ -655,7 +656,7 @@ describe('Next.js Metadata API Integration Tests', () => { }); it('returns 500 on dispatcher exception', async () => { - mockDispatcher.handleMetadata.mockRejectedValueOnce(new Error('Internal error')); + mockDispatcher.dispatch.mockRejectedValueOnce(new Error('Internal error')); const req = makeReq('http://localhost/api/meta/objects'); const res = await handler(req, { params: { objectstack: ['meta', 'objects'] } }); @@ -664,7 +665,7 @@ describe('Next.js Metadata API Integration Tests', () => { }); it('returns custom status code from error', async () => { - mockDispatcher.handleMetadata.mockRejectedValueOnce( + mockDispatcher.dispatch.mockRejectedValueOnce( Object.assign(new Error('Forbidden'), { statusCode: 403 }), ); @@ -682,7 +683,7 @@ describe('Next.js Metadata API Integration Tests', () => { it('correctly joins nested segments', async () => { const req = makeReq('http://localhost/api/meta/objects/account/fields/name'); await handler(req, { params: { objectstack: ['meta', 'objects', 'account', 'fields', 'name'] } }); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'objects/account/fields/name', expect.any(Object), 'GET', @@ -694,7 +695,7 @@ describe('Next.js Metadata API Integration Tests', () => { const req = makeReq('http://localhost/api/meta'); // With just ['meta'], subPath becomes empty after slice(1) await handler(req, { params: { objectstack: ['meta'] } }); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( '', expect.any(Object), 'GET', diff --git a/packages/adapters/nextjs/src/nextjs.test.ts b/packages/adapters/nextjs/src/nextjs.test.ts index fa88e3ffe..024c09960 100644 --- a/packages/adapters/nextjs/src/nextjs.test.ts +++ b/packages/adapters/nextjs/src/nextjs.test.ts @@ -10,6 +10,7 @@ const mockDispatcher = { handleMetadata: vi.fn().mockResolvedValue({ handled: true, response: { body: { objects: [] }, status: 200 } }), handleData: vi.fn().mockResolvedValue({ handled: true, response: { body: { records: [] }, status: 200 } }), handleStorage: vi.fn().mockResolvedValue({ handled: true, response: { body: {}, status: 200 } }), + dispatch: vi.fn().mockResolvedValue({ handled: true, response: { body: { success: true }, status: 200 } }), }; vi.mock('@objectstack/runtime', () => { @@ -272,17 +273,17 @@ describe('createRouteHandler', () => { }); describe('Metadata Endpoint', () => { - it('GET meta/objects calls handleMetadata', async () => { + it('GET meta/objects delegates to dispatch()', async () => { const handler = createRouteHandler({ kernel: mockKernel }); const req = makeReq('http://localhost/api/meta/objects', 'GET'); const res = await handler(req, { params: { objectstack: ['meta', 'objects'] } }); expect(res.status).toBe(200); - expect(res.body).toEqual({ objects: [] }); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( - 'objects', - expect.objectContaining({ request: expect.anything() }), + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'GET', + '/meta/objects', undefined, + expect.any(Object), + expect.objectContaining({ request: expect.anything() }), ); }); @@ -292,11 +293,12 @@ describe('createRouteHandler', () => { const req = makeReq('http://localhost/api/meta/objects', 'PUT', body); const res = await handler(req, { params: { objectstack: ['meta', 'objects'] } }); expect(res.status).toBe(200); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( - 'objects', - expect.objectContaining({ request: expect.anything() }), + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'PUT', + '/meta/objects', body, + expect.any(Object), + expect.objectContaining({ request: expect.anything() }), ); }); @@ -306,26 +308,26 @@ describe('createRouteHandler', () => { const req = makeReq('http://localhost/api/meta/objects', 'POST', body); const res = await handler(req, { params: { objectstack: ['meta', 'objects'] } }); expect(res.status).toBe(200); - expect(mockDispatcher.handleMetadata).toHaveBeenCalledWith( - 'objects', - expect.objectContaining({ request: expect.anything() }), + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'POST', + '/meta/objects', body, + expect.any(Object), + expect.objectContaining({ request: expect.anything() }), ); }); }); describe('Data Endpoint', () => { - it('GET data/account calls handleData', async () => { + it('GET data/account delegates to dispatch()', async () => { const handler = createRouteHandler({ kernel: mockKernel }); const req = makeReq('http://localhost/api/data/account', 'GET'); const res = await handler(req, { params: { objectstack: ['data', 'account'] } }); expect(res.status).toBe(200); - expect(res.body).toEqual({ records: [] }); - expect(mockDispatcher.handleData).toHaveBeenCalledWith( - 'account', + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'GET', - {}, + '/data/account', + undefined, expect.any(Object), expect.objectContaining({ request: expect.anything() }), ); @@ -337,9 +339,9 @@ describe('createRouteHandler', () => { const req = makeReq('http://localhost/api/data/account', 'POST', body); const res = await handler(req, { params: { objectstack: ['data', 'account'] } }); expect(res.status).toBe(200); - expect(mockDispatcher.handleData).toHaveBeenCalledWith( - 'account', + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'POST', + '/data/account', body, expect.any(Object), expect.objectContaining({ request: expect.anything() }), @@ -352,9 +354,9 @@ describe('createRouteHandler', () => { const req = makeReq('http://localhost/api/data/account', 'PATCH', body); const res = await handler(req, { params: { objectstack: ['data', 'account'] } }); expect(res.status).toBe(200); - expect(mockDispatcher.handleData).toHaveBeenCalledWith( - 'account', + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( 'PATCH', + '/data/account', body, expect.any(Object), expect.objectContaining({ request: expect.anything() }), @@ -362,7 +364,7 @@ describe('createRouteHandler', () => { }); it('returns 404 when result is not handled', async () => { - mockDispatcher.handleData.mockResolvedValueOnce({ handled: false }); + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: false }); const handler = createRouteHandler({ kernel: mockKernel }); const req = makeReq('http://localhost/api/data/missing', 'GET'); const res = await handler(req, { params: { objectstack: ['data', 'missing'] } }); @@ -401,6 +403,7 @@ describe('createRouteHandler', () => { describe('Error Handling', () => { it('returns 404 for unknown route segments', async () => { + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: false }); const handler = createRouteHandler({ kernel: mockKernel }); const req = makeReq('http://localhost/api/unknown/path', 'GET'); const res = await handler(req, { params: { objectstack: ['unknown', 'path'] } }); @@ -410,7 +413,7 @@ describe('createRouteHandler', () => { }); it('returns 500 with default message on generic error', async () => { - mockDispatcher.handleData.mockRejectedValueOnce(new Error()); + mockDispatcher.dispatch.mockRejectedValueOnce(new Error()); const handler = createRouteHandler({ kernel: mockKernel }); const req = makeReq('http://localhost/api/data/account', 'GET'); const res = await handler(req, { params: { objectstack: ['data', 'account'] } }); @@ -419,7 +422,7 @@ describe('createRouteHandler', () => { }); it('uses custom statusCode from error', async () => { - mockDispatcher.handleData.mockRejectedValueOnce( + mockDispatcher.dispatch.mockRejectedValueOnce( Object.assign(new Error('Forbidden'), { statusCode: 403 }), ); const handler = createRouteHandler({ kernel: mockKernel }); @@ -432,7 +435,7 @@ describe('createRouteHandler', () => { describe('toResponse', () => { it('handles redirect result', async () => { - mockDispatcher.handleData.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, result: { type: 'redirect', url: 'https://example.com' }, }); @@ -444,7 +447,7 @@ describe('createRouteHandler', () => { it('handles stream result', async () => { const stream = 'mock-stream'; - mockDispatcher.handleData.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, result: { type: 'stream', stream, headers: { 'Content-Type': 'text/plain' } }, }); @@ -457,7 +460,7 @@ describe('createRouteHandler', () => { it('returns raw result when handled but no response/redirect/stream', async () => { const rawResult = { type: 'custom', data: 'test' }; - mockDispatcher.handleData.mockResolvedValueOnce({ + mockDispatcher.dispatch.mockResolvedValueOnce({ handled: true, result: rawResult, }); diff --git a/packages/adapters/nuxt/src/nuxt.test.ts b/packages/adapters/nuxt/src/nuxt.test.ts index d9198ef2c..8ca9cc387 100644 --- a/packages/adapters/nuxt/src/nuxt.test.ts +++ b/packages/adapters/nuxt/src/nuxt.test.ts @@ -7,9 +7,8 @@ const mockDispatcher = { getDiscoveryInfo: vi.fn().mockReturnValue({ version: '1.0', endpoints: [] }), handleAuth: vi.fn().mockResolvedValue({ handled: true, response: { body: { ok: true }, status: 200 } }), handleGraphQL: vi.fn().mockResolvedValue({ data: {} }), - handleMetadata: vi.fn().mockResolvedValue({ handled: true, response: { body: { objects: [] }, status: 200 } }), - handleData: vi.fn().mockResolvedValue({ handled: true, response: { body: { records: [] }, status: 200 } }), handleStorage: vi.fn().mockResolvedValue({ handled: true, response: { body: {}, status: 200 } }), + dispatch: vi.fn().mockResolvedValue({ handled: true, response: { body: { success: true }, status: 200 } }), }; vi.mock('@objectstack/runtime', () => { @@ -101,16 +100,26 @@ describe('createH3Router', () => { const app = createTestApp(); const res = await makeRequest(app, '/api/meta/objects'); expect(res.status).toBe(200); - expect(res.body.objects).toBeDefined(); - expect(mockDispatcher.handleMetadata).toHaveBeenCalled(); + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( + 'GET', + '/meta/objects', + undefined, + expect.any(Object), + expect.objectContaining({ request: expect.anything() }), + ); }); it('handles data route', async () => { const app = createTestApp(); const res = await makeRequest(app, '/api/data/account'); expect(res.status).toBe(200); - expect(res.body.records).toBeDefined(); - expect(mockDispatcher.handleData).toHaveBeenCalled(); + expect(mockDispatcher.dispatch).toHaveBeenCalledWith( + 'GET', + '/data/account', + undefined, + expect.any(Object), + expect.objectContaining({ request: expect.anything() }), + ); }); it('handles storage route', async () => { @@ -121,7 +130,7 @@ describe('createH3Router', () => { }); it('handles errors', async () => { - mockDispatcher.handleData.mockRejectedValueOnce( + mockDispatcher.dispatch.mockRejectedValueOnce( Object.assign(new Error('Forbidden'), { statusCode: 403 }), ); const app = createTestApp();