Files
ai-job-search/.agents/skills/jobindex-search/cli/tests/search-page.test.ts
T
Mads LorentzenandClaude Opus 5 2edf8c41f1 test(portals): cover linkedin card date/location and jobindex parseSearchPage
The linkedin fixture was purpose-built for entity decoding and had no
<time> or location element, so removing the date extraction - a /scrape
contract field on a default-ON portal - survived the suite. jobindex's
parseSearchPage (the Stash parser behind every search) had zero tests,
so meta.total silently dropping hitcount survived too. Both mutations
now fail exactly the new tests. The ASAP deadline branch is deliberately
left to the F12 fix, which changes its behaviour to null. Review finding
F35 (2026-08-19).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 20:03:00 +02:00

55 lines
2.0 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import { parseSearchPage } from "../src/helpers";
// parseSearchPage had no tests at all: mutating total to stop using
// sr.hitcount survived the whole suite (review finding F35, 2026-08-19).
// The fixture mirrors the real Stash nesting documented in helpers.ts:
// jobsearch/result_app -> storeData -> searchResponse -> { hitcount, results[] }.
function stashPage(searchResponse: object): string {
const stash = { jobsearch: { result_app: { storeData: { searchResponse } } } };
return `<html><head><script>var Stash = ${JSON.stringify(stash)};</script></head></html>`;
}
const RESULT = {
tid: "h1689961",
headline: "Softwareudvikler",
company: { name: "Acme A/S", homeurl: "https://acme.example" },
area: "Aarhus",
firstdate: "2026-08-10",
apply_deadline: "2026-09-11T00:00:00",
};
describe("parseSearchPage", () => {
test("total comes from hitcount, not the page's result count", () => {
const page = stashPage({ hitcount: 435, results: [RESULT] });
const parsed = parseSearchPage(page);
expect(parsed.total).toBe(435);
expect(parsed.results).toHaveLength(1);
});
test("total falls back to the result count when hitcount is absent", () => {
const page = stashPage({ results: [RESULT, { ...RESULT, tid: "h2" }] });
expect(parseSearchPage(page).total).toBe(2);
});
test("maps the contract fields from a Stash result", () => {
const [job] = parseSearchPage(stashPage({ hitcount: 1, results: [RESULT] })).results;
expect(job).toMatchObject({
id: "h1689961",
title: "Softwareudvikler",
company: "Acme A/S",
location: "Aarhus",
date: "2026-08-10",
deadline: "2026-09-11",
url: "https://www.jobindex.dk/jobannonce/h1689961",
});
});
test("falls back to lastdate when apply_deadline is absent", () => {
const [job] = parseSearchPage(
stashPage({ hitcount: 1, results: [{ ...RESULT, apply_deadline: undefined, lastdate: "2026-09-30" }] }),
).results;
expect(job.deadline).toBe("2026-09-30");
});
});