mirror of
https://github.com/actionbook/actionbook.git
synced 2026-09-19 03:28:06 +08:00
893315f4aa
* [packages/cli]test: improve CLI E2E test coverage to 93% Add 56 new test cases covering previously untested commands, subcommands, and parameter combinations. New test files for setup, extension, help, and global options. Enhanced existing browser, config, search, and get tests with parameter-level coverage. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * [packages/cli]test: add real assertions to browser E2E tests Replace exit-code-only checks with actual value assertions: - scroll tests verify window.scrollY changes before/after - select/focus verify element value and activeElement - type verifies input field value contains typed text - cookies delete/clear verify cookie is actually removed - navigate goto verifies location.href - inspect verifies output contains element info Move restart/close tests to end to prevent cascade failures. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * [packages/actionbook-rs]test: expand Rust CLI integration tests to match TypeScript E2E coverage Add ~70 new tests bringing total to 123, covering all CLI commands and options: help, browser (57 tests), config, profile, extension, setup, search, get, sources, and global flags. Mirrors the TypeScript E2E test suite structure. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * [packages/cli]fix: relax assertions for offline/extension-mode-only tests - extension install: accept exit code 0 or 1 (network failures in CI) - cookies set --domain: tolerate graceful failure outside extension mode Addresses PR #167 review feedback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * [packages/actionbook-rs]test: add browser E2E tests mirroring TypeScript cli-browser-e2e.test.ts 57 individual #[test] functions covering navigation, page content, form interaction, screenshot/pdf, cookies, scroll, type, select/hover/focus/press, inspect, tab management, and restart/close. Shares browser session via OnceLock, gated by RUN_BROWSER_TESTS=true, runs with --test-threads=1. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * [packages/cli]fix: address PR #167 review comments from Codex - cli_test.rs: fail setup tests explicitly when process is killed by signal (timeout) instead of silently passing - cli_test.rs: isolate extension stop test with temp HOME/XDG dirs to avoid killing real user bridge processes - cli-browser-e2e.test.ts: clarify that cookie --dry-run/--domain tests require extension mode and rename describe block Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
178 lines
6.3 KiB
TypeScript
178 lines
6.3 KiB
TypeScript
import { describe, it, expect, beforeAll, beforeEach } from "vitest";
|
|
import { getActionbookBinary, runCli } from "./helpers/binary.js";
|
|
import { createIsolatedEnv } from "./helpers/config.js";
|
|
|
|
const binary = getActionbookBinary();
|
|
|
|
describe.skipIf(!binary)("config command", () => {
|
|
let isolatedEnv: ReturnType<typeof createIsolatedEnv>;
|
|
|
|
beforeEach(() => {
|
|
isolatedEnv = createIsolatedEnv();
|
|
});
|
|
|
|
// ── config show ────────────────────────────────────────────────────
|
|
|
|
describe("config show", () => {
|
|
it("outputs config in text format", async () => {
|
|
const result = await runCli(["config", "show"], {
|
|
env: isolatedEnv.env,
|
|
});
|
|
expect(result.exitCode).toBe(0);
|
|
// Default config should contain API and browser sections
|
|
expect(result.stdout).toContain("api");
|
|
expect(result.stdout).toContain("browser");
|
|
});
|
|
|
|
it("outputs valid JSON with --json flag", async () => {
|
|
const result = await runCli(["--json", "config", "show"], {
|
|
env: isolatedEnv.env,
|
|
});
|
|
expect(result.exitCode).toBe(0);
|
|
const json = JSON.parse(result.stdout);
|
|
expect(json).toHaveProperty("api");
|
|
expect(json).toHaveProperty("browser");
|
|
});
|
|
});
|
|
|
|
// ── config path ────────────────────────────────────────────────────
|
|
|
|
describe("config path", () => {
|
|
it("outputs a file path", async () => {
|
|
const result = await runCli(["config", "path"], {
|
|
env: isolatedEnv.env,
|
|
});
|
|
expect(result.exitCode).toBe(0);
|
|
expect(result.stdout.trim()).toContain("actionbook");
|
|
expect(result.stdout.trim()).toContain("config");
|
|
});
|
|
|
|
it("outputs JSON with --json flag", async () => {
|
|
const result = await runCli(["--json", "config", "path"], {
|
|
env: isolatedEnv.env,
|
|
});
|
|
expect(result.exitCode).toBe(0);
|
|
const json = JSON.parse(result.stdout);
|
|
expect(json).toHaveProperty("path");
|
|
expect(json.path).toContain("actionbook");
|
|
});
|
|
});
|
|
|
|
// ── config set + get ───────────────────────────────────────────────
|
|
|
|
describe("config set and get", () => {
|
|
it("sets and gets a config value", async () => {
|
|
// Set
|
|
const setResult = await runCli(
|
|
["config", "set", "api.base_url", "https://custom.example.com"],
|
|
{ env: isolatedEnv.env }
|
|
);
|
|
expect(setResult.exitCode).toBe(0);
|
|
|
|
// Get
|
|
const getResult = await runCli(["config", "get", "api.base_url"], {
|
|
env: isolatedEnv.env,
|
|
});
|
|
expect(getResult.exitCode).toBe(0);
|
|
expect(getResult.stdout.trim()).toBe("https://custom.example.com");
|
|
});
|
|
|
|
it("gets config value in JSON format", async () => {
|
|
// Set first
|
|
await runCli(
|
|
["config", "set", "api.base_url", "https://json-test.example.com"],
|
|
{ env: isolatedEnv.env }
|
|
);
|
|
|
|
const result = await runCli(
|
|
["--json", "config", "get", "api.base_url"],
|
|
{ env: isolatedEnv.env }
|
|
);
|
|
expect(result.exitCode).toBe(0);
|
|
const json = JSON.parse(result.stdout);
|
|
expect(json.key).toBe("api.base_url");
|
|
expect(json.value).toBe("https://json-test.example.com");
|
|
});
|
|
|
|
it("rejects unknown config key on set", async () => {
|
|
const result = await runCli(
|
|
["config", "set", "unknown.key", "value"],
|
|
{ env: isolatedEnv.env }
|
|
);
|
|
expect(result.exitCode).toBe(1);
|
|
expect(result.stderr).toContain("Unknown config key");
|
|
});
|
|
|
|
it("rejects unknown config key on get", async () => {
|
|
const result = await runCli(["config", "get", "unknown.key"], {
|
|
env: isolatedEnv.env,
|
|
});
|
|
expect(result.exitCode).toBe(1);
|
|
expect(result.stderr).toContain("Unknown config key");
|
|
});
|
|
});
|
|
|
|
// ── config edit ────────────────────────────────────────────────────
|
|
|
|
describe("config edit", () => {
|
|
it("config edit --help shows description", async () => {
|
|
const result = await runCli(["config", "edit", "--help"], {
|
|
env: isolatedEnv.env,
|
|
});
|
|
expect(result.exitCode).toBe(0);
|
|
expect(result.stdout.length).toBeGreaterThan(0);
|
|
});
|
|
});
|
|
|
|
// ── config reset ───────────────────────────────────────────────────
|
|
|
|
describe("config reset", () => {
|
|
it("resets config successfully in isolated env", async () => {
|
|
const result = await runCli(["config", "reset"], {
|
|
env: isolatedEnv.env,
|
|
});
|
|
expect(result.exitCode).toBe(0);
|
|
});
|
|
|
|
it("outputs JSON with --json flag after reset", async () => {
|
|
const result = await runCli(["--json", "config", "reset"], {
|
|
env: isolatedEnv.env,
|
|
});
|
|
expect(result.exitCode).toBe(0);
|
|
// After reset the output should be valid JSON if --json mode is supported
|
|
try {
|
|
JSON.parse(result.stdout);
|
|
} catch {
|
|
// Plain text success output is also acceptable
|
|
expect(result.stdout.trim().length).toBeGreaterThanOrEqual(0);
|
|
}
|
|
});
|
|
});
|
|
|
|
// ── config argument validation ─────────────────────────────────────
|
|
|
|
describe("argument validation", () => {
|
|
it("config without subcommand fails", async () => {
|
|
const result = await runCli(["config"], { env: isolatedEnv.env });
|
|
expect(result.exitCode).toBe(2);
|
|
expect(result.stderr).toContain("subcommand");
|
|
});
|
|
|
|
it("config set without key fails", async () => {
|
|
const result = await runCli(["config", "set"], {
|
|
env: isolatedEnv.env,
|
|
});
|
|
expect(result.exitCode).toBe(2);
|
|
expect(result.stderr).toContain("KEY");
|
|
});
|
|
|
|
it("config get without key fails", async () => {
|
|
const result = await runCli(["config", "get"], {
|
|
env: isolatedEnv.env,
|
|
});
|
|
expect(result.exitCode).toBe(2);
|
|
expect(result.stderr).toContain("KEY");
|
|
});
|
|
});
|
|
});
|