mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-11-02 13:12:50 +00:00
fix(freehire-search): decode HTML entities and trim whitespace in titles (#505)
Titles are indexed as the source ATS wrote them and toResult passed them through untouched, so `detail intern-fullstack-amp-ai-innovation-noise-edaawqq2` printed `Intern - Fullstack & AI Innovation ` and the same title reached `search` output. In a 93-result /scrape batch, 1 title carried `&` and 3 ended in whitespace; /scrape Step 4.75 reads an undecoded entity in a title as a half-working parser. Run the title through the existing decodeHtmlEntities (already used for detail descriptions) and trim it; an empty or whitespace-only title still falls back to "(untitled)". Three new parsing.test.ts cases pin it; all three fail on the old pass-through. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9187f894a5
commit
4f5520841f
3 files changed
+37
-2
No files matched your search
@@ -145,11 +145,15 @@ export interface JobDetailResult extends JobResult {
|
||||
description: string | null
|
||||
}
|
||||
|
||||
/** Reshape a freehire job into the contract search-result fields. */
|
||||
/**
|
||||
* Reshape a freehire job into the contract search-result fields. The title comes
|
||||
* from the source ATS as indexed, which can carry HTML entities and stray
|
||||
* whitespace ("Intern - Fullstack & AI Innovation "), so it is decoded and trimmed.
|
||||
*/
|
||||
export function toResult(j: FreehireJob): JobResult {
|
||||
return {
|
||||
id: j.public_slug,
|
||||
title: j.title || "(untitled)",
|
||||
title: decodeHtmlEntities(j.title || "").trim() || "(untitled)",
|
||||
company: j.company || null,
|
||||
company_slug: j.company_slug || null,
|
||||
location: j.location || null,
|
||||
|
||||
@@ -49,6 +49,24 @@ describe("toResult — reshape into the portal-skill contract", () => {
|
||||
expect(r.date).toBeNull();
|
||||
expect(r.work_mode).toBeNull();
|
||||
});
|
||||
|
||||
test("decodes HTML entities and trims whitespace in the title", () => {
|
||||
// Real title from the index (freehire slug intern-fullstack-amp-ai-innovation-noise-edaawqq2).
|
||||
expect(toResult(job({ title: "Intern - Fullstack & AI Innovation " })).title).toBe(
|
||||
"Intern - Fullstack & AI Innovation",
|
||||
);
|
||||
expect(toResult(job({ title: "R&D Engineer" })).title).toBe("R&D Engineer");
|
||||
expect(toResult(job({ title: "SDE Intern - Frontend " })).title).toBe("SDE Intern - Frontend");
|
||||
});
|
||||
|
||||
test("a whitespace-only title still falls back to (untitled)", () => {
|
||||
expect(toResult(job({ title: " " })).title).toBe("(untitled)");
|
||||
expect(toResult(job({ title: "" })).title).toBe("(untitled)");
|
||||
});
|
||||
|
||||
test("detail inherits the cleaned title", () => {
|
||||
expect(toDetail(job({ title: "Data & Analytics Intern" })).title).toBe("Data & Analytics Intern");
|
||||
});
|
||||
});
|
||||
|
||||
describe("toDetail — adds cleaned description + enrichment", () => {
|
||||
|
||||
@@ -105,6 +105,19 @@ per-file diff commands.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **`freehire-search` titles no longer carry HTML entities or stray whitespace**
|
||||
(`.agents/skills/freehire-search/cli/src/helpers.ts`) - titles are indexed as the source ATS
|
||||
wrote them and `toResult` passed them through untouched, so `detail
|
||||
intern-fullstack-amp-ai-innovation-noise-edaawqq2` printed `Intern - Fullstack & AI
|
||||
Innovation ` (trailing space included), and the same title reached `search` output. In a
|
||||
93-result `/scrape` batch (`--country IN --seniority intern`), 1 title carried `&` and 3
|
||||
ended in whitespace. `/scrape` Step 4.75 reads undecoded entities in titles as a
|
||||
half-working parser, so by that rule a single such posting marks a healthy portal
|
||||
degraded. The title now goes through the CLI's existing `decodeHtmlEntities` (already used
|
||||
for `detail` descriptions) and is trimmed; an empty or whitespace-only title still falls
|
||||
back to `(untitled)`. Pinned by three new `parsing.test.ts` cases, which fail on the old
|
||||
pass-through.
|
||||
|
||||
- **`freehire-search detail` keeps the salary period, so a yearly figure no longer reads as
|
||||
monthly** (`.agents/skills/freehire-search/cli/src/helpers.ts`, `SKILL.md`) - `formatSalary`
|
||||
printed only the currency and amounts, although freehire's enrichment records the period:
|
||||
|
||||
Reference in new issue
Block a user