/** * Unit tests for src/middleware/orgContext.ts */ import { Request, Response, NextFunction } from 'express'; import { Pool } from 'pg'; import { ITokenPayload } from '../../../src/types/index'; // Mock pg Pool jest.mock('pg', () => { const mockQuery = jest.fn(); return { Pool: jest.fn().mockImplementation(() => ({ query: mockQuery })), }; }); import { createOrgContextMiddleware } from '../../../src/middleware/orgContext'; /** Builds a minimal ITokenPayload for test requests. */ function makeUser(overrides: Partial = {}): ITokenPayload { return { sub: 'agent-abc-123', client_id: 'agent-abc-123', scope: 'agents:read', jti: 'jti-001', iat: 1000, exp: 9999999999, ...overrides, }; } describe('createOrgContextMiddleware', () => { let pool: jest.Mocked; let mockQuery: jest.Mock; let next: jest.MockedFunction; const originalDefaultOrgId = process.env['DEFAULT_ORG_ID']; beforeEach(() => { jest.clearAllMocks(); // Get the mocked pool instance and its query function pool = new Pool() as jest.Mocked; mockQuery = pool.query as jest.Mock; mockQuery.mockResolvedValue({ rows: [], rowCount: 0 }); next = jest.fn(); }); afterEach(() => { if (originalDefaultOrgId === undefined) { delete process.env['DEFAULT_ORG_ID']; } else { process.env['DEFAULT_ORG_ID'] = originalDefaultOrgId; } }); it('should set app.organization_id from req.user.organization_id when present', async () => { const middleware = createOrgContextMiddleware(pool); const req = { user: makeUser({ organization_id: 'org_TENANT123' }), } as Request; const res = {} as Response; await middleware(req, res, next); expect(mockQuery).toHaveBeenCalledWith('SET app.organization_id = $1', ['org_TENANT123']); expect(next).toHaveBeenCalledWith(); expect(next).toHaveBeenCalledTimes(1); }); it('should fall back to DEFAULT_ORG_ID env var when req.user has no organization_id', async () => { process.env['DEFAULT_ORG_ID'] = 'org_default_from_env'; const middleware = createOrgContextMiddleware(pool); const req = { user: makeUser({ organization_id: undefined }), } as Request; const res = {} as Response; await middleware(req, res, next); expect(mockQuery).toHaveBeenCalledWith('SET app.organization_id = $1', ['org_default_from_env']); expect(next).toHaveBeenCalledWith(); }); it('should fall back to "org_system" when req.user is absent and DEFAULT_ORG_ID is not set', async () => { delete process.env['DEFAULT_ORG_ID']; const middleware = createOrgContextMiddleware(pool); const req = {} as Request; const res = {} as Response; await middleware(req, res, next); expect(mockQuery).toHaveBeenCalledWith('SET app.organization_id = $1', ['org_system']); expect(next).toHaveBeenCalledWith(); }); it('should fall back to "org_system" when DEFAULT_ORG_ID is not set and user has no organization_id', async () => { delete process.env['DEFAULT_ORG_ID']; const middleware = createOrgContextMiddleware(pool); const req = { user: makeUser({ organization_id: undefined }), } as Request; const res = {} as Response; await middleware(req, res, next); expect(mockQuery).toHaveBeenCalledWith('SET app.organization_id = $1', ['org_system']); expect(next).toHaveBeenCalledWith(); }); it('should call next(err) when pool.query throws', async () => { const dbError = new Error('Database connection failed'); mockQuery.mockRejectedValue(dbError); const middleware = createOrgContextMiddleware(pool); const req = { user: makeUser({ organization_id: 'org_TENANT123' }), } as Request; const res = {} as Response; await middleware(req, res, next); expect(next).toHaveBeenCalledWith(dbError); expect(next).toHaveBeenCalledTimes(1); }); it('should call next(err) with pool error when req.user is absent and pool throws', async () => { const dbError = new Error('Pool exhausted'); mockQuery.mockRejectedValue(dbError); delete process.env['DEFAULT_ORG_ID']; const middleware = createOrgContextMiddleware(pool); const req = {} as Request; const res = {} as Response; await middleware(req, res, next); expect(next).toHaveBeenCalledWith(dbError); }); });