67 lines
4.2 KiB
JavaScript
67 lines
4.2 KiB
JavaScript
// tests/providers/beesite.test.mjs — moved verbatim from test-all.mjs (#1440).
|
|
import { pass, fail, ROOT } from '../helpers.mjs';
|
|
import { join } from 'path';
|
|
import { pathToFileURL } from 'url';
|
|
|
|
console.log('\nProvider — beesite (milch \& zucker GJB search API)');
|
|
try {
|
|
const beesiteModule = await import(pathToFileURL(join(ROOT, 'providers/beesite.mjs')).href);
|
|
const beesite = beesiteModule.default;
|
|
const { resolveConfig: beeConfig, buildSearchUrl, parseBeesiteDate, parseSearchResult } = beesiteModule;
|
|
|
|
if (beesite.id === 'beesite') pass('beesite.id is "beesite"');
|
|
else fail(`beesite.id is ${JSON.stringify(beesite.id)}`);
|
|
|
|
// resolveConfig — host-anchored, config block passthrough.
|
|
const bCfg = beeConfig({
|
|
api: 'https://mercedes-benz-beesite-production-gjb.app.beesite.de',
|
|
beesite: { languageCode: 'DE', searchCriteria: [{ CriterionName: 'PositionLocation.Country', CriterionValue: [329] }] },
|
|
});
|
|
if (bCfg && bCfg.searchApi === 'https://mercedes-benz-beesite-production-gjb.app.beesite.de/search' && bCfg.languageCode === 'DE' && bCfg.searchCriteria.length === 1) {
|
|
pass('beesite.resolveConfig() parses host and passes the beesite config block through');
|
|
} else {
|
|
fail(`beesite.resolveConfig() wrong: ${JSON.stringify(bCfg)}`);
|
|
}
|
|
if (beesite.detect({ careers_url: 'https://evil.com/x.beesite.de' }) === null && beesite.detect({ careers_url: 'https://beesite.de.evil.com/x' }) === null) {
|
|
pass('beesite.detect() rejects path- and suffix-spoofed hosts');
|
|
} else {
|
|
fail('beesite.detect() should reject spoofed hosts');
|
|
}
|
|
|
|
// buildSearchUrl — FirstItem lands in the encoded payload.
|
|
const bUrl = buildSearchUrl(bCfg, 101);
|
|
if (bUrl.startsWith(bCfg.searchApi + '?data=') && decodeURIComponent(bUrl).includes('"FirstItem":101') && decodeURIComponent(bUrl).includes('"CriterionValue":[329]')) {
|
|
pass('beesite.buildSearchUrl() encodes FirstItem and the pinned criteria');
|
|
} else {
|
|
fail(`beesite.buildSearchUrl() wrong: ${bUrl.slice(0, 140)}`);
|
|
}
|
|
|
|
if (parseBeesiteDate('2026-07-04') === Date.UTC(2026, 6, 4) && parseBeesiteDate('junk') === undefined) pass('beesite.parseBeesiteDate() reads YYYY-MM-DD, rejects junk');
|
|
else fail('beesite.parseBeesiteDate() wrong');
|
|
|
|
// parseSearchResult — id/title/absolute-URL required, cities joined.
|
|
const mkItem = (id, title, uri) => ({ MatchedObjectId: String(id), MatchedObjectDescriptor: { PositionID: `x${id}`, PositionTitle: title, PositionURI: uri, PositionLocation: [{ CityName: 'Bremen' }, { CityName: 'Berlin' }], PublicationStartDate: '2026-07-04' } });
|
|
const beeJson = { SearchResult: { SearchResultCount: 2, SearchResultCountAll: 42, SearchResultItems: [
|
|
mkItem(1, 'IT Architect', 'https://jobs.example.com/a-1'),
|
|
{ MatchedObjectId: '2', MatchedObjectDescriptor: { PositionTitle: 'No URI — dropped', PositionURI: '/relative' } },
|
|
] } };
|
|
const { total: beeTotal, rows: beeRows } = parseSearchResult(beeJson);
|
|
if (beeTotal === 42 && beeRows.length === 1 && beeRows[0].location === 'Bremen / Berlin' && beeRows[0].postedAt === Date.UTC(2026, 6, 4)) {
|
|
pass('beesite.parseSearchResult() maps items, joins cities, drops non-absolute URIs');
|
|
} else {
|
|
fail(`beesite.parseSearchResult() wrong: total=${beeTotal} rows=${JSON.stringify(beeRows)}`);
|
|
}
|
|
|
|
// fetch — paginates by FirstItem until SearchResultCountAll, dedups.
|
|
const beePage = (ids) => ({ SearchResult: { SearchResultCount: ids.length, SearchResultCountAll: 150, SearchResultItems: ids.map((i) => mkItem(i, `Job ${i}`, `https://jobs.example.com/j-${i}`)) } });
|
|
const beePages = [beePage(Array.from({ length: 100 }, (_, i) => i + 1)), beePage([100, 101, 102])];
|
|
let beeCalls = 0;
|
|
const beeSeen = [];
|
|
const beeCtx = { sleep: async () => {}, fetchJson: async (url) => { beeSeen.push(decodeURIComponent(url)); return beePages[beeCalls++] ?? beePage([]); } };
|
|
const beeJobs = await beesite.fetch({ name: 'MB', api: 'https://x.app.beesite.de' }, beeCtx);
|
|
if (beeJobs.length === 102 && beeCalls === 2 && beeSeen[1].includes('"FirstItem":101')) pass('beesite.fetch() paginates via FirstItem and dedups across pages');
|
|
else fail(`beesite.fetch() returned ${beeJobs.length} jobs after ${beeCalls} calls`);
|
|
} catch (e) {
|
|
fail(`beesite provider tests crashed: ${e.message}`);
|
|
}
|