BingLogyBlog-Backend/src/modules/session/session.e2e-spec.ts
laobinghu 37742571ae feat: 完成项目初始化并重构部署流程
主要变更:
- 添加完整的项目结构和模块(admin、articles、comments、users、session、oauth2、email、moderation、analytics、jobs 等)
- 实现系统初始化 API(/init/status 和 /init/run)
- 重写部署流程:迁移到 package.json scripts,删除 Makefile
- 优化部署脚本:deploy.sh、healthcheck.sh、backup.sh、restore.sh、verify-env.sh
- 更新 README.md:简化文档,整合部署指南
- 优化 AGENTS.md:精简到约 150 行,包含完整的代码规范和命令速查
- 配置 Docker Compose 自动化部署(prisma migrate deploy + seed)
- 生成 OAuth2 RSA 密钥对支持
- 添加环境变量验证和数据库备份恢复功能
2026-03-28 16:53:25 +08:00

131 lines
4.1 KiB
TypeScript

import { Test, TestingModule } from '@nestjs/testing';
import request from 'supertest';
import { AppModule } from '../../app.module';
import { INestApplication } from '@nestjs/common';
describe('OAuth2 + Session (e2e)', () => {
let app: INestApplication;
let sessionCookie: string | undefined;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
afterAll(async () => {
await app.close();
});
it('/login (POST) - success', async () => {
const response = await request(app.getHttpServer())
.post('/login')
.send({ emailOrUsername: 'admin@example.com', password: 'password123' })
.expect(200);
expect(response.body).toEqual({ ok: true, user: expect.any(Object) });
const setCookie = response.headers['set-cookie'] as string[];
if (setCookie && setCookie.length > 0) {
sessionCookie = setCookie[0].split(';')[0];
}
expect(sessionCookie).toBeDefined();
});
it('/me (GET) - with session', async () => {
expect(sessionCookie).toBeDefined();
await request(app.getHttpServer())
.get('/me')
.set('Cookie', sessionCookie!)
.expect(200);
});
it('/oauth2/authorize - not logged in, redirect to login', async () => {
const query = new URLSearchParams({
response_type: 'code',
client_id: 'web-client',
redirect_uri: 'http://localhost:3000/auth/callback',
scope: 'read write',
state: 'teststate',
}).toString();
const response = await request(app.getHttpServer())
.get(`/oauth2/authorize?${query}`)
.expect(302);
expect(response.headers.location).toContain('/login?next=');
});
it('/oauth2/authorize - after login, redirect with code', async () => {
// 假设 sessionCookie 已存在
expect(sessionCookie).toBeDefined();
const query = new URLSearchParams({
response_type: 'code',
client_id: 'web-client',
redirect_uri: 'http://localhost:3000/auth/callback',
scope: 'read write',
state: 'teststate',
}).toString();
const response = await request(app.getHttpServer())
.get(`/oauth2/authorize?${query}`)
.set('Cookie', sessionCookie!)
.expect(302);
const location = response.headers.location;
expect(location).toContain('http://localhost:3000/auth/callback?code=');
expect(location).toContain('state=teststate');
});
it('/oauth2/token - authorization_code grant', async () => {
// 先从 authorize 获取 code
const query = new URLSearchParams({
response_type: 'code',
client_id: 'web-client',
redirect_uri: 'http://localhost:3000/auth/callback',
scope: 'read write',
state: 'teststate',
}).toString();
const authResponse = await request(app.getHttpServer())
.get(`/oauth2/authorize?${query}`)
.set('Cookie', sessionCookie!);
const location = authResponse.headers.location;
const code = new URL(location).searchParams.get('code');
expect(code).toBeDefined();
// 用 code 换 token
const tokenResponse = await request(app.getHttpServer())
.post('/oauth2/token')
.type('form')
.send({
grant_type: 'authorization_code',
code,
redirect_uri: 'http://localhost:3000/auth/callback',
client_id: 'web-client',
client_secret: 'change_me',
})
.expect(200);
expect(tokenResponse.body).toEqual({
access_token: expect.any(String),
token_type: 'Bearer',
expires_in: expect.any(Number),
refresh_token: expect.any(String),
scope: 'read write',
});
});
it('/oauth2/token - client_credentials grant', async () => {
const response = await request(app.getHttpServer())
.post('/oauth2/token')
.type('form')
.send({
grant_type: 'client_credentials',
client_id: 'web-client',
client_secret: 'change_me',
})
.expect(200);
expect(response.body).toEqual({
access_token: expect.any(String),
token_type: 'Bearer',
expires_in: expect.any(Number),
scope: 'read write',
});
});
});