set up a basic puppeteer test

This commit is contained in:
Abi Raja 2024-05-17 16:22:45 -04:00
parent e3a4cfa7ab
commit 72d412fa52
6 changed files with 2350 additions and 158 deletions

3
frontend/.gitignore vendored
View File

@ -25,3 +25,6 @@ dist-ssr
# Env files # Env files
.env* .env*
# QA files
qa/**/*

8
frontend/jest.config.js Normal file
View File

@ -0,0 +1,8 @@
export default {
preset: "ts-jest",
testEnvironment: "node",
transform: {
"^.+\\.tsx?$": "ts-jest",
},
testTimeout: 30000,
};

View File

@ -10,7 +10,7 @@
"build-hosted": "tsc && vite build --mode prod", "build-hosted": "tsc && vite build --mode prod",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview", "preview": "vite preview",
"test": "vitest" "test": "jest"
}, },
"dependencies": { "dependencies": {
"@codemirror/lang-html": "^6.4.6", "@codemirror/lang-html": "^6.4.6",
@ -49,7 +49,9 @@
"webm-duration-fix": "^1.0.4" "webm-duration-fix": "^1.0.4"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.5.12",
"@types/node": "^20.9.0", "@types/node": "^20.9.0",
"@types/puppeteer": "^7.0.4",
"@types/react": "^18.2.15", "@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7", "@types/react-dom": "^18.2.7",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
@ -59,8 +61,11 @@
"eslint": "^8.45.0", "eslint": "^8.45.0",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3", "eslint-plugin-react-refresh": "^0.4.3",
"jest": "^29.7.0",
"postcss": "^8.4.31", "postcss": "^8.4.31",
"puppeteer": "^22.6.4",
"tailwindcss": "^3.3.5", "tailwindcss": "^3.3.5",
"ts-jest": "^29.1.2",
"typescript": "^5.0.2", "typescript": "^5.0.2",
"vite": "^4.4.5", "vite": "^4.4.5",
"vite-plugin-html": "^3.2.0", "vite-plugin-html": "^3.2.0",

View File

@ -1,4 +1,3 @@
import { expect, test } from "vitest";
import { extractHistoryTree, renderHistory } from "./utils"; import { extractHistoryTree, renderHistory } from "./utils";
import type { History } from "./history_types"; import type { History } from "./history_types";
@ -84,147 +83,149 @@ const basicBadHistory: History = [
}, },
]; ];
test("should correctly extract the history tree", () => { describe("History Utils", () => {
expect(extractHistoryTree(basicLinearHistory, 2)).toEqual([ test("should correctly extract the history tree", () => {
"<html>1. create</html>", expect(extractHistoryTree(basicLinearHistory, 2)).toEqual([
"use better icons", "<html>1. create</html>",
"<html>2. edit with better icons</html>", "use better icons",
"make text red", "<html>2. edit with better icons</html>",
"<html>3. edit with better icons and red text</html>", "make text red",
]); "<html>3. edit with better icons and red text</html>",
]);
expect(extractHistoryTree(basicLinearHistory, 0)).toEqual([ expect(extractHistoryTree(basicLinearHistory, 0)).toEqual([
"<html>1. create</html>", "<html>1. create</html>",
]); ]);
// Test branching // Test branching
expect(extractHistoryTree(basicBranchingHistory, 3)).toEqual([ expect(extractHistoryTree(basicBranchingHistory, 3)).toEqual([
"<html>1. create</html>", "<html>1. create</html>",
"use better icons", "use better icons",
"<html>2. edit with better icons</html>", "<html>2. edit with better icons</html>",
"make text green", "make text green",
"<html>4. edit with better icons and green text</html>", "<html>4. edit with better icons and green text</html>",
]); ]);
expect(extractHistoryTree(longerBranchingHistory, 4)).toEqual([ expect(extractHistoryTree(longerBranchingHistory, 4)).toEqual([
"<html>1. create</html>", "<html>1. create</html>",
"use better icons", "use better icons",
"<html>2. edit with better icons</html>", "<html>2. edit with better icons</html>",
"make text green", "make text green",
"<html>4. edit with better icons and green text</html>", "<html>4. edit with better icons and green text</html>",
"make text bold", "make text bold",
"<html>5. edit with better icons and green, bold text</html>", "<html>5. edit with better icons and green, bold text</html>",
]); ]);
expect(extractHistoryTree(longerBranchingHistory, 2)).toEqual([ expect(extractHistoryTree(longerBranchingHistory, 2)).toEqual([
"<html>1. create</html>", "<html>1. create</html>",
"use better icons", "use better icons",
"<html>2. edit with better icons</html>", "<html>2. edit with better icons</html>",
"make text red", "make text red",
"<html>3. edit with better icons and red text</html>", "<html>3. edit with better icons and red text</html>",
]); ]);
// Errors // Errors
// Bad index // Bad index
expect(() => extractHistoryTree(basicLinearHistory, 100)).toThrow(); expect(() => extractHistoryTree(basicLinearHistory, 100)).toThrow();
expect(() => extractHistoryTree(basicLinearHistory, -2)).toThrow(); expect(() => extractHistoryTree(basicLinearHistory, -2)).toThrow();
// Bad tree // Bad tree
expect(() => extractHistoryTree(basicBadHistory, 1)).toThrow(); expect(() => extractHistoryTree(basicBadHistory, 1)).toThrow();
}); });
test("should correctly render the history tree", () => { test("should correctly render the history tree", () => {
expect(renderHistory(basicLinearHistory, 2)).toEqual([ expect(renderHistory(basicLinearHistory, 2)).toEqual([
{ {
isActive: false, isActive: false,
parentVersion: null, parentVersion: null,
summary: "Create", summary: "Create",
type: "Create", type: "Create",
}, },
{ {
isActive: false, isActive: false,
parentVersion: null, parentVersion: null,
summary: "use better icons", summary: "use better icons",
type: "Edit", type: "Edit",
}, },
{ {
isActive: true, isActive: true,
parentVersion: null, parentVersion: null,
summary: "make text red", summary: "make text red",
type: "Edit", type: "Edit",
}, },
]); ]);
// Current version is the first version // Current version is the first version
expect(renderHistory(basicLinearHistory, 0)).toEqual([ expect(renderHistory(basicLinearHistory, 0)).toEqual([
{ {
isActive: true, isActive: true,
parentVersion: null, parentVersion: null,
summary: "Create", summary: "Create",
type: "Create", type: "Create",
}, },
{ {
isActive: false, isActive: false,
parentVersion: null, parentVersion: null,
summary: "use better icons", summary: "use better icons",
type: "Edit", type: "Edit",
}, },
{ {
isActive: false, isActive: false,
parentVersion: null, parentVersion: null,
summary: "make text red", summary: "make text red",
type: "Edit", type: "Edit",
}, },
]); ]);
// Render a history with code // Render a history with code
expect(renderHistory(basicLinearHistoryWithCode, 0)).toEqual([ expect(renderHistory(basicLinearHistoryWithCode, 0)).toEqual([
{ {
isActive: true, isActive: true,
parentVersion: null, parentVersion: null,
summary: "Imported from code", summary: "Imported from code",
type: "Imported from code", type: "Imported from code",
}, },
{ {
isActive: false, isActive: false,
parentVersion: null, parentVersion: null,
summary: "use better icons", summary: "use better icons",
type: "Edit", type: "Edit",
}, },
{ {
isActive: false, isActive: false,
parentVersion: null, parentVersion: null,
summary: "make text red", summary: "make text red",
type: "Edit", type: "Edit",
}, },
]); ]);
// Render a non-linear history // Render a non-linear history
expect(renderHistory(basicBranchingHistory, 3)).toEqual([ expect(renderHistory(basicBranchingHistory, 3)).toEqual([
{ {
isActive: false, isActive: false,
parentVersion: null, parentVersion: null,
summary: "Create", summary: "Create",
type: "Create", type: "Create",
}, },
{ {
isActive: false, isActive: false,
parentVersion: null, parentVersion: null,
summary: "use better icons", summary: "use better icons",
type: "Edit", type: "Edit",
}, },
{ {
isActive: false, isActive: false,
parentVersion: null, parentVersion: null,
summary: "make text red", summary: "make text red",
type: "Edit", type: "Edit",
}, },
{ {
isActive: true, isActive: true,
parentVersion: "v2", parentVersion: "v2",
summary: "make text green", summary: "make text green",
type: "Edit", type: "Edit",
}, },
]); ]);
});
}); });

View File

@ -0,0 +1,95 @@
import puppeteer, { Browser, Page, ElementHandle } from "puppeteer";
import { Stack } from "../lib/stacks";
const REPO_PATH = "/Users/abi/Documents/GitHub/screenshot-to-code/frontend";
const DOWNLOAD_PATH = `${REPO_PATH}/qa`;
const SCREENSHOTS_PATH = `${REPO_PATH}/qa/results`;
const IMAGE_PATH = DOWNLOAD_PATH + "/ui_table.png";
describe("Simple Puppeteer Test", () => {
let browser: Browser;
let page: Page;
beforeAll(async () => {
browser = await puppeteer.launch({ headless: true });
page = await browser.newPage();
await page.goto("http://localhost:5173/");
// Set screen size
await page.setViewport({ width: 1080, height: 1024 });
// TODO: Does this need to be moved?
const client = await page.createCDPSession();
// Set download behavior path
await client.send("Page.setDownloadBehavior", {
behavior: "allow",
downloadPath: DOWNLOAD_PATH,
});
});
afterAll(async () => {
await browser.close();
});
const stacks = Object.values(Stack).slice(0, 1);
stacks.forEach((stack) => {
it(`should load the homepage and check the title for stack: ${stack}`, async () => {
const codeGenerationModel = "claude_3_sonnet";
// Set up local storage
const setting = {
openAiApiKey: null,
openAiBaseURL: null,
screenshotOneApiKey: null,
isImageGenerationEnabled: false,
editorTheme: "cobalt",
generatedCodeConfig: stack,
codeGenerationModel: codeGenerationModel,
isTermOfServiceAccepted: false,
accessCode: null,
};
await page.evaluate((setting) => {
localStorage.setItem("setting", JSON.stringify(setting));
}, setting);
// Reload the page to apply the local storage
await page.reload();
// Generate from image
const fileInput = (await page.$(
".file-input"
)) as ElementHandle<HTMLInputElement>;
// Replace with the path to your image
const imagePath = IMAGE_PATH;
if (!fileInput) {
throw new Error("File input element not found");
}
// Upload file
await fileInput.uploadFile(imagePath);
// Screenshot of the uploaded image
await page.screenshot({
path: `${SCREENSHOTS_PATH}/${codeGenerationModel}_${stack}_image_uploaded.png`,
});
console.log("starting image code generation for stack: ", stack);
// Click the generate button and wait for the code to be generated
await page.waitForNetworkIdle();
await page.waitForFunction(() => document.body.innerText.includes("v1"), {
timeout: 30000,
});
await page.screenshot({
path: `${SCREENSHOTS_PATH}/${codeGenerationModel}_${stack}_image_generation_results.png`,
});
console.log(`done with image code generation for stack: ${stack}`);
});
});
});

File diff suppressed because it is too large Load Diff