mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-09-18 09:06:24 +00:00
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>
55 lines
2.0 KiB
TypeScript
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");
|
|
});
|
|
});
|