diff --git a/e2e/basic.spec.ts b/e2e/basic.spec.ts index 36b8d793f6687fa21e826900eea365ac0b2cb815..dbaeb4b9b718f5770e58b919ec1ef44b6a602bb3 100644 --- a/e2e/basic.spec.ts +++ b/e2e/basic.spec.ts @@ -1,6 +1,6 @@ /* eslint-disable turbo/no-undeclared-env-vars */ import { expect, test } from "@playwright/test"; -import { exec } from "child_process"; +import { ChildProcess, exec } from "child_process"; import { execSync } from "node:child_process"; import crypto from "node:crypto"; import { mkdir } from "node:fs/promises"; @@ -21,109 +21,149 @@ test.beforeEach(async () => { await mkdir(cwd, { recursive: true }); }); -const templateTypes: TemplateType[] = ["streaming", "simple"]; -const templateFrameworks: TemplateFramework[] = ["nextjs", "express"]; -const templateEngines: TemplateEngine[] = ["simple", "context"]; -const templateUIs: TemplateUI[] = ["shadcn", "html"]; +type AppType = "--frontend" | "--no-frontend" | ""; + +const templateTypes: TemplateType[] = ["streaming"]; +const templateFrameworks: TemplateFramework[] = ["express"]; +const templateEngines: TemplateEngine[] = ["simple"]; +const templateUIs: TemplateUI[] = ["html"]; +const MODEL = "gpt-3.5-turbo"; for (const templateType of templateTypes) { for (const templateFramework of templateFrameworks) { for (const templateEngine of templateEngines) { for (const templateUI of templateUIs) { - const shouldGenerateFrontendEnum = + const appType: AppType = templateFramework === "express" || templateFramework === "fastapi" - ? ["--frontend", "--no-frontend"] - : [""]; - for (const shouldGenerateFrontend of shouldGenerateFrontendEnum) { - if (templateEngine === "context") { - // we don't test context templates because it needs OPEN_AI_KEY - continue; - } - test(`try create-llama ${templateType} ${templateFramework} ${templateEngine} ${templateUI} ${shouldGenerateFrontend}`, async ({ - page, - }) => { - const createLlama = fileURLToPath( - new URL("../dist/index.js", import.meta.url), - ); + ? "--frontend" + : ""; + if (templateEngine === "context") { + // we don't test context templates because it needs OPEN_AI_KEY + continue; + } + test(`try create-llama ${templateType} ${templateFramework} ${templateEngine} ${templateUI} ${appType}`, async ({ + page, + }) => { + const name = runCreateLlama( + templateType, + templateFramework, + templateEngine, + templateUI, + appType, + ); - const name = [ - templateType, - templateFramework, - templateEngine, - templateUI, - shouldGenerateFrontend, - ].join("-"); - const command = [ - "node", - createLlama, - name, - "--template", - templateType, - "--framework", - templateFramework, - "--engine", - templateEngine, - "--ui", - templateUI, - "--open-ai-key", - process.env.OPEN_AI_KEY || "", - shouldGenerateFrontend, - "--eslint", - ].join(" "); - console.log(`running command '${command}' in ${cwd}`); - execSync(command, { - stdio: "inherit", - cwd, - }); + const port = Math.floor(Math.random() * 10000) + 10000; + const cps = await runApp(name, appType, port); + + // test frontend + await page.goto(`http://localhost:${port}`); + await expect(page.getByText("Built by LlamaIndex")).toBeVisible(); + // TODO: test backend using curl (would need OpenAI key) + // clean processes + cps.forEach((cp) => cp.kill()); + }); + } + } + } +} - const port = Math.floor(Math.random() * 10000) + 10000; +async function runApp( + name: string, + appType: AppType, + port: number, +): Promise<ChildProcess[]> { + const cps = []; - if ( - shouldGenerateFrontend === "--frontend" && - templateFramework === "express" - ) { - execSync("npm install", { - stdio: "inherit", - cwd: `${cwd}/${name}/frontend`, - }); - execSync("npm install", { - stdio: "inherit", - cwd: `${cwd}/${name}/backend`, - }); - } else { - execSync("npm install", { - stdio: "inherit", - cwd: `${cwd}/${name}`, - }); - } + try { + switch (appType) { + case "--no-frontend": + cps.push( + await createProcess("npm run dev", `${cwd}/${name}/backend`, port), + ); + break; + case "--frontend": + cps.push( + await createProcess( + "npm run dev", + `${cwd}/${name}/backend`, + port + 1, + ), + ); + cps.push( + await createProcess("npm run dev", `${cwd}/${name}/frontend`, port), + ); + break; + default: + cps.push(await createProcess("npm run dev", `${cwd}/${name}`, port)); + break; + } + } catch (e) { + cps.forEach((cp) => cp.kill()); + throw e; + } + return cps; +} - if (shouldGenerateFrontend === "--no-frontend") { - return; - } +async function createProcess(command: string, cwd: string, port: number) { + const cp = exec(command, { + cwd, + env: { + ...process.env, + PORT: `${port}`, + }, + }); + if (!cp) throw new Error(`Can't start process ${command} in ${cwd}`); - const cp = exec("npm run dev", { - cwd: - shouldGenerateFrontend === "--frontend" - ? `${cwd}/${name}/frontend` - : `${cwd}/${name}`, - env: { - ...process.env, - PORT: `${port}`, - }, - }); + await waitPort({ + host: "localhost", + port, + timeout: 1000 * 60, + }); + return cp; +} - await waitPort({ - host: "localhost", - port, - timeout: 1000 * 60, - }); +function runCreateLlama( + templateType: string, + templateFramework: string, + templateEngine: string, + templateUI: string, + appType: AppType, +) { + const createLlama = fileURLToPath( + new URL("../dist/index.js", import.meta.url), + ); - await page.goto(`http://localhost:${port}`); - await expect(page.getByText("Built by LlamaIndex")).toBeVisible(); - cp.kill(); - }); - } - } - } - } + const name = [ + templateType, + templateFramework, + templateEngine, + templateUI, + appType, + ].join("-"); + const command = [ + "node", + createLlama, + name, + "--template", + templateType, + "--framework", + templateFramework, + "--engine", + templateEngine, + "--ui", + templateUI, + "--model", + MODEL, + "--open-ai-key", + "testKey", // TODO: pass in OPEN_AI_KEY from CI env if needed for tests + appType, + "--eslint", + "--use-npm", + ].join(" "); + console.log(`running command '${command}' in ${cwd}`); + execSync(command, { + stdio: "inherit", + cwd, + }); + return name; } diff --git a/package.json b/package.json index f0079ecbc156fd6175317c46de6bf7d96bfc1c23..3d77e5f2a539c10e79df5bc7c0ba14e00ebf5d17 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "dev": "ncc build ./index.ts -w -o dist/", "build": "ncc build ./index.ts -o ./dist/ --minify --no-cache --no-source-map-register", "lint": "eslint . --ignore-pattern dist", - "e2e": "playwright test", + "e2e": "playwright test --reporter=list", "prepublishOnly": "cd ../../ && turbo run build" }, "devDependencies": {