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 { 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 { 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, ]); }); });