-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from bcgov/dev
Update to be an API that supports our own implementation of Zen Engine, ability to fetch json files, and rule mapping
- Loading branch information
Showing
25 changed files
with
1,689 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { Controller, Post, Query, Body, HttpException, HttpStatus } from '@nestjs/common'; | ||
import { DecisionsService } from './decisions.service'; | ||
import { EvaluateDecisionDto, EvaluateDecisionWithContentDto } from './dto/evaluate-decision.dto'; | ||
|
||
@Controller('api/decisions') | ||
export class DecisionsController { | ||
constructor(private readonly decisionsService: DecisionsService) {} | ||
|
||
@Post('/evaluate') | ||
async evaluateDecisionByContent(@Body() { content, context, trace }: EvaluateDecisionWithContentDto) { | ||
try { | ||
return await this.decisionsService.runDecision(content, context, { trace }); | ||
} catch (error) { | ||
throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR); | ||
} | ||
} | ||
|
||
@Post('/evaluateByFile') | ||
async evaluateDecisionByFile( | ||
@Query('ruleFileName') ruleFileName: string, | ||
@Body() { context, trace }: EvaluateDecisionDto, | ||
) { | ||
try { | ||
return await this.decisionsService.runDecisionByFile(ruleFileName, context, { trace }); | ||
} catch (error) { | ||
throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { ConfigService } from '@nestjs/config'; | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { ZenEngine, ZenDecision, ZenEvaluateOptions } from '@gorules/zen-engine'; | ||
import { DecisionsService } from './decisions.service'; | ||
import { readFileSafely } from '../../utils/readFile'; | ||
|
||
jest.mock('../../utils/readFile', () => ({ | ||
readFileSafely: jest.fn(), | ||
FileNotFoundError: jest.fn(), | ||
})); | ||
|
||
describe('DecisionsService', () => { | ||
let service: DecisionsService; | ||
let mockEngine: Partial<ZenEngine>; | ||
let mockDecision: Partial<ZenDecision>; | ||
|
||
beforeEach(async () => { | ||
mockDecision = { | ||
evaluate: jest.fn(), | ||
}; | ||
mockEngine = { | ||
createDecision: jest.fn().mockReturnValue(mockDecision), | ||
}; | ||
|
||
const module: TestingModule = await Test.createTestingModule({ | ||
providers: [ConfigService, DecisionsService, { provide: ZenEngine, useValue: mockEngine }], | ||
}).compile(); | ||
|
||
service = module.get<DecisionsService>(DecisionsService); | ||
service.engine = mockEngine as ZenEngine; | ||
}); | ||
|
||
describe('runDecision', () => { | ||
it('should run a decision', async () => { | ||
const content = {}; | ||
const context = {}; | ||
const options: ZenEvaluateOptions = { trace: false }; | ||
await service.runDecision(content, context, options); | ||
expect(mockEngine.createDecision).toHaveBeenCalledWith(content); | ||
expect(mockDecision.evaluate).toHaveBeenCalledWith(context, options); | ||
}); | ||
|
||
it('should throw an error if the decision fails', async () => { | ||
const content = {}; | ||
const context = {}; | ||
const options: ZenEvaluateOptions = { trace: false }; | ||
(mockDecision.evaluate as jest.Mock).mockRejectedValue(new Error('Error')); | ||
await expect(service.runDecision(content, context, options)).rejects.toThrow('Failed to run decision: Error'); | ||
}); | ||
}); | ||
|
||
describe('runDecisionByFile', () => { | ||
it('should read a file and run a decision', async () => { | ||
const ruleFileName = 'rule'; | ||
const context = {}; | ||
const options: ZenEvaluateOptions = { trace: false }; | ||
const content = JSON.stringify({ rule: 'rule' }); | ||
(readFileSafely as jest.Mock).mockResolvedValue(content); | ||
await service.runDecisionByFile(ruleFileName, context, options); | ||
expect(readFileSafely).toHaveBeenCalledWith(service.rulesDirectory, ruleFileName); | ||
expect(mockEngine.createDecision).toHaveBeenCalledWith(content); | ||
expect(mockDecision.evaluate).toHaveBeenCalledWith(context, options); | ||
}); | ||
|
||
it('should throw an error if reading the file fails', async () => { | ||
const ruleFileName = 'rule'; | ||
const context = {}; | ||
const options: ZenEvaluateOptions = { trace: false }; | ||
(readFileSafely as jest.Mock).mockRejectedValue(new Error('Error')); | ||
await expect(service.runDecisionByFile(ruleFileName, context, options)).rejects.toThrow( | ||
'Failed to run decision: Error', | ||
); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.