2026-07-10 13:05:40 +07:00
|
|
|
import { describe, expect, test } from "bun:test";
|
|
|
|
|
import { parseJobPostingFromHtml } from "../src/commands/detail";
|
|
|
|
|
|
|
|
|
|
const HTML_WITHOUT_JSON_LD = `<!doctype html>
|
|
|
|
|
<html lang="da">
|
|
|
|
|
<head>
|
|
|
|
|
<title>Journalistisk udvikler søges | jobdanmark</title>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div class="job-list-details">
|
|
|
|
|
<div class="job-details-head row mx-0">
|
|
|
|
|
<div class="company-logo col-auto">
|
|
|
|
|
<img src="/media/jfm-logo.png?width=100" alt="JFM">
|
|
|
|
|
</div>
|
|
|
|
|
<h3 class="title">Journalistisk udvikler søges</h3>
|
|
|
|
|
<a href="/virksomheder/jfm">JFM</a>
|
|
|
|
|
<span>Banegårdspladsen 1, 5000 Odense C</span>
|
|
|
|
|
</div>
|
|
|
|
|
<p>Hvad nu hvis du med få klik kunne undersøge dit lokalområde?</p>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>identificere relevante datasæt og muligheder</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
<a href="https://jfm.career.emply.com/da/apply/example" class="action primary count-click">Ansøg nu</a>
|
|
|
|
|
<ul class="job-overview list-unstyled">
|
|
|
|
|
<li><strong>Udgivet:</strong> 03-07-2026</li>
|
|
|
|
|
<li><strong>Jobtype:</strong> Fuldtid</li>
|
|
|
|
|
<li><strong>Arbejdssted:</strong> Banegårdspladsen 1, 5000 Odense C</li>
|
|
|
|
|
<li><strong>Ansøgningsfrist:</strong> 02-08-2026 23.59</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</body>
|
|
|
|
|
</html>`;
|
|
|
|
|
|
|
|
|
|
describe("parseJobPostingFromHtml", () => {
|
|
|
|
|
test("falls back to rendered Jobdanmark HTML when JSON-LD is absent", () => {
|
|
|
|
|
const parsed = parseJobPostingFromHtml(
|
|
|
|
|
HTML_WITHOUT_JSON_LD,
|
|
|
|
|
"journalistisk-udvikler",
|
|
|
|
|
"https://jobdanmark.dk/job/journalistisk-udvikler",
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(parsed.title).toBe("Journalistisk udvikler søges");
|
2026-08-19 20:53:24 +02:00
|
|
|
// The fallback must emit the same shapes as the JSON-LD branch: contract
|
|
|
|
|
// dates, not the page's raw DD-MM-YYYY text (review finding F25, 2026-08-19).
|
|
|
|
|
expect(parsed.datePosted).toBe("2026-07-03");
|
|
|
|
|
expect(parsed.validThrough).toBe("2026-08-02");
|
2026-07-10 13:05:40 +07:00
|
|
|
expect(parsed.employmentType).toEqual(["Fuldtid"]);
|
|
|
|
|
expect(parsed.hiringOrganization.name).toBe("JFM");
|
|
|
|
|
expect(parsed.hiringOrganization.logo).toBe("https://jobdanmark.dk/media/jfm-logo.png?width=100");
|
|
|
|
|
expect(parsed.jobLocation.streetAddress).toBe("Banegårdspladsen 1, 5000 Odense C");
|
2026-08-19 20:53:24 +02:00
|
|
|
expect(parsed.jobLocation.addressLocality).toBe("Odense C");
|
2026-07-10 13:05:40 +07:00
|
|
|
expect(parsed.description).toContain("identificere relevante datasæt");
|
|
|
|
|
expect(parsed.applyUrl).toBe("https://jfm.career.emply.com/da/apply/example");
|
|
|
|
|
});
|
2026-07-21 01:11:20 -05:00
|
|
|
|
2026-08-19 20:53:24 +02:00
|
|
|
test("maps a rolling deadline (Løbende) to null in the HTML fallback", () => {
|
|
|
|
|
// "Løbende" is free text meaning rolling/ongoing - jobbank's parser maps
|
|
|
|
|
// its equivalent to null, and a stored "Løbende" deadline would hit every
|
|
|
|
|
// date-arithmetic consumer (review finding F25, 2026-08-19).
|
|
|
|
|
const html = HTML_WITHOUT_JSON_LD.replace(
|
|
|
|
|
"<li><strong>Ansøgningsfrist:</strong> 02-08-2026 23.59</li>",
|
|
|
|
|
"<li><strong>Ansøgningsfrist:</strong> Løbende</li>",
|
|
|
|
|
);
|
|
|
|
|
const parsed = parseJobPostingFromHtml(html, "s", "https://jobdanmark.dk/job/s");
|
|
|
|
|
expect(parsed.validThrough).toBeNull();
|
|
|
|
|
});
|
|
|
|
|
|
2026-07-21 01:11:20 -05:00
|
|
|
test("does not reject titles containing '404' mid-phrase", () => {
|
|
|
|
|
const htmlWith404InTitle = HTML_WITHOUT_JSON_LD.replace(
|
|
|
|
|
"<title>Journalistisk udvikler søges | jobdanmark</title>",
|
|
|
|
|
"<title>HTTP 404 Page Designer | jobdanmark</title>",
|
|
|
|
|
).replace(
|
|
|
|
|
'<h3 class="title">Journalistisk udvikler søges</h3>',
|
|
|
|
|
'<h3 class="title">HTTP 404 Page Designer</h3>',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const parsed = parseJobPostingFromHtml(
|
|
|
|
|
htmlWith404InTitle,
|
|
|
|
|
"http-404-designer",
|
|
|
|
|
"https://jobdanmark.dk/job/http-404-designer",
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(parsed.title).toBe("HTTP 404 Page Designer");
|
|
|
|
|
expect(parsed.hiringOrganization.name).toBe("JFM");
|
|
|
|
|
});
|
2026-07-10 13:05:40 +07:00
|
|
|
});
|