Files
fresh/tests/cli_test.ts
Yuki Shindo e2c54d00b6 test: remove tmp dir (#280)
Co-authored-by: Luca Casonato <hello@lcas.dev>
Co-authored-by: hashrock <hashrock@users.noreply.github.com>
Co-authored-by: kt3k <kt3k@users.noreply.github.com>
2022-10-19 19:08:27 +09:00

394 lines
10 KiB
TypeScript

import { Status } from "../src/server/deps.ts";
import {
assert,
assertEquals,
assertStringIncludes,
delay,
puppeteer,
TextLineStream,
} from "./deps.ts";
type FileTree = {
type: "file";
name: string;
} | {
type: "directory";
name: string;
contents: FileTree[];
};
const assertFileExistence = async (tree: FileTree[], dirname?: string) => {
for (const t of tree) {
const stat = await Deno.stat(
dirname ? [dirname, t.name].join("/") : t.name,
);
assertEquals(t.type === "file", stat.isFile);
if (t.type === "directory") {
assert(stat.isDirectory);
await assertFileExistence(
t.contents,
dirname ? [dirname, t.name].join("/") : t.name,
);
}
}
};
Deno.test({
name: "fresh-init",
async fn(t) {
// Preparation
const tmpDirName = await Deno.makeTempDir();
await t.step("execute init command", async () => {
const cliProcess = Deno.run({
cmd: [
"deno",
"run",
"-A",
"init.ts",
tmpDirName,
],
stdin: "null",
stdout: "null",
});
const { code } = await cliProcess.status();
cliProcess.close();
assertEquals(code, 0);
});
// NOTE: generated by `tree -J <dir>`
const targetFileTree: FileTree[] = [
{
"type": "directory",
"name": tmpDirName,
"contents": [
{ "type": "file", "name": "README.md" },
{ "type": "file", "name": "import_map.json" },
{ "type": "file", "name": "fresh.gen.ts" },
{
"type": "directory",
"name": "components",
"contents": [
{ "type": "file", "name": "Button.tsx" },
],
},
{
"type": "directory",
"name": "islands",
"contents": [
{ "type": "file", "name": "Counter.tsx" },
],
},
{ "type": "file", "name": "main.ts" },
{
"type": "directory",
"name": "routes",
"contents": [
{ "type": "file", "name": "[name].tsx" },
{
"type": "directory",
"name": "api",
"contents": [
{ "type": "file", "name": "joke.ts" },
],
},
{ "type": "file", "name": "index.tsx" },
],
},
{
"type": "directory",
"name": "static",
"contents": [
{ "type": "file", "name": "logo.svg" },
],
},
],
},
];
await t.step("check generated files", async () => {
await assertFileExistence(targetFileTree);
});
await t.step("start up the server and access the root page", async () => {
const serverProcess = Deno.run({
cmd: ["deno", "run", "-A", "--check", "main.ts"],
stdin: "null",
stdout: "piped",
stderr: "inherit",
cwd: tmpDirName,
});
const lines = serverProcess.stdout.readable
.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextLineStream());
let started = false;
for await (const line of lines) {
console.log(line);
if (line.includes("Listening on http://")) {
started = true;
break;
}
}
if (!started) {
throw new Error("Server didn't start up");
}
await delay(100);
// Access the root page
const res = await fetch("http://localhost:8000");
await res.body?.cancel();
assertEquals(res.status, Status.OK);
// verify the island is revived.
const browser = await puppeteer.launch({
args: ["--no-sandbox"],
});
const page = await browser.newPage();
await page.goto("http://localhost:8000", { waitUntil: "networkidle2" });
const counter = await page.$("body > div > div > p");
let counterValue = await counter?.evaluate((el) => el.textContent);
assert(counterValue === "3");
const buttonPlus = await page.$("body > div > div > button:nth-child(3)");
await buttonPlus?.click();
await delay(100);
counterValue = await counter?.evaluate((el) => el.textContent);
assert(counterValue === "4");
await page.close();
await browser.close();
await lines.cancel();
serverProcess.kill("SIGTERM");
await serverProcess.status();
serverProcess.close();
});
await Deno.remove(tmpDirName, { recursive: true });
},
sanitizeOps: false,
sanitizeResources: false,
});
Deno.test({
name: "fresh-init --twind --vscode",
async fn(t) {
// Preparation
const tmpDirName = await Deno.makeTempDir();
await t.step("execute init command", async () => {
const cliProcess = Deno.run({
cmd: [
"deno",
"run",
"-A",
"init.ts",
tmpDirName,
"--twind",
"--vscode",
],
stdin: "null",
stdout: "null",
});
const { code } = await cliProcess.status();
cliProcess.close();
assertEquals(code, 0);
});
// NOTE: generated by `tree -J <dir>`
const targetFileTree: FileTree[] = [
{
"type": "directory",
"name": tmpDirName,
"contents": [
{ "type": "file", "name": "README.md" },
{ "type": "file", "name": "import_map.json" },
{ "type": "file", "name": "fresh.gen.ts" },
{ "type": "file", "name": "twind.config.ts" },
{
"type": "directory",
"name": "components",
"contents": [
{ "type": "file", "name": "Button.tsx" },
],
},
{
"type": "directory",
"name": "islands",
"contents": [
{ "type": "file", "name": "Counter.tsx" },
],
},
{ "type": "file", "name": "main.ts" },
{
"type": "directory",
"name": "routes",
"contents": [
{ "type": "file", "name": "[name].tsx" },
{
"type": "directory",
"name": "api",
"contents": [
{ "type": "file", "name": "joke.ts" },
],
},
{ "type": "file", "name": "index.tsx" },
],
},
{
"type": "directory",
"name": "static",
"contents": [
{ "type": "file", "name": "logo.svg" },
],
},
{
"type": "directory",
"name": ".vscode",
"contents": [
{ "type": "file", "name": "settings.json" },
{ "type": "file", "name": "extensions.json" },
],
},
],
},
];
await t.step("check generated files", async () => {
await assertFileExistence(targetFileTree);
});
await t.step("start up the server and access the root page", async () => {
const serverProcess = Deno.run({
cmd: ["deno", "run", "-A", "--check", "main.ts"],
stdin: "null",
stdout: "piped",
stderr: "inherit",
cwd: tmpDirName,
});
const lines = serverProcess.stdout.readable
.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextLineStream());
let started = false;
for await (const line of lines) {
console.log(line);
if (line.includes("Listening on http://")) {
started = true;
break;
}
}
if (!started) {
throw new Error("Server didn't start up");
}
await delay(100);
// Access the root page
const res = await fetch("http://localhost:8000");
await res.body?.cancel();
assertEquals(res.status, Status.OK);
// verify the island is revived.
const browser = await puppeteer.launch({ args: ["--no-sandbox"] });
const page = await browser.newPage();
await page.goto("http://localhost:8000", { waitUntil: "networkidle2" });
const counter = await page.$("body > div > div > p");
let counterValue = await counter?.evaluate((el) => el.textContent);
assert(counterValue === "3");
const fontWeight = await counter?.evaluate((el) =>
getComputedStyle(el).fontWeight
);
assertEquals(fontWeight, "700");
const buttonPlus = await page.$("body > div > div > button:nth-child(3)");
await buttonPlus?.click();
await delay(100);
counterValue = await counter?.evaluate((el) => el.textContent);
assert(counterValue === "4");
await page.close();
await browser.close();
await lines.cancel();
serverProcess.kill("SIGTERM");
await serverProcess.status();
serverProcess.close();
});
await Deno.remove(tmpDirName, { recursive: true });
},
sanitizeOps: false,
sanitizeResources: false,
});
Deno.test("fresh-init error(help)", async function (t) {
const includeText = "fresh-init";
await t.step(
"execute invalid init command (deno run -A init.ts)",
async () => {
const cliProcess = Deno.run({
cmd: ["deno", "run", "-A", "init.ts"],
stdin: "null",
stderr: "piped",
});
const { code } = await cliProcess.status();
cliProcess.close();
assertEquals(code, 1);
const rawError = await cliProcess.stderrOutput();
const errorString = new TextDecoder().decode(rawError);
assertStringIncludes(errorString, includeText);
},
);
await t.step(
"execute invalid init command (deno run -A init.ts -f)",
async () => {
const cliProcess = Deno.run({
cmd: ["deno", "run", "-A", "init.ts", "-f"],
stdin: "null",
stderr: "piped",
});
const { code } = await cliProcess.status();
cliProcess.close();
assertEquals(code, 1);
const rawError = await cliProcess.stderrOutput();
const errorString = new TextDecoder().decode(rawError);
assertStringIncludes(errorString, includeText);
},
);
await t.step(
"execute invalid init command (deno run -A init.ts --foo)",
async () => {
const cliProcess = Deno.run({
cmd: ["deno", "run", "-A", "init.ts", "--foo"],
stdin: "null",
stderr: "piped",
});
const { code } = await cliProcess.status();
cliProcess.close();
assertEquals(code, 1);
const rawError = await cliProcess.stderrOutput();
const errorString = new TextDecoder().decode(rawError);
assertStringIncludes(errorString, includeText);
},
);
});