slapify 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,452 @@
1
+ # slapify 🖐️
2
+
3
+ **AI-powered E2E testing that slaps** — write tests in plain English.
4
+
5
+ By [slaps.dev](https://slaps.dev)
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ # Install globally
11
+ npm install -g slapify
12
+
13
+ # Or use directly with npx (no install needed)
14
+ npx slapify init
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```bash
20
+ # Initialize in your project (interactive setup)
21
+ slapify init
22
+
23
+ # Or with npx
24
+ npx slapify init
25
+
26
+ # Quick init with defaults (skip prompts)
27
+ slapify init -y
28
+
29
+ # Set your API key
30
+ export ANTHROPIC_API_KEY=your-key
31
+
32
+ # Run the example test
33
+ slapify run tests/example.flow
34
+ ```
35
+
36
+ The interactive `init` command will:
37
+
38
+ - Ask which LLM provider to use (Anthropic/OpenAI)
39
+ - Detect installed browsers on your system
40
+ - Let you choose between system Chrome or downloading Chromium
41
+ - Create a sample test file to get started
42
+
43
+ ## Writing Tests
44
+
45
+ Create `.flow` files with natural language steps:
46
+
47
+ ```
48
+ # tests/login.flow
49
+
50
+ Go to https://myapp.com
51
+ Login with default credentials
52
+ Verify "Welcome" message appears
53
+ [Optional] Close promotional popup
54
+ Navigate to settings
55
+ Verify "Account Settings" page loads
56
+ ```
57
+
58
+ ### Syntax
59
+
60
+ | Feature | Example |
61
+ | ------------- | ------------------------------------------- |
62
+ | Comments | `# This is a comment` |
63
+ | Required step | `Click the login button` |
64
+ | Optional step | `[Optional] Close popup` |
65
+ | Conditional | `If "Accept cookies" appears, click Accept` |
66
+ | Credentials | `Login with admin credentials` |
67
+ | Verification | `Verify "Success" message appears` |
68
+
69
+ ## Configuration
70
+
71
+ ### `.slapify/config.yaml`
72
+
73
+ ```yaml
74
+ # LLM Settings (required)
75
+ llm:
76
+ provider: anthropic
77
+ model: claude-sonnet-4-20250514
78
+ api_key: ${ANTHROPIC_API_KEY}
79
+
80
+ # Browser Settings (optional)
81
+ browser:
82
+ headless: true
83
+ timeout: 30000
84
+ viewport:
85
+ width: 1280
86
+ height: 720
87
+
88
+ # Report Settings (optional)
89
+ report:
90
+ format: html
91
+ screenshots: true
92
+ output_dir: ./test-reports
93
+ ```
94
+
95
+ ### `.slapify/credentials.yaml`
96
+
97
+ ```yaml
98
+ profiles:
99
+ default:
100
+ type: login-form
101
+ username: ${TEST_USERNAME}
102
+ password: ${TEST_PASSWORD}
103
+
104
+ admin:
105
+ type: login-form
106
+ username: admin@example.com
107
+ password: ${ADMIN_PASSWORD}
108
+ totp_secret: JBSWY3DPEHPK3PXP # For 2FA
109
+
110
+ session:
111
+ type: inject
112
+ cookies:
113
+ - name: auth_token
114
+ value: ${AUTH_TOKEN}
115
+ domain: .example.com
116
+ ```
117
+
118
+ ## CLI Commands
119
+
120
+ ```bash
121
+ # Initialize project
122
+ slapify init
123
+
124
+ # Run all tests in tests/ directory
125
+ slapify run
126
+
127
+ # Run specific files
128
+ slapify run tests/login.flow tests/checkout.flow
129
+
130
+ # Run all tests in a directory
131
+ slapify run tests/
132
+
133
+ # Run with visible browser
134
+ slapify run --headed
135
+
136
+ # Run with HTML report
137
+ slapify run --report
138
+
139
+ # Run in parallel (4 workers by default)
140
+ slapify run tests/ --parallel
141
+
142
+ # Run in parallel with 8 workers
143
+ slapify run tests/ -p -w 8
144
+
145
+ # Fix failing tests automatically
146
+ slapify fix tests/broken.flow
147
+
148
+ # Validate flow files
149
+ slapify validate
150
+
151
+ # List all tests
152
+ slapify list
153
+
154
+ # Create a new flow file
155
+ slapify create my-test
156
+
157
+ # Generate flow from prompt
158
+ slapify generate "test login flow for github.com"
159
+
160
+ # Interactive mode
161
+ slapify interactive https://myapp.com
162
+ ```
163
+
164
+ ## Programmatic Usage
165
+
166
+ ### Basic Usage
167
+
168
+ ```typescript
169
+ import { Slapify } from "slapify";
170
+
171
+ // Using config directory
172
+ const slapify = new Slapify({ configDir: ".slapify" });
173
+
174
+ // Or with inline config
175
+ const slapify = new Slapify({
176
+ config: {
177
+ llm: {
178
+ provider: "anthropic",
179
+ model: "claude-sonnet-4-20250514",
180
+ api_key: process.env.ANTHROPIC_API_KEY,
181
+ },
182
+ browser: { headless: true },
183
+ },
184
+ });
185
+
186
+ // Run inline steps
187
+ const result = await slapify.run(
188
+ [
189
+ "Go to https://example.com",
190
+ 'Click on "More information"',
191
+ 'Verify URL contains "iana.org"',
192
+ ],
193
+ "example-test"
194
+ );
195
+
196
+ console.log(result.status); // 'passed' or 'failed'
197
+ console.log(result.passedSteps); // Number of passed steps
198
+ console.log(result.duration); // Total time in ms
199
+ ```
200
+
201
+ ### Run from File
202
+
203
+ ```typescript
204
+ const result = await slapify.runFile("./tests/checkout.flow");
205
+ ```
206
+
207
+ ### Run Multiple Tests
208
+
209
+ ```typescript
210
+ // Sequential
211
+ const results = await slapify.runMultiple([
212
+ "tests/login.flow",
213
+ "tests/checkout.flow",
214
+ ]);
215
+
216
+ // Parallel with 4 workers
217
+ const results = await slapify.runMultiple(["tests/"], {
218
+ parallel: true,
219
+ workers: 4,
220
+ });
221
+
222
+ // Run all tests in a directory
223
+ const results = await slapify.runAll("tests/", { parallel: true });
224
+ ```
225
+
226
+ ### With Progress Callbacks
227
+
228
+ ```typescript
229
+ const result = await slapify.run(steps, "my-test", {
230
+ onTestStart: (name, totalSteps) => {
231
+ console.log(`Starting ${name} with ${totalSteps} steps`);
232
+ },
233
+ onStep: (stepResult, testName) => {
234
+ const icon = stepResult.status === "passed" ? "✓" : "✗";
235
+ console.log(` ${icon} ${stepResult.step.text}`);
236
+ },
237
+ onTestComplete: (result) => {
238
+ console.log(`Finished: ${result.status}`);
239
+ },
240
+ });
241
+ ```
242
+
243
+ ### Generate Reports
244
+
245
+ ```typescript
246
+ // Single test report
247
+ const reportPath = slapify.saveReport(result);
248
+
249
+ // Suite report for multiple tests
250
+ const suiteReportPath = slapify.saveSuiteReport(results);
251
+
252
+ // Get report HTML as string
253
+ const html = slapify.generateReport(result);
254
+ ```
255
+
256
+ ### Jest Integration
257
+
258
+ ```typescript
259
+ import { Slapify } from "slapify";
260
+
261
+ describe("E2E Tests", () => {
262
+ const slapify = new Slapify({ configDir: ".slapify" });
263
+
264
+ test("user can login", async () => {
265
+ const result = await slapify.run(
266
+ [
267
+ "Go to https://myapp.com/login",
268
+ "Fill email with test@example.com",
269
+ "Fill password with secret123",
270
+ "Click Login button",
271
+ 'Verify "Dashboard" appears',
272
+ ],
273
+ "login-test"
274
+ );
275
+
276
+ expect(result.status).toBe("passed");
277
+ }, 60000);
278
+
279
+ test("checkout flow works", async () => {
280
+ const result = await slapify.runFile("tests/checkout.flow");
281
+ expect(result.failedSteps).toBe(0);
282
+ }, 120000);
283
+ });
284
+ ```
285
+
286
+ ### Vitest Integration
287
+
288
+ ```typescript
289
+ import { describe, test, expect } from "vitest";
290
+ import { Slapify } from "slapify";
291
+
292
+ describe("E2E Tests", () => {
293
+ const slapify = new Slapify({ configDir: ".slapify" });
294
+
295
+ test(
296
+ "user can search",
297
+ async () => {
298
+ const result = await slapify.run([
299
+ "Go to https://google.com",
300
+ "Fill search box with slapify",
301
+ "Press Enter",
302
+ "Verify results appear",
303
+ ]);
304
+
305
+ expect(result.status).toBe("passed");
306
+ },
307
+ { timeout: 60000 }
308
+ );
309
+ });
310
+ ```
311
+
312
+ ## How It Works
313
+
314
+ 1. **Parse**: Flow files are parsed into structured steps
315
+ 2. **Interpret**: AI interprets each step and determines browser actions
316
+ 3. **Execute**: Browser automation executes the actions
317
+ 4. **Report**: Results are collected and formatted
318
+
319
+ ### Auto-Handling
320
+
321
+ Slapify automatically handles common interruptions:
322
+
323
+ - Cookie consent banners
324
+ - Newsletter popups
325
+ - Notification prompts
326
+ - Chat widgets
327
+ - CAPTCHAs (basic)
328
+
329
+ All auto-handled items are noted in the report.
330
+
331
+ ### Auto-Retry
332
+
333
+ Failed steps are automatically retried once before marking as failed. This helps with:
334
+
335
+ - Flaky network requests
336
+ - Animation timing issues
337
+ - Element loading delays
338
+
339
+ ### Auto-Fix
340
+
341
+ Use `slapify fix` to automatically analyze and fix failing tests:
342
+
343
+ ```bash
344
+ slapify fix tests/broken.flow
345
+ ```
346
+
347
+ ## Reports
348
+
349
+ Beautiful HTML reports with:
350
+
351
+ - Expandable step details
352
+ - Embedded screenshots
353
+ - Duration metrics
354
+ - Pass/fail summary
355
+ - Assumptions highlighted
356
+ - Auto-handled items noted
357
+
358
+ ## LLM Providers
359
+
360
+ Supports 6 AI providers via Vercel AI SDK. **Cheap models are recommended by default.**
361
+
362
+ ### Recommended (Budget-Friendly)
363
+
364
+ ```yaml
365
+ # Anthropic - Claude Haiku 4.5 (fast & cheap, $1/5M tokens)
366
+ llm:
367
+ provider: anthropic
368
+ model: claude-haiku-4-5-20251001
369
+ api_key: ${ANTHROPIC_API_KEY}
370
+
371
+ # OpenAI - GPT-4o Mini (fast & cheap, $0.15/0.6M tokens)
372
+ llm:
373
+ provider: openai
374
+ model: gpt-4o-mini
375
+ api_key: ${OPENAI_API_KEY}
376
+
377
+ # Google - Gemini 2.0 Flash (fastest & cheapest)
378
+ llm:
379
+ provider: google
380
+ model: gemini-2.0-flash
381
+ api_key: ${GOOGLE_API_KEY}
382
+
383
+ # Groq - Free tier available!
384
+ llm:
385
+ provider: groq
386
+ model: llama-3.3-70b-versatile
387
+ api_key: ${GROQ_API_KEY}
388
+ ```
389
+
390
+ ### More Capable (Higher Cost)
391
+
392
+ ```yaml
393
+ # Anthropic - Claude Sonnet 4 ($3/15M tokens)
394
+ llm:
395
+ provider: anthropic
396
+ model: claude-sonnet-4-20250514
397
+
398
+ # OpenAI - GPT-4o ($2.5/10M tokens)
399
+ llm:
400
+ provider: openai
401
+ model: gpt-4o
402
+ ```
403
+
404
+ ### Local (No API Key)
405
+
406
+ ```yaml
407
+ # Ollama - runs locally, free
408
+ llm:
409
+ provider: ollama
410
+ model: llama3 # or mistral, codellama, phi3
411
+ base_url: http://localhost:11434/v1
412
+ ```
413
+
414
+ ### Other Providers
415
+
416
+ ```yaml
417
+ # Mistral
418
+ llm:
419
+ provider: mistral
420
+ model: mistral-small-latest # or mistral-large-latest
421
+ api_key: ${MISTRAL_API_KEY}
422
+ ```
423
+
424
+ ## Project Structure
425
+
426
+ ```
427
+ your-project/
428
+ ├── .slapify/
429
+ │ ├── config.yaml
430
+ │ ├── credentials.yaml
431
+ │ └── .gitignore
432
+ ├── tests/
433
+ │ ├── auth/
434
+ │ │ ├── login.flow
435
+ │ │ └── signup.flow
436
+ │ ├── checkout/
437
+ │ │ └── purchase.flow
438
+ │ └── smoke.flow
439
+ └── test-reports/
440
+ └── login-1234567890/
441
+ ├── report.html
442
+ └── screenshots...
443
+ ```
444
+
445
+ ## Requirements
446
+
447
+ - Node.js 18+
448
+ - `agent-browser` (installed automatically)
449
+
450
+ ## License
451
+
452
+ MIT — Made with 🖐️ by [slaps.dev](https://slaps.dev)
package/bin/slapify.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "../dist/cli.js";
@@ -0,0 +1,54 @@
1
+ import { LLMConfig, FlowStep, BrowserState, CredentialProfile } from "../types.js";
2
+ /**
3
+ * AI interpreter for converting natural language steps to browser actions
4
+ */
5
+ export declare class AIInterpreter {
6
+ private config;
7
+ constructor(config: LLMConfig);
8
+ /**
9
+ * Interpret a step and generate browser commands
10
+ */
11
+ interpretStep(step: FlowStep, browserState: BrowserState, credentials?: Record<string, CredentialProfile>): Promise<InterpretedStep>;
12
+ /**
13
+ * Check for auto-handle opportunities (popups, banners, etc.)
14
+ */
15
+ checkAutoHandle(browserState: BrowserState): Promise<AutoHandleAction[]>;
16
+ /**
17
+ * Analyze page to find login form for credentials injection
18
+ */
19
+ findLoginForm(browserState: BrowserState): Promise<LoginFormInfo | null>;
20
+ /**
21
+ * Verify an assertion/condition on the page
22
+ */
23
+ verifyCondition(condition: string, browserState: BrowserState): Promise<VerificationResult>;
24
+ }
25
+ export interface InterpretedStep {
26
+ actions: BrowserCommand[];
27
+ assumptions: string[];
28
+ needsCredentials: boolean;
29
+ credentialProfile: string | null;
30
+ skipReason: string | null;
31
+ verified?: boolean;
32
+ }
33
+ export interface BrowserCommand {
34
+ command: string;
35
+ args: string[];
36
+ description: string;
37
+ }
38
+ export interface AutoHandleAction {
39
+ type: string;
40
+ ref: string;
41
+ action: string;
42
+ description: string;
43
+ }
44
+ export interface LoginFormInfo {
45
+ usernameRef: string;
46
+ passwordRef: string;
47
+ submitRef: string;
48
+ }
49
+ export interface VerificationResult {
50
+ satisfied: boolean;
51
+ evidence: string;
52
+ suggestion?: string;
53
+ }
54
+ //# sourceMappingURL=interpreter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interpreter.d.ts","sourceRoot":"","sources":["../../src/ai/interpreter.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,iBAAiB,EAElB,MAAM,aAAa,CAAC;AAoDrB;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAY;gBAEd,MAAM,EAAE,SAAS;IAI7B;;OAEG;IACG,aAAa,CACjB,IAAI,EAAE,QAAQ,EACd,YAAY,EAAE,YAAY,EAC1B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAC9C,OAAO,CAAC,eAAe,CAAC;IAoG3B;;OAEG;IACG,eAAe,CACnB,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAoD9B;;OAEG;IACG,aAAa,CACjB,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IA+ChC;;OAEG;IACG,eAAe,CACnB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,kBAAkB,CAAC;CAkD/B;AAGD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}