OmniRoute/tests/unit/cli-openapi-codegen.test.ts
diegosouzapw cd62899f31 feat(cli): fase 9.3 — codegen de comandos a partir do OpenAPI spec (omniroute api <tag> <op>)
Gera automaticamente 24 grupos de comandos (170+ operações) em bin/cli/api-commands/ a
partir de docs/reference/openapi.yaml via npm run build:cli-api. Integrado em registry.mjs;
prepublishOnly regenera antes de publicar.
2026-05-15 04:58:40 -03:00

92 lines
4.1 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const ROOT = join(__dirname, "..", "..");
const API_COMMANDS_DIR = join(ROOT, "bin", "cli", "api-commands");
const REGISTRY = join(API_COMMANDS_DIR, "registry.mjs");
test("bin/cli/api-commands/ directory exists", () => {
assert.ok(existsSync(API_COMMANDS_DIR), "api-commands dir deve existir");
});
test("registry.mjs foi gerado e exporta registerApiCommands e API_TAGS", () => {
assert.ok(existsSync(REGISTRY), "registry.mjs deve existir");
const src = readFileSync(REGISTRY, "utf8");
assert.ok(
src.includes("export function registerApiCommands"),
"deve exportar registerApiCommands"
);
assert.ok(src.includes("export const API_TAGS"), "deve exportar API_TAGS");
});
test("api-commands/ tem pelo menos 20 tag files gerados", () => {
const files = readdirSync(API_COMMANDS_DIR).filter(
(f) => f.endsWith(".mjs") && f !== "registry.mjs"
);
assert.ok(files.length >= 20, `esperado >=20 arquivos, encontrado ${files.length}`);
});
test("tags esperadas estão presentes (combos, providers, api-keys, settings)", () => {
const files = readdirSync(API_COMMANDS_DIR);
for (const expected of ["combos.mjs", "providers.mjs", "api-keys.mjs", "settings.mjs"]) {
assert.ok(files.includes(expected), `${expected} deve estar presente`);
}
});
test("registerApiCommands registra comando 'api' com subcomandos de tags", async () => {
const { registerApiCommands, API_TAGS } = await import("../../bin/cli/api-commands/registry.mjs");
const { Command } = await import("commander");
const prog = new Command().exitOverride();
registerApiCommands(prog);
const apiCmd = prog.commands.find((c) => c.name() === "api");
assert.ok(apiCmd, "comando 'api' deve existir");
// subcommand 'tags' + all tag groups
assert.ok(apiCmd.commands.length >= API_TAGS.length, "deve ter subcomandos para todos os tags");
});
test("API_TAGS contém pelo menos 20 entradas", async () => {
const { API_TAGS } = await import("../../bin/cli/api-commands/registry.mjs");
assert.ok(Array.isArray(API_TAGS));
assert.ok(API_TAGS.length >= 20, `esperado >=20 tags, encontrado ${API_TAGS.length}`);
assert.ok(API_TAGS.includes("combos"), "'combos' deve estar em API_TAGS");
assert.ok(API_TAGS.includes("providers"), "'providers' deve estar em API_TAGS");
});
test("combos.mjs registra operações de combos com flags corretas", async () => {
const { Command } = await import("commander");
// Importar diretamente o módulo de combos
const combosPath = join(API_COMMANDS_DIR, "combos.mjs");
const src = readFileSync(combosPath, "utf8");
// Deve ter operações CRUD
assert.ok(src.includes("export function register_combos"), "deve exportar register_combos");
assert.ok(src.includes("apiFetch"), "deve usar apiFetch");
assert.ok(src.includes("emit"), "deve usar emit");
});
test("arquivos gerados têm cabeçalho AUTO-GENERATED", () => {
const files = readdirSync(API_COMMANDS_DIR).filter((f) => f.endsWith(".mjs"));
for (const file of files.slice(0, 5)) {
const src = readFileSync(join(API_COMMANDS_DIR, file), "utf8");
assert.ok(src.includes("AUTO-GENERATED"), `${file} deve ter cabeçalho AUTO-GENERATED`);
}
});
test("generate-api-commands.mjs existe em scripts/cli/", () => {
const scriptPath = join(ROOT, "scripts", "cli", "generate-api-commands.mjs");
assert.ok(existsSync(scriptPath), "generate-api-commands.mjs deve existir");
const src = readFileSync(scriptPath, "utf8");
assert.ok(src.includes("IGNORED_OP_IDS"), "deve ter lista IGNORED_OP_IDS");
assert.ok(
src.includes("prepublishOnly") || src.includes("build:cli-api") || src.includes("generate"),
"deve mencionar build"
);
});
test("package.json tem script build:cli-api", () => {
const pkg = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8"));
assert.ok(pkg.scripts?.["build:cli-api"], "build:cli-api deve estar nos scripts");
});