feat: 添加单元测试
All checks were successful
deploy to server / build-and-deploy (push) Successful in 2m47s
All checks were successful
deploy to server / build-and-deploy (push) Successful in 2m47s
This commit is contained in:
@ -1,49 +0,0 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
|
||||||
|
|
||||||
describe('toProductSpecView', () => {
|
|
||||||
it('should map translations.key an value corrently', () => {
|
|
||||||
const raw: ProductSpec = {
|
|
||||||
id: 1,
|
|
||||||
value: '100W',
|
|
||||||
translations: [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
key: 'Power',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const expected: ProductSpecView = {
|
|
||||||
id: 1,
|
|
||||||
key: 'Power',
|
|
||||||
value: '100W',
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(toProductSpecView(raw)).toEqual(expected);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle missing translations gracefully', () => {
|
|
||||||
const raw: ProductSpec = { id: 2, value: '220V', translations: [] };
|
|
||||||
const view = toProductSpecView(raw);
|
|
||||||
expect(view.key).toBe('');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('toProductSpecGroupView', () => {
|
|
||||||
it('should map translations.name and specs correctly', () => {
|
|
||||||
const raw: ProductSpecGroup = {
|
|
||||||
id: 1,
|
|
||||||
translations: [{ id: 1, name: 'Electrical' }],
|
|
||||||
specs: [
|
|
||||||
{ id: 1, value: '100W', translations: [{ id: 1, key: 'Power' }] },
|
|
||||||
{ id: 2, value: '220V', translations: [{ id: 2, key: 'Voltage' }] },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
const view: ProductSpecGroupView = toProductSpecGroupView(raw);
|
|
||||||
|
|
||||||
expect(view.name).toBe('Electrical');
|
|
||||||
expect(view.specs).toHaveLength(2);
|
|
||||||
expect(view.specs[0].key).toBe('Power');
|
|
||||||
expect(view.specs[1].value).toBe('220V');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
66
app/models/utils/object.test.ts
Normal file
66
app/models/utils/object.test.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { expect, test, describe } from 'vitest';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单元测试: isObject
|
||||||
|
*/
|
||||||
|
describe('isObject', () => {
|
||||||
|
test('identify plain object', () => {
|
||||||
|
expect(isObject({})).toBe(true);
|
||||||
|
expect(isObject({ key: 'value' })).toBe(true);
|
||||||
|
});
|
||||||
|
test('identify null as non objevt', () => {
|
||||||
|
expect(isObject(null)).toBe(false);
|
||||||
|
});
|
||||||
|
test('identify non-object types', () => {
|
||||||
|
expect(isObject(undefined)).toBe(false);
|
||||||
|
expect(isObject(42)).toBe(false);
|
||||||
|
expect(isObject('string')).toBe(false);
|
||||||
|
expect(isObject(Symbol('sym'))).toBe(false);
|
||||||
|
expect(isObject(true)).toBe(false);
|
||||||
|
expect(isObject(() => {})).toBe(false);
|
||||||
|
});
|
||||||
|
test('identify arrays as objects', () => {
|
||||||
|
expect(isObject([])).toBe(true);
|
||||||
|
});
|
||||||
|
test('identify narrowed object type', () => {
|
||||||
|
const value: unknown = { id: 1 };
|
||||||
|
if (isObject<{ id: number }>(value)) {
|
||||||
|
expect(value.id).toBe(1);
|
||||||
|
} else {
|
||||||
|
throw new Error('Type narrowing failed');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单元测试: isArrayOfObject
|
||||||
|
*/
|
||||||
|
describe('isArrayOfObject', () => {
|
||||||
|
test('identify array of plain objects', () => {
|
||||||
|
const arr = [{ id: 1 }, { name: 'Alice' }];
|
||||||
|
expect(isArrayOfObject<{ id?: number; name?: string }>(arr)).toBe(true);
|
||||||
|
});
|
||||||
|
test('identify array containing non-objects', () => {
|
||||||
|
expect(isArrayOfObject([1, 2, 3])).toBe(false);
|
||||||
|
expect(isArrayOfObject([{ id: 1 }, null])).toBe(false);
|
||||||
|
expect(isArrayOfObject([{ id: 1 }, 'string'])).toBe(false);
|
||||||
|
});
|
||||||
|
test('identify non-array types', () => {
|
||||||
|
expect(isArrayOfObject(null)).toBe(false);
|
||||||
|
expect(isArrayOfObject({})).toBe(false);
|
||||||
|
expect(isArrayOfObject(42)).toBe(false);
|
||||||
|
});
|
||||||
|
test('identify empty array as array of objects', () => {
|
||||||
|
expect(isArrayOfObject([])).toBe(true);
|
||||||
|
});
|
||||||
|
test('identify narrowed array of object type', () => {
|
||||||
|
const data: unknown = [{ id: 1 }, { id: 2 }];
|
||||||
|
if (isArrayOfObject<{ id: number }>(data)) {
|
||||||
|
// TS 能识别为 { id: number }[]
|
||||||
|
expect(data[0].id).toBe(1);
|
||||||
|
expect(data[1].id).toBe(2);
|
||||||
|
} else {
|
||||||
|
throw new Error('Type guard failed');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
75
app/models/utils/search-converter.test.ts
Normal file
75
app/models/utils/search-converter.test.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { describe, expect, test } from 'vitest';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单元测试: converters
|
||||||
|
*/
|
||||||
|
describe('converters', () => {
|
||||||
|
test('convert product item', () => {
|
||||||
|
const item = {
|
||||||
|
id: 1,
|
||||||
|
name: 'Hydraulic Pump',
|
||||||
|
summary: 'High efficiency',
|
||||||
|
description: 'Detailed description',
|
||||||
|
type: 'pump',
|
||||||
|
};
|
||||||
|
const result = converters.products(item);
|
||||||
|
expect(result).toEqual({
|
||||||
|
id: 1,
|
||||||
|
type: 'product',
|
||||||
|
title: 'Hydraulic Pump',
|
||||||
|
summary: 'High efficiency',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('convert solution item', () => {
|
||||||
|
const item = {
|
||||||
|
id: 1,
|
||||||
|
title: 'Solution A',
|
||||||
|
summary: 'Effective solution',
|
||||||
|
content: 'Detailed content',
|
||||||
|
type: 'Type A',
|
||||||
|
};
|
||||||
|
const result = converters.solutions(item);
|
||||||
|
expect(result).toEqual({
|
||||||
|
id: 1,
|
||||||
|
type: 'solution',
|
||||||
|
title: 'Solution A',
|
||||||
|
summary: 'Effective solution',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('convert question item', () => {
|
||||||
|
const item = {
|
||||||
|
id: 1,
|
||||||
|
title: 'How to use product?',
|
||||||
|
content:
|
||||||
|
'This is a detailed explanation of how to use the product effectively.',
|
||||||
|
products: ['Product A'],
|
||||||
|
product_types: ['Type A'],
|
||||||
|
};
|
||||||
|
const result = converters.questions(item);
|
||||||
|
expect(result).toEqual({
|
||||||
|
id: 1,
|
||||||
|
title: 'How to use product?',
|
||||||
|
summary:
|
||||||
|
'This is a detailed explanation of how to use the product effectively....',
|
||||||
|
type: 'question',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('convert product document item', () => {
|
||||||
|
const item = {
|
||||||
|
id: 1,
|
||||||
|
title: 'User Manual',
|
||||||
|
products: ['Product A'],
|
||||||
|
product_types: ['Type A'],
|
||||||
|
};
|
||||||
|
const result = converters.product_documents(item);
|
||||||
|
expect(result).toEqual({
|
||||||
|
id: 1,
|
||||||
|
title: 'User Manual',
|
||||||
|
summary: undefined,
|
||||||
|
type: 'document',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,8 +1,3 @@
|
|||||||
import {
|
|
||||||
formatFileSize,
|
|
||||||
getFileExtension,
|
|
||||||
formatFileExtension,
|
|
||||||
} from '@/utils/file';
|
|
||||||
import { expect, test, describe } from 'vitest';
|
import { expect, test, describe } from 'vitest';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user