diff --git a/.agents/skills/jobbank-search/cli/src/commands/detail.ts b/.agents/skills/jobbank-search/cli/src/commands/detail.ts index b752b3e..5da2d6e 100644 --- a/.agents/skills/jobbank-search/cli/src/commands/detail.ts +++ b/.agents/skills/jobbank-search/cli/src/commands/detail.ts @@ -1,7 +1,6 @@ import { defineCommand, option } from "@bunli/core" import { z } from "zod" -import { fetchWithUA, writeError, BASE_URL } from "../helpers.js" -import { parse as parseHtml } from "node-html-parser" +import { fetchWithUA, parseJobPostingJsonLd, writeError, BASE_URL } from "../helpers.js" export const detail = defineCommand({ name: "detail", @@ -39,31 +38,7 @@ export const detail = defineCommand({ if (signal.aborted) return - const root = parseHtml(html) - - // Find all ` + +describe("parseJobPostingJsonLd", () => { + test("finds a JobPosting inside an @graph", () => { + const html = script( + JSON.stringify({ + "@context": "https://schema.org", + "@graph": [ + { "@type": "WebPage", name: "Jobs" }, + { "@type": "JobPosting", title: "Data Engineer" }, + ], + }), + ) + + expect(parseJobPostingJsonLd(html)).toEqual({ + "@type": "JobPosting", + title: "Data Engineer", + }) + }) + + test("preserves top-level object and array support", () => { + expect(parseJobPostingJsonLd(script('{"@type":"JobPosting","title":"One"}'))?.title).toBe("One") + expect( + parseJobPostingJsonLd(script('[{"@type":"WebPage"},{"@type":"JobPosting","title":"Two"}]'))?.title, + ).toBe("Two") + }) + + test("skips malformed scripts and checks later JSON-LD", () => { + const html = `${script("{not-json")}${script('{"@type":"JobPosting","title":"Valid"}')}` + + expect(parseJobPostingJsonLd(html)?.title).toBe("Valid") + }) + + test("returns null when no JobPosting exists", () => { + expect(parseJobPostingJsonLd(script('{"@graph":[{"@type":"WebPage"}]}'))).toBeNull() + }) +})