diff --git a/server/mappers/solutionListMapper.test.ts b/server/mappers/solutionListMapper.test.ts new file mode 100644 index 0000000..f063a97 --- /dev/null +++ b/server/mappers/solutionListMapper.test.ts @@ -0,0 +1,109 @@ +import { describe, test, expect } from 'vitest'; +import { toSolutionListView, toSolutionTypeView } from './solutionListMapper'; + +/** + * 单元测试: toSolutionTypeView + */ +describe('toSolutionTypeView', () => { + const baseData: SolutionType = { + id: 1, + translations: [ + { + id: 1, + name: 'Type Name', + }, + ], + sort: 5, + }; + + test('convert raw data to SolutionTypeView correctly', () => { + const rawData: SolutionType = { ...baseData }; + + expect(toSolutionTypeView(rawData)).toEqual({ + id: '1', + name: 'Type Name', + sort: 5, + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: SolutionType = { ...baseData, translations: [] }; + + expect(toSolutionTypeView(rawData)).toEqual({ + id: '1', + name: '', + sort: 5, + }); + }); + + test('convert raw data with missing sort', () => { + const rawData: SolutionType = { ...baseData, sort: undefined }; + + expect(toSolutionTypeView(rawData)).toEqual({ + id: '1', + name: 'Type Name', + sort: 999, + }); + }); + + test('convert null input to default value', () => { + const rawData: SolutionType | string | null = null; + + expect(toSolutionTypeView(rawData)).toEqual({ + id: '-1', + name: 'uncategory', + sort: 999, + }); + }); +}); + +/** + * 单元测试: toSolutionListView + */ +describe('toSolutionListView', () => { + const baseData: Solution = { + id: 1, + translations: [ + { id: 1, title: 'Solution Title', summary: 'Solution Summary' }, + ], + type: { + id: 1, + translations: [{ id: 1, name: 'Type Name' }], + sort: 1, + }, + }; + test('convert raw data to SolutionListView correctly', () => { + const rawData: Solution = { ...baseData }; + + expect(toSolutionListView(rawData)).toEqual({ + id: '1', + title: 'Solution Title', + summary: 'Solution Summary', + solution_type: { + id: '1', + name: 'Type Name', + sort: 1, + }, + cover: '', + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: Solution = { + ...baseData, + translations: [], + }; + + expect(toSolutionListView(rawData)).toEqual({ + id: '1', + title: '', + summary: '', + solution_type: { + id: '1', + name: 'Type Name', + sort: 1, + }, + cover: '', + }); + }); +}); diff --git a/server/mappers/solutionListMapper.ts b/server/mappers/solutionListMapper.ts new file mode 100644 index 0000000..4173e8e --- /dev/null +++ b/server/mappers/solutionListMapper.ts @@ -0,0 +1,58 @@ +import { isObject } from '../../server/utils/object'; + +/** + * 将 Directus 返回的 SolutionType 数据转换为 SolutionTypeView 视图模型 + * + * @param raw: 原始的 SolutionType 数据 + * @returns 转换后的 SolutionTypeView 对象 + * + * --- + * + * @example + * const view = toSolutionTypeView(rawSolutionType); + */ +export function toSolutionTypeView( + raw: SolutionType | string | null +): SolutionTypeView { + if (typeof raw === 'string' || raw === null) { + return { + id: '-1', + name: 'uncategory', + sort: 999, + } satisfies SolutionTypeView; + } + const trans = raw?.translations?.[0]; + + return { + id: raw.id.toString(), + name: trans?.name ?? '', + sort: raw?.sort ?? 999, + }; +} + +/** + * 将 Directus 返回的 Solution 数据转换为 SolutionListView 视图模型 + * + * @param raw: 原始的 Solution 数据 + * @returns 转换后的 SolutionListView 对象 + * + * --- + * + * @example + * const view = toSolutionListView(rawSolution); + */ +export function toSolutionListView(raw: Solution): SolutionListView { + const trans = raw.translations?.[0]; + + const type = toSolutionTypeView(raw.type ?? null); + + const cover = isObject(raw.cover) ? (raw?.cover.id ?? '') : ''; + + return { + id: raw.id.toString(), + title: trans?.title ?? '', + summary: trans?.summary ?? '', + solution_type: type, + cover: cover, + }; +} diff --git a/server/mappers/solutionMapper.test.ts b/server/mappers/solutionMapper.test.ts index dc6c413..4e5034f 100644 --- a/server/mappers/solutionMapper.test.ts +++ b/server/mappers/solutionMapper.test.ts @@ -1,56 +1,5 @@ import { describe, test, expect } from 'vitest'; -import { toSolutionListView, toSolutionView } from './solutionMapper'; - -/** - * 单元测试: toSolutionListView - */ -describe('toSolutionListView', () => { - const baseData: Solution = { - id: 1, - translations: [ - { id: 1, title: 'Solution Title', summary: 'Solution Summary' }, - ], - type: { - id: 1, - translations: [{ id: 1, name: 'Type Name' }], - sort: 1, - }, - }; - test('convert raw data to SolutionListView correctly', () => { - const rawData: Solution = { ...baseData }; - - expect(toSolutionListView(rawData)).toEqual({ - id: '1', - title: 'Solution Title', - summary: 'Solution Summary', - solution_type: { - id: '1', - name: 'Type Name', - sort: 1, - }, - cover: '', - }); - }); - - test('convert raw data with missing translations', () => { - const rawData: Solution = { - ...baseData, - translations: [], - }; - - expect(toSolutionListView(rawData)).toEqual({ - id: '1', - title: '', - summary: '', - solution_type: { - id: '1', - name: 'Type Name', - sort: 1, - }, - cover: '', - }); - }); -}); +import { toSolutionView } from './solutionMapper'; /** * 单元测试: toSolutionView diff --git a/server/mappers/solutionMapper.ts b/server/mappers/solutionMapper.ts index 3c903d1..38a1101 100644 --- a/server/mappers/solutionMapper.ts +++ b/server/mappers/solutionMapper.ts @@ -1,59 +1,3 @@ -import { isObject } from '../../server/utils/object'; - -/** - * 将 Directus 返回的 SolutionType 数据转换为 SolutionTypeView 视图模型 - * - * @param raw: 原始的 SolutionType 数据 - * @returns 转换后的 SolutionTypeView 对象 - * - * --- - * - * @example - * const view = toSolutionTypeView(rawSolutionType); - */ -export function toSolutionTypeView(raw: SolutionType): SolutionTypeView { - const trans = raw?.translations?.[0]; - - return { - id: raw.id.toString(), - name: trans?.name ?? '', - sort: raw?.sort ?? 999, - }; -} - -/** - * 将 Directus 返回的 Solution 数据转换为 SolutionListView 视图模型 - * - * @param raw: 原始的 Solution 数据 - * @returns 转换后的 SolutionListView 对象 - * - * --- - * - * @example - * const view = toSolutionListView(rawSolution); - */ -export function toSolutionListView(raw: Solution): SolutionListView { - const trans = raw.translations?.[0]; - - const type = isObject(raw.type) - ? toSolutionTypeView(raw.type) - : ({ - id: '', - name: 'uncategory', - sort: 999, - } satisfies SolutionTypeView); - - const cover = isObject(raw.cover) ? (raw?.cover.id ?? '') : ''; - - return { - id: raw.id.toString(), - title: trans?.title ?? '', - summary: trans?.summary ?? '', - solution_type: type, - cover: cover, - }; -} - /** * 将 Directus 返回的 Solution 数据转换为 SolutionView 视图模型 * diff --git a/server/services/cms/solutionService.ts b/server/services/cms/solutionService.ts index 6c8f050..ddcb8de 100644 --- a/server/services/cms/solutionService.ts +++ b/server/services/cms/solutionService.ts @@ -1,7 +1,5 @@ -import { - toSolutionView, - toSolutionListView, -} from '~~/server/mappers/solutionMapper'; +import { toSolutionView } from '~~/server/mappers/solutionMapper'; +import { toSolutionListView } from '~~/server/mappers/solutionListMapper'; export const solutionService = { async getSolutionList(locale: string) {