diff --git a/.agents/skills/linkedin-search/cli/src/cli.ts b/.agents/skills/linkedin-search/cli/src/cli.ts index d3f7e597..9815ed11 100644 --- a/.agents/skills/linkedin-search/cli/src/cli.ts +++ b/.agents/skills/linkedin-search/cli/src/cli.ts @@ -9,6 +9,7 @@ import { runSearch, type SearchOpts } from "./commands/search.js" import { runDetail, type DetailOpts } from "./commands/detail.js" +import { workTypeFlag } from "./helpers.js" interface Flags { _: string[] @@ -121,6 +122,17 @@ async function main(): Promise { return 1 } + // workTypeFlag() maps a mode it does not know to null and the request then + // carries no f_WT, so "remote,hybrid", a misspelling or a bare --remote + // searched every workplace type, onsite included, with exit 0. + if (flags.remote !== undefined && (typeof flags.remote !== "string" || workTypeFlag(flags.remote) === null)) { + const got = typeof flags.remote === "string" ? `"${flags.remote}"` : "no value" + process.stderr.write( + JSON.stringify({ error: `--remote must be one of remote|hybrid|onsite, got ${got}`, code: "BAD_ARG" }) + "\n", + ) + return 1 + } + if (flags.jobage !== undefined && flags["jobage-minutes"] !== undefined) { process.stderr.write( JSON.stringify({ diff --git a/.agents/skills/linkedin-search/cli/tests/remote-mode.test.ts b/.agents/skills/linkedin-search/cli/tests/remote-mode.test.ts new file mode 100644 index 00000000..351e1f8b --- /dev/null +++ b/.agents/skills/linkedin-search/cli/tests/remote-mode.test.ts @@ -0,0 +1,44 @@ +import { describe, expect, test } from "bun:test"; +import { runSearchFixture } from "./helpers"; + +const LOCATION = "Copenhagen, Denmark"; + +// workTypeFlag() maps a mode it does not recognise to null, and the search +// URL then carries no f_WT at all. So `--remote remote,hybrid`, a misspelt +// mode, or a bare `--remote` searched every workplace type - onsite included - +// and exited 0 as if the filter had been applied. These run the real CLI +// against the saved search fixture and count the outbound requests. +describe("--remote mode", () => { + for (const args of [ + ["--remote", "remote,hybrid"], + ["--remote", "remotely"], + ["--remote", "--limit", "1"], + ["--remote"], + ]) { + test(`${args.join(" ")} exits 1 with BAD_ARG before any request`, async () => { + const { result, requests } = await runSearchFixture(["search", "-l", LOCATION, "-q", "engineer", ...args]); + expect(result.exitCode).toBe(1); + expect(result.stdout).toBe(""); + const error = JSON.parse(result.stderr); + expect(error.code).toBe("BAD_ARG"); + expect(error.error).toContain("--remote"); + expect(requests).toHaveLength(0); + }); + } + + for (const [mode, wt] of [["remote", "2"], ["hybrid", "3"], ["onsite", "1"], ["on-site", "1"], ["Remote", "2"]]) { + test(`--remote ${mode} sends f_WT=${wt}`, async () => { + const { result, requests } = await runSearchFixture(["search", "-l", LOCATION, "--remote", mode]); + expect(result.exitCode).toBe(0); + expect(requests).toHaveLength(1); + expect(requests[0].searchParams.get("f_WT")).toBe(wt); + }); + } + + test("omitting --remote still searches every workplace type", async () => { + const { result, requests } = await runSearchFixture(["search", "-l", LOCATION]); + expect(result.exitCode).toBe(0); + expect(requests).toHaveLength(1); + expect(requests[0].searchParams.has("f_WT")).toBe(false); + }); +}); diff --git a/CHANGELOG.md b/CHANGELOG.md index 64f839f2..86d0ba7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -115,6 +115,13 @@ per-file diff commands. lookup then failed and `/apply` quietly dropped the benchmark. The converter now exits 2 before reading the workbook or opening the output, and `0` or a finite custom baseline still converts. +- **`linkedin-search` rejects a `--remote` mode it does not recognise instead of searching every + workplace type** (#645, `.agents/skills/linkedin-search/cli/src/cli.ts`, `tests/remote-mode.test.ts`) - + `workTypeFlag()` maps an unknown mode to `null` and the request then carries no `f_WT`, so + `--remote remote,hybrid`, a misspelt mode or a bare `--remote` returned onsite postings too, + with exit 0 and an empty stderr. Anything other than `remote`, `hybrid` or `onsite` (and the + accepted `on-site` spelling) now exits 1 with `BAD_ARG` before any request is sent. + ## [1.7.3] - 2026-10-19 ### Added