mirror of
https://github.com/gosticks/fresh.git
synced 2026-06-28 20:30:03 +00:00
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>
394 lines
10 KiB
TypeScript
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);
|
|
},
|
|
);
|
|
});
|