Skip to content

Commit

Permalink
tests: add help + types integration tests (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucacasonato authored Mar 23, 2021
1 parent 48cc663 commit 3b3ed43
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 12 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ jobs:
- name: Typecheck
run: deno cache deployctl.ts

# - name: Run tests
# run: deno test -A
- name: Run tests
run: deno test -A
14 changes: 13 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
{
"deno.enable": true,
"deno.lint": true
"deno.lint": true,
"[javascript]": {
"editor.defaultFormatter": "denoland.vscode-deno"
},
"[javascriptreact]": {
"editor.defaultFormatter": "denoland.vscode-deno"
},
"[typescript]": {
"editor.defaultFormatter": "denoland.vscode-deno"
},
"[typescriptreact]": {
"editor.defaultFormatter": "denoland.vscode-deno"
}
}
2 changes: 1 addition & 1 deletion deployctl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ switch (subcommand) {
await typesSubcommand(args);
break;
default:
console.log(help);
console.error(help);
Deno.exit(1);
}
3 changes: 3 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ fmt:

lint:
deno lint

test:
deno test -A
2 changes: 1 addition & 1 deletion src/error.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { bold, red } from "../deps.ts";

export function error(message: string): never {
console.log(red(`${bold("error")}: ${message}`));
console.error(red(`${bold("error")}: ${message}`));
Deno.exit(1);
}
8 changes: 4 additions & 4 deletions src/subcommands/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ export default async function (rawArgs: Record<string, any>): Promise<void> {
? rawArgs._[0]
: null;
if (args.help) {
console.log(help);
console.error(help);
Deno.exit(1);
}
if (entrypoint === null) {
console.log(help);
console.error(help);
error("No entrypoint specifier given.");
}
if (rawArgs._.length > 1) {
console.log(help);
console.error(help);
error("Too many positional arguments given.");
}

Expand Down Expand Up @@ -110,7 +110,7 @@ async function watch(opts: RunOpts) {
for await (const event of watcher) {
if (typeof debouncer == "number") clearTimeout(debouncer);
debouncer = setTimeout(async () => {
console.log(yellow(`${event.paths[0]} changed. Restarting...`));
console.warn(yellow(`${event.paths[0]} changed. Restarting...`));
if (proc) {
proc.close();
}
Expand Down
4 changes: 2 additions & 2 deletions src/subcommands/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ export default async function (rawArgs: Record<string, any>): Promise<void> {
help: !!rawArgs.help,
};
if (args.help) {
console.log(help);
console.error(help);
Deno.exit(1);
}
if (rawArgs._.length > 0) {
console.log(help);
console.error(help);
error("Too many positional arguments given.");
}

Expand Down
2 changes: 1 addition & 1 deletion src/utils/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export async function analyzeDeps(specifier: URL): Promise<string[]> {
],
stdout: "piped",
});
const raw = await proc.output();
const status = await proc.status();
if (!status) throw new Error("Failed to analyze dependencies.");
const raw = await proc.output();
const modules: Array<{ specifier: string }> =
JSON.parse(new TextDecoder().decode(raw)).modules;
return modules.map((module) => module.specifier)
Expand Down
1 change: 1 addition & 0 deletions tests/deps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "https://deno.land/[email protected]/testing/asserts.ts";
36 changes: 36 additions & 0 deletions tests/help_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { assertEquals, assertStringIncludes } from "./deps.ts";
import { output, test } from "./utils.ts";

test({ args: [] }, async (proc) => {
const [stdout, stderr, { code }] = await output(proc);
assertStringIncludes(stderr, "SUBCOMMANDS:");
assertStringIncludes(stderr, "run ");
assertStringIncludes(stderr, "types ");
assertEquals(code, 1);
assertEquals(stdout, "");
});

test({ args: ["-h"] }, async (proc) => {
const [stdout, stderr, { code }] = await output(proc);
assertStringIncludes(stderr, "SUBCOMMANDS:");
assertStringIncludes(stderr, "run ");
assertStringIncludes(stderr, "types ");
assertEquals(code, 1);
assertEquals(stdout, "");
});

test({ args: ["run", "-h"] }, async (proc) => {
const [stdout, stderr, { code }] = await output(proc);
assertStringIncludes(stderr, "USAGE:");
assertStringIncludes(stderr, "deployctl run");
assertEquals(code, 1);
assertEquals(stdout, "");
});

test({ args: ["types", "-h"] }, async (proc) => {
const [stdout, stderr, { code }] = await output(proc);
assertStringIncludes(stderr, "USAGE:");
assertStringIncludes(stderr, "deployctl types");
assertEquals(code, 1);
assertEquals(stdout, "");
});
9 changes: 9 additions & 0 deletions tests/types_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { assertEquals, assertStringIncludes } from "./deps.ts";
import { output, test } from "./utils.ts";

test({ args: ["types"] }, async (proc) => {
const [stdout, stderr, { code }] = await output(proc);
assertEquals(stderr, "");
assertEquals(code, 0);
assertStringIncludes(stdout, `/// <reference no-default-lib="true" />`);
});
73 changes: 73 additions & 0 deletions tests/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
export interface Permissions {
net: boolean;
read: boolean;
write: boolean;
env: boolean;
run: boolean;
}

export function deployctl(
args: string[],
permissions: Permissions = {
net: true,
read: true,
write: true,
env: true,
run: true,
},
): Deno.Process {
const cmd = [
Deno.execPath(),
"run",
"--no-check",
];

if (permissions?.net) cmd.push("--allow-net");
if (permissions?.read) cmd.push("--allow-read");
if (permissions?.write) cmd.push("--allow-write");
if (permissions?.env) cmd.push("--allow-env");
if (permissions?.run) cmd.push("--allow-run");

cmd.push(new URL("../deployctl.ts", import.meta.url).toString());

return Deno.run({
cmd: [...cmd, ...args],
stdin: "null",
stdout: "piped",
stderr: "piped",
});
}

export interface TestOptions {
args: string[];
name?: string;
permissions?: Permissions;
}

export function test(
opts: TestOptions,
fn: (proc: Deno.Process) => void | Promise<void>,
) {
const name = opts.name ?? ["deployctl", ...opts.args].join(" ");
Deno.test(name, async () => {
const proc = deployctl(opts.args, opts.permissions);
try {
await fn(proc);
} finally {
proc.close();
}
});
}

export async function output(
proc: Deno.Process,
): Promise<[string, string, Deno.ProcessStatus]> {
const stdout = await proc.output();
const stderr = await proc.stderrOutput();
const status = await proc.status();
return [
new TextDecoder().decode(stdout),
new TextDecoder().decode(stderr),
status,
];
}

0 comments on commit 3b3ed43

Please sign in to comment.