fix(linkedin-search): require a value for --query instead of dropping the keywords (#646)

* fix(linkedin-search): require a value for --query instead of dropping the keywords

parseFlags stores a bare -q as true and -q "" as an empty string, and the
search took --query only when it was a non-empty string. A bare flag, an
empty argument or a blank query therefore returned every posting in the
location with exit 0. Reject a present --query without keywords with
BAD_ARG before any request; omitting the flag stays a location-only search,
matching the Danish portals (#573) and freehire-search (#568).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* changelog: place the #646 entry under [Unreleased]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Mads Lorentzen <madslorentzen_17@hotmail.com>
This commit is contained in:
authored and GitHub committed 2026-10-19 19:57:08 +02:00
1 parent 5f0b799479
commit ce2755e5aa
3 files changed
+60

No files matched your search

@@ -114,6 +114,15 @@ async function main(): Promise<number> {
)
return 1
}
// --query is optional, but a present one needs keywords: parseFlags stores
// a bare -q as true and -q "" as "", and both used to be treated as unset,
// returning every posting in the location as if it matched.
if (flags.query !== undefined && (typeof flags.query !== "string" || !flags.query.trim())) {
process.stderr.write(
JSON.stringify({ error: "--query requires a non-empty value", code: "BAD_ARG" }) + "\n",
)
return 1
}
const fmt = flags.format !== undefined ? String(flags.format) : "json"
if (!["json", "table", "plain"].includes(fmt)) {
process.stderr.write(
@@ -0,0 +1,42 @@
import { describe, expect, test } from "bun:test";
import { runSearchFixture } from "./helpers";
const LOCATION = "Copenhagen, Denmark";
// parseFlags stores a value-less flag as `true` and an empty argument as "",
// and the search took `--query` only when it was a non-empty string. So a
// bare `-q`, `-q ""` (an unset shell variable) or a blank query dropped the
// keywords and returned every posting in the location with exit 0. These run
// the real CLI against the saved search fixture and count outbound requests.
describe("--query requires a value", () => {
for (const args of [
["-q"],
["-q", "--jobage", "7"],
["--query", ""],
["-q", " "],
]) {
test(`${JSON.stringify(args)} exits 1 with BAD_ARG before any request`, async () => {
const { result, requests } = await runSearchFixture(["search", "-l", LOCATION, ...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("--query");
expect(requests).toHaveLength(0);
});
}
test("a query is sent as keywords", async () => {
const { result, requests } = await runSearchFixture(["search", "-l", LOCATION, "-q", "data engineer"]);
expect(result.exitCode).toBe(0);
expect(requests).toHaveLength(1);
expect(requests[0].searchParams.get("keywords")).toBe("data engineer");
});
test("omitting --query is still an intentional location-only search", async () => {
const { result, requests } = await runSearchFixture(["search", "-l", LOCATION]);
expect(result.exitCode).toBe(0);
expect(requests).toHaveLength(1);
expect(requests[0].searchParams.has("keywords")).toBe(false);
});
});