import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import { PostprocessingService } from './postprocessing.service'; import { Postprocessing } from '../database/entities/postprocessing.entity'; import { PostprocessingAction } from '../database/entities/postprocessing-action.entity'; import { PaperlessService } from '../paperless/paperless.service'; const mockRules: Partial[] = [ { Id: 1, Name: 'Rule1', DocumentTypeId: 5, CorrespondentId: null, OwnerId: null, TagId: null, Order: 1, IsActive: true, NoFurther: false, }, { Id: 2, Name: 'StopRule', DocumentTypeId: null, CorrespondentId: null, OwnerId: null, TagId: null, Order: 2, IsActive: true, NoFurther: true, }, ]; const mockActions: Partial[] = [ { Id: 1, PostprocessingId: 1, ActionType: 2, Content: '99', Order: 1, IsActive: true, }, ]; describe('PostprocessingService', () => { let service: PostprocessingService; let ppRepo: any; let ppActionRepo: any; let paperlessService: any; beforeEach(async () => { ppRepo = { find: jest.fn().mockResolvedValue(mockRules) }; ppActionRepo = { find: jest.fn().mockResolvedValue(mockActions) }; paperlessService = { updateDocument: jest.fn().mockResolvedValue({}) }; const module: TestingModule = await Test.createTestingModule({ providers: [ PostprocessingService, { provide: getRepositoryToken(Postprocessing), useValue: ppRepo }, { provide: getRepositoryToken(PostprocessingAction), useValue: ppActionRepo, }, { provide: PaperlessService, useValue: paperlessService }, ], }).compile(); service = module.get(PostprocessingService); }); it('should be defined', () => { expect(service).toBeDefined(); }); it('evaluate loads active rules in order', async () => { await service.evaluate({ documentId: 100, documentTypeId: 5, tagIds: [] }); expect(ppRepo.find).toHaveBeenCalledWith({ where: { IsActive: true }, order: { Order: 'ASC' }, }); }); it('evaluate executes matching actions', async () => { // Rule1 matches documentTypeId=5 → action adds tag await service.evaluate({ documentId: 100, documentTypeId: 5, tagIds: [] }); expect(ppActionRepo.find).toHaveBeenCalledWith({ where: { PostprocessingId: 1, IsActive: true }, order: { Order: 'ASC' }, }); expect(paperlessService.updateDocument).toHaveBeenCalledWith(100, { tags: [99], }); }); it('evaluate stops at NoFurther rule', async () => { // Rule1 matches, Rule2 also matches (no filters) + NoFurther → stops await service.evaluate({ documentId: 100, documentTypeId: 5, tagIds: [] }); // Actions loaded for rule 1 and rule 2, but no rule after rule 2 expect(ppActionRepo.find).toHaveBeenCalledTimes(2); }); it('evaluate skips non-matching rules', async () => { // documentTypeId=999 doesn't match Rule1 (requires 5) but matches Rule2 (no filter) ppActionRepo.find.mockResolvedValue([]); await service.evaluate({ documentId: 100, documentTypeId: 999, tagIds: [], }); // Rule1 skipped, Rule2 matched → only 1 action lookup expect(ppActionRepo.find).toHaveBeenCalledTimes(1); expect(ppActionRepo.find).toHaveBeenCalledWith({ where: { PostprocessingId: 2, IsActive: true }, order: { Order: 'ASC' }, }); }); });