Files
wehub-resource-sync 9b395f5cc3
E2E Headed Chrome / e2e-headed (macos-15) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (ubuntu-latest) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (windows-latest) (push) Has been cancelled
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
CI / unit-test (push) Has been cancelled
CI / bun-test (push) Has been cancelled
CI / adapter-test (push) Has been cancelled
CI / smoke-test (macos-latest) (push) Has been cancelled
CI / smoke-test (ubuntu-latest) (push) Has been cancelled
Security Audit / audit (push) Has been cancelled
Build Chrome Extension / build (push) Has been cancelled
Trigger Website Rebuild (Docs Updated) / dispatch (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:39:48 +08:00

154 lines
7.6 KiB
JavaScript

import { describe, expect, it } from 'vitest';
import { __test__ } from './search.js';
describe('jianyu search helpers', () => {
it('builds candidate URLs with supsearch as preferred entry', () => {
const candidates = __test__.buildSearchCandidates('procurement');
expect(candidates[0]).toContain('/jylab/supsearch/index.html');
expect(candidates[0]).toContain('keywords=procurement');
expect(candidates[0]).toContain('selectType=title');
expect(candidates[0]).toContain('searchGroup=1');
});
it('builds supsearch URL with required query params', () => {
const url = __test__.buildSearchUrl('procurement');
expect(url).toContain('keywords=procurement');
expect(url).toContain('selectType=title');
expect(url).toContain('searchGroup=1');
});
it('normalizes common date formats', () => {
expect(__test__.normalizeDate('2026-4-7')).toBe('2026-04-07');
expect(__test__.normalizeDate('2026年4月7日')).toBe('2026-04-07');
expect(__test__.normalizeDate('发布时间: 2026/04/07 09:00')).toBe('2026-04-07');
});
it('deduplicates by title and url', () => {
const deduped = __test__.dedupeCandidates([
{ title: 'A', url: 'https://example.com/1', date: '2026-04-07' },
{ title: 'A', url: 'https://example.com/1', date: '2026-04-07' },
{ title: 'A', url: 'https://example.com/2', date: '2026-04-07' },
]);
expect(deduped).toHaveLength(2);
});
it('filters obvious navigation rows before quality gate', () => {
const filtered = __test__.filterNavigationRows('电梯', [
{ title: '招标公告', url: 'https://www.jianyu360.cn/list/stype/ZBGG.html', date: '' },
{ title: '帮助中心', url: 'https://www.jianyu360.cn/helpCenter/index', date: '' },
{ title: '某项目电梯采购公告', url: 'https://www.jianyu360.cn/notice/detail/123', date: '2026-04-07' },
]);
expect(filtered).toHaveLength(1);
expect(filtered[0].title).toContain('电梯采购公告');
});
it('rejects procurement rows that do not contain query evidence', () => {
const filtered = __test__.filterNavigationRows('电梯', [
{
title: '某项目采购公告',
url: 'https://www.jianyu360.cn/notice/detail/123',
date: '2026-04-07',
contextText: '招标公告 项目编号:ABC-123',
},
]);
expect(filtered).toHaveLength(0);
});
it('parses search-index markdown headings', () => {
const rows = __test__.parseSearchIndexMarkdown(`
## [标题一](http://duckduckgo.com/l/?uddg=https%3A%2F%2Fbeijing.jianyu360.cn%2Fjybx%2F20260401_26033143187897.html)
## [标题二](https://www.jianyu360.cn/nologin/content/ABC.html)
`);
expect(rows).toHaveLength(2);
expect(rows[0].title).toBe('标题一');
expect(rows[1].url).toContain('jianyu360.cn/nologin/content');
});
it('unwraps duckduckgo redirect links', () => {
const direct = __test__.unwrapDuckDuckGoUrl('https://duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.jianyu360.cn%2Fnologin%2Fcontent%2FXYZ.html');
expect(direct).toBe('https://www.jianyu360.cn/nologin/content/XYZ.html');
});
it('extracts publish date from jianyu jybx urls', () => {
const date = __test__.extractDateFromJianyuUrl('https://shandong.jianyu360.cn/jybx/20260310_26030938267551.html');
expect(date).toBe('2026-03-10');
});
it('normalizes api payload rows with fallback url/title fields', () => {
const normalized = __test__.normalizeApiRow({
noticeTitle: '某项目电梯采购公告',
detailUrl: '/jybx/20260310_26030938267551.html',
publishTime: '2026-03-10 09:00:00',
buyer: '测试单位',
});
expect(normalized).toBeTruthy();
expect(normalized?.title).toContain('电梯采购公告');
expect(normalized?.url).toContain('/jybx/20260310_26030938267551.html');
expect(normalized?.date).toBe('2026-03-10');
});
it('keeps later bucket unique api rows before final filtering and slice', async () => {
const page = {
goto: async () => { },
wait: async () => { },
evaluate: async () => ({
challenge: false,
responses: [
{
type: 'fType',
ok: true,
status: 200,
payload: {
list: [
{
noticeTitle: '某项目电梯采购公告',
detailUrl: '/jybx/20260310_26030938267551.html',
publishTime: '2026-03-10 09:00:00',
},
{
noticeTitle: '某项目电梯采购公告',
detailUrl: '/jybx/20260310_26030938267551.html',
publishTime: '2026-03-10 09:00:00',
},
],
},
},
{
type: 'eType',
ok: true,
status: 200,
payload: {
list: [
{
noticeTitle: '另一条电梯采购公告',
detailUrl: '/jybx/20260311_26030938267552.html',
publishTime: '2026-03-11 09:00:00',
},
],
},
},
],
}),
};
const result = await __test__.fetchJianyuApiRows(page, '电梯', 1);
expect(result.challenge).toBe(false);
expect(result.rows).toHaveLength(2);
expect(result.rows[0].title).toContain('电梯采购公告');
expect(result.rows[1].title).toContain('另一条电梯采购公告');
});
it('classifies nologin links as blocked detail targets', () => {
const signal = __test__.classifyDetailStatus('https://www.jianyu360.cn/nologin/content/ABC.html');
expect(signal.detail_status).toBe('blocked');
});
it('classifies accessible detail urls as ok even when they are not jybx paths', () => {
const signal = __test__.classifyDetailStatus('https://www.jianyu360.cn/notice/detail/123');
expect(signal.detail_status).toBe('ok');
expect(signal.detail_reason).toBe('detail_candidate');
});
it('classifies list pages as entry_only', () => {
const signal = __test__.classifyDetailStatus('https://www.jianyu360.cn/list/stype/ZBGG.html');
expect(signal.detail_status).toBe('entry_only');
});
it('extracts stable notice id from jybx urls', () => {
const id = __test__.extractNoticeId('https://shandong.jianyu360.cn/jybx/20260310_26030938267551.html');
expect(id).toBe('20260310_26030938267551');
});
it('keeps only rows inside recency window', () => {
const within = __test__.isWithinSinceDays('2026-03-20', 30, new Date('2026-04-09T00:00:00Z'));
const stale = __test__.isWithinSinceDays('2026-02-01', 30, new Date('2026-04-09T00:00:00Z'));
const missing = __test__.isWithinSinceDays('', 30, new Date('2026-04-09T00:00:00Z'));
expect(within).toBe(true);
expect(stale).toBe(false);
expect(missing).toBe(false);
});
});