Files
LWLT-AIBOT/tools/product-lookup.test.mjs
2026-09-02 19:29:04 +08:00

113 lines
5.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import test from 'node:test';
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { readFileSync } from 'node:fs';
const require = createRequire(import.meta.url);
const lookup = require('../chrome-extension/ltjt-order-assistant/product-lookup.js');
const sourceRegion = require('../chrome-extension/ltjt-order-assistant/source-region.js');
function candidate(cpid, label) {
return { cpid, label, name: lookup.productNameAndDuration(label).name, duration: lookup.productNameAndDuration(label).duration };
}
test('matches the ERP product name and duration as separate fields', () => {
const row = candidate('365', '江西老挝 10D9N');
const result = lookup.productQueryMatch(row, '江西老挝10D');
assert.equal(result.matched, true);
assert.equal(row.name, '江西老挝');
assert.equal(row.duration, '10D9N');
assert.match(result.rule, /^unique_(contiguous|name_duration_tokens)$/);
});
test('does not confuse a reversed route fragment with the 江西 product', () => {
const result = lookup.productQueryMatch(candidate('419', '尊享邂逅老挝--江西--9.10月份 8D7N'), '江西老挝10D');
assert.equal(result.matched, false);
});
test('matches punctuation-separated Chinese fragments and Chinese duration aliases', () => {
const result = lookup.productQueryMatch(candidate('412', '老挝行程--广东 8D7N'), '老挝广东8天');
assert.equal(result.matched, true);
assert.equal(result.rule, 'unique_name_duration_tokens');
});
test('preserves numeric product names while matching a duration suffix', () => {
const result = lookup.productQueryMatch(candidate('368', '尊享老挝3.10 8D7N'), '尊享老挝3.10');
assert.equal(result.matched, true);
assert.equal(result.rule, 'unique_contiguous');
});
test('uses the complete ERP product name as the first native search query', () => {
const keyword = '全国散--八天--版纳动车拉邦进万象出';
assert.deepEqual(lookup.nativeProductSearchQueries(keyword), [keyword, '']);
const matches = lookup.matchProductCandidates([
candidate('live-target', '全国散--八天--版纳动车拉邦进万象出 8D7N')
], keyword);
assert.equal(matches.length, 1);
assert.equal(matches[0].cpid, 'live-target');
});
test('removes only a trailing numeric duration from the native name query', () => {
assert.deepEqual(lookup.nativeProductSearchQueries('江西老挝10D'), ['江西老挝', '']);
assert.deepEqual(lookup.nativeProductSearchQueries('老挝广东8天'), ['老挝广东', '']);
assert.deepEqual(
lookup.nativeProductSearchQueries('全国散--八天--版纳动车拉邦进万象出 8D7N'),
['全国散--八天--版纳动车拉邦进万象出', '']
);
assert.deepEqual(lookup.nativeProductSearchQueries('尊享老挝3.10'), ['尊享老挝3.10', '']);
});
test('both S_chanpinming order adapters execute the planned native queries', () => {
const sources = [
readFileSync(new URL('../chrome-extension/ltjt-order-assistant/inpage.js', import.meta.url), 'utf8'),
readFileSync(new URL('../chrome-extension/ltjt-order-assistant/team-batch-inpage.js', import.meta.url), 'utf8')
];
for (const source of sources) {
assert.match(source, /for \(const nativeQuery of nativeProductSearchQueries\(/u);
assert.match(source, /reloadProductsForLocalMatch\([^\n]+nativeQuery\)/u);
assert.match(source, /native_query_then_local/u);
}
});
test('keeps unique-match safety when multiple candidates satisfy a shorthand', () => {
const matches = lookup.matchProductCandidates([
candidate('401', '老挝广东 8D7N'),
candidate('402', '老挝广东 8D6N')
], '老挝广东8D');
assert.equal(matches.length, 2);
});
test('keeps source-region tokens as a customer-only fallback, not a product/customer gate', () => {
const result = sourceRegion.uniqueSourceRegionCandidate([
{ id: '661', name: 'LW衡阳国旅云南分社广东市场' }
], { name: '广东衡阳客户' });
assert.equal(result.ok, true);
assert.equal(result.reason, 'unique_source_region_candidate');
assert.deepEqual(result.source_tokens, ['广东', '衡阳']);
assert.equal(result.candidate.id, '661');
});
test('resolves a non-canonical customer phrase by all source-region tokens only when unique', () => {
const candidates = [
{ id: '518', name: 'LW衡阳国旅北京市场' },
{ id: '661', name: 'LW衡阳国旅云南分社广东市场' },
{ id: '272', name: '广东光大国际正东分公司' }
];
const result = sourceRegion.uniqueSourceRegionCandidate(candidates, { name: '广东衡阳客户' });
assert.equal(result.ok, true);
assert.equal(result.match_count, 1);
assert.deepEqual(result.source_tokens, ['广东', '衡阳']);
assert.equal(result.candidate.id, '661');
});
test('does not guess when source-region keywords match multiple customer masters', () => {
const result = sourceRegion.uniqueSourceRegionCandidate([
{ id: '661', name: 'LW衡阳国旅云南分社广东市场' },
{ id: '1661', name: 'LW衡阳国旅深圳分社广东市场' }
], { name: '广东衡阳客户' });
assert.equal(result.ok, false);
assert.equal(result.reason, 'ambiguous_source_region_candidates');
assert.equal(result.match_count, 2);
assert.equal(result.candidate, null);
});