Module

x/fresh/tests/init_test.ts

The next-gen web framework.
Extremely Popular
Latest
File
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
import * as path from "$std/path/mod.ts";import { STATUS_CODE } from "../src/server/deps.ts";import { assert, assertEquals, assertNotMatch, assertStringIncludes, delay, puppeteer, retry,} from "./deps.ts";import { assertTextMany, clickWhenListenerReady, fetchHtml, getStdOutput, startFreshServer, waitForText,} from "./test_utils.ts";
const assertFileExistence = async (files: string[], dirname: string) => { for (const filePath of files) { const parts = filePath.split("/").slice(1);
const osFilePath = path.join(dirname, ...parts); const stat = await Deno.stat(osFilePath); assert(stat.isFile, `Could not find file ${osFilePath}`); }};
Deno.test({ name: "fresh-init", async fn(t) { // Preparation const tmpDirName = await Deno.makeTempDir();
await t.step("execute init command", async () => { const cliProcess = new Deno.Command(Deno.execPath(), { args: [ "run", "-A", "--no-config", "init.ts", tmpDirName, ], stdin: "null", stdout: "null", }); const { code } = await cliProcess.output(); assertEquals(code, 0); });
const files = [ `/README.md`, `/.gitignore`, `/deno.json`, `/fresh.gen.ts`, `/components/Button.tsx`, `/islands/Counter.tsx`, `/main.ts`, `/routes/greet/[name].tsx`, `/routes/api/joke.ts`, `/routes/_app.tsx`, `/routes/index.tsx`, `/static/logo.svg`, ];
await t.step("check generated files", async () => { await assertFileExistence(files, tmpDirName); });
await t.step("check project", async () => { const cliProcess = new Deno.Command(Deno.execPath(), { args: [ "task", "check", ], cwd: tmpDirName, stdin: "null", stdout: "piped", stderr: "piped", }); const { code } = await cliProcess.output(); assertEquals(code, 0); });
await t.step("check deno.json", async () => { const configPath = path.join(tmpDirName, "deno.json"); const json = JSON.parse(await Deno.readTextFile(configPath));
// Check tasks assert(json.tasks.start, "Missing 'start' task"); assert(json.tasks.build, "Missing 'build' task"); assert(json.tasks.preview, "Missing 'preview' task");
// Check lint settings assertEquals(json.lint.rules.tags, ["fresh", "recommended"]);
// Check exclude settings assertEquals(json.exclude, ["**/_fresh/*"]); });
await t.step("start up the server and access the root page", async () => { const { serverProcess, lines, address } = await startFreshServer({ args: ["run", "-A", "--check", "main.ts"], cwd: tmpDirName, });
await delay(100);
// Access the root page const res = await fetch(address); await res.body?.cancel(); assertEquals(res.status, STATUS_CODE.OK);
// verify the island is revived. const browser = await puppeteer.launch({ args: ["--no-sandbox"], }); const page = await browser.newPage(); await page.goto(address, { waitUntil: "networkidle2" }); const counter = await page.$("body > div > div > div > p"); let counterValue = await counter?.evaluate((el) => el.textContent); assert(counterValue === "3");
await clickWhenListenerReady( page, "body > div > div > div > button:nth-child(3)", );
await waitForText(page, "body > div > div > div > p", "4");
counterValue = await counter?.evaluate((el) => el.textContent); assert(counterValue === "4"); await page.close(); await browser.close();
serverProcess.kill("SIGTERM"); await serverProcess.status;
// Drain the lines stream for await (const _ of lines) { /* noop */ } });
await retry(() => Deno.remove(tmpDirName, { recursive: true })); },});
Deno.test({ name: "fresh-init --tailwind --vscode", async fn(t) { // Preparation const tmpDirName = await Deno.makeTempDir();
await t.step("execute init command", async () => { const cliProcess = new Deno.Command(Deno.execPath(), { args: [ "run", "-A", "--no-config", "init.ts", tmpDirName, "--tailwind", "--vscode", ], stdin: "null", stdout: "null", }); const { code } = await cliProcess.output(); assertEquals(code, 0); });
const files = [ "/README.md", "/fresh.gen.ts", "/tailwind.config.ts", "/components/Button.tsx", "/islands/Counter.tsx", "/main.ts", "/routes/greet/[name].tsx", "/routes/api/joke.ts", "/routes/_app.tsx", "/routes/index.tsx", "/static/logo.svg", "/.vscode/settings.json", "/.vscode/extensions.json", "/.gitignore", ];
await t.step("check generated files", async () => { await assertFileExistence(files, tmpDirName); });
await t.step("start up the server and access the root page", async () => { const { serverProcess, lines, address } = await startFreshServer({ args: ["run", "-A", "--check", "main.ts"], cwd: tmpDirName, });
await delay(100);
// Access the root page const res = await fetch(address); await res.body?.cancel(); assertEquals(res.status, STATUS_CODE.OK);
// verify the island is revived. const browser = await puppeteer.launch({ args: ["--no-sandbox"] }); const page = await browser.newPage(); await page.goto(address, { waitUntil: "networkidle2" });
const counter = await page.$("body > div > div > div > p"); let counterValue = await counter?.evaluate((el) => el.textContent); assertEquals(counterValue, "3");
const fontWeight = await counter?.evaluate((el) => getComputedStyle(el).fontWeight ); assertEquals(fontWeight, "400");
const buttonPlus = await page.$( "body > div > div > div > button:nth-child(3)", ); await buttonPlus?.click();
await waitForText(page, "body > div > div > div > p", "4");
counterValue = await counter?.evaluate((el) => el.textContent); assert(counterValue === "4"); await page.close(); await browser.close();
serverProcess.kill("SIGTERM"); await serverProcess.status;
// Drain the lines stream for await (const _ of lines) { /* noop */ } });
await retry(() => Deno.remove(tmpDirName, { recursive: true })); },});
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 = new Deno.Command(Deno.execPath(), { args: [ "run", "-A", "init.ts", tmpDirName, "--twind", "--vscode", ], stdin: "null", stdout: "null", }); const { code } = await cliProcess.output(); assertEquals(code, 0); });
const files = [ "/README.md", "/fresh.gen.ts", "/twind.config.ts", "/components/Button.tsx", "/islands/Counter.tsx", "/main.ts", "/routes/greet/[name].tsx", "/routes/api/joke.ts", "/routes/_app.tsx", "/routes/index.tsx", "/static/logo.svg", "/.vscode/settings.json", "/.vscode/extensions.json", "/.gitignore", ];
await t.step("check generated files", async () => { await assertFileExistence(files, tmpDirName); });
await t.step("start up the server and access the root page", async () => { const { serverProcess, lines, address } = await startFreshServer({ args: ["run", "-A", "--check", "main.ts"], cwd: tmpDirName, });
await delay(100);
// Access the root page const res = await fetch(address); await res.body?.cancel(); assertEquals(res.status, STATUS_CODE.OK);
// verify the island is revived. const browser = await puppeteer.launch({ args: ["--no-sandbox"] }); const page = await browser.newPage(); await page.goto(address, { waitUntil: "networkidle2" });
const counter = await page.$("body > div > div > div > p"); let counterValue = await counter?.evaluate((el) => el.textContent); assertEquals(counterValue, "3");
const fontWeight = await counter?.evaluate((el) => getComputedStyle(el).fontWeight ); assertEquals(fontWeight, "400");
const buttonPlus = await page.$( "body > div > div > div > button:nth-child(3)", ); await buttonPlus?.click();
await waitForText(page, "body > div > div > div > p", "4");
counterValue = await counter?.evaluate((el) => el.textContent); assert(counterValue === "4"); await page.close(); await browser.close();
serverProcess.kill("SIGTERM"); await serverProcess.status;
// Drain the lines stream for await (const _ of lines) { /* noop */ } });
await retry(() => Deno.remove(tmpDirName, { recursive: true })); },});
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 = new Deno.Command(Deno.execPath(), { args: ["run", "-A", "--no-config", "init.ts"], stdin: "null", stderr: "piped", }); const { code, stderr } = await cliProcess.output(); assertEquals(code, 1);
const errorString = new TextDecoder().decode(stderr); assertStringIncludes(errorString, includeText); }, );
await t.step( "execute invalid init command (deno run -A init.ts -f)", async () => { const cliProcess = new Deno.Command(Deno.execPath(), { args: ["run", "-A", "--no-config", "init.ts", "-f"], }); const { code, stderr } = await cliProcess.output(); assertEquals(code, 1);
const errorString = new TextDecoder().decode(stderr); assertStringIncludes(errorString, includeText); }, );
await t.step( "execute invalid init command (deno run -A init.ts --foo)", async () => { const cliProcess = new Deno.Command(Deno.execPath(), { args: ["run", "-A", "--no-config", "init.ts", "--foo"], }); const { code, stderr } = await cliProcess.output(); assertEquals(code, 1);
const errorString = new TextDecoder().decode(stderr); assertStringIncludes(errorString, includeText); }, );});
Deno.test("fresh-init .", async function (t) { // Preparation const tmpDirName = await Deno.makeTempDir();
await t.step("execute init command", async () => { const cliProcess = new Deno.Command(Deno.execPath(), { args: [ "run", "-A", "--no-config", path.join(Deno.cwd(), "init.ts"), ".", ], cwd: tmpDirName, stdin: "null", stdout: "piped", stderr: "piped", }); const { code, stdout } = await cliProcess.output(); const output = new TextDecoder().decode(stdout); assertNotMatch(output, /Enter your project directory/); assertEquals(code, 0); });});
Deno.test({ name: "fresh-init subdirectory", async fn(t) { // Preparation const tmpDirName = await Deno.makeTempDir();
await Deno.mkdir(path.join(tmpDirName, "subdirectory"));
const cliProcess = new Deno.Command(Deno.execPath(), { args: [ "run", "-A", "--no-config", path.join(Deno.cwd(), "init.ts"), "subdirectory/subsubdirectory", ], cwd: tmpDirName, stdin: "null", stdout: "piped", stderr: "inherit", });
await cliProcess.output();
// move deno.json one level up await Deno.rename( path.join(tmpDirName, "subdirectory", "subsubdirectory", "deno.json"), path.join(tmpDirName, "deno.json"), );
const files = [ "/deno.json", "/subdirectory/subsubdirectory/main.ts", "/subdirectory/subsubdirectory/dev.ts", "/subdirectory/subsubdirectory/fresh.gen.ts", ];
await t.step("check generated files", async () => { await assertFileExistence(files, tmpDirName); });
await t.step("start up the server", async () => { const { serverProcess, lines } = await startFreshServer({ args: ["run", "-A", "--check", "subdirectory/subsubdirectory/dev.ts"], cwd: tmpDirName, });
await delay(100);
serverProcess.kill("SIGTERM"); await serverProcess.status;
// Drain the lines stream for await (const _ of lines) { /* noop */ } });
await retry(() => Deno.remove(tmpDirName, { recursive: true })); },});
Deno.test({ name: "fresh-init loads env variables", async fn(t) { // Preparation const tmpDirName = await Deno.makeTempDir();
const cliProcess = new Deno.Command(Deno.execPath(), { args: [ "run", "-A", "--no-config", "init.ts", tmpDirName, "--tailwind", "--vscode", ], stdin: "null", stdout: "piped", stderr: "inherit", });
await cliProcess.output();
// Add .env file await Deno.writeTextFile(path.join(tmpDirName, ".env"), "FOO=true\n"); await Deno.writeTextFile( path.join(tmpDirName, "routes", "env.tsx"), `export default function Page() { return <h1>{Deno.env.get("FOO")}</h1> }`, );
await t.step("start up the server", async () => { const { serverProcess, lines, address } = await startFreshServer({ args: ["run", "-A", "--no-check", "dev.ts"], cwd: tmpDirName, });
const doc = await fetchHtml(`${address}/env`); assertTextMany(doc, "h1", ["true"]);
serverProcess.kill("SIGTERM"); await serverProcess.status;
// Drain the lines stream for await (const _ of lines) { /* noop */ } });
await t.step("build code and start server again", async () => { await new Deno.Command(Deno.execPath(), { args: [ "task", "build", ], cwd: tmpDirName, stdin: "null", stdout: "piped", stderr: "inherit", }).output();
const { serverProcess, lines, address, output } = await startFreshServer({ args: ["run", "-A", "--no-check", "main.ts"], cwd: tmpDirName, });
assert( output.find((line) => /Using snapshot found a/.test(line)), "Snapshot message not printed", );
const doc = await fetchHtml(`${address}/env`); assertTextMany(doc, "h1", ["true"]);
serverProcess.kill("SIGTERM"); await serverProcess.status;
// Drain the lines stream for await (const _ of lines) { /* noop */ } });
await retry(() => Deno.remove(tmpDirName, { recursive: true })); },});
Deno.test("init - show help screen", async (t) => { await t.step("--help", async () => { const output1 = await new Deno.Command(Deno.execPath(), { args: [ "run", "-A", "--no-config", "init.ts", "--help", ], stdin: "null", stdout: "piped", stderr: "piped", }).output();
assertEquals(output1.code, 0); const { stdout } = getStdOutput(output1); assertStringIncludes(stdout, "Initialize a new Fresh project"); });
await t.step("-h", async () => { const output1 = await new Deno.Command(Deno.execPath(), { args: [ "run", "-A", "--no-config", "init.ts", "-h", ], stdin: "null", stdout: "piped", stderr: "piped", }).output();
assertEquals(output1.code, 0); const { stdout } = getStdOutput(output1); assertStringIncludes(stdout, "Initialize a new Fresh project"); });});
Deno.test({ name: "regenerate manifest", async fn(t) { const MANIFEST_FILENAME = "fresh.gen.ts"; const tmpDirName = await Deno.makeTempDir(); const manifestFilePath = path.join(tmpDirName, MANIFEST_FILENAME);
await t.step("execute init command", async () => { const cliProcess = new Deno.Command(Deno.execPath(), { args: [ "run", "-A", "init.ts", tmpDirName, ], stdin: "null", stdout: "null", }); const { code } = await cliProcess.output(); assertEquals(code, 0); });
let oldManifestContent: string; await t.step("store the contents of the manifest", async () => { oldManifestContent = await Deno.readTextFile(manifestFilePath); });
await t.step("delete the manifest", async () => { await Deno.remove(manifestFilePath); });
await t.step("regenerate the manifest", async () => { const cliProcess = new Deno.Command(Deno.execPath(), { args: [ "task", "manifest", ], cwd: tmpDirName, stdin: "null", stdout: "piped", stderr: "piped", });
const output = await cliProcess.output();
assertEquals(output.code, 0); });
await t.step("assert the old and new contents are equal", async () => { const newManifestContent = await Deno.readTextFile(manifestFilePath); assertEquals(oldManifestContent, newManifestContent); });
await retry(() => Deno.remove(tmpDirName, { recursive: true })); }, sanitizeResources: false,});