Skip to content

Commit

Permalink
feat: chat repo
Browse files Browse the repository at this point in the history
- setup mongodb
- implement chat repo and test
- use dotenv in jest
- CI add mongodb
  • Loading branch information
hhow09 committed Jan 22, 2025
1 parent 0d61fbc commit 38c4c6e
Show file tree
Hide file tree
Showing 11 changed files with 325 additions and 17 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ on:

jobs:
test:
services:
mongo:
image: mongo:6.0.20
ports:
- 27017:27017
# health check
# ref: https://engineering.synatic.com/a-simple-way-to-run-a-mongodb-replica-set-in-github-actions
options: >-
--health-cmd "mongosh --eval 'db.runCommand(\"ping\")'"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
MONGODB_URI: mongodb://localhost:27017
strategy:
matrix:
directory: [ "./backend" ]
Expand Down
1 change: 1 addition & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MONGODB_URI=mongodb://localhost:27017
17 changes: 17 additions & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Backend
## Run at Local
### Setup Infrastructure
```bash
cp .env.example .env # modify .env as needed
docker run --name mongodb -p 27017:27017 -d mongo:6.0.20
```

### Run server
```bash
npm run start
```

### Run tests
```bash
npm run test
```
1 change: 1 addition & 0 deletions backend/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ module.exports = {
transform: {
"^.+.tsx?$": ["ts-jest",{}],
},
setupFiles: ["dotenv/config"]
};

153 changes: 152 additions & 1 deletion backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
"@types/body-parser": "^1.19.5",
"@types/express": "^5.0.0",
"@types/node": "^22.10.7",
"dotenv": "^16.4.7",
"express": "^4.21.2",
"mathjs": "^14.0.1",
"mongodb": "^6.12.0",
"pino": "^9.6.0",
"socket.io": "^4.8.1"
},
Expand Down
18 changes: 13 additions & 5 deletions backend/src/command-service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@ const mockRepository = {
getLatest: jest.fn(),
};

type TestCase = {
command: string;
expected?: string;
hasError?: boolean;
};

describe('evaluate', () => {
describe.each([
const logger = pino();
describe.each<TestCase>([
{ command: '', hasError: true },
{ command: ' ', hasError: true },
{ command: '1', expected: '1' },
Expand All @@ -30,13 +37,14 @@ describe('evaluate', () => {
{ command: '5 * 7 / 3 * 3', expected: '35' },

])('.evaluate($command)', ({ command, hasError, expected }) => {
test(`returns ${hasError}`, () => {
test(`returns ${hasError}`, async () => {
const clientId = 'whatever';
const commandService = new CommandService(pino(), mockRepository);
const commandService = new CommandService(logger, mockRepository);
if (hasError) {
expect(() => commandService.evaluateAndSave(clientId, command)).toThrow('Invalid command');
await expect(commandService.evaluateAndSave(clientId, command)).rejects.toThrow('Invalid command');
} else {
expect(commandService.evaluateAndSave(clientId, command)).toBe(expected);
const res = await commandService.evaluateAndSave(clientId, command);
expect(res).toBe(expected);
expect(mockRepository.saveCommand).toHaveBeenCalledWith(clientId, command, expected);
}
});
Expand Down
16 changes: 5 additions & 11 deletions backend/src/command-service.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { Logger } from "pino";
import { evaluate as evaluateMathjs } from 'mathjs';
import { CommandAndResult } from "./entities/command-result.entity";

interface IRepository {
saveCommand(clientId: string, command: string, result: string): void;
getLatest(clientId: string, count: number): CommandAndResult[];
}

const historyCount = 10;
import { IRepository } from "./repositories";

class CommandService {
private operators = new Set(['+', '-', '*', '/']);
Expand All @@ -19,15 +13,15 @@ class CommandService {
}

// evaluateAndSave evaluates a mathematical expression and saves the result to the repository
public evaluateAndSave(clientId: string, expression: string): string {
public async evaluateAndSave(clientId: string, expression: string): Promise<string> {
const result = this.evaluate(expression);
this.repository.saveCommand(clientId, expression, result);
await this.repository.saveCommand(clientId, expression, result);
return result;
}

// getHistory returns the latest 10 commands for a client
public getHistory(clientId: string): CommandAndResult[] {
return this.repository.getLatest(clientId, historyCount);
public async getHistory(clientId: string): Promise<CommandAndResult[]> {
return this.repository.getLatest(clientId);
}

// evaluate evaluate a mathematical expression
Expand Down
Loading

0 comments on commit 38c4c6e

Please sign in to comment.