diff --git a/test/index.test.ts b/src/__tests__/index.test.ts similarity index 93% rename from test/index.test.ts rename to src/__tests__/index.test.ts index e7bfe55..fd57bc8 100644 --- a/test/index.test.ts +++ b/src/__tests__/index.test.ts @@ -7,8 +7,8 @@ import { } from 'vitest'; import { FastifyInstance } from 'fastify'; 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'); diff --git a/src/modules/card/__tests__/controller.test.ts b/src/modules/card/__tests__/controller.test.ts new file mode 100644 index 0000000..ce1fb17 --- /dev/null +++ b/src/modules/card/__tests__/controller.test.ts @@ -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'); + }); + }); +}); diff --git a/src/modules/card/__tests__/service.test.ts b/src/modules/card/__tests__/service.test.ts new file mode 100644 index 0000000..3e6a857 --- /dev/null +++ b/src/modules/card/__tests__/service.test.ts @@ -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']); + }); + }); +}); diff --git a/src/modules/card/controller.ts b/src/modules/card/controller.ts index 0e0896f..4f94490 100644 --- a/src/modules/card/controller.ts +++ b/src/modules/card/controller.ts @@ -1,10 +1,20 @@ 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) => { const query = request.query as Record; const cardSources = query.cards as string[] | undefined; - reply.send(CardServiceImpl.generate(cardSources)); + const card = this.cardService.generate(cardSources); + reply.send(card); }; } diff --git a/src/modules/card/service.ts b/src/modules/card/service.ts index 81751a6..5e155a2 100644 --- a/src/modules/card/service.ts +++ b/src/modules/card/service.ts @@ -1,9 +1,19 @@ 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 { - static generate(cards?: string[]) { - return coreGenerate(cards); + private readonly generateInternal: GenerateInternal; + + constructor() { + this.generateInternal = coreGenerate; + } + + generate(cards?: string[]): string { + return this.generateInternal(cards); } } diff --git a/src/utils/types/Controller.ts b/src/utils/types/Controller.ts new file mode 100644 index 0000000..a386985 --- /dev/null +++ b/src/utils/types/Controller.ts @@ -0,0 +1,7 @@ +import { RouteHandlerMethod } from 'fastify' + +type Controller = { + [key in T]: RouteHandlerMethod; +}; + +export default Controller; diff --git a/src/utils/types/index.ts b/src/utils/types/index.ts new file mode 100644 index 0000000..d978849 --- /dev/null +++ b/src/utils/types/index.ts @@ -0,0 +1 @@ +export { default as Controller } from './Controller'; diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index 3d14e86..b297200 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -1,6 +1,6 @@ { "exclude": ["node_modules"], - "include": ["src", "types", "test"], + "include": ["src", "types"], "compilerOptions": { "module": "ESNext", "lib": ["DOM", "ESNext"],