Skip to content

Commit

Permalink
examples: add playwright demo. (#65)
Browse files Browse the repository at this point in the history
* .git: ignore all temp files

* examples: add playwright driver.

* feat: improve playwright driver.

* package: add playwright test script.
  • Loading branch information
asafkorem authored Jan 26, 2025
1 parent 5bd84db commit c36b8c5
Show file tree
Hide file tree
Showing 10 changed files with 588 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,6 @@ dist
.dist

# Examples
examples/puppeteer/temp/
**/*/temp/

**/*/detox_copilot_cache.json
14 changes: 14 additions & 0 deletions examples/playwright/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['**/tests/**/*.test.ts'],
moduleFileExtensions: ['ts', 'js', 'json', 'node'],
moduleDirectories: ['node_modules', '<rootDir>/node_modules'],
transformIgnorePatterns: ['node_modules/(?!examples)'],
moduleNameMapper: {
'^@copilot$': '<rootDir>/../../src',
'^@copilot/(.*)$': '<rootDir>/../../src/$1',
'^@/(.*)$': '<rootDir>/../../src/$1'
}
};
19 changes: 19 additions & 0 deletions examples/playwright/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "detox-copilot-playwright-example",
"version": "1.0.0",
"private": true,
"scripts": {
"test": "jest"
},
"dependencies": {
"detox-copilot": "file:../.."
},
"devDependencies": {
"@types/jest": "^29.5.12",
"jest": "^29.7.0",
"ts-jest": "^29.2.4",
"typescript": "^5.3.3",
"playwright": "^1.42.1",
"@playwright/test": "^1.42.1"
}
}
41 changes: 41 additions & 0 deletions examples/playwright/tests/example.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import copilot from "@copilot";
import { PromptHandler } from "../../utils/promptHandler";
import { PlaywrightFrameworkDriver } from "@copilot/drivers/playwright";

describe("Example Test Suite", () => {
jest.setTimeout(300000);

let frameworkDriver: PlaywrightFrameworkDriver;

beforeAll(async () => {
const promptHandler: PromptHandler = new PromptHandler();

frameworkDriver = new PlaywrightFrameworkDriver();

copilot.init({
frameworkDriver,
promptHandler,
});
});

afterAll(async () => {
const page = frameworkDriver.getCurrentPage();
if (page) {
await page.context().browser()?.close();
}
});

beforeEach(async () => {
copilot.start();
});

afterEach(async () => {
copilot.end();
});

it("perform test with pilot", async () => {
await copilot.pilot(
"Open https://www.wix.com/domains and search for the domain Shraga.com, is it available?",
);
});
});
14 changes: 14 additions & 0 deletions examples/playwright/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"baseUrl": "../../src",
"rootDir": ".",
"paths": {
"@/*": ["./*"],
"@copilot": ["./index"],
"@copilot/*": ["./*"]
}
},
"include": ["tests/**/*"],
"exclude": ["node_modules"]
}
65 changes: 65 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"build": "tsc && tsc-alias",
"test": "jest",
"test:examples:puppeteer": "cd examples/puppeteer && jest",
"test:examples:playwright": "cd examples/playwright && jest",
"bump-version": "npm version patch && git push && git push --tags",
"release": "npm run test && npm run bump-version && npm run build && npm publish",
"lint": "eslint . --ext .ts",
Expand All @@ -36,19 +37,21 @@
"url": "https://github.com/wix-incubator/detox-copilot/issues"
},
"devDependencies": {
"@playwright/test": "^1.50.0",
"@types/jest": "^29.5.12",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"axios": "^1.7.9",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"jest": "^29.7.0",
"playwright": "^1.50.0",
"prettier": "^3.2.5",
"puppeteer": "^20.8.0",
"ts-jest": "^29.2.4",
"tsc-alias": "^1.8.10",
"typescript": "^5.3.3",
"puppeteer": "^20.8.0",
"axios": "^1.7.9"
"typescript": "^5.3.3"
},
"dependencies": {
"blockhash-core": "^0.1.0",
Expand Down
11 changes: 11 additions & 0 deletions src/actions/CopilotStepPerformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,17 @@ export class CopilotStepPerformer {
color: "greenBright",
});

if (attempt > 1) {
logger.info(
`🔄 Attempt ${attempt}/${maxAttempts} succeeded for step "${step}", generated code:\n`,
{
message: `\n\`\`\`javascript\n${code}\n\`\`\``,
isBold: false,
color: "gray",
},
);
}

return result;
} catch (error) {
lastError = error;
Expand Down
73 changes: 73 additions & 0 deletions src/drivers/playwright/getCleanDOM.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import * as playwright from "playwright";

/**
* Get clean DOM from the page content
* - Removes hidden elements
* - Removes ads, analytics, tracking elements
* - Removes unnecessary attributes
* - Removes empty elements
* @param page
*/
export default async function getCleanDOM(page: playwright.Page) {
await page.waitForSelector("body");

return await page.evaluate(() => {
const copiedDocument = document.cloneNode(true) as Document;

copiedDocument
.querySelectorAll('[hidden], [aria-hidden="true"]')
.forEach((el) => el.remove());

const removeSelectors = [
"script",
"style",
"link",
"meta",
"noscript",
"iframe",
'[class*="ads"]',
'[id*="ads"]',
'[class*="analytics"]',
'[class*="tracking"]',
"footer",
"header",
"nav",
"path",
"aside",
];

const allowedAttributes = [
"src",
"href",
"alt",
"title",
"aria-label",
"aria-labelledby",
"aria-describedby",
"aria-hidden",
"role",
"class",
"id",
"data-*",
];

copiedDocument.querySelectorAll("*").forEach((el) => {
Array.from(el.attributes).forEach((attr) => {
if (!allowedAttributes.includes(attr.name)) {
el.removeAttribute(attr.name);
}
});

if (!el.innerHTML.trim()) {
el.remove();
}
});

removeSelectors.forEach((selector) => {
copiedDocument.querySelectorAll(selector).forEach((el) => el.remove());
});

const mainContent = copiedDocument.body.innerHTML;
return mainContent.replace(/\s+/g, " ").trim();
});
}
Loading

0 comments on commit c36b8c5

Please sign in to comment.