diff --git a/packages/backend/src/usecases/__tests__/getDonFromIdUsecase.test.ts b/packages/backend/src/usecases/__tests__/getDonFromIdUsecase.test.ts new file mode 100644 index 0000000..62228aa --- /dev/null +++ b/packages/backend/src/usecases/__tests__/getDonFromIdUsecase.test.ts @@ -0,0 +1,184 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { getDonFromIdUseCase } from '../getDonFromIdUsecase'; +import { donStatus } from '../../utils/status'; +import { ApiError } from '../../utils/ApiError'; +import { randomUUID } from 'crypto'; +import prisma from '../../lib/prismaClient'; + +vi.mock('../../utils/status'); +vi.mock('../../lib/prismaClient', () => ({ + default: { + dons: { + findUnique: vi.fn(), + }, + }, +})); + +const mockPrisma = vi.mocked(prisma) as unknown as { + dons: { + findUnique: ReturnType; + }; +}; + +describe('getDonFromIdUseCase', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('指定されたIDのDonを正常に取得する場合', async () => { + const donId = randomUUID(); + const orderId = randomUUID(); + const mockDon = { + id: donId, + order_id: orderId, + create_datetime: new Date('2023-01-01'), + update_datetime: new Date('2023-01-02'), + status: 1, + order: { id: orderId }, + customizes: [ + { + is_discount: true, + customize: { + id: randomUUID(), + label: 'Extra sauce', + available: true, + price: 100, + }, + }, + { + is_discount: false, + customize: { + id: randomUUID(), + label: 'Extra cheese', + available: true, + price: 200, + }, + }, + ], + }; + + mockPrisma.dons.findUnique.mockResolvedValue(mockDon); + vi.mocked(donStatus).mockReturnValue('ordered'); + + const result = await getDonFromIdUseCase(donId); + + expect(mockPrisma.dons.findUnique).toHaveBeenCalledWith({ + where: { + id: donId, + }, + include: { + order: true, + customizes: { + include: { + customize: true, + }, + }, + }, + }); + + expect(result).toEqual({ + id: mockDon.id, + orderId: mockDon.order_id, + createDatetime: mockDon.create_datetime, + updateDatetime: mockDon.update_datetime, + status: 'ordered', + customizes: mockDon.customizes.map((c) => ({ + id: c.customize.id, + label: c.customize.label, + available: c.customize.available, + isDiscount: c.is_discount, + })), + }); + + expect(donStatus).toHaveBeenCalledWith(1); + }); + + it('カスタマイズがないDonを正常に取得する場合', async () => { + const donId = randomUUID(); + const orderId = randomUUID(); + const mockDon = { + id: donId, + order_id: orderId, + create_datetime: new Date('2023-01-03'), + update_datetime: new Date('2023-01-04'), + status: 2, + order: { id: orderId }, + customizes: [], + }; + + mockPrisma.dons.findUnique.mockResolvedValue(mockDon); + vi.mocked(donStatus).mockReturnValue('cooking'); + + const result = await getDonFromIdUseCase(donId); + + expect(mockPrisma.dons.findUnique).toHaveBeenCalledWith({ + where: { + id: donId, + }, + include: { + order: true, + customizes: { + include: { + customize: true, + }, + }, + }, + }); + + expect(result).toEqual({ + id: mockDon.id, + orderId: mockDon.order_id, + createDatetime: mockDon.create_datetime, + updateDatetime: mockDon.update_datetime, + status: 'cooking', + customizes: [], + }); + + expect(donStatus).toHaveBeenCalledWith(2); + }); + + it('指定されたIDのDonが見つからない場合にApiErrorを投げる', async () => { + const donId = randomUUID(); + + mockPrisma.dons.findUnique.mockResolvedValue(null); + + await expect(getDonFromIdUseCase(donId)).rejects.toThrow(ApiError); + await expect(getDonFromIdUseCase(donId)).rejects.toThrow('INTERNAL_PROBLEMS'); + + expect(mockPrisma.dons.findUnique).toHaveBeenCalledWith({ + where: { + id: donId, + }, + include: { + order: true, + customizes: { + include: { + customize: true, + }, + }, + }, + }); + }); + + it('donStatusがundefinedを返した時にApiErrorを投げる', async () => { + const donId = randomUUID(); + const orderId = randomUUID(); + const mockDon = { + id: donId, + order_id: orderId, + create_datetime: new Date('2023-01-01'), + update_datetime: new Date('2023-01-02'), + status: 999, // 無効なステータス + order: { id: orderId }, + customizes: [], + }; + + mockPrisma.dons.findUnique.mockResolvedValue(mockDon); + vi.mocked(donStatus).mockReturnValue(undefined); + + await expect(getDonFromIdUseCase(donId)).rejects.toThrow(ApiError); + await expect(getDonFromIdUseCase(donId)).rejects.toThrow('INTERNAL_PROBLEMS'); + + expect(donStatus).toHaveBeenCalledWith(999); + }); +}); diff --git a/packages/backend/src/usecases/getDonFromIdUsecase.ts b/packages/backend/src/usecases/getDonFromIdUsecase.ts new file mode 100644 index 0000000..8dfde45 --- /dev/null +++ b/packages/backend/src/usecases/getDonFromIdUsecase.ts @@ -0,0 +1,45 @@ +import { components } from 'api/schema'; +import { ApiError } from '@/utils/ApiError'; +import { donStatus } from '@/utils/status'; +import prisma from '@/lib/prismaClient'; + +type Don = components['schemas']['Don']; + +export const getDonFromIdUseCase = async (id: string): Promise => { + // そのIDのDonを取得する + const don = await prisma.dons.findUnique({ + where: { + id: id, + }, + include: { + order: true, + customizes: { + include: { + customize: true, + }, + }, + }, + }); + + // そのIDのDonがない場合,エラーを返す. + if (!don) { + throw ApiError.internalProblems(); + } + + const status = donStatus(don.status); + if (!status) throw ApiError.internalProblems(); + + return { + id: don.id, + orderId: don.order_id, + createDatetime: don.create_datetime, + updateDatetime: don.update_datetime, + status, + customizes: don.customizes.map((c) => ({ + id: c.customize.id, + label: c.customize.label, + available: c.customize.available, + isDiscount: c.is_discount, + })), + }; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bad7505..a668ca0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,7 +45,7 @@ importers: devDependencies: '@mermaid-js/mermaid-cli': specifier: ^11.4.2 - version: 11.6.0(@types/react@18.3.23)(puppeteer@23.11.1(typescript@5.8.3)) + version: 11.6.0(@types/react@18.3.23)(puppeteer@23.11.1(typescript@5.8.3))(ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3)) '@types/cors': specifier: ^2.8.19 version: 2.8.19 @@ -60,7 +60,7 @@ importers: version: 2.4.4 prisma-erd-generator: specifier: ^2.0.4 - version: 2.0.4(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3))(@types/react@18.3.23)(puppeteer@23.11.1(typescript@5.8.3)) + version: 2.0.4(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3))(@types/react@18.3.23)(puppeteer@23.11.1(typescript@5.8.3))(ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3)) puppeteer: specifier: ^23.11.1 version: 23.11.1(typescript@5.8.3) @@ -7019,7 +7019,7 @@ packages: puppeteer@23.11.1: resolution: {integrity: sha512-53uIX3KR5en8l7Vd8n5DUv90Ae9QDQsyIthaUFVzwV6yU750RjqRznEtNMBT20VthqAdemnJN+hxVdmMHKt7Zw==} engines: {node: '>=18'} - deprecated: < 24.9.0 is no longer supported + deprecated: < 24.10.2 is no longer supported hasBin: true qs@6.14.0: @@ -10691,7 +10691,7 @@ snapshots: react-dom: 19.1.0(react@19.1.0) use-sync-external-store: 1.5.0(react@19.1.0) - '@headlessui/tailwindcss@0.2.2(tailwindcss@3.4.17)': + '@headlessui/tailwindcss@0.2.2(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3)))': dependencies: tailwindcss: 3.4.17(ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3)) @@ -10753,7 +10753,7 @@ snapshots: '@antfu/install-pkg': 1.1.0 '@antfu/utils': 8.1.1 '@iconify/types': 2.0.0 - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 globals: 15.15.0 kolorist: 1.8.0 local-pkg: 1.1.1 @@ -11087,9 +11087,9 @@ snapshots: '@marijn/find-cluster-break@1.0.2': {} - '@mermaid-js/mermaid-cli@11.6.0(@types/react@18.3.23)(puppeteer@23.11.1(typescript@5.8.3))': + '@mermaid-js/mermaid-cli@11.6.0(@types/react@18.3.23)(puppeteer@23.11.1(typescript@5.8.3))(ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3))': dependencies: - '@mermaid-js/mermaid-zenuml': 0.2.1(@types/react@18.3.23)(mermaid@11.9.0) + '@mermaid-js/mermaid-zenuml': 0.2.1(@types/react@18.3.23)(mermaid@11.9.0)(ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3)) chalk: 5.4.1 commander: 14.0.0 import-meta-resolve: 4.1.0 @@ -11100,9 +11100,9 @@ snapshots: - supports-color - ts-node - '@mermaid-js/mermaid-zenuml@0.2.1(@types/react@18.3.23)(mermaid@11.9.0)': + '@mermaid-js/mermaid-zenuml@0.2.1(@types/react@18.3.23)(mermaid@11.9.0)(ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3))': dependencies: - '@zenuml/core': 3.34.0(@types/react@18.3.23) + '@zenuml/core': 3.34.0(@types/react@18.3.23)(ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3)) mermaid: 11.9.0 transitivePeerDependencies: - '@types/react' @@ -11662,7 +11662,7 @@ snapshots: '@puppeteer/browsers@2.6.1': dependencies: - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 extract-zip: 2.0.1 progress: 2.0.3 proxy-agent: 6.5.0 @@ -13270,11 +13270,11 @@ snapshots: loupe: 2.3.7 pretty-format: 29.7.0 - '@zenuml/core@3.34.0(@types/react@18.3.23)': + '@zenuml/core@3.34.0(@types/react@18.3.23)(ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3))': dependencies: '@floating-ui/react': 0.27.13(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@headlessui/react': 2.2.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@headlessui/tailwindcss': 0.2.2(tailwindcss@3.4.17) + '@headlessui/tailwindcss': 0.2.2(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3))) antlr4: 4.11.0 class-variance-authority: 0.7.1 clsx: 2.1.1 @@ -13615,7 +13615,7 @@ snapshots: dependencies: bytes: 3.1.2 content-type: 1.0.5 - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 http-errors: 2.0.0 iconv-lite: 0.6.3 on-finished: 2.4.1 @@ -14300,6 +14300,10 @@ snapshots: dayjs@1.11.13: {} + debug@4.4.1: + dependencies: + ms: 2.1.3 + debug@4.4.1(supports-color@10.0.0): dependencies: ms: 2.1.3 @@ -14763,7 +14767,7 @@ snapshots: content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.2.2 - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -14797,7 +14801,7 @@ snapshots: extract-zip@2.0.1: dependencies: - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -14899,7 +14903,7 @@ snapshots: finalhandler@2.1.0: dependencies: - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -15120,7 +15124,7 @@ snapshots: dependencies: basic-ftp: 5.0.5 data-uri-to-buffer: 6.0.2 - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -15302,7 +15306,7 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -15320,6 +15324,13 @@ snapshots: transitivePeerDependencies: - supports-color + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.3 + debug: 4.4.1 + transitivePeerDependencies: + - supports-color + https-proxy-agent@7.0.6(supports-color@10.0.0): dependencies: agent-base: 7.1.3 @@ -15677,7 +15688,7 @@ snapshots: decimal.js: 10.6.0 html-encoding-sniffer: 4.0.0 http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6(supports-color@10.0.0) + https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 nwsapi: 2.2.20 parse5: 7.3.0 @@ -16633,10 +16644,10 @@ snapshots: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.3 - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 get-uri: 6.0.5 http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6(supports-color@10.0.0) + https-proxy-agent: 7.0.6 pac-resolver: 7.0.1 socks-proxy-agent: 8.0.5 transitivePeerDependencies: @@ -16917,9 +16928,9 @@ snapshots: printable-characters@1.0.42: {} - prisma-erd-generator@2.0.4(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3))(@types/react@18.3.23)(puppeteer@23.11.1(typescript@5.8.3)): + prisma-erd-generator@2.0.4(@prisma/client@6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3))(@types/react@18.3.23)(puppeteer@23.11.1(typescript@5.8.3))(ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3)): dependencies: - '@mermaid-js/mermaid-cli': 11.6.0(@types/react@18.3.23)(puppeteer@23.11.1(typescript@5.8.3)) + '@mermaid-js/mermaid-cli': 11.6.0(@types/react@18.3.23)(puppeteer@23.11.1(typescript@5.8.3))(ts-node@10.9.2(@types/node@22.15.30)(typescript@5.8.3)) '@prisma/client': 6.12.0(prisma@6.12.0(typescript@5.8.3))(typescript@5.8.3) '@prisma/generator-helper': 6.12.0 dotenv: 16.4.7 @@ -16992,9 +17003,9 @@ snapshots: proxy-agent@6.5.0: dependencies: agent-base: 7.1.3 - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6(supports-color@10.0.0) + https-proxy-agent: 7.0.6 lru-cache: 7.18.3 pac-proxy-agent: 7.2.0 proxy-from-env: 1.1.0 @@ -17021,7 +17032,7 @@ snapshots: dependencies: '@puppeteer/browsers': 2.6.1 chromium-bidi: 0.11.0(devtools-protocol@0.0.1367902) - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 devtools-protocol: 0.0.1367902 typed-query-selector: 2.12.0 ws: 8.18.3 @@ -17432,7 +17443,7 @@ snapshots: router@2.2.0: dependencies: - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 depd: 2.0.0 is-promise: 4.0.0 parseurl: 1.3.3 @@ -17503,7 +17514,7 @@ snapshots: send@1.2.0: dependencies: - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -17725,7 +17736,7 @@ snapshots: socks-proxy-agent@8.0.5: dependencies: agent-base: 7.1.3 - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 socks: 2.8.6 transitivePeerDependencies: - supports-color @@ -18492,7 +18503,7 @@ snapshots: vite-node@1.6.1(@types/node@22.15.30): dependencies: cac: 6.7.14 - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 pathe: 1.1.2 picocolors: 1.1.1 vite: 5.4.19(@types/node@22.15.30) @@ -18540,7 +18551,7 @@ snapshots: '@vitest/utils': 1.6.1 acorn-walk: 8.3.4 chai: 4.5.0 - debug: 4.4.1(supports-color@10.0.0) + debug: 4.4.1 execa: 8.0.1 local-pkg: 0.5.1 magic-string: 0.30.17