Files
YGChatCS/scripts/regression-long-answer-parsed-value-view.mjs

208 lines
5.5 KiB
JavaScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
import { pathToFileURL } from "node:url";
import { fileURLToPath } from "node:url";
const scriptDir = dirname(fileURLToPath(import.meta.url));
const componentPath = resolve(
scriptDir,
"../src/pages/ChatMain/ChatLongAnswer/ParsedValueView.vue"
);
const detailPagePath = resolve(
scriptDir,
"../src/pages/ChatMain/ChatLongAnswer/index.vue"
);
const longTextCardPath = resolve(scriptDir, "../src/utils/longTextCard.js");
const componentSource = readFileSync(componentPath, "utf8");
const detailPageSource = readFileSync(detailPagePath, "utf8");
const longTextCardSource = readFileSync(longTextCardPath, "utf8");
const {
appendLongTextChunk,
createLongTextData,
getLongTextSections,
} = await import(pathToFileURL(longTextCardPath));
assert.doesNotMatch(
longTextCardSource,
/normalizeLongText/,
"longTextCard should not contain field-specific normalize helpers"
);
assert.doesNotMatch(
longTextCardSource,
/spot_longitude|spot_latitude|spot_tag/,
"longTextCard should not know spot_locate child field names"
);
assert.doesNotMatch(
componentSource,
/isGenericObjectSectionField/,
"ParsedValueView should use renderFieldEntries instead of a separate generic object branch"
);
assert.match(
componentSource,
/getRenderEntriesForObject/,
"ParsedValueView should derive object rows through the existing entry renderer"
);
assert.doesNotMatch(
componentSource,
/STRUCTURED_SECTION_CONFIG/,
"ParsedValueView should not require per-field structured section config"
);
assert.doesNotMatch(
componentSource,
/LONG_TEXT_KEYS\.(preparationSection|sectionSuggestion|pitfallSection|viewSection|suggestionSection|lightReminder|photoSpotSection|phoneSection|decisionSection|routeWarning|tourRoutes|facilitiesAlongTheWay)/,
"ParsedValueView should not reference ordinary section keys individually"
);
assert.doesNotMatch(
componentSource,
/content-body-section-dot|content-body-section-list/,
"generic object arrays should keep the original list-card rendering style"
);
assert.doesNotMatch(
componentSource,
/entry\.type\s*===\s*'(question-suggest|photo-list|aigc-componet|commodity-list|spot-locate)'/,
"renderFieldEntries should only render generic text/image/list entries"
);
assert.doesNotMatch(
componentSource,
/createSpecialFieldEntry/,
"dedicated long text components should be selected by top-level computed branches only"
);
assert.match(
componentSource,
/shouldRenderQuestionSuggest/,
"top-level question_suggest fields should render through the dedicated chips"
);
assert.match(
componentSource,
/shouldRenderCommodityList/,
"top-level commodity_list fields should render through the dedicated product list"
);
assert.match(
componentSource,
/shouldRenderPhotoList/,
"top-level photo_list fields should render through the dedicated photo swiper"
);
assert.match(
componentSource,
/shouldRenderAigcComponet/,
"top-level aigc_componet fields should render through the dedicated AIGC card"
);
assert.match(
componentSource,
/shouldRenderSpotLocate/,
"top-level spot_locate fields should render through the dedicated POI card"
);
assert.doesNotMatch(
componentSource,
/createRenderEntry\(key,\s*entryKey,\s*value\[key\]\)/,
"nested object keys should not trigger dedicated long text components"
);
assert.match(
componentSource,
/openMap\(spotLocateValue\)/,
"ParsedValueView should render spot_locate with the dedicated POI action card"
);
assert.match(
componentSource,
/getSpotLocateValue/,
"ParsedValueView should own spot_locate value shaping"
);
assert.doesNotMatch(
componentSource,
/spot_longitude:|spot_latitude:|spot_tag:/,
"ParsedValueView should not read malformed spot_locate keys"
);
assert.match(
componentSource,
/shouldRenderQuestionSuggest/,
"ParsedValueView should render question_suggest with dedicated FAQ chips"
);
assert.match(
componentSource,
/getQuestionSuggestItems/,
"ParsedValueView should own question_suggest value shaping"
);
assert.match(
componentSource,
/sendReply\(question\)/,
"question_suggest chips should send the selected follow-up question"
);
assert.doesNotMatch(
detailPageSource,
/LONG_TEXT_KEYS\.content\b/,
"long answer detail page should not reference removed content key"
);
assert.match(
componentSource,
/LONG_TEXT_KEYS\.contentImage\b/,
"ParsedValueView should render content_image with the dedicated image style"
);
const ignoredFieldKeysMatch = componentSource.match(
/const\s+IGNORED_FIELD_KEYS\s*=\s*\[([\s\S]*?)\];/
);
assert.ok(
ignoredFieldKeysMatch,
"ParsedValueView should define IGNORED_FIELD_KEYS"
);
assert.doesNotMatch(
ignoredFieldKeysMatch[1],
/["']content_summary["']/,
"ParsedValueView should not ignore content_summary"
);
const receivedKeys = [
"tag",
"title",
"content_summary",
"scene_image",
"content_image",
"view_section",
"suggestion_section",
"light_reminder",
"spot_locate",
"question_suggest",
];
const longTextData = createLongTextData();
receivedKeys.forEach((key) => {
appendLongTextChunk(longTextData, { contentKey: key, contentValue: key });
});
appendLongTextChunk(longTextData, {
contentKey: "view_section_items",
contentValue: "old flat field",
});
assert.deepEqual(
getLongTextSections(longTextData).map((section) => section.contentKey),
[...receivedKeys, "view_section_items"],
"long text detail sections should keep configured fields first and preserve unknown contentKey fields"
);