feat(h5): update skin scoring, age display and capture countdown
This commit is contained in:
@@ -22,6 +22,13 @@ const child = spawn(process.execPath, ['-e', `
|
||||
const fs=require('fs'), vm=require('vm'), w={};
|
||||
vm.runInNewContext(fs.readFileSync('assets/mock/report-fixture.js','utf8'),{window:w});
|
||||
const f=w.MOCK_FIXTURE;
|
||||
if(process.env.H5_ACNE_MAX_TEST==='1') {
|
||||
const keys=['closed_comedones','acne','acne_pustule','acne_nodule','acne_mark'];
|
||||
const set=(target,counts)=>keys.forEach((k,i)=>target[k]={count:counts[i]});
|
||||
set(f.result,[2,0,0,0,3]);f.result.score_info.acne_score=100;
|
||||
f.side.left.left_acne_info={score:0};set(f.side.left.left_acne_info,[5,1,0,0,1]);
|
||||
f.side.right.right_acne_info={score:0};set(f.side.right.right_acne_info,[3,1,0,0,4]);
|
||||
}
|
||||
global.fetch=async()=>({ok:true,status:200,json:async()=>({result:f.result,face_rectangle:f.face_rectangle,left_side_result:f.side.left,right_side_result:f.side.right})});
|
||||
require('./server.js');
|
||||
`], { cwd: h5, env: { ...process.env, PORT: '18089', HOST: '127.0.0.1', JUZI_DATA_ROOT: dataRoot,
|
||||
@@ -50,7 +57,8 @@ try {
|
||||
assert.equal(result.vm.total, expectedTotal);
|
||||
assert.notEqual(expectedTotal, result.result.score_info.total_score, 'fixture distinguishes weighted score from API total');
|
||||
assert(result.vm.skinAgeRaw < 32);
|
||||
assert.equal(result.vm.skinAgeDisplay, result.vm.skinAgeRaw);
|
||||
const expectedAge = Math.max(55, Math.min(65, result.vm.skinAgeRaw));
|
||||
assert.equal(result.vm.skinAgeDisplay, expectedAge);
|
||||
assert.equal(result.vm.essence.tier, 1); // Raw age, never actual60.
|
||||
assert.equal(result.presentation.product.tier, 1);
|
||||
const adminRecord = (await (await api.get(base + 'api/admin/records/' + result.record_id)).json()).record;
|
||||
@@ -60,16 +68,23 @@ try {
|
||||
assert.equal(adminRecord.skin_age_display, result.vm.skinAgeDisplay);
|
||||
assert.equal(adminRecord.total_score, expectedTotal);
|
||||
assert.equal(adminRecord.total_score_rule, 'dimensions-433-v1');
|
||||
assert.deepEqual(adminRecord.acne_scoring,result.vm.cats.acne.vars.acne_scoring);
|
||||
assert.deepEqual(adminRecord.tone_scoring,result.vm.cats.tone.vars.tone_scoring);
|
||||
if(process.env.H5_ACNE_MAX_TEST==='1') {
|
||||
assert.deepEqual(result.vm.cats.acne.vars.acne_counts,{closed_comedones:5,acne:1,acne_pustule:0,acne_nodule:0,acne_mark:4});
|
||||
assert.equal(adminRecord.acne_scoring.deduction,13);assert.equal(adminRecord.cats.acne.P,87);
|
||||
}
|
||||
for (const key of ['firm', 'vita', 'stab']) assert.equal(adminRecord.dims[key].S, result.vm.dims[key].S);
|
||||
const list = await (await api.get(base + 'api/admin/records')).json();
|
||||
assert.equal(list.items[0].skin_age, result.vm.skinAgeRaw);
|
||||
assert.equal(list.items[0].skin_age_display, result.vm.skinAgeRaw);
|
||||
assert.equal(list.items[0].skin_age_display, expectedAge);
|
||||
assert.deepEqual(list.items[0].recommendation, result.vm.recommendation);
|
||||
assert.equal(list.items[0].total_score, expectedTotal);
|
||||
const csv = await (await api.get(base + 'api/admin/export')).text();
|
||||
assert(csv.includes('原始肌龄(推荐依据),前端展示肌龄'));
|
||||
assert(csv.includes(result.vm.recommendation.version));
|
||||
assert(csv.includes('综合得分(4:3:3)'));
|
||||
assert.equal(csv.trim().split('\n')[1].split(',')[14],String(expectedAge));
|
||||
assert.equal(csv.trim().split('\n')[1].split(',')[12], String(expectedTotal));
|
||||
const snapshot = await (await api.get(base + 'api/reports/' + result.record_id)).json();
|
||||
assert.equal(snapshot.report.photos.length, 3);
|
||||
@@ -85,10 +100,10 @@ try {
|
||||
await row.waitFor();
|
||||
assert.equal(await row.locator('td').nth(6).textContent(), String(expectedTotal));
|
||||
assert((await row.textContent()).includes('原始 ' + result.vm.skinAgeRaw + '岁'));
|
||||
assert((await row.textContent()).includes('展示 ' + result.vm.skinAgeRaw + '岁'));
|
||||
assert((await row.textContent()).includes('展示 ' + expectedAge + '岁'));
|
||||
assert((await row.textContent()).includes("1'me 主场精华 I(25+)"));
|
||||
for (const key of ['firm', 'vita', 'stab']) {
|
||||
assert((await row.textContent()).includes(ReportUI.dimNames[key] + ' ' + result.vm.dims[key].S.toFixed(1) + ' ' + ReportUI.levelMap[result.vm.dims[key].level]));
|
||||
assert((await row.textContent()).includes(ReportUI.dimNames[key] + ' ' + ReportUI.dimensionScore(result.vm.dims[key].S) + ' ' + ReportUI.levelMap[result.vm.dims[key].level]));
|
||||
}
|
||||
assert.deepEqual(await desktop.locator('#f-dimlevel option').allTextContents(), ['不限档位', '改善', '良好', '优秀']);
|
||||
if (process.env.H5_ARTIFACT_DIR) {
|
||||
@@ -105,9 +120,16 @@ try {
|
||||
const detailText = await desktop.locator('#d-body').textContent();
|
||||
assert(detailText.includes('综合得分 ' + expectedTotal));
|
||||
assert(detailText.includes('紧塑力×4+透亮感×3+稳韧力×3'));
|
||||
assert(detailText.includes('痘痘三视图计分明细'));
|
||||
assert(detailText.includes('黑眼圈评分×20%'));
|
||||
const acneAuditRows=desktop.locator('.d-sec').filter({hasText:'痘痘三视图计分明细'}).locator('tbody tr');
|
||||
assert.equal(await acneAuditRows.count(),5);
|
||||
for(const [i,t] of adminRecord.acne_scoring.types.entries()) {
|
||||
assert.deepEqual(await acneAuditRows.nth(i).locator('td').allTextContents(),[t.name,...['front','left','right'].map(k=>t.views[k]==null?'-':String(t.views[k])),t.count==null?'-':String(t.count),String(t.weight),t.deduction==null?'-':String(t.deduction)]);
|
||||
}
|
||||
if (process.env.H5_ARTIFACT_DIR) await desktop.screenshot({ path: path.join(process.env.H5_ARTIFACT_DIR, 'admin-weighted-detail.png') });
|
||||
assert(detailText.includes(result.vm.recommendation.reason));
|
||||
assert(detailText.includes('前端展示肌龄 ' + result.vm.skinAgeRaw + '岁'));
|
||||
assert(detailText.includes('前端展示肌龄 ' + expectedAge + '岁'));
|
||||
for (const view of result.presentation.views) assert(detailText.includes(view.text));
|
||||
for (const care of result.presentation.care) assert(detailText.includes(care.text));
|
||||
if (process.env.H5_ARTIFACT_DIR) {
|
||||
@@ -181,13 +203,17 @@ try {
|
||||
await page.click('[data-action="history"]');
|
||||
await page.click('[data-report-id]');
|
||||
await page.waitForSelector('#s-report.active');
|
||||
assert.equal(await page.locator('#stat-age b').textContent(), String(result.vm.skinAgeRaw), 'old saved display clamp must not override original skin age');
|
||||
assert.equal(await page.locator('#stat-age b').textContent(), String(expectedAge), 'historical raw age uses current ±5 display rule, not saved display');
|
||||
assert.equal(await page.locator('#stat-score b').textContent(), String(expectedTotal), 'old H5 report uses saved dimensions, not saved upstream total');
|
||||
const legacyList = await (await api.get(base + 'api/admin/records')).json();
|
||||
assert.equal(legacyList.items[0].skin_age_display, expectedAge);
|
||||
assert.equal(legacyList.items[0].total_score, expectedTotal);
|
||||
const legacyDetail = await (await api.get(base + 'api/admin/records/' + result.record_id)).json();
|
||||
assert.equal(legacyDetail.record.skin_age_display, expectedAge);
|
||||
assert.equal(legacyDetail.record.total_score, expectedTotal);
|
||||
assert.equal((await (await api.get(base + 'api/admin/export')).text()).trim().split('\n')[1].split(',')[12], String(expectedTotal));
|
||||
const legacyCsv=(await (await api.get(base + 'api/admin/export')).text()).trim().split('\n')[1].split(',');
|
||||
assert.equal(legacyCsv[12], String(expectedTotal));
|
||||
assert.equal(legacyCsv[14], String(expectedAge));
|
||||
assert.equal(await page.locator('#product-title').textContent(), ReportUI.products[1].title);
|
||||
assert.equal(await page.locator('#product-image').getAttribute('src'), ReportUI.products[1].image, 'refresh artwork crop, never the historical recommendation/copy');
|
||||
assert((await page.locator('.ditem-para').allTextContents()).includes(legacy.presentation.views[0].text));
|
||||
@@ -195,7 +221,7 @@ try {
|
||||
await desktop.locator('#tbl-records tbody tr').first().click();
|
||||
await desktop.waitForFunction(() => document.querySelector('#d-body').textContent.includes('历史报告原文'));
|
||||
assert((await desktop.locator('#d-body').textContent()).includes('旧版规则(历史记录)'));
|
||||
assert((await desktop.locator('#d-body').textContent()).includes('前端展示肌龄 ' + result.vm.skinAgeRaw + '岁'));
|
||||
assert((await desktop.locator('#d-body').textContent()).includes('前端展示肌龄 ' + expectedAge + '岁'));
|
||||
assert.equal(fs.readFileSync(snapshotFile, 'utf8'), storedBytes);
|
||||
assert.equal(fs.readFileSync(recordFile, 'utf8'), recordBytes);
|
||||
// An incomplete set must show no total everywhere, not fall back to the API score.
|
||||
|
||||
Reference in New Issue
Block a user