Files
2026-07-13 13:39:12 +08:00

119 lines
5.6 KiB
TypeScript

import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import path from "node:path";
import {
detectCommandOutput,
detectCommandType,
} from "../../../open-sse/services/compression/index.ts";
const FIXTURES = path.join(path.dirname(fileURLToPath(import.meta.url)), "fixtures", "rtk");
function fixture(name: string): string {
return readFileSync(path.join(FIXTURES, name), "utf8");
}
describe("RTK command detector", () => {
it("detects planned command output classes", () => {
assert.equal(
detectCommandType(fixture("git-status-sample.txt"), "git status").type,
"git-status"
);
assert.equal(detectCommandType(fixture("git-diff-sample.txt"), "git diff").type, "git-diff");
assert.equal(detectCommandType("commit abcdef1\nAuthor: A", "git log").type, "git-log");
assert.equal(
detectCommandType(fixture("vitest-output-sample.txt"), "vitest").type,
"test-vitest"
);
assert.equal(detectCommandType("FAIL test\nTests: 1 failed", "jest").type, "test-jest");
assert.equal(detectCommandType("FAILED test_a.py::test_a", "pytest").type, "test-pytest");
assert.equal(
detectCommandType(fixture("typescript-errors-sample.txt"), "tsc --noEmit").type,
"build-typescript"
);
assert.equal(
detectCommandType(fixture("eslint-output-sample.txt"), "eslint .").type,
"build-eslint"
);
assert.equal(
detectCommandType("CONTAINER ID IMAGE COMMAND", "docker ps").type,
"docker-ps"
);
assert.equal(detectCommandType(fixture("json-output-sample.txt")).type, "json-output");
assert.equal(detectCommandType("Error: boom\n at fn").type, "generic-error");
});
it("detects RTK parity command output classes", () => {
const cases: Array<[string, string | null, string]> = [
["* feature/rtk\n main", "git branch", "git-branch"],
["running 2 tests\ntest a ... FAILED\ntest result: FAILED", "cargo test", "test-cargo"],
["--- FAIL: TestA\nFAIL\t./pkg\t0.1s", "go test ./...", "test-go"],
["webpack 5.0.0 compiled with 1 error", "webpack", "build-webpack"],
["vite v5.0.0\n✓ built in 100ms", "vite build", "build-vite"],
["2026-05-02T00:00:00Z ERROR failed", "docker logs app", "docker-logs"],
["./src/a.ts\n./src/b.ts", "find . -name '*.ts'", "shell-find"],
["src/a.ts:1:match", "rg match", "shell-grep"],
["found 1 vulnerabilities\ncritical severity", "npm audit", "npm-audit"],
['Traceback (most recent call last):\n File "a.py", line 1', null, "error-stacktrace"],
["make[1]: Entering directory '/repo'\nmake: *** [all] Error 2", "make", "make"],
[
"Terraform will perform the following actions:\nPlan: 1 to add",
"terraform plan",
"terraform-plan",
],
["OpenTofu will perform the following actions:\nPlan: 1 to add", "tofu plan", "tofu-plan"],
["Active: failed (Result: exit-code)", "systemctl status omniroute", "systemctl-status"],
["Checked 12 files in 18ms. No fixes applied.", "biome check .", "biome"],
["Checking formatting...\n[warn] src/app.ts", "prettier --check .", "prettier"],
["• Packages in scope: web\nTasks: 1 successful", "turbo build", "turbo"],
["NX Running target build for 2 projects", "nx build web", "nx"],
["Running 3 tests using 1 worker", "playwright test", "playwright"],
["src/app.py:1:1: F401 unused import", "ruff check .", "ruff"],
["src/app.py:12: error: incompatible type", "mypy src", "mypy"],
["Collecting requests\nSuccessfully installed requests", "pip install requests", "pip"],
["Resolved 42 packages\nInstalled 3 packages", "uv sync", "uv-sync"],
["Installing dependencies from lock file", "poetry install", "poetry-install"],
["pkg/main.go:22:1: issue\n2 issues:", "golangci-lint run", "golangci-lint"],
["Bundle complete! 12 Gemfile dependencies", "bundle install", "bundle-install"],
["Inspecting 2 files\napp.rb:1:1: C: Style/FrozenStringLiteralComment", "rubocop", "rubocop"],
["An error occurred (AccessDenied) when calling", "aws s3 ls", "aws"],
["ERROR: (gcloud.run.deploy) PERMISSION_DENIED", "gcloud run deploy", "gcloud"],
["Permission denied (publickey).", "ssh host", "ssh"],
["sending incremental file list\nrsync error: code 23", "rsync -av src host:", "rsync"],
["HTTP/1.1 500 Internal Server Error", "curl -i example.test", "curl"],
["ERROR 404: Not Found.", "wget example.test/missing", "wget"],
["USER PID %CPU COMMAND", "ps aux", "shell-ps"],
["Filesystem Size Used Avail Use% Mounted on", "df -h", "shell-df"],
["120M node_modules", "du -sh *", "shell-du"],
];
for (const [text, command, expected] of cases) {
const detection = detectCommandType(text, command);
assert.equal(detection.type, expected);
assert.ok(detection.matchedPatterns.length > 0);
assert.ok(detection.confidence >= 0.25);
}
});
it("detects git-status when command is a composite like 'cd /x && git status'", () => {
assert.equal(
detectCommandType(fixture("git-status-sample.txt"), "cd /x && git status").type,
"git-status"
);
assert.equal(
detectCommandType(fixture("git-diff-sample.txt"), "cd /repo && git diff").type,
"git-diff"
);
});
it("returns unknown for generic text and exposes planned alias", () => {
const detection = detectCommandOutput("ordinary prose without command output");
assert.equal(detection.type, "unknown");
assert.ok(detection.confidence > 0);
assert.deepEqual(detection.matchedPatterns, []);
});
});