diff --git a/.gitignore b/.gitignore index aa1dde58..6fce9eaa 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ .DS_Store .DS_Store? dist +testing/__snapshots__/assert_snapshot_call_test_fixture.ts.snap +testing/__snapshots__/assert_snapshot_call_test_fixture_2.ts.snap +__snapshots_test__ diff --git a/README.md b/README.md index 3dd5c8d5..b4ec9eaf 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,8 @@ The [documentation](https://cliffy.io/docs) is available on - **[table](https://cliffy.io/docs/table/):** Create cli tables with border, padding, nested tables, etc... +- **[testing](https://cliffy.io/docs/testing/):** Helper functions for testing. + ## Contributing Any kind of contribution is welcome! Please take a look at the diff --git a/command/test/integration/__snapshots__/test.ts.snap b/command/test/integration/__snapshots__/test.ts.snap index db20a68c..5fb9cb39 100644 --- a/command/test/integration/__snapshots__/test.ts.snap +++ b/command/test/integration/__snapshots__/test.ts.snap @@ -1,36 +1,52 @@ export const snapshot = {}; snapshot[`command integration > should complete boolean arg 1`] = ` -"true -false" +"stdout: +true +false +stderr: +" `; snapshot[`command integration > should complete boolean arg from foo command 1`] = ` -"true -false" +"stdout: +true +false +stderr: +" `; snapshot[`command integration > should complete boolean arg from foo bar command 1`] = ` -"true -false" +"stdout: +true +false +stderr: +" `; snapshot[`command integration > should complete available commands for help command 1`] = ` -"foo +"stdout: +foo bar validation-error help -completions" +completions +stderr: +" `; snapshot[`command integration > should complete enum 1`] = ` -"blue +"stdout: +blue yellow -red" +red +stderr: +" `; snapshot[`command integration > should generate bash completions 1`] = ` -\`#!/usr/bin/env bash +\`stdout: +#!/usr/bin/env bash # bash completion support for completions-test v1.0.0 _completions_test() { @@ -339,11 +355,14 @@ _completions_test() { } complete -F _completions_test -o bashdefault -o default completions-test + +stderr: \` `; snapshot[`command integration > should generate fish completions 1`] = ` -\`#!/usr/bin/env fish +\`stdout: +#!/usr/bin/env fish # fish completion support for completions-test v1.0.0 function __fish_completions_test_using_command @@ -425,11 +444,14 @@ complete -c completions-test -n '__fish_completions_test_using_command __complet complete -c completions-test -n '__fish_completions_test_using_command __completions_test' -k -f -a help -d 'Show this help or the help of a sub-command.' complete -c completions-test -n '__fish_completions_test_using_command __completions_test_help' -k -f -a '(completions-test completions complete command help)' complete -c completions-test -n '__fish_completions_test_using_command __completions_test_help' -s h -l help -x -k -f -d 'Show this help.' + +stderr: \` `; snapshot[`command integration > should generate zsh completions 1`] = ` -\`#!/usr/bin/env zsh +\`stdout: +#!/usr/bin/env zsh # zsh completion support for completions-test v1.0.0 autoload -U is-at-least @@ -881,11 +903,14 @@ function _completions_test_completions_zsh_help() { # _completions_test "\${@}" compdef _completions_test completions-test + +stderr: \` `; snapshot[`command integration > should output command help with help command 1`] = ` -\` +\`stdout: + \\x1b[1mUsage:\\x1b[22m \\x1b[95mcompletions-test \\x1b[33m<\\x1b[95m\\x1b[95mcolor\\x1b[95m\\x1b[33m>\\x1b[95m \\x1b[33m[\\x1b[95m\\x1b[95mpath...\\x1b[95m\\x1b[33m]\\x1b[95m\\x1b[39m \\x1b[1mVersion:\\x1b[22m \\x1b[33m1.0.0\\x1b[39m @@ -917,11 +942,14 @@ snapshot[`command integration > should output command help with help command 1`] \\x1b[94mhelp\\x1b[39m \\x1b[33m[\\x1b[39m\\x1b[95mcommand\\x1b[39m\\x1b[33m]\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show this help or the help of a sub-command. \\x1b[94mcompletions\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Generate shell completions. + +stderr: \` `; snapshot[`command integration > should output sub-command help with help command 1`] = ` -\` +\`stdout: + \\x1b[1mUsage:\\x1b[22m \\x1b[95mcompletions-test foo\\x1b[39m \\x1b[1mVersion:\\x1b[22m \\x1b[33m1.0.0\\x1b[39m @@ -941,11 +969,14 @@ snapshot[`command integration > should output sub-command help with help command \\x1b[94mhelp\\x1b[39m \\x1b[33m[\\x1b[39m\\x1b[95mcommand\\x1b[39m\\x1b[33m]\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show this help or the help of a sub-command. \\x1b[94mbar\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Bar command. + +stderr: \` `; snapshot[`command integration > should output short help with -h flag 1`] = ` -\` +\`stdout: + \\x1b[1mUsage:\\x1b[22m \\x1b[95mcompletions-test \\x1b[33m<\\x1b[95m\\x1b[95mcolor\\x1b[95m\\x1b[33m>\\x1b[95m \\x1b[33m[\\x1b[95m\\x1b[95mpath...\\x1b[95m\\x1b[33m]\\x1b[95m\\x1b[39m \\x1b[1mVersion:\\x1b[22m \\x1b[33m1.0.0\\x1b[39m @@ -977,11 +1008,14 @@ snapshot[`command integration > should output short help with -h flag 1`] = ` \\x1b[94mhelp\\x1b[39m \\x1b[33m[\\x1b[39m\\x1b[95mcommand\\x1b[39m\\x1b[33m]\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show this help or the help of a sub-command. \\x1b[94mcompletions\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Generate shell completions. + +stderr: \` `; snapshot[`command integration > should output long help with --help flag 1`] = ` -\` +\`stdout: + \\x1b[1mUsage:\\x1b[22m \\x1b[95mcompletions-test \\x1b[33m<\\x1b[95m\\x1b[95mcolor\\x1b[95m\\x1b[33m>\\x1b[95m \\x1b[33m[\\x1b[95m\\x1b[95mpath...\\x1b[95m\\x1b[33m]\\x1b[95m\\x1b[39m \\x1b[1mVersion:\\x1b[22m \\x1b[33m1.0.0\\x1b[39m @@ -1018,88 +1052,33 @@ snapshot[`command integration > should output long help with --help flag 1`] = ` \\x1b[94mhelp\\x1b[39m \\x1b[33m[\\x1b[39m\\x1b[95mcommand\\x1b[39m\\x1b[33m]\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show this help or the help of a sub-command. \\x1b[94mcompletions\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Generate shell completions. + +stderr: \` `; snapshot[`command integration > should output short version with -V flag 1`] = ` -\` - \\x1b[1mUsage:\\x1b[22m \\x1b[95mcompletions-test \\x1b[33m<\\x1b[95m\\x1b[95mcolor\\x1b[95m\\x1b[33m>\\x1b[95m \\x1b[33m[\\x1b[95m\\x1b[95mpath...\\x1b[95m\\x1b[33m]\\x1b[95m\\x1b[39m - \\x1b[1mVersion:\\x1b[22m \\x1b[33m1.0.0\\x1b[39m - - \\x1b[1mmeta1: \\x1b[22mvalue1 - \\x1b[1mmeta2: \\x1b[22mvalue2 - \\x1b[1mmeta3: \\x1b[22mvalue3 - - \\x1b[1mDescription:\\x1b[22m - - Completions test. - - Completions test. - Completions test. - - \\x1b[1mOptions:\\x1b[22m - - \\x1b[94m-h\\x1b[39m, \\x1b[94m--help\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show this help. - \\x1b[94m-V\\x1b[39m, \\x1b[94m--version\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show the version number for this program. - \\x1b[94m-g\\x1b[39m, \\x1b[94m--global\\x1b[39m \\x1b[33m<\\x1b[39m\\x1b[95mval\\x1b[39m\\x1b[33m>\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Foo option. - \\x1b[94m-m\\x1b[39m, \\x1b[94m--main\\x1b[39m \\x1b[33m<\\x1b[39m\\x1b[95mval\\x1b[39m\\x1b[33m>\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Bar option. - \\x1b[94m--color\\x1b[39m \\x1b[33m<\\x1b[39m\\x1b[95mval\\x1b[39m\\x1b[33m>\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Color option with "'quotes'" and ([{brackets}]) (\\x1b[1mValues: \\x1b[22m\\x1b[32m"blue"\\x1b[39m, \\x1b[32m"yellow"\\x1b[39m, \\x1b[32m"red"\\x1b[39m) - \\x1b[94m-C\\x1b[39m, \\x1b[94m--colors\\x1b[39m \\x1b[33m<\\x1b[39m\\x1b[95mval...\\x1b[39m\\x1b[33m>\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Color option. (\\x1b[1mValues: \\x1b[22m\\x1b[32m"blue"\\x1b[39m, \\x1b[32m"yellow"\\x1b[39m, \\x1b[32m"red"\\x1b[39m) - - \\x1b[1mCommands:\\x1b[22m - - \\x1b[94mfoo\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Foo command with "'quotes'" and ([{brackets}]) - \\x1b[94mbar\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m - \\x1b[94mvalidation-error\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m - \\x1b[94mhelp\\x1b[39m \\x1b[33m[\\x1b[39m\\x1b[95mcommand\\x1b[39m\\x1b[33m]\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show this help or the help of a sub-command. - \\x1b[94mcompletions\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Generate shell completions. +"stdout: +1.0.0 -\` +stderr: +" `; snapshot[`command integration > should output long version with --version flag 1`] = ` -\` - \\x1b[1mUsage:\\x1b[22m \\x1b[95mcompletions-test \\x1b[33m<\\x1b[95m\\x1b[95mcolor\\x1b[95m\\x1b[33m>\\x1b[95m \\x1b[33m[\\x1b[95m\\x1b[95mpath...\\x1b[95m\\x1b[33m]\\x1b[95m\\x1b[39m - \\x1b[1mVersion:\\x1b[22m \\x1b[33m1.0.0\\x1b[39m - - \\x1b[1mmeta1: \\x1b[22mvalue1 - \\x1b[1mmeta2: \\x1b[22mvalue2 - \\x1b[1mmeta3: \\x1b[22mvalue3 - - \\x1b[1mDescription:\\x1b[22m - - Completions test. - - Completions test. - Completions test. - - \\x1b[1mOptions:\\x1b[22m - - \\x1b[94m-h\\x1b[39m, \\x1b[94m--help\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show this help. - \\x1b[94m-V\\x1b[39m, \\x1b[94m--version\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show the version number for this program. - \\x1b[94m-g\\x1b[39m, \\x1b[94m--global\\x1b[39m \\x1b[33m<\\x1b[39m\\x1b[95mval\\x1b[39m\\x1b[33m>\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Foo option. - \\x1b[94m-m\\x1b[39m, \\x1b[94m--main\\x1b[39m \\x1b[33m<\\x1b[39m\\x1b[95mval\\x1b[39m\\x1b[33m>\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Bar option. - foo bar baz. foo bar baz. - - foo bar baz. - foo bar baz. - \\x1b[94m--color\\x1b[39m \\x1b[33m<\\x1b[39m\\x1b[95mval\\x1b[39m\\x1b[33m>\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Color option with "'quotes'" and ([{brackets}]) (\\x1b[1mValues: \\x1b[22m\\x1b[32m"blue"\\x1b[39m, \\x1b[32m"yellow"\\x1b[39m, \\x1b[32m"red"\\x1b[39m) - and line breaks. - \\x1b[94m-C\\x1b[39m, \\x1b[94m--colors\\x1b[39m \\x1b[33m<\\x1b[39m\\x1b[95mval...\\x1b[39m\\x1b[33m>\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Color option. (\\x1b[1mValues: \\x1b[22m\\x1b[32m"blue"\\x1b[39m, \\x1b[32m"yellow"\\x1b[39m, \\x1b[32m"red"\\x1b[39m) +"stdout: +\\x1b[1mcompletions-test\\x1b[22m \\x1b[94m1.0.0\\x1b[39m +\\x1b[1mmeta1\\x1b[22m \\x1b[94mvalue1\\x1b[39m +\\x1b[1mmeta2\\x1b[22m \\x1b[94mvalue2\\x1b[39m +\\x1b[1mmeta3\\x1b[22m \\x1b[94mvalue3\\x1b[39m - \\x1b[1mCommands:\\x1b[22m - - \\x1b[94mfoo\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Foo command with "'quotes'" and ([{brackets}]) - \\x1b[94mbar\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m - \\x1b[94mvalidation-error\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m - \\x1b[94mhelp\\x1b[39m \\x1b[33m[\\x1b[39m\\x1b[95mcommand\\x1b[39m\\x1b[33m]\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show this help or the help of a sub-command. - \\x1b[94mcompletions\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Generate shell completions. - -\` +stderr: +" `; snapshot[`command integration > should print the help of sub-command on validation error 1`] = ` -' +'stdout: + \\x1b[1mUsage:\\x1b[22m \\x1b[95mcompletions-test bar\\x1b[39m \\x1b[1mVersion:\\x1b[22m \\x1b[33m1.0.0\\x1b[39m @@ -1113,13 +1092,16 @@ snapshot[`command integration > should print the help of sub-command on validati \\x1b[94mhelp\\x1b[39m \\x1b[33m[\\x1b[39m\\x1b[95mcommand\\x1b[39m\\x1b[33m]\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show this help or the help of a sub-command. + +stderr: \\x1b[31m \\x1b[1merror\\x1b[22m: Missing required option "--file". \\x1b[39m ' `; snapshot[`command integration > should print error message for unknown option with suggestion 1`] = ` -\` +\`stdout: + \\x1b[1mUsage:\\x1b[22m \\x1b[95mcompletions-test \\x1b[33m<\\x1b[95m\\x1b[95mcolor\\x1b[95m\\x1b[33m>\\x1b[95m \\x1b[33m[\\x1b[95m\\x1b[95mpath...\\x1b[95m\\x1b[33m]\\x1b[95m\\x1b[39m \\x1b[1mVersion:\\x1b[22m \\x1b[33m1.0.0\\x1b[39m @@ -1151,13 +1133,16 @@ snapshot[`command integration > should print error message for unknown option wi \\x1b[94mhelp\\x1b[39m \\x1b[33m[\\x1b[39m\\x1b[95mcommand\\x1b[39m\\x1b[33m]\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show this help or the help of a sub-command. \\x1b[94mcompletions\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Generate shell completions. + +stderr: \\x1b[31m \\x1b[1merror\\x1b[22m: Unknown option "--colorr". Did you mean option "--color"? \\x1b[39m \` `; -snapshot[`command integration > should print help and error message when validation error is thrown 1`] = ` -" +snapshot[`command integration > should print help and error message when validation error 1`] = ` +"stdout: + \\x1b[1mUsage:\\x1b[22m \\x1b[95mcompletions-test validation-error\\x1b[39m \\x1b[1mVersion:\\x1b[22m \\x1b[33m1.0.0\\x1b[39m @@ -1170,6 +1155,8 @@ snapshot[`command integration > should print help and error message when validat \\x1b[94mhelp\\x1b[39m \\x1b[33m[\\x1b[39m\\x1b[95mcommand\\x1b[39m\\x1b[33m]\\x1b[39m \\x1b[31m\\x1b[1m-\\x1b[22m\\x1b[39m Show this help or the help of a sub-command. + +stderr: \\x1b[31m \\x1b[1merror\\x1b[22m: Validation error message. \\x1b[39m " diff --git a/command/test/integration/test.ts b/command/test/integration/test.ts index 9a9589e6..47decb09 100644 --- a/command/test/integration/test.ts +++ b/command/test/integration/test.ts @@ -1,99 +1,107 @@ -import { assertSnapshot, describe, it } from "../../../dev_deps.ts"; -import { runCommand } from "./utils.ts"; - -describe({ +import { assertSnapshotCall } from "../../../testing/assert_snapshot_call.ts"; +import { + Command, + CompletionsCommand, + EnumType, + HelpCommand, + ValidationError, +} from "../../mod.ts"; + +await assertSnapshotCall({ name: "command integration", + meta: import.meta, ignore: Deno.build.os === "windows", - fn() { - it("should complete boolean arg", async (t) => { - const output: string = await runCommand("completions complete boolean"); - await assertSnapshot(t, output); - }); - - it("should complete boolean arg from foo command", async (t) => { - const output: string = await runCommand( - "completions complete boolean foo", - ); - await assertSnapshot(t, output); - }); - - it("should complete boolean arg from foo bar command", async (t) => { - const output: string = await runCommand( - "completions complete boolean foo bar", - ); - await assertSnapshot(t, output); - }); - - it("should complete available commands for help command", async (t) => { - const output: string = await runCommand( - "completions complete command help", - ); - await assertSnapshot(t, output); - }); - - it("should complete enum", async (t) => { - const output: string = await runCommand("completions complete color"); - await assertSnapshot(t, output); - }); - - it("should generate bash completions", async (t) => { - const output: string = await runCommand("completions bash"); - await assertSnapshot(t, output); - }); - - it("should generate fish completions", async (t) => { - const output: string = await runCommand("completions fish"); - await assertSnapshot(t, output); - }); - - it("should generate zsh completions", async (t) => { - const output: string = await runCommand("completions zsh"); - await assertSnapshot(t, output); - }); - - it("should output command help with help command", async (t) => { - const output: string = await runCommand("help"); - await assertSnapshot(t, output); - }); - - it("should output sub-command help with help command", async (t) => { - const output: string = await runCommand("help foo"); - await assertSnapshot(t, output); - }); - - it("should output short help with -h flag", async (t) => { - const output: string = await runCommand("-h"); - await assertSnapshot(t, output); - }); - - it("should output long help with --help flag", async (t) => { - const output: string = await runCommand("--help"); - await assertSnapshot(t, output); - }); - - it("should output short version with -V flag", async (t) => { - const output: string = await runCommand("-h"); - await assertSnapshot(t, output); - }); - - it("should output long version with --version flag", async (t) => { - const output: string = await runCommand("--help"); - await assertSnapshot(t, output); - }); - - it("should print the help of sub-command on validation error", async (t) => { - const output: string = await runCommand("bar", true); - await assertSnapshot(t, output); - }); - - it("should print error message for unknown option with suggestion", async (t) => { - const output: string = await runCommand("--colorr", true); - await assertSnapshot(t, output); - }); - - it("should print help and error message when validation error is thrown", async (t) => { - const output: string = await runCommand("validation-error", true); - await assertSnapshot(t, output); - }); + colors: true, + steps: { + "should complete boolean arg": { + args: ["completions", "complete", "boolean"], + }, + "should complete boolean arg from foo command": { + args: ["completions", "complete", "boolean", "foo"], + }, + "should complete boolean arg from foo bar command": { + args: ["completions", "complete", "boolean", "foo", "bar"], + }, + "should complete available commands for help command": { + args: ["completions", "complete", "command", "help"], + }, + "should complete enum": { args: ["completions", "complete", "color"] }, + "should generate bash completions": { args: ["completions", "bash"] }, + "should generate fish completions": { args: ["completions", "fish"] }, + "should generate zsh completions": { args: ["completions", "zsh"] }, + "should output command help with help command": { args: ["help"] }, + "should output sub-command help with help command": { + args: ["help", "foo"], + }, + "should output short help with -h flag": { args: ["-h"] }, + "should output long help with --help flag": { args: ["--help"] }, + "should output short version with -V flag": { args: ["-V"] }, + "should output long version with --version flag": { args: ["--version"] }, + "should print the help of sub-command on validation error": { + args: ["bar"], + canFail: true, + }, + "should print error message for unknown option with suggestion": { + args: ["--colorr"], + canFail: true, + }, + "should print help and error message when validation error": { + args: ["validation-error"], + canFail: true, + }, + }, + async fn() { + await new Command() + .version("1.0.0") + .name("completions-test") + .description(` + Completions test. + + Completions test. + Completions test. + `) + .meta("meta1", "value1") + .meta("meta2", "value2") + .meta("meta3", "value3") + .globalType("color", new EnumType(["blue", "yellow", "red"])) + .globalOption("-g, --global ", "Foo option.") + .option( + "-m, --main ", + ` + Bar option. + foo bar baz. foo bar baz. + + foo bar baz. + foo bar baz.`, + ) + .option( + "--color=", + "Color option with \"'quotes'\" and ([{brackets}]) \n and line breaks.", + ) + .option("-C, --colors ", "Color option.") + .arguments(" [path...:file]") + .default("help") + // foo + .command( + "foo", + new Command() + .description( + "Foo command with \"'quotes'\" and ([{brackets}]) \n and line breaks.", + ) + .option("-f, --foo", "Foo option.") + // bar + .command("bar", "Bar command.") + .option("-b, --bar", "Bar option.") + .reset(), + ) + .command("bar") + .option("-f, --file ", "...", { required: true }) + .command("validation-error") + .action(() => { + throw new ValidationError("Validation error message.", { exitCode: 1 }); + }) + .command("help", new HelpCommand().global()) + .command("completions", new CompletionsCommand()) + .parse(); }, }); diff --git a/deno.jsonc b/deno.jsonc index e149b342..25f812bb 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -12,8 +12,8 @@ "tasks": { "lint": "deno lint && deno fmt --check", "fmt": "deno fmt", - "test": "deno test --doc --allow-env --allow-read=./ --allow-run=deno --ignore=./CHANGELOG.md --parallel", - "snapshot": "deno task test --allow-write=./ -- --update", + "test": "deno test --doc --allow-run=deno --allow-env --allow-read=./ --allow-write=./ --ignore=./CHANGELOG.md --parallel", + "snapshot": "deno task test -- --update", "coverage": "deno task test --coverage=./dist/coverage/all/result && deno coverage --lcov ./dist/coverage/all/result > ./dist/coverage/all/cov.lcov", "coverage:ansi": "deno task test ansi --coverage=./dist/coverage/ansi/result && deno coverage --lcov ./dist/coverage/ansi/result > ./dist/coverage/ansi/cov.lcov", "coverage:command": "deno task test command --coverage=./dist/coverage/command/result && deno coverage --lcov ./dist/coverage/command/result > ./dist/coverage/command/cov.lcov", diff --git a/prompt/test/integration/__snapshots__/checkbox_test.ts.snap b/prompt/test/integration/__snapshots__/checkbox_test.ts.snap new file mode 100644 index 00000000..00a95f1e --- /dev/null +++ b/prompt/test/integration/__snapshots__/checkbox_test.ts.snap @@ -0,0 +1,25 @@ +export const snapshot = {}; + +snapshot[`checkbox prompt > should check an option 1`] = ` +"stdout: +? Select an option +❯ ✘ Foo + ✘ Bar + ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + ✘ Foo +❯ ✘ Bar + ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + ✘ Foo + ✘ Bar +❯ ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + ✘ Foo + ✘ Bar +❯ ✔ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option › Baz +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/checkbox_test.ts.windows.snap b/prompt/test/integration/__snapshots__/checkbox_test.ts.windows.snap new file mode 100644 index 00000000..7f33a25d --- /dev/null +++ b/prompt/test/integration/__snapshots__/checkbox_test.ts.windows.snap @@ -0,0 +1,25 @@ +export const snapshot = {}; + +snapshot[`checkbox prompt > should check an option 1`] = ` +"stdout: +? Select an option +❯ × Foo + × Bar + × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + × Foo +❯ × Bar + × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + × Foo + × Bar +❯ × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + × Foo + × Bar +❯ √ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option » Baz +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/confirm_test.ts.snap b/prompt/test/integration/__snapshots__/confirm_test.ts.snap new file mode 100644 index 00000000..c35edcf5 --- /dev/null +++ b/prompt/test/integration/__snapshots__/confirm_test.ts.snap @@ -0,0 +1,35 @@ +export const snapshot = {}; + +snapshot[`confirm prompt > should confirm 1`] = ` +"stdout: +? Please confirm (y/N) › +❯ some hint\\x1b[1A\\x1b[26G\\x1b[G\\x1b[0J +? Please confirm (y/N) › yes +❯ some hint\\x1b[1A\\x1b[27G\\x1b[G\\x1b[0J +? Please confirm (y/N) › Yes +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`confirm prompt > should not confirm 1`] = ` +"stdout: +? Please confirm (y/N) › +❯ some hint\\x1b[1A\\x1b[26G\\x1b[G\\x1b[0J +? Please confirm (y/N) › no +❯ some hint\\x1b[1A\\x1b[27G\\x1b[G\\x1b[0J +? Please confirm (y/N) › No +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`confirm prompt > should not confirm by default 1`] = ` +"stdout: +? Please confirm (y/N) › +❯ some hint\\x1b[1A\\x1b[26G\\x1b[G\\x1b[0J +? Please confirm (y/N) › No +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/confirm_test.ts.windows.snap b/prompt/test/integration/__snapshots__/confirm_test.ts.windows.snap new file mode 100644 index 00000000..00978108 --- /dev/null +++ b/prompt/test/integration/__snapshots__/confirm_test.ts.windows.snap @@ -0,0 +1,35 @@ +export const snapshot = {}; + +snapshot[`confirm prompt > should confirm 1`] = ` +"stdout: +? Please confirm (y/N) » +❯ some hint\\x1b[1A\\x1b[26G\\x1b[G\\x1b[0J +? Please confirm (y/N) » yes +❯ some hint\\x1b[1A\\x1b[27G\\x1b[G\\x1b[0J +? Please confirm (y/N) » Yes +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`confirm prompt > should not confirm 1`] = ` +"stdout: +? Please confirm (y/N) » +❯ some hint\\x1b[1A\\x1b[26G\\x1b[G\\x1b[0J +? Please confirm (y/N) » no +❯ some hint\\x1b[1A\\x1b[27G\\x1b[G\\x1b[0J +? Please confirm (y/N) » No +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`confirm prompt > should not confirm by default 1`] = ` +"stdout: +? Please confirm (y/N) » +❯ some hint\\x1b[1A\\x1b[26G\\x1b[G\\x1b[0J +? Please confirm (y/N) » No +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/input_test.ts.snap b/prompt/test/integration/__snapshots__/input_test.ts.snap new file mode 100644 index 00000000..1ac569e6 --- /dev/null +++ b/prompt/test/integration/__snapshots__/input_test.ts.snap @@ -0,0 +1,65 @@ +export const snapshot = {}; + +snapshot[`input prompt > should enter some text 1`] = ` +"stdout: +? Whats your name? (foo) › \\x1b[28G\\x1b[G\\x1b[0J +? Whats your name? (foo) › foo bar\\x1b[35G\\x1b[G\\x1b[0J +? Whats your name? (foo) › foo bar +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`input prompt with suggestions > should enable suggestions and list 1`] = ` +"stdout: +? Whats your name? (foo) › + foo + bar + baz\\x1b[3A\\x1b[28G\\x1b[G\\x1b[0J +? Whats your name? (foo) › foo +❯ foo\\x1b[1A\\x1b[31G\\x1b[G\\x1b[0J +? Whats your name? (foo) › foo +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`input prompt with prefix > should change prefix 1`] = ` +"stdout: +PREFIX Whats your name? (foo) › \\x1b[33G\\x1b[G\\x1b[0J +PREFIX Whats your name? (foo) › bar\\x1b[36G\\x1b[G\\x1b[0J +PREFIX Whats your name? (foo) › bar +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`input prompt with writer set to stderr > should enter some text 1`] = ` +"stdout: + +stderr: +? Whats your name? (foo) › \\x1b[28G\\x1b[G\\x1b[0J +? Whats your name? (foo) › foo bar\\x1b[35G\\x1b[G\\x1b[0J +? Whats your name? (foo) › foo bar +\\x1b[?25h\\x1b[?25h" +`; + +snapshot[`input prompt without prefix > should disable prefix 1`] = ` +"stdout: +Whats your name? (foo) › \\x1b[26G\\x1b[G\\x1b[0J +Whats your name? (foo) › bar\\x1b[29G\\x1b[G\\x1b[0J +Whats your name? (foo) › bar +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`input prompt with no location flag > should work without --location flag 1`] = ` +"stdout: +? Works without --location? (hope so) › \\x1b[41G\\x1b[G\\x1b[0J +? Works without --location? (hope so) › yes\\x1b[44G\\x1b[G\\x1b[0J +? Works without --location? (hope so) › yes +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/input_test.ts.windows.snap b/prompt/test/integration/__snapshots__/input_test.ts.windows.snap new file mode 100644 index 00000000..b979ac03 --- /dev/null +++ b/prompt/test/integration/__snapshots__/input_test.ts.windows.snap @@ -0,0 +1,65 @@ +export const snapshot = {}; + +snapshot[`input prompt > should enter some text 1`] = ` +"stdout: +? Whats your name? (foo) » \\x1b[28G\\x1b[G\\x1b[0J +? Whats your name? (foo) » foo bar\\x1b[35G\\x1b[G\\x1b[0J +? Whats your name? (foo) » foo bar +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`input prompt with suggestions > should enable suggestions and list 1`] = ` +"stdout: +? Whats your name? (foo) » + foo + bar + baz\\x1b[3A\\x1b[28G\\x1b[G\\x1b[0J +? Whats your name? (foo) » foo +❯ foo\\x1b[1A\\x1b[31G\\x1b[G\\x1b[0J +? Whats your name? (foo) » foo +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`input prompt with prefix > should change prefix 1`] = ` +"stdout: +PREFIX Whats your name? (foo) » \\x1b[33G\\x1b[G\\x1b[0J +PREFIX Whats your name? (foo) » bar\\x1b[36G\\x1b[G\\x1b[0J +PREFIX Whats your name? (foo) » bar +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`input prompt with writer set to stderr > should enter some text 1`] = ` +"stdout: + +stderr: +? Whats your name? (foo) » \\x1b[28G\\x1b[G\\x1b[0J +? Whats your name? (foo) » foo bar\\x1b[35G\\x1b[G\\x1b[0J +? Whats your name? (foo) » foo bar +\\x1b[?25h\\x1b[?25h" +`; + +snapshot[`input prompt without prefix > should disable prefix 1`] = ` +"stdout: +Whats your name? (foo) » \\x1b[26G\\x1b[G\\x1b[0J +Whats your name? (foo) » bar\\x1b[29G\\x1b[G\\x1b[0J +Whats your name? (foo) » bar +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`input prompt with no location flag > should work without --location flag 1`] = ` +"stdout: +? Works without --location? (hope so) » \\x1b[41G\\x1b[G\\x1b[0J +? Works without --location? (hope so) » yes\\x1b[44G\\x1b[G\\x1b[0J +? Works without --location? (hope so) » yes +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/list_test.ts.snap b/prompt/test/integration/__snapshots__/list_test.ts.snap new file mode 100644 index 00000000..e14e5d33 --- /dev/null +++ b/prompt/test/integration/__snapshots__/list_test.ts.snap @@ -0,0 +1,13 @@ +export const snapshot = {}; + +snapshot[`list prompt > should enter some keywords 1`] = ` +"stdout: +? Enter some keywords (foo, far) › +❯ some hint...\\x1b[1A\\x1b[36G\\x1b[G\\x1b[0J +? Enter some keywords (foo, far) › foo, bar +❯ some hint...\\x1b[1A\\x1b[44G\\x1b[G\\x1b[0J +? Enter some keywords (foo, far) › foo, bar +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/list_test.ts.windows.snap b/prompt/test/integration/__snapshots__/list_test.ts.windows.snap new file mode 100644 index 00000000..67545dc0 --- /dev/null +++ b/prompt/test/integration/__snapshots__/list_test.ts.windows.snap @@ -0,0 +1,13 @@ +export const snapshot = {}; + +snapshot[`list prompt > should enter some keywords 1`] = ` +"stdout: +? Enter some keywords (foo, far) » +❯ some hint...\\x1b[1A\\x1b[36G\\x1b[G\\x1b[0J +? Enter some keywords (foo, far) » foo, bar +❯ some hint...\\x1b[1A\\x1b[44G\\x1b[G\\x1b[0J +? Enter some keywords (foo, far) » foo, bar +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/number_test.ts.snap b/prompt/test/integration/__snapshots__/number_test.ts.snap new file mode 100644 index 00000000..23443a1c --- /dev/null +++ b/prompt/test/integration/__snapshots__/number_test.ts.snap @@ -0,0 +1,34 @@ +export const snapshot = {}; + +snapshot[`number prompt > should enter a number 1`] = ` +"stdout: +? How old are you? (7) › \\x1b[26G\\x1b[G\\x1b[0J +? How old are you? (7) › 19\\x1b[28G\\x1b[G\\x1b[0J +? How old are you? (7) › 20\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) › 21\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) › 20\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) › 19\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) › 18\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) › 17\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) › 18\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) › 19\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) › 20\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) › 20 +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`number prompt with float > should enter a floating number 1`] = ` +"stdout: +? How old are you? (7) › \\x1b[26G\\x1b[G\\x1b[0J +? How old are you? (7) › 19.\\x1b[29G\\x1b[G\\x1b[0J +? How old are you? (7) › 19.1\\x1b[29G\\x1b[G\\x1b[0J +? How old are you? (7) › 19.2\\x1b[29G\\x1b[G\\x1b[0J +? How old are you? (7) › 19.3\\x1b[29G\\x1b[G\\x1b[0J +? How old are you? (7) › 19.4\\x1b[29G\\x1b[G\\x1b[0J +? How old are you? (7) › 19.4 +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/number_test.ts.windows.snap b/prompt/test/integration/__snapshots__/number_test.ts.windows.snap new file mode 100644 index 00000000..3c2ab433 --- /dev/null +++ b/prompt/test/integration/__snapshots__/number_test.ts.windows.snap @@ -0,0 +1,34 @@ +export const snapshot = {}; + +snapshot[`number prompt > should enter a number 1`] = ` +"stdout: +? How old are you? (7) » \\x1b[26G\\x1b[G\\x1b[0J +? How old are you? (7) » 19\\x1b[28G\\x1b[G\\x1b[0J +? How old are you? (7) » 20\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) » 21\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) » 20\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) » 19\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) » 18\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) » 17\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) » 18\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) » 19\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) » 20\\x1b[27G\\x1b[G\\x1b[0J +? How old are you? (7) » 20 +\\x1b[?25h\\x1b[?25h +stderr: +" +`; + +snapshot[`number prompt with float > should enter a floating number 1`] = ` +"stdout: +? How old are you? (7) » \\x1b[26G\\x1b[G\\x1b[0J +? How old are you? (7) » 19.\\x1b[29G\\x1b[G\\x1b[0J +? How old are you? (7) » 19.1\\x1b[29G\\x1b[G\\x1b[0J +? How old are you? (7) » 19.2\\x1b[29G\\x1b[G\\x1b[0J +? How old are you? (7) » 19.3\\x1b[29G\\x1b[G\\x1b[0J +? How old are you? (7) » 19.4\\x1b[29G\\x1b[G\\x1b[0J +? How old are you? (7) » 19.4 +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/prompt_test.ts.snap b/prompt/test/integration/__snapshots__/prompt_test.ts.snap new file mode 100644 index 00000000..4421d827 --- /dev/null +++ b/prompt/test/integration/__snapshots__/prompt_test.ts.snap @@ -0,0 +1,52 @@ +export const snapshot = {}; + +snapshot[`prompt method > should check an option 1`] = ` +'stdout: +[checkbox:before] input is: foo +{ input: "foo", number: 43, confirm: true, toggle: true, checkbox: [ "bar", "baz" ] } + +stderr: +? Enter some text (default value) › \\x1b[37G\\x1b[G\\x1b[0J +? Enter some text (default value) › f\\x1b[38G\\x1b[G\\x1b[0J +? Enter some text (default value) › fo\\x1b[39G\\x1b[G\\x1b[0J +? Enter some text (default value) › foo\\x1b[40G\\x1b[G\\x1b[0J +? Enter some text (default value) › foo +\\x1b[?25h\\x1b[?25h\\x1b[?25h? Enter a number › \\x1b[20G\\x1b[G\\x1b[0J +? Enter a number › 4\\x1b[21G\\x1b[G\\x1b[0J +? Enter a number › 43\\x1b[22G\\x1b[G\\x1b[0J +? Enter a number › 43 +\\x1b[?25h\\x1b[?25h\\x1b[?25h? Please confirm (y/n) › \\x1b[26G\\x1b[G\\x1b[0J +? Please confirm (y/n) › yes\\x1b[27G\\x1b[G\\x1b[0J +? Please confirm (y/n) › Yes +\\x1b[?25h\\x1b[?25h\\x1b[?25h? Please toggle (No) › No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please toggle (No) › No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please toggle (No) › No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please toggle (No) › No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please toggle (No) › Yes +\\x1b[?25h\\x1b[?25h\\x1b[?25h? Select an option +❯ ✘ Foo + ✘ Bar + ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + ✘ Foo +❯ ✘ Bar + ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + ✘ Foo +❯ ✔ Bar + ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + ✘ Foo + ✔ Bar +❯ ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + ✘ Foo + ✔ Bar +❯ ✔ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option › Bar, Baz +\\x1b[?25h\\x1b[?25h\\x1b[?25h' +`; diff --git a/prompt/test/integration/__snapshots__/prompt_test.ts.windows.snap b/prompt/test/integration/__snapshots__/prompt_test.ts.windows.snap new file mode 100644 index 00000000..9d1088ec --- /dev/null +++ b/prompt/test/integration/__snapshots__/prompt_test.ts.windows.snap @@ -0,0 +1,52 @@ +export const snapshot = {}; + +snapshot[`prompt method > should check an option 1`] = ` +'stdout: +[checkbox:before] input is: foo +{ input: "foo", number: 43, confirm: true, toggle: true, checkbox: [ "bar", "baz" ] } + +stderr: +? Enter some text (default value) » \\x1b[37G\\x1b[G\\x1b[0J +? Enter some text (default value) » f\\x1b[38G\\x1b[G\\x1b[0J +? Enter some text (default value) » fo\\x1b[39G\\x1b[G\\x1b[0J +? Enter some text (default value) » foo\\x1b[40G\\x1b[G\\x1b[0J +? Enter some text (default value) » foo +\\x1b[?25h\\x1b[?25h\\x1b[?25h? Enter a number » \\x1b[20G\\x1b[G\\x1b[0J +? Enter a number » 4\\x1b[21G\\x1b[G\\x1b[0J +? Enter a number » 43\\x1b[22G\\x1b[G\\x1b[0J +? Enter a number » 43 +\\x1b[?25h\\x1b[?25h\\x1b[?25h? Please confirm (y/n) » \\x1b[26G\\x1b[G\\x1b[0J +? Please confirm (y/n) » yes\\x1b[27G\\x1b[G\\x1b[0J +? Please confirm (y/n) » Yes +\\x1b[?25h\\x1b[?25h\\x1b[?25h? Please toggle (No) » No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please toggle (No) » No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please toggle (No) » No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please toggle (No) » No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please toggle (No) » Yes +\\x1b[?25h\\x1b[?25h\\x1b[?25h? Select an option +❯ × Foo + × Bar + × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + × Foo +❯ × Bar + × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + × Foo +❯ √ Bar + × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + × Foo + √ Bar +❯ × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + × Foo + √ Bar +❯ √ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option » Bar, Baz +\\x1b[?25h\\x1b[?25h\\x1b[?25h' +`; diff --git a/prompt/test/integration/__snapshots__/secret_test.ts.snap b/prompt/test/integration/__snapshots__/secret_test.ts.snap new file mode 100644 index 00000000..c1786ac1 --- /dev/null +++ b/prompt/test/integration/__snapshots__/secret_test.ts.snap @@ -0,0 +1,11 @@ +export const snapshot = {}; + +snapshot[`secret prompt > should enter a secret 1`] = ` +"stdout: +? enter your secret › \\x1b[23G\\x1b[G\\x1b[0J +? enter your secret › ***\\x1b[26G\\x1b[G\\x1b[0J +? enter your secret › *** +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/secret_test.ts.windows.snap b/prompt/test/integration/__snapshots__/secret_test.ts.windows.snap new file mode 100644 index 00000000..8fd1cc96 --- /dev/null +++ b/prompt/test/integration/__snapshots__/secret_test.ts.windows.snap @@ -0,0 +1,11 @@ +export const snapshot = {}; + +snapshot[`secret prompt > should enter a secret 1`] = ` +"stdout: +? enter your secret » \\x1b[23G\\x1b[G\\x1b[0J +? enter your secret » ***\\x1b[26G\\x1b[G\\x1b[0J +? enter your secret » *** +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/select_test.ts.snap b/prompt/test/integration/__snapshots__/select_test.ts.snap new file mode 100644 index 00000000..531787d7 --- /dev/null +++ b/prompt/test/integration/__snapshots__/select_test.ts.snap @@ -0,0 +1,21 @@ +export const snapshot = {}; + +snapshot[`select prompt > should select an option 1`] = ` +"stdout: +? Select an option +❯ Foo + Bar + Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + Foo +❯ Bar + Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + Foo + Bar +❯ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option › Baz +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/select_test.ts.windows.snap b/prompt/test/integration/__snapshots__/select_test.ts.windows.snap new file mode 100644 index 00000000..03f5fdd7 --- /dev/null +++ b/prompt/test/integration/__snapshots__/select_test.ts.windows.snap @@ -0,0 +1,21 @@ +export const snapshot = {}; + +snapshot[`select prompt > should select an option 1`] = ` +"stdout: +? Select an option +❯ Foo + Bar + Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + Foo +❯ Bar + Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option + Foo + Bar +❯ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J +? Select an option » Baz +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/test.ts.snap b/prompt/test/integration/__snapshots__/test.ts.snap deleted file mode 100644 index b6be2465..00000000 --- a/prompt/test/integration/__snapshots__/test.ts.snap +++ /dev/null @@ -1,265 +0,0 @@ -export const snapshot = {}; - -snapshot[`prompt - integration - checkbox 1`] = ` -"stdout: -? Select an option -❯ ✘ Foo - ✘ Bar - ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - ✘ Foo -❯ ✘ Bar - ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - ✘ Foo - ✘ Bar -❯ ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - ✘ Foo - ✘ Bar -❯ ✔ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option › Baz -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - confirm 1`] = ` -"stdout: -? Please confirm (y/N) › -❯ some hint\\x1b[1A\\x1b[26G\\x1b[G\\x1b[0J -? Please confirm (y/N) › yes -❯ some hint\\x1b[1A\\x1b[27G\\x1b[G\\x1b[0J -? Please confirm (y/N) › Yes -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - confirm 2`] = ` -"stdout: -? Please confirm (y/N) › -❯ some hint\\x1b[1A\\x1b[26G\\x1b[G\\x1b[0J -? Please confirm (y/N) › no -❯ some hint\\x1b[1A\\x1b[27G\\x1b[G\\x1b[0J -? Please confirm (y/N) › No -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - confirm 3`] = ` -"stdout: -? Please confirm (y/N) › -❯ some hint\\x1b[1A\\x1b[26G\\x1b[G\\x1b[0J -? Please confirm (y/N) › No -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - input 1`] = ` -"stdout: -? Whats your name? (foo) › \\x1b[28G\\x1b[G\\x1b[0J -? Whats your name? (foo) › foo bar\\x1b[35G\\x1b[G\\x1b[0J -? Whats your name? (foo) › foo bar -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - input no location flag 1`] = ` -"stdout: -? Works without --location? (hope so) › \\x1b[41G\\x1b[G\\x1b[0J -? Works without --location? (hope so) › yes\\x1b[44G\\x1b[G\\x1b[0J -? Works without --location? (hope so) › yes -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - input no prefix 1`] = ` -"stdout: -Whats your name? (foo) › \\x1b[26G\\x1b[G\\x1b[0J -Whats your name? (foo) › bar\\x1b[29G\\x1b[G\\x1b[0J -Whats your name? (foo) › bar -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - input output stream 1`] = ` -"stdout: - -stderr: -? Whats your name? (foo) › \\x1b[28G\\x1b[G\\x1b[0J -? Whats your name? (foo) › foo bar\\x1b[35G\\x1b[G\\x1b[0J -? Whats your name? (foo) › foo bar -\\x1b[?25h\\x1b[?25h" -`; - -snapshot[`prompt - integration - input prefix 1`] = ` -"stdout: -PREFIX Whats your name? (foo) › \\x1b[33G\\x1b[G\\x1b[0J -PREFIX Whats your name? (foo) › bar\\x1b[36G\\x1b[G\\x1b[0J -PREFIX Whats your name? (foo) › bar -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - input suggestions 1`] = ` -"stdout: -? Whats your name? (foo) › - foo - bar - baz\\x1b[3A\\x1b[28G\\x1b[G\\x1b[0J -? Whats your name? (foo) › foo -❯ foo\\x1b[1A\\x1b[31G\\x1b[G\\x1b[0J -? Whats your name? (foo) › foo -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - list 1`] = ` -"stdout: -? Enter some keywords (foo, far) › -❯ some hint...\\x1b[1A\\x1b[36G\\x1b[G\\x1b[0J -? Enter some keywords (foo, far) › foo, bar -❯ some hint...\\x1b[1A\\x1b[44G\\x1b[G\\x1b[0J -? Enter some keywords (foo, far) › foo, bar -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - number 1`] = ` -"stdout: -? How old are you? (7) › \\x1b[26G\\x1b[G\\x1b[0J -? How old are you? (7) › 19\\x1b[28G\\x1b[G\\x1b[0J -? How old are you? (7) › 20\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) › 21\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) › 20\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) › 19\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) › 18\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) › 17\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) › 18\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) › 19\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) › 20\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) › 20 -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - number decimal 1`] = ` -"stdout: -? How old are you? (7) › \\x1b[26G\\x1b[G\\x1b[0J -? How old are you? (7) › 19.\\x1b[29G\\x1b[G\\x1b[0J -? How old are you? (7) › 19.1\\x1b[29G\\x1b[G\\x1b[0J -? How old are you? (7) › 19.2\\x1b[29G\\x1b[G\\x1b[0J -? How old are you? (7) › 19.3\\x1b[29G\\x1b[G\\x1b[0J -? How old are you? (7) › 19.4\\x1b[29G\\x1b[G\\x1b[0J -? How old are you? (7) › 19.4 -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - prompt list 1`] = ` -'stdout: -[checkbox:before] input is: foo -{ input: "foo", number: 43, confirm: true, toggle: true, checkbox: [ "bar", "baz" ] } - -stderr: -? Enter some text (default value) › \\x1b[37G\\x1b[G\\x1b[0J -? Enter some text (default value) › f\\x1b[38G\\x1b[G\\x1b[0J -? Enter some text (default value) › fo\\x1b[39G\\x1b[G\\x1b[0J -? Enter some text (default value) › foo\\x1b[40G\\x1b[G\\x1b[0J -? Enter some text (default value) › foo -\\x1b[?25h\\x1b[?25h\\x1b[?25h? Enter a number › \\x1b[20G\\x1b[G\\x1b[0J -? Enter a number › 4\\x1b[21G\\x1b[G\\x1b[0J -? Enter a number › 43\\x1b[22G\\x1b[G\\x1b[0J -? Enter a number › 43 -\\x1b[?25h\\x1b[?25h\\x1b[?25h? Please confirm (y/n) › \\x1b[26G\\x1b[G\\x1b[0J -? Please confirm (y/n) › yes\\x1b[27G\\x1b[G\\x1b[0J -? Please confirm (y/n) › Yes -\\x1b[?25h\\x1b[?25h\\x1b[?25h? Please toggle (No) › No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please toggle (No) › No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please toggle (No) › No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please toggle (No) › No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please toggle (No) › Yes -\\x1b[?25h\\x1b[?25h\\x1b[?25h? Select an option -❯ ✘ Foo - ✘ Bar - ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - ✘ Foo -❯ ✘ Bar - ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - ✘ Foo -❯ ✔ Bar - ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - ✘ Foo - ✔ Bar -❯ ✘ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - ✘ Foo - ✔ Bar -❯ ✔ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option › Bar, Baz -\\x1b[?25h\\x1b[?25h\\x1b[?25h' -`; - -snapshot[`prompt - integration - secret 1`] = ` -"stdout: -? enter your secret › \\x1b[23G\\x1b[G\\x1b[0J -? enter your secret › ***\\x1b[26G\\x1b[G\\x1b[0J -? enter your secret › *** -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - select 1`] = ` -"stdout: -? Select an option -❯ Foo - Bar - Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - Foo -❯ Bar - Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - Foo - Bar -❯ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option › Baz -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - toggle 1`] = ` -"stdout: -? Please confirm (No) › No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please confirm (No) › No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please confirm (No) › No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please confirm (No) › No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please confirm (No) › Yes -\\x1b[?25h\\x1b[?25h -stderr: -" -`; diff --git a/prompt/test/integration/__snapshots__/test.ts.windows.snap b/prompt/test/integration/__snapshots__/test.ts.windows.snap deleted file mode 100644 index 7c93a4bb..00000000 --- a/prompt/test/integration/__snapshots__/test.ts.windows.snap +++ /dev/null @@ -1,265 +0,0 @@ -export const snapshot = {}; - -snapshot[`prompt - integration - checkbox 1`] = ` -"stdout: -? Select an option -❯ × Foo - × Bar - × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - × Foo -❯ × Bar - × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - × Foo - × Bar -❯ × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - × Foo - × Bar -❯ √ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option » Baz -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - confirm 1`] = ` -"stdout: -? Please confirm (y/N) » -❯ some hint\\x1b[1A\\x1b[26G\\x1b[G\\x1b[0J -? Please confirm (y/N) » yes -❯ some hint\\x1b[1A\\x1b[27G\\x1b[G\\x1b[0J -? Please confirm (y/N) » Yes -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - confirm 2`] = ` -"stdout: -? Please confirm (y/N) » -❯ some hint\\x1b[1A\\x1b[26G\\x1b[G\\x1b[0J -? Please confirm (y/N) » no -❯ some hint\\x1b[1A\\x1b[27G\\x1b[G\\x1b[0J -? Please confirm (y/N) » No -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - confirm 3`] = ` -"stdout: -? Please confirm (y/N) » -❯ some hint\\x1b[1A\\x1b[26G\\x1b[G\\x1b[0J -? Please confirm (y/N) » No -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - input 1`] = ` -"stdout: -? Whats your name? (foo) » \\x1b[28G\\x1b[G\\x1b[0J -? Whats your name? (foo) » foo bar\\x1b[35G\\x1b[G\\x1b[0J -? Whats your name? (foo) » foo bar -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - input no location flag 1`] = ` -"stdout: -? Works without --location? (hope so) » \\x1b[41G\\x1b[G\\x1b[0J -? Works without --location? (hope so) » yes\\x1b[44G\\x1b[G\\x1b[0J -? Works without --location? (hope so) » yes -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - input no prefix 1`] = ` -"stdout: -Whats your name? (foo) » \\x1b[26G\\x1b[G\\x1b[0J -Whats your name? (foo) » bar\\x1b[29G\\x1b[G\\x1b[0J -Whats your name? (foo) » bar -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - input output stream 1`] = ` -"stdout: - -stderr: -? Whats your name? (foo) » \\x1b[28G\\x1b[G\\x1b[0J -? Whats your name? (foo) » foo bar\\x1b[35G\\x1b[G\\x1b[0J -? Whats your name? (foo) » foo bar -\\x1b[?25h\\x1b[?25h" -`; - -snapshot[`prompt - integration - input prefix 1`] = ` -"stdout: -PREFIX Whats your name? (foo) » \\x1b[33G\\x1b[G\\x1b[0J -PREFIX Whats your name? (foo) » bar\\x1b[36G\\x1b[G\\x1b[0J -PREFIX Whats your name? (foo) » bar -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - input suggestions 1`] = ` -"stdout: -? Whats your name? (foo) » - foo - bar - baz\\x1b[3A\\x1b[28G\\x1b[G\\x1b[0J -? Whats your name? (foo) » foo -❯ foo\\x1b[1A\\x1b[31G\\x1b[G\\x1b[0J -? Whats your name? (foo) » foo -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - list 1`] = ` -"stdout: -? Enter some keywords (foo, far) » -❯ some hint...\\x1b[1A\\x1b[36G\\x1b[G\\x1b[0J -? Enter some keywords (foo, far) » foo, bar -❯ some hint...\\x1b[1A\\x1b[44G\\x1b[G\\x1b[0J -? Enter some keywords (foo, far) » foo, bar -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - number 1`] = ` -"stdout: -? How old are you? (7) » \\x1b[26G\\x1b[G\\x1b[0J -? How old are you? (7) » 19\\x1b[28G\\x1b[G\\x1b[0J -? How old are you? (7) » 20\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) » 21\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) » 20\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) » 19\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) » 18\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) » 17\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) » 18\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) » 19\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) » 20\\x1b[27G\\x1b[G\\x1b[0J -? How old are you? (7) » 20 -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - number decimal 1`] = ` -"stdout: -? How old are you? (7) » \\x1b[26G\\x1b[G\\x1b[0J -? How old are you? (7) » 19.\\x1b[29G\\x1b[G\\x1b[0J -? How old are you? (7) » 19.1\\x1b[29G\\x1b[G\\x1b[0J -? How old are you? (7) » 19.2\\x1b[29G\\x1b[G\\x1b[0J -? How old are you? (7) » 19.3\\x1b[29G\\x1b[G\\x1b[0J -? How old are you? (7) » 19.4\\x1b[29G\\x1b[G\\x1b[0J -? How old are you? (7) » 19.4 -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - prompt list 1`] = ` -'stdout: -[checkbox:before] input is: foo -{ input: "foo", number: 43, confirm: true, toggle: true, checkbox: [ "bar", "baz" ] } - -stderr: -? Enter some text (default value) » \\x1b[37G\\x1b[G\\x1b[0J -? Enter some text (default value) » f\\x1b[38G\\x1b[G\\x1b[0J -? Enter some text (default value) » fo\\x1b[39G\\x1b[G\\x1b[0J -? Enter some text (default value) » foo\\x1b[40G\\x1b[G\\x1b[0J -? Enter some text (default value) » foo -\\x1b[?25h\\x1b[?25h\\x1b[?25h? Enter a number » \\x1b[20G\\x1b[G\\x1b[0J -? Enter a number » 4\\x1b[21G\\x1b[G\\x1b[0J -? Enter a number » 43\\x1b[22G\\x1b[G\\x1b[0J -? Enter a number » 43 -\\x1b[?25h\\x1b[?25h\\x1b[?25h? Please confirm (y/n) » \\x1b[26G\\x1b[G\\x1b[0J -? Please confirm (y/n) » yes\\x1b[27G\\x1b[G\\x1b[0J -? Please confirm (y/n) » Yes -\\x1b[?25h\\x1b[?25h\\x1b[?25h? Please toggle (No) » No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please toggle (No) » No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please toggle (No) » No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please toggle (No) » No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please toggle (No) » Yes -\\x1b[?25h\\x1b[?25h\\x1b[?25h? Select an option -❯ × Foo - × Bar - × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - × Foo -❯ × Bar - × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - × Foo -❯ √ Bar - × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - × Foo - √ Bar -❯ × Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - × Foo - √ Bar -❯ √ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option » Bar, Baz -\\x1b[?25h\\x1b[?25h\\x1b[?25h' -`; - -snapshot[`prompt - integration - secret 1`] = ` -"stdout: -? enter your secret » \\x1b[23G\\x1b[G\\x1b[0J -? enter your secret » ***\\x1b[26G\\x1b[G\\x1b[0J -? enter your secret » *** -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - select 1`] = ` -"stdout: -? Select an option -❯ Foo - Bar - Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - Foo -❯ Bar - Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option - Foo - Bar -❯ Baz\\x1b[3A\\x1b[19G\\x1b[?25l\\x1b[G\\x1b[0J -? Select an option » Baz -\\x1b[?25h\\x1b[?25h -stderr: -" -`; - -snapshot[`prompt - integration - toggle 1`] = ` -"stdout: -? Please confirm (No) » No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please confirm (No) » No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please confirm (No) » No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please confirm (No) » No / Yes -❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J -? Please confirm (No) » Yes -\\x1b[?25h\\x1b[?25h -stderr: -" -`; diff --git a/prompt/test/integration/__snapshots__/toggle_test.ts.snap b/prompt/test/integration/__snapshots__/toggle_test.ts.snap new file mode 100644 index 00000000..9d22d7e1 --- /dev/null +++ b/prompt/test/integration/__snapshots__/toggle_test.ts.snap @@ -0,0 +1,17 @@ +export const snapshot = {}; + +snapshot[`toggle prompt > should toggle the prompt 1`] = ` +"stdout: +? Please confirm (No) › No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please confirm (No) › No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please confirm (No) › No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please confirm (No) › No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please confirm (No) › Yes +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/__snapshots__/toggle_test.ts.windows.snap b/prompt/test/integration/__snapshots__/toggle_test.ts.windows.snap new file mode 100644 index 00000000..318c742d --- /dev/null +++ b/prompt/test/integration/__snapshots__/toggle_test.ts.windows.snap @@ -0,0 +1,17 @@ +export const snapshot = {}; + +snapshot[`toggle prompt > should toggle the prompt 1`] = ` +"stdout: +? Please confirm (No) » No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please confirm (No) » No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please confirm (No) » No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please confirm (No) » No / Yes +❯ some hint\\x1b[1A\\x1b[0G\\x1b[?25l\\x1b[G\\x1b[0J +? Please confirm (No) » Yes +\\x1b[?25h\\x1b[?25h +stderr: +" +`; diff --git a/prompt/test/integration/checkbox_test.ts b/prompt/test/integration/checkbox_test.ts new file mode 100644 index 00000000..8d2e16cb --- /dev/null +++ b/prompt/test/integration/checkbox_test.ts @@ -0,0 +1,25 @@ +import { ansi } from "../../../ansi/ansi.ts"; +import { Checkbox } from "../../checkbox.ts"; +import { assertSnapshotCall } from "../../../testing/assert_snapshot_call.ts"; + +await assertSnapshotCall({ + name: "checkbox prompt > should check an option", + meta: import.meta, + osSuffix: ["windows"], + stdin: ansi + .cursorDown + .cursorDown + .text(" ") + .text("\n") + .toArray(), + async fn() { + await Checkbox.prompt({ + message: "Select an option", + options: [ + { name: "Foo", value: "foo" }, + { name: "Bar", value: "bar" }, + { name: "Baz", value: "baz" }, + ], + }); + }, +}); diff --git a/prompt/test/integration/confirm_test.ts b/prompt/test/integration/confirm_test.ts new file mode 100644 index 00000000..2e85dbef --- /dev/null +++ b/prompt/test/integration/confirm_test.ts @@ -0,0 +1,21 @@ +import { Confirm } from "../../confirm.ts"; +import { assertSnapshotCall } from "../../../testing/assert_snapshot_call.ts"; + +await assertSnapshotCall({ + name: "confirm prompt", + meta: import.meta, + osSuffix: ["windows"], + // args: ["--allow-env=ASSERT_SNAPSHOT_CALL_TEST_NAME"], + steps: { + "should confirm": { stdin: ["y", "\n"] }, + "should not confirm": { stdin: ["n", "\n"] }, + "should not confirm by default": { stdin: ["", "\n"] }, + }, + async fn() { + await Confirm.prompt({ + message: "Please confirm", + hint: "some hint", + default: false, + }); + }, +}); diff --git a/prompt/test/integration/fixtures/checkbox.ts b/prompt/test/integration/fixtures/checkbox.ts deleted file mode 100644 index e96af0b5..00000000 --- a/prompt/test/integration/fixtures/checkbox.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ansi } from "../../../../ansi/ansi.ts"; -import { Checkbox } from "../../../checkbox.ts"; - -export const tests = import.meta.main ? null : { - "should check an option": ansi - .cursorDown - .cursorDown - .text(" ") - .text("\n") - .toArray(), -}; - -if (import.meta.main) { - await Checkbox.prompt({ - message: "Select an option", - options: [ - { name: "Foo", value: "foo" }, - { name: "Bar", value: "bar" }, - { name: "Baz", value: "baz" }, - ], - }); -} diff --git a/prompt/test/integration/fixtures/confirm.ts b/prompt/test/integration/fixtures/confirm.ts deleted file mode 100644 index a5c5d442..00000000 --- a/prompt/test/integration/fixtures/confirm.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Confirm } from "../../../confirm.ts"; - -export const tests = import.meta.main ? null : { - "should confirm": ["y", "\n"], - "should not confirm": ["n", "\n"], - "should not confirm by default": ["", "\n"], -}; - -if (import.meta.main) { - await Confirm.prompt({ - message: "Please confirm", - hint: "some hint", - default: false, - }); -} diff --git a/prompt/test/integration/fixtures/input.ts b/prompt/test/integration/fixtures/input.ts deleted file mode 100644 index 86d678b4..00000000 --- a/prompt/test/integration/fixtures/input.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Input } from "../../../input.ts"; - -export const tests = import.meta.main ? null : { - "should enter som text": ["foo bar", "\n"], -}; - -if (import.meta.main) { - await Input.prompt({ - message: "Whats your name?", - default: "foo", - }); -} diff --git a/prompt/test/integration/fixtures/input_no_location_flag.ts b/prompt/test/integration/fixtures/input_no_location_flag.ts deleted file mode 100644 index 66ade498..00000000 --- a/prompt/test/integration/fixtures/input_no_location_flag.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Input } from "../../../input.ts"; - -export const tests = import.meta.main ? null : { - "should work without --location flag": ["yes", "\n"], -}; - -if (import.meta.main) { - await Input.prompt({ - message: "Works without --location?", - default: "hope so", - }); -} diff --git a/prompt/test/integration/fixtures/input_no_prefix.ts b/prompt/test/integration/fixtures/input_no_prefix.ts deleted file mode 100644 index c0dffb5c..00000000 --- a/prompt/test/integration/fixtures/input_no_prefix.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Input } from "../../../input.ts"; - -export const tests = import.meta.main ? null : { - "should disable prefix": ["bar", "\n"], -}; - -if (import.meta.main) { - await Input.prompt({ - message: "Whats your name?", - default: "foo", - prefix: "", - }); -} diff --git a/prompt/test/integration/fixtures/input_output_stream.ts b/prompt/test/integration/fixtures/input_output_stream.ts deleted file mode 100644 index 940d034d..00000000 --- a/prompt/test/integration/fixtures/input_output_stream.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Input } from "../../../input.ts"; - -export const tests = import.meta.main ? null : { - "should enter some text": ["foo bar", "\n"], -}; - -if (import.meta.main) { - await Input.prompt({ - message: "Whats your name?", - default: "foo", - writer: Deno.stderr, - }); -} diff --git a/prompt/test/integration/fixtures/input_prefix.ts b/prompt/test/integration/fixtures/input_prefix.ts deleted file mode 100644 index 9a2dde0a..00000000 --- a/prompt/test/integration/fixtures/input_prefix.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Input } from "../../../input.ts"; - -export const tests = import.meta.main ? null : { - "should change prefix": ["bar", "\n"], -}; - -if (import.meta.main) { - await Input.prompt({ - message: "Whats your name?", - default: "foo", - prefix: "PREFIX ", - }); -} diff --git a/prompt/test/integration/fixtures/input_suggestions.ts b/prompt/test/integration/fixtures/input_suggestions.ts deleted file mode 100644 index f65ebdcc..00000000 --- a/prompt/test/integration/fixtures/input_suggestions.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Input } from "../../../input.ts"; - -export const tests = import.meta.main ? null : { - "should enable suggestions and list": ["foo", "\n"], -}; - -if (import.meta.main) { - await Input.prompt({ - message: "Whats your name?", - default: "foo", - suggestions: ["foo", "bar", "baz"], - list: true, - }); -} diff --git a/prompt/test/integration/fixtures/list.ts b/prompt/test/integration/fixtures/list.ts deleted file mode 100644 index b879fcf5..00000000 --- a/prompt/test/integration/fixtures/list.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { List } from "../../../list.ts"; - -export const tests = import.meta.main ? null : { - "should enter some keywords": ["foo,bar", "\n"], -}; - -if (import.meta.main) { - await List.prompt({ - message: "Enter some keywords", - default: ["foo", "far"], - hint: "some hint...", - }); -} diff --git a/prompt/test/integration/fixtures/number.ts b/prompt/test/integration/fixtures/number.ts deleted file mode 100644 index 986d71ba..00000000 --- a/prompt/test/integration/fixtures/number.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ansi } from "../../../../ansi/ansi.ts"; -import { Number } from "../../../number.ts"; - -export const tests = import.meta.main ? null : { - "should enter a number": ansi - .text("19") - .cursorUp - .text("u") - .cursorDown - .cursorDown - .cursorDown - .cursorDown - .cursorUp - .cursorUp - .cursorUp - .text("\n") - .toArray(), -}; - -if (import.meta.main) { - await Number.prompt({ - message: "How old are you?", - default: 7, - max: 20, - min: 18, - }); -} diff --git a/prompt/test/integration/fixtures/number_decimal.ts b/prompt/test/integration/fixtures/number_decimal.ts deleted file mode 100644 index 37749d84..00000000 --- a/prompt/test/integration/fixtures/number_decimal.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ansi } from "../../../../ansi/ansi.ts"; -import { Number } from "../../../number.ts"; - -export const tests = import.meta.main ? null : { - "should enter a floating number": ansi - .text("19.") - .cursorUp - .cursorUp - .cursorUp - .cursorUp - .text("\n") - .toArray(), -}; - -if (import.meta.main) { - await Number.prompt({ - message: "How old are you?", - default: 7, - max: 20, - min: 18, - float: true, - }); -} diff --git a/prompt/test/integration/fixtures/prompt_list.ts b/prompt/test/integration/fixtures/prompt_list.ts deleted file mode 100644 index 057f36af..00000000 --- a/prompt/test/integration/fixtures/prompt_list.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { ansi } from "../../../../ansi/ansi.ts"; -import { assertType, IsExact } from "../../../../dev_deps.ts"; -import { Checkbox, CheckboxOptions } from "../../../checkbox.ts"; -import { Confirm } from "../../../confirm.ts"; -import { Input } from "../../../input.ts"; -import { Number } from "../../../number.ts"; -import { prompt, PromptMiddleware, PromptOptions } from "../../../prompt.ts"; -import { Toggle } from "../../../toggle.ts"; - -export const tests = import.meta.main ? null : { - "should check an option": ansi - // input - .text("f") - .text("o") - .text("o") - .text("\n") - // number - .text("4") - .text("3") - .text("\n") - // confirm - .text("y") - .text("\n") - // toggle - .text("y") - .text("n") - .text("y") - .text("\n") - // checkbox - .cursorDown - .text(" ") - .cursorDown - .text(" ") - .text("\n") - .toArray(), -}; - -if (import.meta.main) { - const checkboxOptions: PromptOptions< - "checkbox", - typeof Checkbox, - { input?: string } - > = { - name: "checkbox", - type: Checkbox, - message: "Select an option", - options: [ - { name: "Foo", value: "foo" }, - { name: "Bar", value: "bar" }, - { name: "Baz", value: "baz" }, - ], - before({ input }, next) { - console.log("[checkbox:before] input is:", input); - return next(); - }, - }; - - const result = await prompt([{ - name: "input", - type: Input, - message: "Enter some text", - default: "default value", - }, { - name: "number", - type: Number, - message: "Enter a number", - }, { - name: "confirm", - type: Confirm, - message: "Please confirm", - }, { - name: "toggle", - type: Toggle, - message: "Please toggle", - hint: "some hint", - default: false, - }, checkboxOptions], { - reader: Deno.stdin, - writer: Deno.stderr, - }); - - assertType< - IsExact - >(true); - - assertType< - IsExact< - typeof checkboxOptions, - { - name: "checkbox"; - type: typeof Checkbox; - before?: PromptMiddleware<{ checkbox?: Array; input?: string }>; - after?: PromptMiddleware<{ checkbox?: Array; input?: string }>; - } & CheckboxOptions - > - >(true); - - console.log(result); -} diff --git a/prompt/test/integration/fixtures/secret.ts b/prompt/test/integration/fixtures/secret.ts deleted file mode 100644 index 477b0a0b..00000000 --- a/prompt/test/integration/fixtures/secret.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Secret } from "../../../secret.ts"; - -export const tests = import.meta.main ? null : { - "should enter a secret": ["123", "\n"], -}; - -if (import.meta.main) { - await Secret.prompt({ - message: "enter your secret", - }); -} diff --git a/prompt/test/integration/fixtures/select.ts b/prompt/test/integration/fixtures/select.ts deleted file mode 100644 index 72991360..00000000 --- a/prompt/test/integration/fixtures/select.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ansi } from "../../../../ansi/ansi.ts"; -import { Select } from "../../../select.ts"; - -export const tests = import.meta.main ? null : { - "should select an option": ansi - .cursorDown - .cursorDown - .text("\n") - .toArray(), -}; - -if (import.meta.main) { - await Select.prompt({ - message: "Select an option", - options: [ - { name: "Foo", value: "foo" }, - { name: "Bar", value: "bar" }, - { name: "Baz", value: "baz" }, - ], - }); -} diff --git a/prompt/test/integration/fixtures/toggle.ts b/prompt/test/integration/fixtures/toggle.ts deleted file mode 100644 index 65ce58e8..00000000 --- a/prompt/test/integration/fixtures/toggle.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Toggle } from "../../../toggle.ts"; - -export const tests = import.meta.main ? null : { - "should toggle the prompt": ["y", "n", "y", "\n"], -}; - -if (import.meta.main) { - await Toggle.prompt({ - message: "Please confirm", - hint: "some hint", - default: false, - }); -} diff --git a/prompt/test/integration/input_test.ts b/prompt/test/integration/input_test.ts new file mode 100644 index 00000000..2d753ef2 --- /dev/null +++ b/prompt/test/integration/input_test.ts @@ -0,0 +1,97 @@ +import { Input } from "../../input.ts"; +import { assertSnapshotCall } from "../../../testing/assert_snapshot_call.ts"; + +await assertSnapshotCall({ + name: "input prompt", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should enter some text": { stdin: ["foo bar", "\n"] }, + }, + async fn() { + await Input.prompt({ + message: "Whats your name?", + default: "foo", + }); + }, +}); + +await assertSnapshotCall({ + name: "input prompt with suggestions", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should enable suggestions and list": { stdin: ["foo", "\n"] }, + }, + async fn() { + await Input.prompt({ + message: "Whats your name?", + default: "foo", + suggestions: ["foo", "bar", "baz"], + list: true, + }); + }, +}); + +await assertSnapshotCall({ + name: "input prompt with prefix", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should change prefix": { stdin: ["bar", "\n"] }, + }, + async fn() { + await Input.prompt({ + message: "Whats your name?", + default: "foo", + prefix: "PREFIX ", + }); + }, +}); + +await assertSnapshotCall({ + name: "input prompt with writer set to stderr", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should enter some text": { stdin: ["foo bar", "\n"] }, + }, + async fn() { + await Input.prompt({ + message: "Whats your name?", + default: "foo", + writer: Deno.stderr, + }); + }, +}); + +await assertSnapshotCall({ + name: "input prompt without prefix", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should disable prefix": { stdin: ["bar", "\n"] }, + }, + async fn() { + await Input.prompt({ + message: "Whats your name?", + default: "foo", + prefix: "", + }); + }, +}); + +await assertSnapshotCall({ + name: "input prompt with no location flag", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should work without --location flag": { stdin: ["yes", "\n"] }, + }, + async fn() { + await Input.prompt({ + message: "Works without --location?", + default: "hope so", + }); + }, +}); diff --git a/prompt/test/integration/list_test.ts b/prompt/test/integration/list_test.ts new file mode 100644 index 00000000..3f8ee9ac --- /dev/null +++ b/prompt/test/integration/list_test.ts @@ -0,0 +1,18 @@ +import { List } from "../../list.ts"; +import { assertSnapshotCall } from "../../../testing/assert_snapshot_call.ts"; + +await assertSnapshotCall({ + name: "list prompt", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should enter some keywords": { stdin: ["foo,bar", "\n"] }, + }, + async fn() { + await List.prompt({ + message: "Enter some keywords", + default: ["foo", "far"], + hint: "some hint...", + }); + }, +}); diff --git a/prompt/test/integration/number_test.ts b/prompt/test/integration/number_test.ts new file mode 100644 index 00000000..feec72f6 --- /dev/null +++ b/prompt/test/integration/number_test.ts @@ -0,0 +1,61 @@ +import { ansi } from "../../../ansi/ansi.ts"; +import { Number } from "../../number.ts"; +import { assertSnapshotCall } from "../../../testing/assert_snapshot_call.ts"; + +await assertSnapshotCall({ + name: "number prompt", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should enter a number": { + stdin: ansi + .text("19") + .cursorUp + .text("u") + .cursorDown + .cursorDown + .cursorDown + .cursorDown + .cursorUp + .cursorUp + .cursorUp + .text("\n") + .toArray(), + }, + }, + async fn() { + await Number.prompt({ + message: "How old are you?", + default: 7, + max: 20, + min: 18, + }); + }, +}); + +await assertSnapshotCall({ + name: "number prompt with float", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should enter a floating number": { + stdin: ansi + .text("19.") + .cursorUp + .cursorUp + .cursorUp + .cursorUp + .text("\n") + .toArray(), + }, + }, + async fn() { + await Number.prompt({ + message: "How old are you?", + default: 7, + max: 20, + min: 18, + float: true, + }); + }, +}); diff --git a/prompt/test/integration/prompt_test.ts b/prompt/test/integration/prompt_test.ts new file mode 100644 index 00000000..5344edc8 --- /dev/null +++ b/prompt/test/integration/prompt_test.ts @@ -0,0 +1,116 @@ +import { ansi } from "../../../ansi/ansi.ts"; +import { assertType, IsExact } from "../../../dev_deps.ts"; +import { Checkbox, CheckboxOptions } from "../../checkbox.ts"; +import { Confirm } from "../../confirm.ts"; +import { Input } from "../../input.ts"; +import { Number } from "../../number.ts"; +import { prompt, PromptMiddleware, PromptOptions } from "../../prompt.ts"; +import { Toggle } from "../../toggle.ts"; +import { assertSnapshotCall } from "../../../testing/assert_snapshot_call.ts"; + +await assertSnapshotCall({ + name: "prompt method", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should check an option": { + stdin: ansi + // input + .text("f") + .text("o") + .text("o") + .text("\n") + // number + .text("4") + .text("3") + .text("\n") + // confirm + .text("y") + .text("\n") + // toggle + .text("y") + .text("n") + .text("y") + .text("\n") + // checkbox + .cursorDown + .text(" ") + .cursorDown + .text(" ") + .text("\n") + .toArray(), + }, + }, + async fn() { + const checkboxOptions: PromptOptions< + "checkbox", + typeof Checkbox, + { input?: string } + > = { + name: "checkbox", + type: Checkbox, + message: "Select an option", + options: [ + { name: "Foo", value: "foo" }, + { name: "Bar", value: "bar" }, + { name: "Baz", value: "baz" }, + ], + before({ input }, next) { + console.log("[checkbox:before] input is:", input); + return next(); + }, + }; + + const result = await prompt([{ + name: "input", + type: Input, + message: "Enter some text", + default: "default value", + }, { + name: "number", + type: Number, + message: "Enter a number", + }, { + name: "confirm", + type: Confirm, + message: "Please confirm", + }, { + name: "toggle", + type: Toggle, + message: "Please toggle", + hint: "some hint", + default: false, + }, checkboxOptions], { + reader: Deno.stdin, + writer: Deno.stderr, + }); + + assertType< + IsExact + >(true); + + assertType< + IsExact< + typeof checkboxOptions, + { + name: "checkbox"; + type: typeof Checkbox; + before?: PromptMiddleware< + { checkbox?: Array; input?: string } + >; + after?: PromptMiddleware< + { checkbox?: Array; input?: string } + >; + } & CheckboxOptions + > + >(true); + + console.log(result); + }, +}); diff --git a/prompt/test/integration/secret_test.ts b/prompt/test/integration/secret_test.ts new file mode 100644 index 00000000..c7a2b31b --- /dev/null +++ b/prompt/test/integration/secret_test.ts @@ -0,0 +1,16 @@ +import { Secret } from "../../secret.ts"; +import { assertSnapshotCall } from "../../../testing/assert_snapshot_call.ts"; + +await assertSnapshotCall({ + name: "secret prompt", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should enter a secret": { stdin: ["123", "\n"] }, + }, + async fn() { + await Secret.prompt({ + message: "enter your secret", + }); + }, +}); diff --git a/prompt/test/integration/select_test.ts b/prompt/test/integration/select_test.ts new file mode 100644 index 00000000..bc79f6c5 --- /dev/null +++ b/prompt/test/integration/select_test.ts @@ -0,0 +1,28 @@ +import { ansi } from "../../../ansi/ansi.ts"; +import { Select } from "../../select.ts"; +import { assertSnapshotCall } from "../../../testing/assert_snapshot_call.ts"; + +await assertSnapshotCall({ + name: "select prompt", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should select an option": { + stdin: ansi + .cursorDown + .cursorDown + .text("\n") + .toArray(), + }, + }, + async fn() { + await Select.prompt({ + message: "Select an option", + options: [ + { name: "Foo", value: "foo" }, + { name: "Bar", value: "bar" }, + { name: "Baz", value: "baz" }, + ], + }); + }, +}); diff --git a/prompt/test/integration/test.ts b/prompt/test/integration/test.ts deleted file mode 100644 index 121e3940..00000000 --- a/prompt/test/integration/test.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { eraseDown } from "../../../ansi/ansi_escapes.ts"; -import { - assertSnapshot, - dirname, - expandGlob, - WalkEntry, -} from "../../../dev_deps.ts"; - -type TestModule = { - tests?: Record>; -}; - -const baseDir = `${dirname(import.meta.url).replace("file://", "")}`; -const encoder = new TextEncoder(); - -for await (const file: WalkEntry of expandGlob(`${baseDir}/fixtures/*.ts`)) { - if (file.isFile) { - const name = file.name.replace(/_/g, " ").replace(".ts", ""); - - Deno.test({ - name: `prompt - integration - ${name}`, - async fn(ctx) { - const testModule: TestModule = await import("file://" + file.path); - const tests = Object.entries(testModule.tests ?? {}); - - if (!tests.length) { - throw new Error(`Now tests defined for: ${file.path}`); - } - - for (const [name, inputs] of tests) { - await ctx.step({ - name, - async fn() { - const output: string = await runPrompt(file, inputs); - const os = Deno.build.os === "windows" ? ".windows" : ""; - await assertSnapshot(ctx, output, { - path: `__snapshots__/test.ts${os}.snap`, - }); - }, - }); - } - }, - }); - } -} - -function getCmdFlagsForFile(file: WalkEntry): string[] { - if (file.name === "input_no_location_flag.ts") { - return [ - "--allow-all", - ]; - } - return [ - "--allow-all", - "--location", - "https://cliffy.io", - ]; -} - -async function runPrompt( - file: WalkEntry, - inputs: Array, -): Promise { - const flags = getCmdFlagsForFile(file); - const cmd = new Deno.Command("deno", { - stdin: "piped", - stdout: "piped", - stderr: "piped", - args: [ - "run", - ...flags, - file.path, - ], - env: { - NO_COLOR: "true", - }, - }); - const child: Deno.ChildProcess = cmd.spawn(); - const writer = child.stdin.getWriter(); - - for (const input of inputs) { - await writer.write(encoder.encode(input)); - // Ensure all inputs are processed and rendered separately. - await new Promise((resolve) => setTimeout(resolve, 500)); - } - - const { success, stdout, stderr } = await child.output(); - writer.releaseLock(); - await child.stdin.close(); - - if (!success) { - throw new Error(`test failed: ${file}`); - } - - // Add a line break after each test input. - return "stdout:\n" + new TextDecoder().decode(stdout).replaceAll( - eraseDown(), - eraseDown() + "\n", - ) + "\nstderr:\n" + new TextDecoder().decode(stderr).replaceAll( - eraseDown(), - eraseDown() + "\n", - ); -} diff --git a/prompt/test/integration/toggle_test.ts b/prompt/test/integration/toggle_test.ts new file mode 100644 index 00000000..0645471c --- /dev/null +++ b/prompt/test/integration/toggle_test.ts @@ -0,0 +1,18 @@ +import { Toggle } from "../../toggle.ts"; +import { assertSnapshotCall } from "../../../testing/assert_snapshot_call.ts"; + +await assertSnapshotCall({ + name: "toggle prompt", + meta: import.meta, + osSuffix: ["windows"], + steps: { + "should toggle the prompt": { stdin: ["y", "n", "y", "\n"] }, + }, + async fn() { + await Toggle.prompt({ + message: "Please confirm", + hint: "some hint", + default: false, + }); + }, +}); diff --git a/testing/README.md b/testing/README.md new file mode 100644 index 00000000..b5bd472c --- /dev/null +++ b/testing/README.md @@ -0,0 +1,3 @@ +# Testing + +The documentation has been moved to https://cliffy.io/docs/testing. diff --git a/testing/__snapshots__/assert_snapshot_call_test.ts.snap b/testing/__snapshots__/assert_snapshot_call_test.ts.snap new file mode 100644 index 00000000..4d590937 --- /dev/null +++ b/testing/__snapshots__/assert_snapshot_call_test.ts.snap @@ -0,0 +1,79 @@ +export const snapshot = {}; + +snapshot[`should run snapshot tests 1`] = ` +"export const snapshot = {}; + +snapshot[\`should create a simple snapshot 1\`] = \` +\\"stdout: +foo + +stderr: +bar +\\" +\`; + +snapshot[\`should set deno args > step 1 1\`] = \` +'stdout: +[ \\"foo\\", \\"bar\\", \\"beep\\" ] + +stderr: +' +\`; + +snapshot[\`should set deno args > step 2 1\`] = \` +'stdout: +[ \\"foo\\", \\"bar\\", \\"boop\\" ] + +stderr: +' +\`; + +snapshot[\`should write to stdin > step 1 1\`] = \` +\\"stdout: +# stdin start +foo +# stdin end + +stderr: +\\" +\`; + +snapshot[\`should write to stdin > step 2 1\`] = \` +\\"stdout: +# stdin start +bar +# stdin end + +stderr: +\\" +\`; +" +`; + +snapshot[`should run snapshot tests 2`] = ` +'export const snapshot = {}; + +snapshot[\`should change the snapshot path 1\`] = \` +"stdout: +foo + +stderr: +bar +" +\`; +' +`; + +snapshot[`should run snapshot tests 3`] = ` +'export const snapshot = {}; + +snapshot[\`should change the snapshot dir 1\`] = \` +"stdout: +foo + +stderr: +bar +" +\`; +' +`; diff --git a/testing/assert_snapshot_call.ts b/testing/assert_snapshot_call.ts new file mode 100644 index 00000000..9723a9c5 --- /dev/null +++ b/testing/assert_snapshot_call.ts @@ -0,0 +1,220 @@ +import { eraseDown } from "../ansi/ansi_escapes.ts"; +import { AssertionError, assertSnapshot, basename, red } from "./deps.ts"; + +export interface AssertSnapshotCallStep { + /** Data written to the test process. */ + stdin?: Array | string; + /** Arguments passed to the test file. */ + args?: Array; + /** If enabled, test error will be ignored. */ + canFail?: true; +} + +export interface AssertSnapshotCallOptions extends AssertSnapshotCallStep { + /** Test name. */ + name: string; + /** Import meta. Required to determine the import url of the test file. */ + meta: ImportMeta; + /** Test function. */ + fn(): void | Promise; + /** + * Object of test steps. Key is the test name and the value is an array of + * input sequences/characters. + */ + steps?: Record; + /** + * Arguments passed to the `deno test` command when executing the snapshot + * tests. `--allow-env=ASSERT_SNAPSHOT_CALL` is passed by default. + */ + denoArgs?: Array; + /** + * Snapshot output directory. Snapshot files will be written to this directory. + * This can be relative to the test directory or an absolute path. + * + * If both `dir` and `path` are specified, the `dir` option will be ignored and + * the `path` option will be handled as normal. + */ + dir?: string; + /** + * Snapshot output path. The snapshot will be written to this file. This can be + * a path relative to the test directory or an absolute path. + * + * If both `dir` and `path` are specified, the `dir` option will be ignored and + * the `path` option will be handled as normal. + */ + path?: string; + /** + * Operating system snapshot suffix. This is useful when your test produces + * different output on different operating systems. + */ + osSuffix?: Array; + /** Enable/disable colors. Default is `false`. */ + colors?: boolean; + /** + * Timeout in milliseconds to wait until the input stream data is buffered + * before writing the next data to the stream. This ensures that each user + * input is rendered as separate line in the snapshot file. If your test gets + * flaky, try to increase the timeout. The default timeout is `600`. + */ + timeout?: number; + /** If truthy the current test step will be ignored. + * + * It is a quick way to skip over a step, but also can be used for + * conditional logic, like determining if an environment feature is present. + */ + ignore?: boolean; + /** If at least one test has `only` set to `true`, only run tests that have + * `only` set to `true` and fail the test suite. */ + only?: boolean; +} + +const encoder = new TextEncoder(); + +/** + * Run prompt snapshot tests. + * + * ```ts + * import { assertSnapshotCall } from "./assert_snapshot_call.ts"; + * import { Input } from "../prompt/input.ts"; + * + * await assertSnapshotCall({ + * name: "test name", + * meta: import.meta, + * osSuffix: ["windows"], + * steps: { + * "should enter some text": { stdin: ["foo bar", "\n"] }, + * }, + * async fn() { + * await Input.prompt({ + * message: "Whats your name?", + * default: "foo", + * }); + * }, + * }); + * ``` + * + * @param options Test options + */ +export async function assertSnapshotCall( + options: AssertSnapshotCallOptions, +): Promise { + if (options.meta.main) { + await runTest(options); + } else { + registerTest(options); + } +} + +function registerTest(options: AssertSnapshotCallOptions) { + const fileName = basename(options.meta.url); + + Deno.test({ + name: options.name, + ignore: options.ignore, + only: options.only, + async fn(ctx) { + const steps = Object.entries(options.steps ?? {}); + if (steps.length) { + for (const [name, inputs] of steps) { + await ctx.step({ + name, + fn: (ctx) => fn(ctx, inputs), + }); + } + } else { + await fn(ctx); + } + }, + }); + + async function fn(ctx: Deno.TestContext, step?: AssertSnapshotCallStep) { + const output: string = await runPrompt(options, step); + const suffix = options.osSuffix?.includes(Deno.build.os) + ? `.${Deno.build.os}` + : ""; + + await assertSnapshot(ctx, output, { + dir: options.dir, + path: options.path ?? + (options.dir ? undefined : `__snapshots__/${fileName}${suffix}.snap`), + }); + } +} + +async function runPrompt( + options: AssertSnapshotCallOptions, + step?: AssertSnapshotCallStep, +): Promise { + let output: Deno.CommandOutput | undefined; + let stdout: string | undefined; + let stderr: string | undefined; + + try { + const cmd = new Deno.Command("deno", { + stdin: "piped", + stdout: "piped", + stderr: "piped", + args: [ + "run", + ...options.denoArgs ?? ["--allow-env=ASSERT_SNAPSHOT_CALL"], + options.meta.url, + ...options.args ?? [], + ...step?.args ?? [], + ], + env: { + ASSERT_SNAPSHOT_CALL: options.name, + ...options.colors ? {} : { NO_COLOR: "true" }, + }, + }); + const child: Deno.ChildProcess = cmd.spawn(); + const writer = child.stdin.getWriter(); + + const stdin = [ + ...options?.stdin ?? [], + ...step?.stdin ?? [], + ]; + + if (stdin.length) { + for (const data of stdin) { + await writer.write(encoder.encode(data)); + // Ensure all inputs are processed and rendered separately. + await new Promise((resolve) => + setTimeout(resolve, options.timeout ?? 600) + ); + } + } + + output = await child.output(); + stdout = new TextDecoder().decode(output.stdout); + stderr = new TextDecoder().decode(output.stderr); + + writer.releaseLock(); + await child.stdin.close(); + } catch (error: unknown) { + const assertionError = new AssertionError( + `Prompt snapshot test failed: ${options.meta.url}.\n${red(stderr ?? "")}`, + ); + assertionError.cause = error; + throw assertionError; + } + + if (!output.success && !options.canFail && !step?.canFail) { + throw new AssertionError( + `Prompt snapshot test failed: ${options.meta.url}.` + + `Test command failed with a none zero exit code: ${output.code}.\n${ + red(stderr ?? "") + }`, + ); + } + + // Add a line break after each test input. + return "stdout:\n" + stdout.replaceAll(eraseDown(), eraseDown() + "\n") + + "\nstderr:\n" + stderr.replaceAll(eraseDown(), eraseDown() + "\n"); +} + +async function runTest(options: AssertSnapshotCallOptions) { + const testName = Deno.env.get("ASSERT_SNAPSHOT_CALL"); + if (testName === options.name) { + await options.fn(); + } +} diff --git a/testing/assert_snapshot_call_test.ts b/testing/assert_snapshot_call_test.ts new file mode 100644 index 00000000..c09d3df2 --- /dev/null +++ b/testing/assert_snapshot_call_test.ts @@ -0,0 +1,47 @@ +import { assert, assertSnapshot } from "../dev_deps.ts"; +import { dirname, fromFileUrl } from "./deps.ts"; + +Deno.test({ + name: "should run snapshot tests", + async fn(ctx) { + const testDir = dirname(fromFileUrl(import.meta.url)); + const snapshotDir = testDir + "/__snapshots__"; + const snapshotTestDir = testDir + "/__snapshots_test__"; + + const snapshotPath = + `${snapshotDir}/assert_snapshot_call_test_fixture.ts.snap`; + const snapshot2Path = + `${snapshotDir}/assert_snapshot_call_test_fixture_2.ts.snap`; + const snapshot3Path = + `${snapshotTestDir}/assert_snapshot_call_test_fixture.ts.snap`; + + const args = [ + "test", + "--allow-run=deno", + `--allow-read=${testDir}`, + `--allow-write=${testDir}`, + "testing/assert_snapshot_call_test_fixture.ts", + "--", + "--update", + ]; + + const cmd = new Deno.Command("deno", { args }); + + const { success, stdout, stderr } = await cmd.output(); + + const decoder = new TextDecoder(); + assert(success, decoder.decode(stderr) + decoder.decode(stdout)); + + const snapshotContent = await Deno.readTextFile(snapshotPath); + const snapshot2Content = await Deno.readTextFile(snapshot2Path); + const snapshot3Content = await Deno.readTextFile(snapshot3Path); + + await assertSnapshot(ctx, snapshotContent); + await assertSnapshot(ctx, snapshot2Content); + await assertSnapshot(ctx, snapshot3Content); + + await Deno.remove(snapshotPath); + await Deno.remove(snapshot2Path); + await Deno.remove(snapshotTestDir, { recursive: true }); + }, +}); diff --git a/testing/assert_snapshot_call_test_fixture.ts b/testing/assert_snapshot_call_test_fixture.ts new file mode 100644 index 00000000..6d17e0be --- /dev/null +++ b/testing/assert_snapshot_call_test_fixture.ts @@ -0,0 +1,66 @@ +import { assertSnapshotCall } from "./assert_snapshot_call.ts"; + +await assertSnapshotCall({ + name: "should create a simple snapshot", + meta: import.meta, + fn() { + console.log("foo"); + console.error("bar"); + }, +}); + +await assertSnapshotCall({ + name: "should change the snapshot path", + meta: import.meta, + path: "__snapshots__/assert_snapshot_call_test_fixture_2.ts.snap", + fn() { + console.log("foo"); + console.error("bar"); + }, +}); + +await assertSnapshotCall({ + name: "should change the snapshot dir", + meta: import.meta, + dir: "__snapshots_test__", + fn() { + console.log("foo"); + console.error("bar"); + }, +}); + +await assertSnapshotCall({ + name: "should set deno args", + meta: import.meta, + args: ["foo", "bar"], + steps: { + "step 1": { args: ["beep"] }, + "step 2": { args: ["boop"] }, + }, + fn() { + console.log(Deno.args); + }, +}); + +await assertSnapshotCall({ + name: "should write to stdin", + meta: import.meta, + args: ["foo", "bar"], + steps: { + "step 1": { stdin: ["foo"] }, + "step 2": { stdin: ["bar"] }, + }, + async fn() { + console.log("# stdin start"); + const decoder = new TextDecoder(); + let text = ""; + for await (const chunk of Deno.stdin.readable) { + text += decoder.decode(chunk); + if (text.length === 3) { + break; + } + } + console.log(text); + console.log("# stdin end"); + }, +}); diff --git a/testing/deps.ts b/testing/deps.ts new file mode 100644 index 00000000..d3c50d27 --- /dev/null +++ b/testing/deps.ts @@ -0,0 +1,11 @@ +export { + assertEquals, + AssertionError, +} from "https://deno.land/std@0.170.0/testing/asserts.ts"; +export { assertSnapshot } from "https://deno.land/std@0.170.0/testing/snapshot.ts"; +export { red } from "https://deno.land/std@0.170.0/fmt/colors.ts"; +export { + basename, + dirname, + fromFileUrl, +} from "https://deno.land/std@0.170.0/path/mod.ts"; diff --git a/testing/mod.ts b/testing/mod.ts new file mode 100644 index 00000000..06c95d85 --- /dev/null +++ b/testing/mod.ts @@ -0,0 +1 @@ +export * from "./assert_snapshot_call.ts";