Skip to content

Commit 13546ed

Browse files
authored
Feat: Shortest (#80)
# AI-Powered E2E Testing Framework Addresses: #69 This PR introduces a complete end-to-end testing framework powered by Claude AI. The framework enables writing tests in natural language and executes them through AI-driven browser automation. ## Key Features - Natural language test definitions using a fluent API - AI-powered test execution using Claude computer use - Automated browser interaction with precise coordinate handling - Detailed test reporting with pass/fail status ## Technical Highlights - Direct integration with Anthropic's Claude API - Playwright-based browser automation - Coordinate scaling system for reliable element targeting - Visual mouse tracking for debugging - Modular architecture with clear separation of concerns
2 parents 275e5cf + e1cb9e1 commit 13546ed

32 files changed

+4265
-29
lines changed

.gitignore

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
22

33
# dependencies
4-
/node_modules
4+
node_modules/
5+
.pnpm-store/
56
/.pnp
67
.pnp.js
78
.yarn/install-state.gz
@@ -16,6 +17,10 @@
1617
# production
1718
/build
1819

20+
# Build outputs
21+
dist/
22+
*.tsbuildinfo
23+
1924
# misc
2025
.DS_Store
2126
*.pem
@@ -40,4 +45,7 @@ next-env.d.ts
4045
# docker
4146
.docker
4247
docker-compose.override.yml
43-
docker-compose.yml
48+
docker-compose.yml
49+
50+
# screenshots
51+
screenshots/

README.md

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
## Local Development Setup Guide
66

7-
This guide will help you set up the Shortest project for local development.
7+
This guide will help you set up the Shortest web app for local development.
88

99
### Prerequisites
1010

@@ -123,8 +123,51 @@ Open [http://localhost:3000](http://localhost:3000) in your browser to see the a
123123

124124
### Running Tests
125125

126-
To run specs:
126+
To run unit tests:
127127

128128
```bash
129129
pnpm vitest
130130
```
131+
132+
133+
## Setup Guide for Running and Building Shortest Package Locally
134+
135+
When running `pnpm install` in the root, the `shortest` package will built and added in the `node_modules` folder. However, in order to run the tests locally using `pnpm test` or `shortest cli`, you need to do the following:
136+
137+
### Prerequisites
138+
139+
- Playwright
140+
- Chromium
141+
142+
### Install Playwright and build package
143+
144+
```bash
145+
pnpm add playwright
146+
pnpm exec playwright install
147+
148+
# to install shortest package
149+
pnpm install
150+
```
151+
152+
### Setup Shortest CLI
153+
```bash
154+
# packages/shortest
155+
cd packages/shortest
156+
pnpm link --global
157+
158+
# root
159+
cd ../..
160+
pnpm link --global shortest
161+
```
162+
163+
## Run Tests
164+
You can either run tests using the `shortest` cli:
165+
```bash
166+
shortest
167+
```
168+
169+
or use the `pnpm` command:
170+
171+
```bash
172+
pnpm test
173+
```

app/__tests__/home.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { afterAll, beforeAll, define, UITestBuilder } from 'shortest';
2+
3+
interface loginButton {
4+
url: string;
5+
}
6+
7+
define('Validate login button in home page', () => {
8+
9+
new UITestBuilder<loginButton>('/')
10+
.test('Validate login button is visible and works')
11+
.given('baseUrl', { url: 'http://localhost:3000' })
12+
.expect('Should redirect to login page')
13+
14+
});

app/__tests__/login.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { afterAll, beforeAll, define, UITestBuilder } from 'shortest';
2+
3+
interface LoginState {
4+
username: string;
5+
password: string;
6+
}
7+
8+
define('Validate login feature implemented with Clerk', () => {
9+
10+
new UITestBuilder<LoginState>('/')
11+
.test('Login to the app using Email and Password')
12+
.given('username and password', { username: 'argo.mohrad@gmail.com', password: 'Shortest1234' })
13+
.when('Logged in, click on view dashboard button')
14+
.expect('should successfully redirect to /')
15+
16+
// new UITestBuilder<LoginState>('/')
17+
// .test('Login to the app using Google account')
18+
// .given('username and password', { username: 'test', password: 'test' })
19+
// .expect('should successfully redirect to /dashboard')
20+
21+
});

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
"js-yaml": "^4.1.0",
8080
"jsdom": "^25.0.1",
8181
"smee-client": "^2.0.3",
82-
"vitest": "^2.1.1"
82+
"vitest": "^2.1.1",
83+
"shortest": "workspace:*"
8384
}
8485
}

packages/shortest/package.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"name": "shortest",
3+
"version": "0.0.1",
4+
"description": "AI-powered natural language end-to-end testing framework",
5+
"type": "module",
6+
"main": "./dist/index.js",
7+
"module": "./dist/index.js",
8+
"types": "./dist/index.d.ts",
9+
"bin": {
10+
"shortest": "./dist/cli/bin.js"
11+
},
12+
"exports": {
13+
".": {
14+
"types": "./dist/index.d.ts",
15+
"import": "./dist/index.js",
16+
"require": "./dist/index.cjs"
17+
}
18+
},
19+
"files": [
20+
"dist"
21+
],
22+
"scripts": {
23+
"build": "rm -rf dist && pnpm build:types && pnpm build:js && pnpm build:cli",
24+
"build:types": "tsc --emitDeclarationOnly",
25+
"build:js": "esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/index.js --external:fsevents --external:chokidar --external:glob --external:esbuild --external:playwright --external:playwright-core --external:chromium-bidi",
26+
"build:cli": "esbuild src/cli/bin.ts --bundle --platform=node --format=esm --outfile=dist/cli/bin.js --external:fsevents --external:chokidar --external:glob --external:esbuild --banner:js='import { createRequire } from \"module\"; const require = createRequire(import.meta.url); import { fileURLToPath } from \"url\"; const __filename = fileURLToPath(import.meta.url); import { dirname } from \"path\"; const __dirname = dirname(__filename);' --external:events --external:path --external:fs --external:util --external:stream --external:os --external:assert --external:url",
27+
"dev": "pnpm build:types --watch",
28+
"prepare": "pnpm exec playwright install && pnpm build && chmod +x dist/cli/bin.js",
29+
"preinstall": "pnpm build",
30+
"postinstall": "pnpm exec playwright install",
31+
"test:ai": "tsx scripts/test-ai.ts",
32+
"test:browser": "tsx scripts/test-browser.ts",
33+
"test:coordinates": "tsx scripts/test-coordinates.ts"
34+
},
35+
"dependencies": {
36+
"@anthropic-ai/sdk": "0.32.0",
37+
"ai": "^3.4.31",
38+
"chokidar": "^3.5.3",
39+
"chromium-bidi": "^0.5.2",
40+
"esbuild": "^0.20.1",
41+
"glob": "^10.3.10",
42+
"picocolors": "^1.0.0",
43+
"playwright": "^1.42.1"
44+
},
45+
"devDependencies": {
46+
"@types/node": "^20.11.24",
47+
"tsx": "^4.7.1",
48+
"typescript": "~5.6.2"
49+
}
50+
}

0 commit comments

Comments
 (0)