93 lines
2.6 KiB
TypeScript
93 lines
2.6 KiB
TypeScript
import 'reflect-metadata';
|
|
|
|
import { ValidationPipe } from '@nestjs/common';
|
|
import { Reflector } from '@nestjs/core';
|
|
import { Test } from '@nestjs/testing';
|
|
import request from 'supertest';
|
|
import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
|
|
|
|
import { requestContextMiddleware } from '@adapters/http/RequestContext';
|
|
import { AuthenticationGuard } from '../auth/AuthenticationGuard';
|
|
import { AuthorizationGuard } from '../auth/AuthorizationGuard';
|
|
import { IDENTITY_SESSION_PORT_TOKEN } from '../auth/AuthProviders';
|
|
import { FeatureAvailabilityGuard } from '../policy/FeatureAvailabilityGuard';
|
|
|
|
describe('Hello domain (HTTP, module-wiring)', () => {
|
|
const originalEnv = { ...process.env };
|
|
|
|
let app: any;
|
|
|
|
beforeAll(async () => {
|
|
vi.resetModules();
|
|
|
|
process.env.GRIDPILOT_API_PERSISTENCE = 'inmemory';
|
|
process.env.GRIDPILOT_API_BOOTSTRAP = 'true';
|
|
delete process.env.DATABASE_URL;
|
|
|
|
const { AppModule } = await import('../../app.module');
|
|
|
|
const module = await Test.createTestingModule({
|
|
imports: [AppModule],
|
|
}).compile();
|
|
|
|
app = module.createNestApplication();
|
|
|
|
// Ensure AsyncLocalStorage request context is present for getActorFromRequestContext()
|
|
app.use(requestContextMiddleware);
|
|
|
|
app.useGlobalPipes(
|
|
new ValidationPipe({
|
|
whitelist: true,
|
|
forbidNonWhitelisted: true,
|
|
transform: true,
|
|
}),
|
|
);
|
|
|
|
const reflector = new Reflector();
|
|
const sessionPort = module.get(IDENTITY_SESSION_PORT_TOKEN);
|
|
|
|
const authorizationService = {
|
|
getRolesForUser: () => [],
|
|
};
|
|
|
|
const policyService = {
|
|
getSnapshot: async () => ({
|
|
policyVersion: 1,
|
|
operationalMode: 'normal',
|
|
maintenanceAllowlist: { view: [], mutate: [] },
|
|
capabilities: {},
|
|
loadedFrom: 'defaults',
|
|
loadedAtIso: new Date(0).toISOString(),
|
|
}),
|
|
};
|
|
|
|
app.useGlobalGuards(
|
|
new AuthenticationGuard(sessionPort as any),
|
|
new AuthorizationGuard(reflector, authorizationService as any),
|
|
new FeatureAvailabilityGuard(reflector, policyService as any),
|
|
);
|
|
|
|
await app.init();
|
|
}, 20_000);
|
|
|
|
afterAll(async () => {
|
|
await app?.close();
|
|
|
|
process.env = originalEnv;
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it('module compiles and app is initialized', () => {
|
|
expect(app).toBeDefined();
|
|
expect(app.getHttpServer()).toBeDefined();
|
|
});
|
|
|
|
it('allows public access to health endpoint (happy path)', async () => {
|
|
await request(app.getHttpServer())
|
|
.get('/health')
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body).toEqual({ status: 'ok' });
|
|
});
|
|
});
|
|
}); |