Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/nu-bang/__tests__/real-world.test.ts

Raw
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterAll, beforeAll, describe, expect, test } from "vitest";
import {
	executeNu,
	nuCompletions,
	wrapNuAutocompleteProvider,
} from "../index.js";

let dir = "";
const directoryCompletion =
	process.platform === "win32" ? "`my dir`" : "`my dir/`";

async function seedFiles(): Promise<void> {
	await writeFile(
		join(dir, "people.json"),
		JSON.stringify([
			{ name: "Ada", role: "compiler", score: 99 },
			{ name: "Grace", role: "systems", score: 95 },
			{ name: "Linus", role: "kernel", score: 88 },
		]),
		"utf8",
	);
	await writeFile(
		join(dir, "logs.csv"),
		"service,level,count\napi,info,3\napi,error,1\nweb,info,5\n",
		"utf8",
	);
	await writeFile(
		join(dir, "config.nuon"),
		"{host: localhost, ports: [8080, 8081], enabled: true}",
		"utf8",
	);
	await writeFile(
		join(dir, "alpha.nu"),
		"export def greet [name: string] { $'hello ($name)' }",
		"utf8",
	);
	await writeFile(join(dir, "beta.txt"), "hello\nworld\n", "utf8");
	await writeFile(join(dir, "my file.txt"), "space path\n", "utf8");
	await mkdir(join(dir, "my dir"));
}

function run(command: string): ReturnType<typeof executeNu> {
	return executeNu(command, dir);
}

beforeAll(async () => {
	dir = await mkdtemp(join(tmpdir(), "pi-nu-bang-test-"));
	await seedFiles();
});

afterAll(async () => {
	await rm(dir, {
		recursive: true,
		force: true,
		maxRetries: 20,
		retryDelay: 50,
	});
});

// Exhaustive real-world coverage lives in real-world-full.test.ts.
// This smoke shard stays below the per-file benchmark while still hitting Nu exec, cwd IO, and completions.
describe.concurrent("nu-bang real-world smoke", () => {
	test("covers common Nushell data pipelines in one process", async () => {
		const result = await run(String.raw`
[
	{name: "ls", value: (ls | sort-by name | first | get name)}
	{name: "json", value: (open people.json | where score > 90 | get name | str join ",")}
	{name: "csv", value: (open logs.csv | group-by service | transpose service rows | insert total {|r| $r.rows.count | math sum } | get total | math sum | into string)}
	{name: "nuon", value: (open config.nuon | get ports | math max | into string)}
	{name: "module", value: (do { use ./alpha.nu greet; greet Ada })}
	{name: "save", value: (do { "created" | save generated.txt --force; open generated.txt })}
] | to json --raw
`);
		expect(result.exitCode).toBe(0);
		expect(
			Object.fromEntries(
				JSON.parse(result.output).map(
					(item: { name: string; value: string }) => [item.name, item.value],
				),
			),
		).toMatchObject({
			ls: "alpha.nu",
			json: "Ada,Grace",
			csv: "9",
			nuon: "8081",
			module: "hello Ada",
			save: "created",
		});
	});

	test("completes pipeline commands and paths", async () => {
		const [commands, paths] = await Promise.all([
			nuCompletions("ls | wh", 7, dir),
			nuCompletions("open ", 5, dir),
		]);
		expect(commands).toContain("where");
		expect(commands).toContain("which");
		expect(paths).toContain("people.json");
		expect(paths).toContain("logs.csv");
	});

	test("filters escaped-space path suggestions to the typed prefix", async () => {
		const provider = wrapNuAutocompleteProvider(
			{
				async getSuggestions() {
					return null;
				},
				applyCompletion() {
					throw new Error("not used");
				},
			},
			dir,
		);

		const [broadSuggestions, suggestions, directorySuggestions] =
			await Promise.all([
				provider.getSuggestions(["!open my\\ "], 0, 10, {
					signal: new AbortController().signal,
					force: true,
				}),
				provider.getSuggestions(["!open my\\ f"], 0, 11, {
					signal: new AbortController().signal,
					force: true,
				}),
				provider.getSuggestions(["!open my\\ d"], 0, 11, {
					signal: new AbortController().signal,
					force: true,
				}),
			]);
		expect(broadSuggestions?.prefix).toBe("my\\ ");
		expect(broadSuggestions?.items.map((item) => item.value)).toEqual([
			directoryCompletion,
			"`my file.txt`",
		]);
		expect(suggestions?.items.map((item) => item.value)).toEqual([
			"`my file.txt`",
		]);
		expect(directorySuggestions?.items.map((item) => item.value)).toEqual([
			directoryCompletion,
		]);
	});
});