mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-09-17 00:26:26 +00:00
fix(portal-clis): accept full posting URLs in jobbank, jobdanmark, and jobnet detail commands (#430)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { defineCommand, option } from "@bunli/core"
|
||||
import { z } from "zod"
|
||||
import { apiFetch, writeError, stripHtml } from "../helpers.js"
|
||||
import { apiFetch, normalizeJobId, writeError, stripHtml } from "../helpers.js"
|
||||
|
||||
export interface DetailApiResponse {
|
||||
id: string
|
||||
@@ -87,12 +87,18 @@ export const detail = defineCommand({
|
||||
handler: async ({ positional, flags, signal }) => {
|
||||
if (signal.aborted) return
|
||||
|
||||
const id = positional[0] as string | undefined
|
||||
if (!id) {
|
||||
const rawId = positional[0] as string | undefined
|
||||
if (!rawId) {
|
||||
writeError("Job ad ID is required", "MISSING_REQUIRED")
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const id = normalizeJobId(rawId)
|
||||
if (!id) {
|
||||
writeError(`Could not parse job ad ID from "${rawId}"`, "BAD_ID")
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
try {
|
||||
const data = prepareDetail(
|
||||
await apiFetch<DetailApiResponse>(`/FindJob/JobAdDetails/${id}`, {
|
||||
|
||||
@@ -55,3 +55,13 @@ export function stripHtml(html: string): string {
|
||||
.replace(/\s+/g, " ")
|
||||
.trim()
|
||||
}
|
||||
|
||||
export function normalizeJobId(input: string): string | null {
|
||||
const trimmed = input.trim()
|
||||
if (!trimmed) return null
|
||||
if (/^[a-zA-Z0-9_-]+$/.test(trimmed)) return trimmed
|
||||
const match = trimmed.match(/(?:\/find-job\/|\/JobAdDetails\/|\/Details\/)(?:detaljer\/)?([a-zA-Z0-9_-]+)(?:\/|$|\?|#)/i)
|
||||
if (match) return match[1]
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { normalizeJobId } from "../src/helpers.js"
|
||||
import { runCLI } from "./helpers.js"
|
||||
|
||||
describe("jobnet-search normalizeJobId", () => {
|
||||
test("accepts bare numeric ID", () => {
|
||||
expect(normalizeJobId("6123456")).toBe("6123456")
|
||||
expect(normalizeJobId(" 6123456 ")).toBe("6123456")
|
||||
})
|
||||
|
||||
test("accepts alphanumeric ID", () => {
|
||||
expect(normalizeJobId("E123456")).toBe("E123456")
|
||||
expect(normalizeJobId("job_12345")).toBe("job_12345")
|
||||
})
|
||||
|
||||
test("extracts ID from /find-job/ URL with trailing slash", () => {
|
||||
expect(normalizeJobId("https://jobnet.dk/find-job/6123456/")).toBe("6123456")
|
||||
})
|
||||
|
||||
test("extracts ID from /find-job/ URL without trailing slash", () => {
|
||||
expect(normalizeJobId("https://jobnet.dk/find-job/6123456")).toBe("6123456")
|
||||
})
|
||||
|
||||
test("extracts ID from /find-job/detaljer/ URL", () => {
|
||||
expect(normalizeJobId("https://jobnet.dk/find-job/detaljer/6123456")).toBe("6123456")
|
||||
expect(normalizeJobId("https://jobnet.dk/find-job/detaljer/6123456/")).toBe("6123456")
|
||||
})
|
||||
|
||||
test("extracts ID from /FindJob/JobAdDetails/ URL", () => {
|
||||
expect(normalizeJobId("https://jobnet.dk/FindJob/JobAdDetails/6123456")).toBe("6123456")
|
||||
})
|
||||
|
||||
test("extracts ID from legacy /CV/FindWork/Details/ URL", () => {
|
||||
expect(normalizeJobId("https://job.jobnet.dk/CV/FindWork/Details/6123456")).toBe("6123456")
|
||||
})
|
||||
|
||||
test("extracts ID from URL with query parameters and hash fragments", () => {
|
||||
expect(normalizeJobId("https://jobnet.dk/find-job/6123456?ref=share&utm=test")).toBe("6123456")
|
||||
expect(normalizeJobId("https://jobnet.dk/find-job/6123456#main")).toBe("6123456")
|
||||
})
|
||||
|
||||
test("rejects empty string and invalid URLs", () => {
|
||||
expect(normalizeJobId("")).toBeNull()
|
||||
expect(normalizeJobId(" ")).toBeNull()
|
||||
expect(normalizeJobId("https://example.com/other/6123456")).toBeNull()
|
||||
})
|
||||
|
||||
test("CLI detail command rejects invalid ID format with BAD_ID", async () => {
|
||||
const result = await runCLI(["detail", "https://invalid.com/not-jobnet"])
|
||||
expect(result.exitCode).toBe(1)
|
||||
const err = JSON.parse(result.stderr)
|
||||
expect(err.code).toBe("BAD_ID")
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user