feat(card): 构建全球6大赛道高保真Demo数据并完成线上数据库与服务部署
这个提交包含在:
@@ -74,15 +74,33 @@ describe('多张多媒体名片数据 (配图与配视频) 规格与集成测试
|
||||
|
||||
it('4. 每张名片必须包含图文案例与文章,且配置了真实多媒体封面配图与量化商业指标', () => {
|
||||
MOCK_CARDS_DATA.forEach((bundle: MockCardBundle) => {
|
||||
// 检查案例
|
||||
// 检查案例 (每个名片至少 2 个标杆产品相册与案例)
|
||||
expect(Array.isArray(bundle.cases)).toBe(true);
|
||||
expect(bundle.cases.length).toBeGreaterThanOrEqual(1);
|
||||
expect(bundle.cases.length).toBeGreaterThanOrEqual(2);
|
||||
bundle.cases.forEach(c => {
|
||||
expect(c.title).toBeTruthy();
|
||||
expect(c.client).toBeTruthy();
|
||||
expect(c.metrics).toBeTruthy(); // 必须包含量化商业成果
|
||||
expect(c.description).toBeTruthy();
|
||||
expect(c.coverImage).toMatch(/^https?:\/\/.+\.(png|jpe?g|webp)(\?.*)?$/i);
|
||||
|
||||
// 验证产品相册多图画廊 (metaJson.images 必须存在且至少 3 张高清产品/场景图)
|
||||
let meta = c.metaJson;
|
||||
if (typeof meta === 'string') {
|
||||
meta = JSON.parse(meta);
|
||||
}
|
||||
expect(meta).toBeDefined();
|
||||
const images = (meta as any)?.images;
|
||||
expect(Array.isArray(images)).toBe(true);
|
||||
expect(images.length).toBeGreaterThanOrEqual(3);
|
||||
images.forEach((img: string) => {
|
||||
expect(img).toMatch(/^https?:\/\/.+\.(png|jpe?g|webp)(\?.*)?$/i);
|
||||
});
|
||||
|
||||
// 验证结构化 KPI (metaJson.kpis 必须存在且至少 2 个指标)
|
||||
const kpis = (meta as any)?.kpis;
|
||||
expect(Array.isArray(kpis)).toBe(true);
|
||||
expect(kpis.length).toBeGreaterThanOrEqual(2);
|
||||
});
|
||||
|
||||
// 检查文章
|
||||
@@ -156,19 +174,35 @@ describe('多张多媒体名片数据 (配图与配视频) 规格与集成测试
|
||||
expect(html).toContain(firstBundle.cases[0].title);
|
||||
});
|
||||
|
||||
it('7. 控制器公开路由 /mock-cards 能返回 6 套名片高保真预览清单', async () => {
|
||||
// 动态验证 OpenCardPortalController.mockCards
|
||||
it('7. 控制器公开路由 /mock-cards:默认空数组,ALLOW_PORTAL_MOCK=1 才返回演示清单', async () => {
|
||||
const { OpenCardPortalController } = require('../../../src/modules/card/controller/open/portal');
|
||||
const controller = new OpenCardPortalController();
|
||||
controller.ok = jest.fn((data: any) => ({ code: 1000, data }));
|
||||
const prevAllow = process.env.ALLOW_PORTAL_MOCK;
|
||||
|
||||
const res = await controller.mockCards();
|
||||
expect(res.code).toBe(1000);
|
||||
expect(Array.isArray(res.data)).toBe(true);
|
||||
expect(res.data.length).toBe(6);
|
||||
expect(res.data[0].slug).toBe('alex-zheng');
|
||||
expect(res.data[5].slug).toBe('marcus-weber');
|
||||
expect(res.data[0].bentoBlocksCount).toBeGreaterThanOrEqual(5);
|
||||
try {
|
||||
delete process.env.ALLOW_PORTAL_MOCK;
|
||||
const emptyRes = await controller.mockCards();
|
||||
expect(emptyRes.code).toBe(1000);
|
||||
expect(Array.isArray(emptyRes.data)).toBe(true);
|
||||
expect(emptyRes.data).toEqual([]);
|
||||
expect(JSON.stringify(emptyRes.data)).not.toContain('Alex Zheng');
|
||||
|
||||
process.env.ALLOW_PORTAL_MOCK = '1';
|
||||
const res = await controller.mockCards();
|
||||
expect(res.code).toBe(1000);
|
||||
expect(Array.isArray(res.data)).toBe(true);
|
||||
expect(res.data.length).toBe(6);
|
||||
expect(res.data[0].slug).toBe('alex-zheng');
|
||||
expect(res.data[5].slug).toBe('marcus-weber');
|
||||
expect(res.data[0].bentoBlocksCount).toBeGreaterThanOrEqual(5);
|
||||
} finally {
|
||||
if (prevAllow === undefined) {
|
||||
delete process.env.ALLOW_PORTAL_MOCK;
|
||||
} else {
|
||||
process.env.ALLOW_PORTAL_MOCK = prevAllow;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('8. seedCardsToDatabase 函数能够幂等同步数据到仓库', async () => {
|
||||
|
||||
在新工单中引用
屏蔽一个用户