Skip to content

Commit

Permalink
test(prompt): add integration tests (#172)
Browse files Browse the repository at this point in the history
  • Loading branch information
c4spar committed Apr 18, 2021
1 parent 83c644a commit 0031490
Show file tree
Hide file tree
Showing 43 changed files with 322 additions and 11 deletions.
1 change: 1 addition & 0 deletions dev_deps.ts
Expand Up @@ -12,5 +12,6 @@ export {
} from "https://deno.land/std@0.93.0/fmt/colors.ts";
export { dirname } from "https://deno.land/std@0.93.0/path/mod.ts";
export { expandGlob } from "https://deno.land/std@0.93.0/fs/mod.ts";
export type { WalkEntry } from "https://deno.land/std@0.93.0/fs/mod.ts";

export { gt, lt } from "https://deno.land/x/semver@v1.3.0/mod.ts";
1 change: 1 addition & 0 deletions prompt/test/integration/fixtures/checkbox.in
@@ -0,0 +1 @@
\x1bd\x1bd\x1b
11 changes: 11 additions & 0 deletions prompt/test/integration/fixtures/checkbox.out
@@ -0,0 +1,11 @@
? Select an option
❯ ✘ Foo
✘ Bar
✘ Baz\x1b[3A\x1b[20G\x1b[?25l\x1b[G\x1b[0J ? Select an option
✔ Foo
❯ ✘ Bar
✘ Baz\x1b[3A\x1b[20G\x1b[?25l\x1b[G\x1b[0J ? Select an option
✔ Foo
✘ Bar
❯ ✔ Baz\x1b[3A\x1b[20G\x1b[?25l\x1b[G\x1b[0J ? Select an option › Foo, Baz
\x1b[?25h\x1b[?25h
10 changes: 10 additions & 0 deletions prompt/test/integration/fixtures/checkbox.ts
@@ -0,0 +1,10 @@
import { Checkbox } from "../../../checkbox.ts";

await Checkbox.prompt({
message: "Select an option",
options: [
{ name: "Foo", value: "foo" },
{ name: "Bar", value: "bar" },
{ name: "Baz", value: "baz" },
],
});
11 changes: 11 additions & 0 deletions prompt/test/integration/fixtures/checkbox.windows.out
@@ -0,0 +1,11 @@
? Select an option
❯ × Foo
× Bar
× Baz\x1b[3A\x1b[20G\x1b[?25l\x1b[G\x1b[0J ? Select an option
√ Foo
❯ × Bar
× Baz\x1b[3A\x1b[20G\x1b[?25l\x1b[G\x1b[0J ? Select an option
√ Foo
× Bar
❯ √ Baz\x1b[3A\x1b[20G\x1b[?25l\x1b[G\x1b[0J ? Select an option » Foo, Baz
\x1b[?25h\x1b[?25h
1 change: 1 addition & 0 deletions prompt/test/integration/fixtures/confirm.in
@@ -0,0 +1 @@
y
3 changes: 3 additions & 0 deletions prompt/test/integration/fixtures/confirm.out
@@ -0,0 +1,3 @@
? Please confirm (y/N) ›
❯ some hint\x1b[1A\x1b[27G\x1b[G\x1b[0J ? Please confirm (y/N) › Yes
\x1b[?25h\x1b[?25h
7 changes: 7 additions & 0 deletions prompt/test/integration/fixtures/confirm.ts
@@ -0,0 +1,7 @@
import { Confirm } from "../../../confirm.ts";

await Confirm.prompt({
message: "Please confirm",
hint: "some hint",
default: false,
});
3 changes: 3 additions & 0 deletions prompt/test/integration/fixtures/confirm.windows.out
@@ -0,0 +1,3 @@
? Please confirm (y/N) »
❯ some hint\x1b[1A\x1b[27G\x1b[G\x1b[0J ? Please confirm (y/N) » Yes
\x1b[?25h\x1b[?25h
1 change: 1 addition & 0 deletions prompt/test/integration/fixtures/input.in
@@ -0,0 +1 @@
bar
2 changes: 2 additions & 0 deletions prompt/test/integration/fixtures/input.out
@@ -0,0 +1,2 @@
? Whats your name? (foo) › \x1b[29G\x1b[G\x1b[0J ? Whats your name? (foo) › bar
\x1b[?25h\x1b[?25h
6 changes: 6 additions & 0 deletions prompt/test/integration/fixtures/input.ts
@@ -0,0 +1,6 @@
import { Input } from "../../../input.ts";

await Input.prompt({
message: "Whats your name?",
default: "foo",
});
2 changes: 2 additions & 0 deletions prompt/test/integration/fixtures/input.windows.out
@@ -0,0 +1,2 @@
? Whats your name? (foo) » \x1b[29G\x1b[G\x1b[0J ? Whats your name? (foo) » bar
\x1b[?25h\x1b[?25h
1 change: 1 addition & 0 deletions prompt/test/integration/fixtures/input_suggestions.in
@@ -0,0 +1 @@
foo
5 changes: 5 additions & 0 deletions prompt/test/integration/fixtures/input_suggestions.out
@@ -0,0 +1,5 @@
? Whats your name? (foo) ›
foo
bar
baz\x1b[3A\x1b[29G\x1b[G\x1b[0J ? Whats your name? (foo) › foo
\x1b[?25h\x1b[?25h
8 changes: 8 additions & 0 deletions prompt/test/integration/fixtures/input_suggestions.ts
@@ -0,0 +1,8 @@
import { Input } from "../../../input.ts";

await Input.prompt({
message: "Whats your name?",
default: "foo",
suggestions: ["foo", "bar", "baz"],
list: true,
});
@@ -0,0 +1,5 @@
? Whats your name? (foo) »
foo
bar
baz\x1b[3A\x1b[29G\x1b[G\x1b[0J ? Whats your name? (foo) » foo
\x1b[?25h\x1b[?25h
1 change: 1 addition & 0 deletions prompt/test/integration/fixtures/list.in
@@ -0,0 +1 @@
bar, foo
4 changes: 4 additions & 0 deletions prompt/test/integration/fixtures/list.out
@@ -0,0 +1,4 @@
? Enter some keywords (foo, far) ›
❯ some hint...\x1b[1A\x1b[37G\x1b[G\x1b[0J ? Enter some keywords (foo, far) › bar, foo
❯ some hint...\x1b[1A\x1b[45G\x1b[G\x1b[0J ? Enter some keywords (foo, far) › bar, foo
\x1b[?25h\x1b[?25h
7 changes: 7 additions & 0 deletions prompt/test/integration/fixtures/list.ts
@@ -0,0 +1,7 @@
import { List } from "../../../list.ts";

await List.prompt({
message: "Enter some keywords",
default: ["foo", "far"],
hint: "some hint...",
});
4 changes: 4 additions & 0 deletions prompt/test/integration/fixtures/list.windows.out
@@ -0,0 +1,4 @@
? Enter some keywords (foo, far) »
❯ some hint...\x1b[1A\x1b[37G\x1b[G\x1b[0J ? Enter some keywords (foo, far) » bar, foo
❯ some hint...\x1b[1A\x1b[45G\x1b[G\x1b[0J ? Enter some keywords (foo, far) » bar, foo
\x1b[?25h\x1b[?25h
3 changes: 3 additions & 0 deletions prompt/test/integration/fixtures/number.in
@@ -0,0 +1,3 @@
19uu
dddd
uuu
3 changes: 3 additions & 0 deletions prompt/test/integration/fixtures/number.out
@@ -0,0 +1,3 @@
? How old are you? (7) › \x1b[27G\x1b[G\x1b[0J ? How old are you? (7) › 18
✘ Value must be lower or equal than 20\x1b[1A\x1b[28G\x1b[G\x1b[0J ? How old are you? (7) › 20
\x1b[?25h\x1b[?25h
8 changes: 8 additions & 0 deletions prompt/test/integration/fixtures/number.ts
@@ -0,0 +1,8 @@
import { Number } from "../../../number.ts";

await Number.prompt({
message: "How old are you?",
default: 7,
max: 20,
min: 18,
});
3 changes: 3 additions & 0 deletions prompt/test/integration/fixtures/number.windows.out
@@ -0,0 +1,3 @@
? How old are you? (7) » \x1b[27G\x1b[G\x1b[0J ? How old are you? (7) » 19
× Value must be lower or equal than 20\x1b[1A\x1b[28G\x1b[G\x1b[0J ? How old are you? (7) » 20
\x1b[?25h\x1b[?25h
1 change: 1 addition & 0 deletions prompt/test/integration/fixtures/number_decimal.in
@@ -0,0 +1 @@
19.uuuu
2 changes: 2 additions & 0 deletions prompt/test/integration/fixtures/number_decimal.out
@@ -0,0 +1,2 @@
? How old are you? (7) › \x1b[27G\x1b[G\x1b[0J ? How old are you? (7) › 19.4
\x1b[?25h\x1b[?25h
9 changes: 9 additions & 0 deletions prompt/test/integration/fixtures/number_decimal.ts
@@ -0,0 +1,9 @@
import { Number } from "../../../number.ts";

await Number.prompt({
message: "How old are you?",
default: 7,
max: 20,
min: 18,
float: true,
});
2 changes: 2 additions & 0 deletions prompt/test/integration/fixtures/number_decimal.windows.out
@@ -0,0 +1,2 @@
? How old are you? (7) » \x1b[27G\x1b[G\x1b[0J ? How old are you? (7) » 19.4
\x1b[?25h\x1b[?25h
1 change: 1 addition & 0 deletions prompt/test/integration/fixtures/secret.in
@@ -0,0 +1 @@
123
2 changes: 2 additions & 0 deletions prompt/test/integration/fixtures/secret.out
@@ -0,0 +1,2 @@
? enter your secret › \x1b[24G\x1b[G\x1b[0J ? enter your secret › ***
\x1b[?25h\x1b[?25h
5 changes: 5 additions & 0 deletions prompt/test/integration/fixtures/secret.ts
@@ -0,0 +1,5 @@
import { Secret } from "../../../secret.ts";

await Secret.prompt({
message: "enter your secret",
});
2 changes: 2 additions & 0 deletions prompt/test/integration/fixtures/secret.windows.out
@@ -0,0 +1,2 @@
? enter your secret » \x1b[24G\x1b[G\x1b[0J ? enter your secret » ***
\x1b[?25h\x1b[?25h
1 change: 1 addition & 0 deletions prompt/test/integration/fixtures/select.in
@@ -0,0 +1 @@
\x1bd\x1bd
8 changes: 8 additions & 0 deletions prompt/test/integration/fixtures/select.out
@@ -0,0 +1,8 @@
? Select an option
❯ Foo
Bar
Baz\x1b[3A\x1b[20G\x1b[?25l\x1b[G\x1b[0J ? Select an option
Foo
❯ Bar
Baz\x1b[3A\x1b[20G\x1b[?25l\x1b[G\x1b[0J ? Select an option › Baz
\x1b[?25h\x1b[?25h
10 changes: 10 additions & 0 deletions prompt/test/integration/fixtures/select.ts
@@ -0,0 +1,10 @@
import { Select } from "../../../select.ts";

await Select.prompt({
message: "Select an option",
options: [
{ name: "Foo", value: "foo" },
{ name: "Bar", value: "bar" },
{ name: "Baz", value: "baz" },
],
});
8 changes: 8 additions & 0 deletions prompt/test/integration/fixtures/select.windows.out
@@ -0,0 +1,8 @@
? Select an option
❯ Foo
Bar
Baz\x1b[3A\x1b[20G\x1b[?25l\x1b[G\x1b[0J ? Select an option
Foo
❯ Bar
Baz\x1b[3A\x1b[20G\x1b[?25l\x1b[G\x1b[0J ? Select an option » Baz
\x1b[?25h\x1b[?25h
3 changes: 3 additions & 0 deletions prompt/test/integration/fixtures/toggle.in
@@ -0,0 +1,3 @@
yny
- suggestions
- hidden
3 changes: 3 additions & 0 deletions prompt/test/integration/fixtures/toggle.out
@@ -0,0 +1,3 @@
? 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
7 changes: 7 additions & 0 deletions prompt/test/integration/fixtures/toggle.ts
@@ -0,0 +1,7 @@
import { Toggle } from "../../../toggle.ts";

await Toggle.prompt({
message: "Please confirm",
hint: "some hint",
default: false,
});
3 changes: 3 additions & 0 deletions prompt/test/integration/fixtures/toggle.windows.out
@@ -0,0 +1,3 @@
? 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
69 changes: 69 additions & 0 deletions prompt/test/integration/test.ts
@@ -0,0 +1,69 @@
import {
assert,
assertEquals,
dirname,
expandGlob,
WalkEntry,
} from "../../../dev_deps.ts";

const baseDir = `${dirname(import.meta.url).replace("file://", "")}`;

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() {
const output: string = await runPrompt(file);
const expectedOutput: string = await getExpectedOutput(file.path);
assertEquals(
output,
expectedOutput
.replace(/\\x1b/g, "\x1b")
.replace(/\r\n/g, "\n"),
);
},
});
}
}

async function getExpectedOutput(path: string) {
const osOutputPath = path.replace(/\.ts$/, `.${Deno.build.os}.out`);
try {
return await Deno.readTextFile(osOutputPath);
} catch (_) {
const outputPath = path.replace(/\.ts$/, ".out");
return await Deno.readTextFile(outputPath);
}
}

async function runPrompt(file: WalkEntry): Promise<string> {
const inputPath: string = file.path.replace(/\.ts$/, ".in");
const inputFile = await Deno.open(inputPath);
const process = Deno.run({
stdin: "piped",
stdout: "piped",
cmd: [
"deno",
"run",
"--unstable",
"--allow-all",
file.path,
],
env: {
NO_COLOR: "true",
},
});

const [output, bytesCopied] = await Promise.all([
process.output(),
Deno.copy(inputFile, process.stdin),
]);
inputFile.close();
process.stdin.close();
process.close();

assert(bytesCopied > 0, "No bytes copied");

return new TextDecoder().decode(output);
}

0 comments on commit 0031490

Please sign in to comment.