|
| 1 | +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; |
| 2 | +import { tmpdir } from "node:os"; |
| 3 | +import { join } from "node:path"; |
| 4 | +import { afterAll, expect, test } from "vite-plus/test"; |
| 5 | +import { runCli } from "./helpers.ts"; |
| 6 | + |
| 7 | +const configDirectory = mkdtempSync(join(tmpdir(), "bl-aliyun-compat-")); |
| 8 | +afterAll(() => rmSync(configDirectory, { recursive: true, force: true })); |
| 9 | + |
| 10 | +function runCompatible(arguments_: string[], language = "en-US", compatibility = "aliyun bl") { |
| 11 | + writeFileSync(join(configDirectory, "config.json"), JSON.stringify({ language })); |
| 12 | + return runCli(arguments_, { |
| 13 | + BAILIAN_CONFIG_DIR: configDirectory, |
| 14 | + ALIBABA_CLOUD_BL_COMPAT_MODE: compatibility, |
| 15 | + DASHSCOPE_API_KEY: "", |
| 16 | + ALIBABA_CLOUD_ACCESS_KEY_ID: "", |
| 17 | + ALIBABA_CLOUD_ACCESS_KEY_SECRET: "", |
| 18 | + ALIBABA_CLOUD_SECURITY_TOKEN: "", |
| 19 | + NO_UPDATE_NOTIFIER: "1", |
| 20 | + DO_NOT_TRACK: "1", |
| 21 | + }); |
| 22 | +} |
| 23 | + |
| 24 | +test.each(["en-US", "zh-CN"])( |
| 25 | + "host help and onboarding use the invocation prefix (%s)", |
| 26 | + async (language) => { |
| 27 | + const root = await runCompatible(["--help"], language); |
| 28 | + expect(root.exitCode, root.stderr).toBe(0); |
| 29 | + expect(root.stderr).toContain("aliyun bl <resource> <command> [flags]"); |
| 30 | + expect(root.stderr).toContain("aliyun bl auth login --console"); |
| 31 | + }, |
| 32 | +); |
| 33 | + |
| 34 | +test.each( |
| 35 | + ["en-US", "zh-CN"].flatMap((language) => |
| 36 | + ["app", "app list", "skill init", "managed-agent plan"].map((path) => ({ language, path })), |
| 37 | + ), |
| 38 | +)("host nested help uses the invocation prefix ($language, $path)", async ({ language, path }) => { |
| 39 | + const result = await runCompatible([...path.split(" "), "--help"], language); |
| 40 | + expect(result.exitCode, result.stderr).toBe(0); |
| 41 | + expect(result.stderr).toContain(`aliyun bl ${path}`); |
| 42 | + expect(result.stderr).not.toMatch(/(?<!aliyun )\bbl (?:auth|skill|managed-agent) /); |
| 43 | +}); |
| 44 | + |
| 45 | +test("host introspection keeps product identity but qualifies executable examples", async () => { |
| 46 | + const result = await runCompatible(["auth", "status", "--introspect"]); |
| 47 | + expect(result.exitCode, result.stderr).toBe(0); |
| 48 | + const schema = JSON.parse(result.stdout); |
| 49 | + expect(schema.bin).toBe("bl"); |
| 50 | + expect(schema.commands[0].path).toEqual(["auth", "status"]); |
| 51 | + expect(schema.commands[0].usage).toMatch(/^aliyun bl auth status/); |
| 52 | + expect(schema.commands[0].examples[0]).toBe("aliyun bl auth status"); |
| 53 | +}); |
| 54 | + |
| 55 | +test("host version is display-only and absent or unknown COMPAT keeps standalone", async () => { |
| 56 | + const hosted = await runCompatible(["--version"]); |
| 57 | + expect(hosted.stdout).toMatch(/^aliyun bl \d+\.\d+\.\d+\n$/); |
| 58 | + for (const compatibility of ["", " ", "unrecognized-host"]) { |
| 59 | + const standalone = await runCompatible(["--version"], "en-US", compatibility); |
| 60 | + expect(standalone.stdout).toMatch(/^bl \d+\.\d+\.\d+\n$/); |
| 61 | + } |
| 62 | +}); |
| 63 | + |
| 64 | +test.each(["text", "json"])( |
| 65 | + "missing Console credentials use host instructions (%s)", |
| 66 | + async (output) => { |
| 67 | + const result = await runCompatible(["app", "list", "--output", output]); |
| 68 | + expect(result.exitCode, result.stderr).toBe(3); |
| 69 | + const diagnostic = output === "json" ? JSON.parse(result.stderr).error.hint : result.stderr; |
| 70 | + expect(diagnostic).toContain("aliyun bl auth login --console"); |
| 71 | + expect(diagnostic).not.toMatch(/(?<!aliyun )\bbl auth login/); |
| 72 | + }, |
| 73 | +); |
| 74 | + |
| 75 | +test("auth status operation hints use the host prefix without changing authentication", async () => { |
| 76 | + const result = await runCompatible(["auth", "status", "--output", "json"]); |
| 77 | + expect(result.exitCode, result.stderr).toBe(0); |
| 78 | + const status = JSON.parse(result.stdout); |
| 79 | + expect(status.authenticated).toBe(false); |
| 80 | + expect(status.hint).toContain("aliyun bl auth login --api-key"); |
| 81 | +}); |
0 commit comments