package.json test:e2e:prepare 现在是 migrate reset --force && prisma generate && seed 为 seed 运行时补充 JS Prisma client 生成器: schema.prisma 修复 seed 在 ESM/CJS 下的 Prisma 导入兼容: seed.mjs 修复 Jest 环境未加载 .env 导致连到 127.0.0.1 的问题: e2e-app.helper.ts 修复夹具依赖“名称”导致被组织测试改名后失效的问题(改为按 seed openId 反查): e2e-fixtures.helper.ts 修复组织测试的状态污染与清理逻辑,并收敛 afterAll 资源释放: organization.e2e-spec.ts e2e-context.helper.ts
130 lines
4.0 KiB
TypeScript
130 lines
4.0 KiB
TypeScript
import request from 'supertest';
|
||
import { Role } from '../../../src/generated/prisma/enums.js';
|
||
import {
|
||
closeE2EContext,
|
||
createE2EContext,
|
||
type E2EContext,
|
||
} from '../helpers/e2e-context.helper.js';
|
||
import { assertRoleMatrix } from '../helpers/e2e-matrix.helper.js';
|
||
import {
|
||
expectErrorEnvelope,
|
||
expectSuccessEnvelope,
|
||
uniquePhone,
|
||
uniqueSeedValue,
|
||
} from '../helpers/e2e-http.helper.js';
|
||
|
||
describe('AuthController (e2e)', () => {
|
||
let ctx: E2EContext;
|
||
|
||
beforeAll(async () => {
|
||
ctx = await createE2EContext();
|
||
});
|
||
|
||
afterAll(async () => {
|
||
await closeE2EContext(ctx);
|
||
});
|
||
|
||
describe('POST /auth/register', () => {
|
||
it('成功:注册医生账号', async () => {
|
||
const response = await request(ctx.app.getHttpServer())
|
||
.post('/auth/register')
|
||
.send({
|
||
name: uniqueSeedValue('Auth 注册医生'),
|
||
phone: uniquePhone(),
|
||
password: 'Seed@1234',
|
||
role: Role.DOCTOR,
|
||
hospitalId: ctx.fixtures.hospitalAId,
|
||
departmentId: ctx.fixtures.departmentA1Id,
|
||
groupId: ctx.fixtures.groupA1Id,
|
||
openId: uniqueSeedValue('auth-register-openid'),
|
||
});
|
||
|
||
expectSuccessEnvelope(response, 201);
|
||
expect(response.body.data.role).toBe(Role.DOCTOR);
|
||
});
|
||
|
||
it('失败:参数不合法返回 400', async () => {
|
||
const response = await request(ctx.app.getHttpServer())
|
||
.post('/auth/register')
|
||
.send({
|
||
name: 'bad-register',
|
||
phone: '13800009999',
|
||
password: '123',
|
||
role: Role.DOCTOR,
|
||
hospitalId: ctx.fixtures.hospitalAId,
|
||
departmentId: ctx.fixtures.departmentA1Id,
|
||
groupId: ctx.fixtures.groupA1Id,
|
||
});
|
||
|
||
expectErrorEnvelope(response, 400, 'password 长度至少 8 位');
|
||
});
|
||
});
|
||
|
||
describe('POST /auth/login', () => {
|
||
it('成功:seed 账号登录并拿到 token', async () => {
|
||
const response = await request(ctx.app.getHttpServer())
|
||
.post('/auth/login')
|
||
.send({
|
||
phone: '13800001004',
|
||
password: 'Seed@1234',
|
||
role: Role.DOCTOR,
|
||
hospitalId: ctx.fixtures.hospitalAId,
|
||
});
|
||
|
||
expectSuccessEnvelope(response, 201);
|
||
expect(response.body.data.accessToken).toEqual(expect.any(String));
|
||
expect(response.body.data.actor.role).toBe(Role.DOCTOR);
|
||
});
|
||
|
||
it('失败:密码错误返回 401', async () => {
|
||
const response = await request(ctx.app.getHttpServer())
|
||
.post('/auth/login')
|
||
.send({
|
||
phone: '13800001004',
|
||
password: 'Seed@12345',
|
||
role: Role.DOCTOR,
|
||
hospitalId: ctx.fixtures.hospitalAId,
|
||
});
|
||
|
||
expectErrorEnvelope(response, 401, '手机号、角色或密码错误');
|
||
});
|
||
});
|
||
|
||
describe('GET /auth/me', () => {
|
||
it('成功:已登录用户可读取当前信息', async () => {
|
||
const response = await request(ctx.app.getHttpServer())
|
||
.get('/auth/me')
|
||
.set('Authorization', `Bearer ${ctx.tokens[Role.DOCTOR]}`);
|
||
|
||
expectSuccessEnvelope(response, 200);
|
||
expect(response.body.data.role).toBe(Role.DOCTOR);
|
||
});
|
||
|
||
it('失败:未登录返回 401', async () => {
|
||
const response = await request(ctx.app.getHttpServer()).get('/auth/me');
|
||
expectErrorEnvelope(response, 401, '缺少 Bearer Token');
|
||
});
|
||
|
||
it('角色矩阵:6 角色都可访问,未登录 401', async () => {
|
||
await assertRoleMatrix({
|
||
name: 'GET /auth/me role matrix',
|
||
tokens: ctx.tokens,
|
||
expectedStatusByRole: {
|
||
[Role.SYSTEM_ADMIN]: 200,
|
||
[Role.HOSPITAL_ADMIN]: 200,
|
||
[Role.DIRECTOR]: 200,
|
||
[Role.LEADER]: 200,
|
||
[Role.DOCTOR]: 200,
|
||
[Role.ENGINEER]: 200,
|
||
},
|
||
sendAsRole: async (_role, token) =>
|
||
request(ctx.app.getHttpServer())
|
||
.get('/auth/me')
|
||
.set('Authorization', `Bearer ${token}`),
|
||
sendWithoutToken: async () =>
|
||
request(ctx.app.getHttpServer()).get('/auth/me'),
|
||
});
|
||
});
|
||
});
|
||
});
|