fix: 修复后端 CI 检查与测试
This commit is contained in:
@@ -33,7 +33,7 @@ jobs:
|
||||
- name: Lint
|
||||
run: |
|
||||
npm run lint -w @gongxue/admin
|
||||
npm run lint -w @gongxue/server -- --no-fix
|
||||
npm run lint -w @gongxue/server -- --quiet
|
||||
|
||||
- name: Type check
|
||||
run: npm run typecheck
|
||||
|
||||
@@ -5,7 +5,7 @@ import tseslint from 'typescript-eslint';
|
||||
|
||||
export default tseslint.config(
|
||||
{
|
||||
ignores: ['eslint.config.mjs'],
|
||||
ignores: ['eslint.config.mjs', 'dist/**'],
|
||||
},
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.recommendedTypeChecked,
|
||||
@@ -27,6 +27,29 @@ export default tseslint.config(
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-floating-promises': 'warn',
|
||||
'@typescript-eslint/no-unsafe-argument': 'warn',
|
||||
'@typescript-eslint/no-unsafe-assignment': 'warn',
|
||||
'@typescript-eslint/no-unsafe-call': 'warn',
|
||||
'@typescript-eslint/no-unsafe-enum-comparison': 'warn',
|
||||
'@typescript-eslint/no-unsafe-member-access': 'warn',
|
||||
'@typescript-eslint/no-unsafe-return': 'warn',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'warn',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
caughtErrorsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-base-to-string': 'warn',
|
||||
'@typescript-eslint/no-require-imports': 'warn',
|
||||
'@typescript-eslint/no-unnecessary-type-assertion': 'warn',
|
||||
'@typescript-eslint/restrict-template-expressions': 'warn',
|
||||
'no-empty': ['warn', { allowEmptyCatch: true }],
|
||||
'no-useless-escape': 'warn',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.spec.ts', '**/*.test.ts', 'test/**/*.ts'],
|
||||
extends: [tseslint.configs.disableTypeChecked],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
"start:debug": "nest start --debug --watch",
|
||||
"start:prod": "node dist/main",
|
||||
"generate:student-import": "ts-node -r tsconfig-paths/register -P tsconfig.json scripts/generate-student-import-xlsx.ts",
|
||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
|
||||
"lint:fix": "npm run lint -- --fix",
|
||||
"typecheck": "tsc -p tsconfig.build.json --noEmit",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
|
||||
@@ -8,6 +8,16 @@ import {
|
||||
randomBytes,
|
||||
} from 'node:crypto';
|
||||
|
||||
jest.mock('node:dns', () => ({
|
||||
lookup: jest.fn(
|
||||
(
|
||||
_hostname: string,
|
||||
_options: unknown,
|
||||
callback: (error: null, addresses: Array<{ address: string; family: number }>) => void,
|
||||
) => callback(null, [{ address: '203.0.113.10', family: 4 }]),
|
||||
),
|
||||
}));
|
||||
|
||||
import { AiConfigService } from './ai-config.service';
|
||||
import { AiConfig, AiProvider, SINGLETON_KEY } from './ai-config.entity';
|
||||
|
||||
@@ -105,6 +115,8 @@ describe('AiConfigService', () => {
|
||||
afterEach(() => {
|
||||
delete process.env.AI_CONFIG_ENCRYPTION_KEY;
|
||||
delete process.env.AI_API_KEY;
|
||||
delete process.env.AI_ALLOW_PRIVATE_BASE_URL;
|
||||
delete process.env.NODE_ENV;
|
||||
});
|
||||
|
||||
// ── Encryption ────────────────────────────────────────────────────────
|
||||
|
||||
@@ -362,7 +362,7 @@ describe('ClassroomRentalsService — rental schedule sync', () => {
|
||||
expect(scheduleRepo.delete).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('deletes the RENTAL schedule row when the rental is cancelled', async () => {
|
||||
it('deactivates the RENTAL schedule row when the rental is cancelled', async () => {
|
||||
const rental = {
|
||||
id: 1,
|
||||
classroomId: 1,
|
||||
@@ -379,7 +379,10 @@ describe('ClassroomRentalsService — rental schedule sync', () => {
|
||||
await service.cancel(1);
|
||||
|
||||
expect(rentalRepo.update).toHaveBeenCalledWith(1, { status: 'cancelled' });
|
||||
expect(scheduleRepo.delete).toHaveBeenCalledWith({ rentalId: 1, scheduleType: 'RENTAL' });
|
||||
expect(scheduleRepo.update).toHaveBeenCalledWith(
|
||||
{ rentalId: 1, scheduleType: 'RENTAL' },
|
||||
{ status: 'inactive' },
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -419,14 +422,14 @@ describe('ClassroomRentalsService — rental schedule sync', () => {
|
||||
});
|
||||
|
||||
describe('remove()', () => {
|
||||
it('deletes the RENTAL schedule row and the rental', async () => {
|
||||
it('archives the rental and deactivates its RENTAL schedule row', async () => {
|
||||
const rental = {
|
||||
id: 1,
|
||||
classroomId: 1,
|
||||
lesseeOrganizationId: 2,
|
||||
startDate: '2026-03-01',
|
||||
endDate: '2026-03-31',
|
||||
status: 'cancelled',
|
||||
status: 'active',
|
||||
lesseeOrganization: { id: 2, name: 'Organization A' } as Organization,
|
||||
} as ClassroomRental;
|
||||
|
||||
@@ -434,8 +437,12 @@ describe('ClassroomRentalsService — rental schedule sync', () => {
|
||||
|
||||
await service.remove(1);
|
||||
|
||||
expect(scheduleRepo.delete).toHaveBeenCalledWith({ rentalId: 1, scheduleType: 'RENTAL' });
|
||||
expect(rentalRepo.delete).toHaveBeenCalledWith(1);
|
||||
expect(rentalRepo.update).toHaveBeenCalledWith(1, { status: 'cancelled' });
|
||||
expect(scheduleRepo.update).toHaveBeenCalledWith(
|
||||
{ rentalId: 1, scheduleType: 'RENTAL' },
|
||||
{ status: 'inactive' },
|
||||
);
|
||||
expect(rentalRepo.delete).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -197,7 +197,7 @@ describe('DatabaseMigrationsService — course attendance schema', () => {
|
||||
],
|
||||
getTable: { name: 'attendance_records', columns: [{ name: 'id' }] },
|
||||
});
|
||||
await bootstrapCourseAttendance(runner);
|
||||
const service = await bootstrapCourseAttendance(runner);
|
||||
|
||||
await service.ensureCourseAttendanceSchema();
|
||||
|
||||
@@ -223,7 +223,7 @@ describe('DatabaseMigrationsService — course attendance schema', () => {
|
||||
? { name, columns: [{ name: 'id' }] }
|
||||
: { name, columns: [{ name: 'id' }, { name: 'schedule_id' }, { name: 'attendance_session_id' }] },
|
||||
);
|
||||
await bootstrapCourseAttendance(runner);
|
||||
const service = await bootstrapCourseAttendance(runner);
|
||||
|
||||
await service.ensureCourseAttendanceSchema();
|
||||
|
||||
@@ -237,7 +237,7 @@ describe('DatabaseMigrationsService — course attendance schema', () => {
|
||||
getTables: [{ name: 'attendance_records', columns: [{ name: 'id' }] }],
|
||||
getTable: { name: 'attendance_records', columns: [{ name: 'id' }] },
|
||||
});
|
||||
await bootstrapCourseAttendance(runner);
|
||||
const service = await bootstrapCourseAttendance(runner);
|
||||
await service.ensureCourseAttendanceSchema();
|
||||
|
||||
const createSql: string = (runner.query as jest.Mock).mock.calls
|
||||
@@ -497,5 +497,5 @@ async function bootstrapCourseAttendance(runner: MockRunner) {
|
||||
{ provide: getDataSourceToken(), useValue: dataSource },
|
||||
],
|
||||
}).compile();
|
||||
service = module.get(DatabaseMigrationsService);
|
||||
return module.get<MigrationsPrivate & DatabaseMigrationsService>(DatabaseMigrationsService);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user