feat(amazon-shopping): scaffold amazon product search skill
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
|
||||
import { buildSearchUrl, parseCliRequest, runCli } from "../src/cli.js";
|
||||
|
||||
function createOutput() {
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
return {
|
||||
stdout: { write: (chunk: string) => { stdout += chunk; return true; } },
|
||||
stderr: { write: (chunk: string) => { stderr += chunk; return true; } },
|
||||
get stdoutText() { return stdout; },
|
||||
get stderrText() { return stderr; }
|
||||
};
|
||||
}
|
||||
|
||||
describe("amazon-shopping CLI", () => {
|
||||
it("prints help", async () => {
|
||||
const output = createOutput();
|
||||
const code = await runCli(["--help"], output);
|
||||
|
||||
assert.equal(code, 0);
|
||||
assert.match(output.stdoutText, /scripts\/search-products/);
|
||||
assert.match(output.stdoutText, /--dry-run/);
|
||||
});
|
||||
|
||||
it("defaults to 15 results and two search pages", () => {
|
||||
const request = parseCliRequest(["usb c cable"]);
|
||||
|
||||
assert.equal(request.query, "usb c cable");
|
||||
assert.equal(request.limit, 15);
|
||||
assert.equal(request.maxSearchPages, 2);
|
||||
assert.equal(request.output, "json");
|
||||
});
|
||||
|
||||
it("maps kebab-case CLI filters into the request contract", () => {
|
||||
const request = parseCliRequest([
|
||||
"--query",
|
||||
"100w led bulbs",
|
||||
"--min-rating",
|
||||
"4.5",
|
||||
"--min-reviews",
|
||||
"200",
|
||||
"--max-unit-price",
|
||||
"4",
|
||||
"--max-search-pages",
|
||||
"3",
|
||||
"--skip-details",
|
||||
"--dry-run"
|
||||
]);
|
||||
|
||||
assert.equal(request.query, "100w led bulbs");
|
||||
assert.equal(request.filters.minRating, 4.5);
|
||||
assert.equal(request.filters.minReviews, 200);
|
||||
assert.equal(request.filters.maxUnitPrice, 4);
|
||||
assert.equal(request.maxSearchPages, 3);
|
||||
assert.equal(request.skipDetails, true);
|
||||
assert.equal(request.dryRun, true);
|
||||
});
|
||||
|
||||
it("maps output modes", () => {
|
||||
assert.equal(parseCliRequest(["usb c cable", "--json"]).output, "json");
|
||||
assert.equal(parseCliRequest(["usb c cable", "--markdown"]).output, "markdown");
|
||||
assert.equal(parseCliRequest(["usb c cable", "--json", "--markdown"]).output, "both");
|
||||
});
|
||||
|
||||
it("rejects limits below one", () => {
|
||||
assert.throws(
|
||||
() => parseCliRequest(["usb c cable", "--limit", "0"]),
|
||||
/limit must be an integer greater than 0/
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects unsafe large limits unless explicitly allowed", () => {
|
||||
assert.throws(
|
||||
() => parseCliRequest(["usb c cable", "--limit", "31"]),
|
||||
/require --allow-large-limit/
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects search page caps above five", () => {
|
||||
assert.throws(
|
||||
() => parseCliRequest(["usb c cable", "--max-search-pages", "6"]),
|
||||
/max-search-pages must be 5 or less/
|
||||
);
|
||||
});
|
||||
|
||||
it("builds the Amazon search URL without live network access", () => {
|
||||
assert.equal(
|
||||
buildSearchUrl("100w led bulbs"),
|
||||
"https://www.amazon.com/s?k=100w%20led%20bulbs"
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user