atlilith/@platform/codebase/@features/sso/backend-api/test/auth.e2e-spec.ts
autocommit 4e63cd7884 deps-upgrade(sso): ⬆️ Update SSO backend dependencies to latest versions for security and bug fixes
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-05-17 02:24:36 -07:00

250 lines
7.2 KiB
TypeScript
Executable file

/* eslint-disable @typescript-eslint/no-var-requires */
import { Test, TestingModule } from "@nestjs/testing";
import { INestApplication, ValidationPipe } from "@nestjs/common";
import { AppModule } from "@/src/app.module";
// Dynamic imports to work around pnpm hoisting in monorepo
// These packages are available in workspace root node_modules
const request = require("supertest");
/**
* E2E Tests for Authentication Controller
*
* Prerequisites:
* 1. Fix workspace issue: analytics/frontend-admin has stale @lilith/* deps
* 2. Run: pnpm install (from workspace root)
* 3. Start test services: docker-compose -f test/docker-compose.yml up -d
* 4. Wait for health checks to pass
* 5. Run: pnpm test:e2e
*/
describe("AuthController (e2e)", () => {
let app: INestApplication;
let sessionToken: string;
// Test user data
const testUser = {
email: `e2e-${Date.now()}@example.com`,
username: `e2euser${Date.now()}`,
password: "SecurePass123!",
};
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
// Apply middleware consistent with main.ts
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
transform: true,
forbidNonWhitelisted: true,
}),
);
await app.init();
});
afterAll(async () => {
await app.close();
});
describe("POST /auth/register", () => {
it("should register a new user", () => {
return request(app.getHttpServer())
.post("/auth/register")
.send(testUser)
.expect(200)
.expect((res) => {
expect(res.body.success).toBe(true);
expect(res.body.user).toBeDefined();
expect(res.body.user.email).toBe(testUser.email);
expect(res.body.user.username).toBe(testUser.username);
expect(res.body.user.passwordHash).toBeUndefined(); // Should not expose hash
// Extract session token for later tests
expect(res.body.sessionId).toBeDefined();
sessionToken = res.body.sessionId;
});
});
it("should reject duplicate email registration", () => {
return request(app.getHttpServer())
.post("/auth/register")
.send(testUser)
.expect(400)
.expect((res) => {
expect(res.body.message).toContain("already registered");
});
});
it("should validate required fields", () => {
return request(app.getHttpServer())
.post("/auth/register")
.send({ email: "incomplete" })
.expect(400);
});
it("should validate email format", () => {
return request(app.getHttpServer())
.post("/auth/register")
.send({
email: "not-an-email",
username: "validuser",
password: "SecurePass123!",
})
.expect(400);
});
});
describe("POST /auth/login", () => {
it("should login with valid credentials", () => {
return request(app.getHttpServer())
.post("/auth/login")
.send({
email: testUser.email,
password: testUser.password,
})
.expect(200)
.expect((res) => {
expect(res.body.success).toBe(true);
expect(res.body.user).toBeDefined();
expect(res.body.user.email).toBe(testUser.email);
// Should return session token
expect(res.body.sessionId).toBeDefined();
sessionToken = res.body.sessionId;
});
});
it("should reject invalid password", () => {
return request(app.getHttpServer())
.post("/auth/login")
.send({
email: testUser.email,
password: "WrongPassword123!",
})
.expect(401);
});
it("should reject non-existent user", () => {
return request(app.getHttpServer())
.post("/auth/login")
.send({
email: "nonexistent@example.com",
password: "AnyPassword123!",
})
.expect(401);
});
});
describe("GET /auth/validate", () => {
it("should validate authenticated session", () => {
return request(app.getHttpServer())
.get("/auth/validate")
.set("Authorization", `Bearer ${sessionToken}`)
.expect(200)
.expect((res) => {
expect(res.body.authenticated).toBe(true);
expect(res.body.user).toBeDefined();
expect(res.body.user.email).toBe(testUser.email);
});
});
it("should reject request without authorization header", () => {
return request(app.getHttpServer()).get("/auth/validate").expect(401);
});
it("should reject invalid session token", () => {
return request(app.getHttpServer())
.get("/auth/validate")
.set("Authorization", "Bearer invalid-session-id")
.expect(401);
});
});
describe("GET /auth/me", () => {
it("should return user data for authenticated session", () => {
return request(app.getHttpServer())
.get("/auth/me")
.set("Authorization", `Bearer ${sessionToken}`)
.expect(200)
.expect((res) => {
expect(res.body.authenticated).toBe(true);
expect(res.body.user).toBeDefined();
});
});
it("should return authenticated: false without authorization", () => {
return request(app.getHttpServer())
.get("/auth/me")
.expect(200)
.expect((res) => {
expect(res.body.authenticated).toBe(false);
});
});
});
describe("POST /auth/refresh", () => {
it("should refresh valid session", () => {
return request(app.getHttpServer())
.post("/auth/refresh")
.set("Authorization", `Bearer ${sessionToken}`)
.expect(200)
.expect((res) => {
expect(res.body.success).toBe(true);
});
});
it("should reject refresh without authorization", () => {
return request(app.getHttpServer()).post("/auth/refresh").expect(401);
});
});
describe("POST /auth/logout", () => {
it("should logout and invalidate session", () => {
return request(app.getHttpServer())
.post("/auth/logout")
.set("Authorization", `Bearer ${sessionToken}`)
.expect(200)
.expect((res) => {
expect(res.body.success).toBe(true);
});
});
it("should handle logout without authorization gracefully", () => {
return request(app.getHttpServer())
.post("/auth/logout")
.expect(200)
.expect((res) => {
expect(res.body.success).toBe(true);
});
});
it("should invalidate session after logout", async () => {
// First, login to get a fresh session
const loginRes = await request(app.getHttpServer())
.post("/auth/login")
.send({
email: testUser.email,
password: testUser.password,
});
const freshToken = loginRes.body.sessionId;
// Logout
await request(app.getHttpServer())
.post("/auth/logout")
.set("Authorization", `Bearer ${freshToken}`)
.expect(200);
// Validate should now fail
return request(app.getHttpServer())
.get("/auth/validate")
.set("Authorization", `Bearer ${freshToken}`)
.expect(401);
});
});
});