From 7ba7f4a15afe6fc5b2ee40a5938ccddcd4cb8900 Mon Sep 17 00:00:00 2001 From: R2m1liA <15258427350@163.com> Date: Thu, 6 Nov 2025 16:46:56 +0800 Subject: [PATCH] =?UTF-8?q?test:=20=E4=B8=BAmapper=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mappers/companyProfileMapper.test.ts | 31 ++++ app/models/mappers/contactInfoMapper.test.ts | 30 ++++ app/models/mappers/documentMapper.test.ts | 106 +++++++++++ app/models/mappers/homepageMapper.test.ts | 78 ++++++++ app/models/mappers/productMapper.test.ts | 168 ++++++++++++++++++ app/models/mappers/productMapper.ts | 13 +- app/models/mappers/questionMapper.test.ts | 113 ++++++++++++ app/models/mappers/questionMapper.ts | 2 +- app/models/mappers/solutionMapper.test.ts | 88 +++++++++ app/models/mappers/solutionMapper.ts | 10 +- 10 files changed, 629 insertions(+), 10 deletions(-) create mode 100644 app/models/mappers/companyProfileMapper.test.ts create mode 100644 app/models/mappers/contactInfoMapper.test.ts create mode 100644 app/models/mappers/documentMapper.test.ts create mode 100644 app/models/mappers/homepageMapper.test.ts create mode 100644 app/models/mappers/productMapper.test.ts create mode 100644 app/models/mappers/questionMapper.test.ts create mode 100644 app/models/mappers/solutionMapper.test.ts diff --git a/app/models/mappers/companyProfileMapper.test.ts b/app/models/mappers/companyProfileMapper.test.ts new file mode 100644 index 0000000..59ea13b --- /dev/null +++ b/app/models/mappers/companyProfileMapper.test.ts @@ -0,0 +1,31 @@ +import { expect, test, describe } from 'vitest'; + +/** + * 单元测试: companyProfileMapper + */ +describe('companyProfileMapper', () => { + test('convert raw data to CompanyProfileView correctly', () => { + const rawData: CompanyProfile = { + id: 1, + translations: [ + { id: 10, content: 'This is raw data of company profile' }, + ], + }; + + expect(toCompanyProfileView(rawData)).toEqual({ + id: 1, + content: 'This is raw data of company profile', + }); + }); + test('convert raw data with missing translations', () => { + const rawData: CompanyProfile = { + id: 1, + translations: [], + }; + + expect(toCompanyProfileView(rawData)).toEqual({ + id: 1, + content: '', + }); + }); +}); diff --git a/app/models/mappers/contactInfoMapper.test.ts b/app/models/mappers/contactInfoMapper.test.ts new file mode 100644 index 0000000..c73d203 --- /dev/null +++ b/app/models/mappers/contactInfoMapper.test.ts @@ -0,0 +1,30 @@ +import { describe, test, expect } from 'vitest'; + +/** + * 单元测试: contactInfoMapper + */ +describe('contactInfoMapper', () => { + test('convert raw data to ContactInfoView correctly', () => { + const rawData: ContactInfo = { + id: 1, + translations: [{ id: 10, content: 'This is raw data of contact info' }], + }; + + expect(toContactInfoView(rawData)).toEqual({ + id: 1, + content: 'This is raw data of contact info', + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: ContactInfo = { + id: 1, + translations: [], + }; + + expect(toContactInfoView(rawData)).toEqual({ + id: 1, + content: '', + }); + }); +}); diff --git a/app/models/mappers/documentMapper.test.ts b/app/models/mappers/documentMapper.test.ts new file mode 100644 index 0000000..319ba4c --- /dev/null +++ b/app/models/mappers/documentMapper.test.ts @@ -0,0 +1,106 @@ +import { describe, test, expect } from 'vitest'; + +/** + * 单元测试: toProductDocumentView + */ +describe('toProductDocumentView', () => { + test('convert raw data with fileId to ProductDocumentView correctly', () => { + const rawData: ProductDocument = { + id: 1, + file: 'rand-om__-uuid-1234', + translations: [{ id: 10, title: 'Document Title' }], + }; + + expect(toProductDocumentView(rawData)).toEqual({ + id: 1, + fileId: 'rand-om__-uuid-1234', + filename: undefined, + title: 'Document Title', + url: 'http://localhost:8055/assets/rand-om__-uuid-1234', + size: undefined, + }); + }); + + test('convert raw data with fileMeta to ProductDocumentView correctly', () => { + const rawData: ProductDocument = { + id: 1, + file: { + id: 'rand-om__-uuid-1234', + filename_download: 'document.pdf', + filesize: 2048, + }, + translations: [{ id: 10, title: 'Document Title' }], + }; + + expect(toProductDocumentView(rawData)).toEqual({ + id: 1, + fileId: 'rand-om__-uuid-1234', + filename: 'document.pdf', + title: 'Document Title', + url: 'http://localhost:8055/assets/rand-om__-uuid-1234', + size: 2048, + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: ProductDocument = { + id: 1, + file: 'rand-om__-uuid-1234', + translations: [], + }; + + expect(toProductDocumentView(rawData)).toEqual({ + id: 1, + fileId: 'rand-om__-uuid-1234', + filename: undefined, + title: '', + url: 'http://localhost:8055/assets/rand-om__-uuid-1234', + size: undefined, + }); + }); +}); + +/** + * 单元测试: toDocumentListView + */ +describe('toProductDocumentView', () => { + test('convert raw data with fileId to DocumentListView correctly', () => { + const rawData: ProductDocument = { + id: 1, + file: 'rand-om__-uuid-1234', + translations: [{ id: 10, title: 'Document Title' }], + products: [ + { + id: 10, + products_id: { + id: 1, + translations: [{ id: 1, name: 'Product A' }], + product_type: { + id: 1, + translations: [{ id: 1, name: 'Type A' }], + }, + }, + }, + ], + }; + + expect(toDocumentListView(rawData)).toEqual({ + id: 1, + fileId: 'rand-om__-uuid-1234', + filename: undefined, + title: 'Document Title', + url: 'http://localhost:8055/assets/rand-om__-uuid-1234', + size: undefined, + products: [ + { + id: 1, + name: 'Product A', + type: { + id: 1, + name: 'Type A', + }, + }, + ], + }); + }); +}); diff --git a/app/models/mappers/homepageMapper.test.ts b/app/models/mappers/homepageMapper.test.ts new file mode 100644 index 0000000..de881c7 --- /dev/null +++ b/app/models/mappers/homepageMapper.test.ts @@ -0,0 +1,78 @@ +import { describe, test, expect } from 'vitest'; + +/** + * 单元测试: toHomepageView + */ +describe('toHomepageView', () => { + test('convert raw data to HomepageView correctly', () => { + const rawData: Homepage = { + id: 1, + carousel: [ + { id: 1, directus_files_id: 'file-uuid-1' }, + { id: 2, directus_files_id: 'file-uuid-2' }, + ], + recommend_products: [ + { + id: 1, + translations: [{ id: 1, name: 'Product 1', summary: 'Summary 1' }], + cover: 'cover-file-uuid-1', + }, + { + id: 2, + translations: [{ id: 2, name: 'Product 2', summary: 'Summary 2' }], + cover: { id: 'cover-file-uuid-2' }, + }, + ], + recommend_solutions: [ + { + id: 1, + translations: [{ id: 1, title: 'Solution 1', summary: 'Summary 1' }], + cover: 'cover-file-uuid-1', + }, + ], + }; + + expect(toHomepageView(rawData)).toEqual({ + id: 1, + carousel: ['file-uuid-1', 'file-uuid-2'], + recommendProducts: [ + { + id: 1, + name: 'Product 1', + summary: 'Summary 1', + cover: 'cover-file-uuid-1', + }, + { + id: 2, + name: 'Product 2', + summary: 'Summary 2', + cover: 'cover-file-uuid-2', + }, + ], + recommendSolutions: [ + { + id: 1, + title: 'Solution 1', + summary: 'Summary 1', + cover: 'cover-file-uuid-1', + }, + ], + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: Homepage = { + id: 1, + carousel: [], + recommend_products: [{ id: 1, translations: [], cover: null }], + recommend_solutions: [{ id: 1, translations: [], cover: null }], + }; + + expect(toHomepageView(rawData)).toEqual({ + id: 1, + carousel: [], + recommendProducts: [{ id: 1, name: '', summary: '', cover: null }], + recommendSolutions: [{ id: 1, title: '', summary: '', cover: null }], + }); + }); +}); diff --git a/app/models/mappers/productMapper.test.ts b/app/models/mappers/productMapper.test.ts new file mode 100644 index 0000000..177641a --- /dev/null +++ b/app/models/mappers/productMapper.test.ts @@ -0,0 +1,168 @@ +import { describe, test, expect } from 'vitest'; + +/** + * 单元测试: toProductListView + */ +describe('toProductListView', () => { + test('convert raw data to ProductListView correctly', () => { + const rawData: Product = { + id: 1, + translations: [ + { id: 10, name: 'Product Name', summary: 'Product Summary' }, + ], + cover: 'cover-file-uuid-1234', + product_type: { + id: 1, + translations: [{ id: 20, name: 'Type Name' }], + }, + }; + + expect(toProductListView(rawData)).toEqual({ + id: 1, + name: 'Product Name', + summary: 'Product Summary', + cover: 'cover-file-uuid-1234', + product_type: 'Type Name', + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: Product = { + id: 1, + translations: [], + cover: 'cover-file-uuid-1234', + product_type: { + id: 20, + translations: [], + }, + }; + + expect(toProductListView(rawData)).toEqual({ + id: 1, + name: '', + summary: '', + cover: 'cover-file-uuid-1234', + product_type: '', + }); + }); +}); + +/** + * 单元测试: toProductSpecView + */ +describe('toProductSpecView', () => { + test('convert raw data to ProductSpecView correctly', () => { + const rawData: ProductSpec = { + id: 1, + translations: [{ id: 1, key: 'Key', value: 'Value' }], + }; + + expect(toProductSpecView(rawData)).toEqual({ + id: 1, + key: 'Key', + value: 'Value', + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: ProductSpec = { + id: 1, + translations: [], + }; + + expect(toProductSpecView(rawData)).toEqual({ + id: 1, + key: '', + value: '', + }); + }); +}); + +/** + * 单元测试: toProductSpecGroupView + */ +describe('toProductSpecGroupView', () => { + test('convert raw data to ProductSpecGroupView correctly', () => { + const rawData: ProductSpecGroup = { + id: 1, + translations: [{ id: 1, name: 'Group Name' }], + specs: [ + { id: 1, translations: [{ id: 1, key: 'Key1', value: 'Value1' }] }, + { id: 2, translations: [{ id: 2, key: 'Key2', value: 'Value2' }] }, + ], + }; + + expect(toProductSpecGroupView(rawData)).toEqual({ + id: 1, + name: 'Group Name', + specs: [ + { id: 1, key: 'Key1', value: 'Value1' }, + { id: 2, key: 'Key2', value: 'Value2' }, + ], + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: ProductSpecGroup = { + id: 1, + translations: [], + specs: [], + }; + + expect(toProductSpecGroupView(rawData)).toEqual({ + id: 1, + name: '', + specs: [], + }); + }); +}); + +/** + * 单元测试: toProductView + */ +describe('toProductView', () => { + test('convert raw data to ProductView correctly', () => { + const rawData: Product = { + id: 1, + translations: [ + { + id: 1, + name: 'Product Name', + summary: 'Product Summary', + description: 'Product Description', + }, + ], + }; + + expect(toProductView(rawData)).toEqual({ + id: 1, + name: 'Product Name', + summary: 'Product Summary', + description: 'Product Description', + product_type: '', + images: [], + documents: [], + faqs: [], + specs: [], + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: Product = { + id: 1, + translations: [], + }; + + expect(toProductView(rawData)).toEqual({ + id: 1, + name: '', + summary: '', + description: '', + product_type: '', + images: [], + documents: [], + faqs: [], + specs: [], + }); + }); +}); diff --git a/app/models/mappers/productMapper.ts b/app/models/mappers/productMapper.ts index 5eefde8..9597c49 100644 --- a/app/models/mappers/productMapper.ts +++ b/app/models/mappers/productMapper.ts @@ -10,14 +10,15 @@ export function toProductListView(raw: Product): ProductListView { const trans = raw.translations?.[0] ?? { name: '', summary: '' }; + const type = isObject(raw.product_type) + ? raw.product_type.translations.length === 0 + ? '' + : raw.product_type.translations[0].name + : ''; + return { id: raw.id, - product_type: - typeof raw.product_type === 'string' - ? raw.product_type - : typeof raw.product_type === 'object' && raw.product_type - ? raw.product_type.translations[0].name || '' - : '', + product_type: type, name: trans.name, summary: trans.summary, cover: raw.cover.toString(), diff --git a/app/models/mappers/questionMapper.test.ts b/app/models/mappers/questionMapper.test.ts new file mode 100644 index 0000000..4705dc1 --- /dev/null +++ b/app/models/mappers/questionMapper.test.ts @@ -0,0 +1,113 @@ +import { describe, expect, test } from 'vitest'; + +/** + * 单元测试: toProductQuestionView + */ +describe('toProductQuestionView', () => { + test('convert raw data to ProductQuestionView correctly', () => { + const rawData: Question = { + id: 1, + translations: [ + { id: 1, title: 'Question Title', content: 'Question Answer' }, + ], + }; + + expect(toProductQuestionView(rawData)).toEqual({ + id: 1, + title: 'Question Title', + content: 'Question Answer', + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: Question = { + id: 1, + translations: [], + }; + + expect(toProductQuestionView(rawData)).toEqual({ + id: 1, + title: '', + content: '', + }); + }); +}); + +/** + * 单元测试: toQuestionListView + */ +describe('toQuestionListView', () => { + test('convert raw data to QuestionListView correctly', () => { + const rawData: Question = { + id: 1, + translations: [ + { id: 1, title: 'Question Title', content: 'Question Answer' }, + ], + products: [ + { + id: 1, + products_id: { + id: 1, + translations: [{ id: 1, name: 'Product Name' }], + product_type: { + id: 1, + translations: [{ id: 1, name: 'Type Name' }], + }, + }, + }, + ], + }; + + expect(toQuestionListView(rawData)).toEqual({ + id: 1, + title: 'Question Title', + content: 'Question Answer', + products: [ + { + id: 1, + name: 'Product Name', + type: { + id: 1, + name: 'Type Name', + }, + }, + ], + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: Question = { + id: 1, + translations: [], + products: [ + { + id: 1, + products_id: { + id: 1, + translations: [], + product_type: { + id: 1, + translations: [], + }, + }, + }, + ], + }; + + expect(toQuestionListView(rawData)).toEqual({ + id: 1, + title: '', + content: '', + products: [ + { + id: 1, + name: '', + type: { + id: 1, + name: '', + }, + }, + ], + }); + }); +}); diff --git a/app/models/mappers/questionMapper.ts b/app/models/mappers/questionMapper.ts index f84ac6e..5f37926 100644 --- a/app/models/mappers/questionMapper.ts +++ b/app/models/mappers/questionMapper.ts @@ -40,7 +40,7 @@ export function toQuestionListView(raw: Question): QuestionListView { isObject(item.product_type) && ({ id: item.product_type.id, - name: item.product_type.translations[0]?.name, + name: item.product_type.translations[0]?.name ?? '', } satisfies QuestionListProductType); return { diff --git a/app/models/mappers/solutionMapper.test.ts b/app/models/mappers/solutionMapper.test.ts new file mode 100644 index 0000000..1850d47 --- /dev/null +++ b/app/models/mappers/solutionMapper.test.ts @@ -0,0 +1,88 @@ +import { describe, test, expect } from 'vitest'; + +/** + * 单元测试: toSolutionListView + */ +describe('toSolutionListView', () => { + test('convert raw data to SolutionListView correctly', () => { + const rawData: Solution = { + id: 1, + translations: [ + { id: 1, title: 'Solution Title', summary: 'Solution Summary' }, + ], + type: { + id: 1, + translations: [{ id: 1, name: 'Type Name' }], + }, + }; + + expect(toSolutionListView(rawData)).toEqual({ + id: 1, + title: 'Solution Title', + summary: 'Solution Summary', + solution_type: 'Type Name', + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: Solution = { + id: 1, + translations: [], + type: { + id: 1, + translations: [], + }, + }; + + expect(toSolutionListView(rawData)).toEqual({ + id: 1, + title: '', + summary: '', + solution_type: '', + }); + }); +}); + +/** + * 单元测试: toSolutionView + */ +describe('toSolutionView', () => { + test('convert raw data to SolutionView correctly', () => { + const rawData: Solution = { + id: 1, + translations: [ + { + id: 1, + title: 'Solution Title', + summary: 'Solution Summary', + content: 'Solution Content', + }, + ], + create_at: '2023-01-01T00:00:00Z', + }; + + expect(toSolutionView(rawData)).toEqual({ + id: 1, + title: 'Solution Title', + summary: 'Solution Summary', + content: 'Solution Content', + createAt: '2023-01-01T00:00:00Z', + }); + }); + + test('convert raw data with missing translations', () => { + const rawData: Solution = { + id: 1, + translations: [], + create_at: '2023-01-01T00:00:00Z', + }; + + expect(toSolutionView(rawData)).toEqual({ + id: 1, + title: '', + summary: '', + content: '', + createAt: '2023-01-01T00:00:00Z', + }); + }); +}); diff --git a/app/models/mappers/solutionMapper.ts b/app/models/mappers/solutionMapper.ts index 4fd05b1..baf1694 100644 --- a/app/models/mappers/solutionMapper.ts +++ b/app/models/mappers/solutionMapper.ts @@ -15,13 +15,17 @@ export function toSolutionListView(raw: Solution): SolutionListView { summary: '', }; + const type = isObject(raw.type) + ? raw.type.translations.length === 0 + ? '' + : raw.type.translations[0].name + : ''; + return { id: raw.id, title: trans.title, summary: trans.summary, - solution_type: isObject(raw.type) - ? raw.type.translations[0].name - : '', + solution_type: type, cover: isObject(raw.cover) ? raw.cover.id : raw.cover, }; } -- 2.49.0