80 lines
3.6 KiB
JavaScript
80 lines
3.6 KiB
JavaScript
import test from 'node:test';
|
||
import assert from 'node:assert/strict';
|
||
import { createRequire } from 'node:module';
|
||
|
||
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('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);
|
||
});
|