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); });