Make the project consistent with others, also provide individual tests to module components.master
@@ -7,8 +7,8 @@ import { | |||||
} from 'vitest'; | } from 'vitest'; | ||||
import { FastifyInstance } from 'fastify'; | import { FastifyInstance } from 'fastify'; | ||||
import { generate } from '@theoryofnekomata/oblique-strategies-core'; | import { generate } from '@theoryofnekomata/oblique-strategies-core'; | ||||
import { createServer } from '../src/server'; | |||||
import { addRoutes } from '../src/routes'; | |||||
import { createServer } from '../server'; | |||||
import { addRoutes } from '../routes'; | |||||
vi.mock('@theoryofnekomata/oblique-strategies-core'); | vi.mock('@theoryofnekomata/oblique-strategies-core'); | ||||
@@ -0,0 +1,37 @@ | |||||
import { | |||||
beforeEach, | |||||
describe, | |||||
expect, | |||||
it, | |||||
vi, | |||||
} from 'vitest'; | |||||
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'; | |||||
import { CardServiceImpl } from '../service'; | |||||
import { CardController, CardControllerImpl } from '../controller'; | |||||
describe('CardController', () => { | |||||
let cardController: CardController; | |||||
beforeEach(() => { | |||||
cardController = new CardControllerImpl(); | |||||
}); | |||||
describe('generate', () => { | |||||
it('generates cards', async () => { | |||||
vi | |||||
.spyOn(CardServiceImpl.prototype, 'generate') | |||||
.mockReturnValueOnce('random card'); | |||||
const request = { | |||||
query: {}, | |||||
} as FastifyRequest; | |||||
const reply = { | |||||
send: vi.fn(), | |||||
} as unknown as FastifyReply; | |||||
const fastifyInstance = {} as unknown as FastifyInstance; | |||||
const generate = cardController.generate.bind(fastifyInstance); | |||||
await generate(request, reply); | |||||
expect(reply.send).toBeCalledWith('random card'); | |||||
}); | |||||
}); | |||||
}); |
@@ -0,0 +1,31 @@ | |||||
import { | |||||
beforeEach, | |||||
describe, | |||||
expect, | |||||
it, | |||||
vi, | |||||
} from 'vitest'; | |||||
import { generate } from '@theoryofnekomata/oblique-strategies-core'; | |||||
import { CardService, CardServiceImpl } from '../service'; | |||||
vi.mock('@theoryofnekomata/oblique-strategies-core'); | |||||
describe('CardService', () => { | |||||
let cardService: CardService; | |||||
beforeEach(() => { | |||||
cardService = new CardServiceImpl(); | |||||
}); | |||||
describe('generate', () => { | |||||
it('returns a random card from default set', () => { | |||||
cardService.generate(); | |||||
expect(generate).toBeCalled(); | |||||
}); | |||||
it('returns a random card from custom set', () => { | |||||
cardService.generate(['default', 'text:hello|world']); | |||||
expect(generate).toBeCalledWith(['default', 'text:hello|world']); | |||||
}); | |||||
}); | |||||
}); |
@@ -1,10 +1,20 @@ | |||||
import { RouteHandlerMethod } from 'fastify'; | import { RouteHandlerMethod } from 'fastify'; | ||||
import { CardServiceImpl } from './service'; | |||||
import { Controller } from '../../utils/types'; | |||||
import { CardService, CardServiceImpl } from './service'; | |||||
export interface CardController extends Controller<'generate'> {} | |||||
export class CardControllerImpl implements CardController { | |||||
private readonly cardService: CardService; | |||||
constructor() { | |||||
this.cardService = new CardServiceImpl(); | |||||
} | |||||
export class CardControllerImpl { | |||||
readonly generate: RouteHandlerMethod = async (request, reply) => { | readonly generate: RouteHandlerMethod = async (request, reply) => { | ||||
const query = request.query as Record<string, unknown>; | const query = request.query as Record<string, unknown>; | ||||
const cardSources = query.cards as string[] | undefined; | const cardSources = query.cards as string[] | undefined; | ||||
reply.send(CardServiceImpl.generate(cardSources)); | |||||
const card = this.cardService.generate(cardSources); | |||||
reply.send(card); | |||||
}; | }; | ||||
} | } |
@@ -1,9 +1,19 @@ | |||||
import { generate as coreGenerate } from '@theoryofnekomata/oblique-strategies-core'; | import { generate as coreGenerate } from '@theoryofnekomata/oblique-strategies-core'; | ||||
export interface CardService {} | |||||
export interface CardService { | |||||
generate(cards?: string[]): string | |||||
} | |||||
type GenerateInternal = (cards?: string[]) => string | |||||
export class CardServiceImpl implements CardService { | export class CardServiceImpl implements CardService { | ||||
static generate(cards?: string[]) { | |||||
return coreGenerate(cards); | |||||
private readonly generateInternal: GenerateInternal; | |||||
constructor() { | |||||
this.generateInternal = coreGenerate; | |||||
} | |||||
generate(cards?: string[]): string { | |||||
return this.generateInternal(cards); | |||||
} | } | ||||
} | } |
@@ -0,0 +1,7 @@ | |||||
import { RouteHandlerMethod } from 'fastify' | |||||
type Controller<T extends string> = { | |||||
[key in T]: RouteHandlerMethod; | |||||
}; | |||||
export default Controller; |
@@ -0,0 +1 @@ | |||||
export { default as Controller } from './Controller'; |
@@ -1,6 +1,6 @@ | |||||
{ | { | ||||
"exclude": ["node_modules"], | "exclude": ["node_modules"], | ||||
"include": ["src", "types", "test"], | |||||
"include": ["src", "types"], | |||||
"compilerOptions": { | "compilerOptions": { | ||||
"module": "ESNext", | "module": "ESNext", | ||||
"lib": ["DOM", "ESNext"], | "lib": ["DOM", "ESNext"], | ||||