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/dist/index.js ADDED
@@ -0,0 +1,260 @@
1
+ // Main exports for programmatic usage
2
+ export { loadConfig, loadCredentials, initConfig, getConfigDir, findSystemBrowsers, checkBrowserPath, } from "./config/loader.js";
3
+ export { parseFlowFile, parseFlowContent, findFlowFiles, validateFlowFile, getFlowSummary, } from "./parser/flow.js";
4
+ export { BrowserAgent } from "./browser/agent.js";
5
+ export { AIInterpreter } from "./ai/interpreter.js";
6
+ export { TestRunner } from "./runner/index.js";
7
+ export { ReportGenerator } from "./report/generator.js";
8
+ // Convenience class for programmatic usage
9
+ import { loadConfig, loadCredentials } from "./config/loader.js";
10
+ import { parseFlowFile, parseFlowContent, findFlowFiles, } from "./parser/flow.js";
11
+ import { TestRunner } from "./runner/index.js";
12
+ import { ReportGenerator } from "./report/generator.js";
13
+ /**
14
+ * Main Slapify class for programmatic usage
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { Slapify } from 'testpilot';
19
+ *
20
+ * // Using config file
21
+ * const pilot = new Slapify({ configDir: '.testpilot' });
22
+ *
23
+ * // Or with inline config
24
+ * const pilot = new Slapify({
25
+ * config: {
26
+ * llm: { provider: 'anthropic', model: 'claude-sonnet-4-20250514', api_key: process.env.ANTHROPIC_API_KEY },
27
+ * browser: { headless: true }
28
+ * }
29
+ * });
30
+ *
31
+ * // Run inline steps
32
+ * const result = await pilot.run([
33
+ * 'Go to https://example.com',
34
+ * 'Click on "More information" link',
35
+ * 'Verify URL contains "iana.org"'
36
+ * ]);
37
+ *
38
+ * console.log(result.status); // 'passed' or 'failed'
39
+ * ```
40
+ */
41
+ export class Slapify {
42
+ config;
43
+ credentials;
44
+ reporter;
45
+ constructor(options = {}) {
46
+ // Load config from directory or use provided
47
+ if (options.configDir) {
48
+ this.config = { ...loadConfig(options.configDir), ...options.config };
49
+ this.credentials =
50
+ options.credentials || loadCredentials(options.configDir);
51
+ }
52
+ else if (options.config?.llm) {
53
+ this.config = {
54
+ llm: options.config.llm,
55
+ browser: options.config.browser || { headless: true, timeout: 30000 },
56
+ report: options.config.report || {
57
+ format: "html",
58
+ screenshots: true,
59
+ },
60
+ };
61
+ this.credentials = options.credentials || { profiles: {} };
62
+ }
63
+ else {
64
+ // Try to load from cwd
65
+ this.config = loadConfig();
66
+ this.credentials = loadCredentials();
67
+ }
68
+ this.reporter = new ReportGenerator(this.config.report);
69
+ }
70
+ /**
71
+ * Create a new runner instance (each test needs its own runner for parallel execution)
72
+ */
73
+ createRunner() {
74
+ return new TestRunner(this.config, this.credentials);
75
+ }
76
+ /**
77
+ * Run a flow file
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const result = await pilot.runFile('tests/login.flow');
82
+ * ```
83
+ */
84
+ async runFile(filePath, options = {}) {
85
+ const flow = parseFlowFile(filePath);
86
+ return this.runFlow(flow, options);
87
+ }
88
+ /**
89
+ * Run steps from an array of strings
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * const result = await pilot.run([
94
+ * 'Go to https://google.com',
95
+ * 'Fill search box with "testpilot"',
96
+ * 'Press Enter',
97
+ * 'Verify results contain "testpilot"'
98
+ * ], 'google-search');
99
+ * ```
100
+ */
101
+ async run(steps, name = "inline", options = {}) {
102
+ const content = steps.join("\n");
103
+ const flow = parseFlowContent(content, name);
104
+ return this.runFlow(flow, options);
105
+ }
106
+ /**
107
+ * Run a flow from string content
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * const flowContent = `
112
+ * Go to https://example.com
113
+ * Click on "More information"
114
+ * Verify page loads
115
+ * `;
116
+ * const result = await pilot.runContent(flowContent, 'example-test');
117
+ * ```
118
+ */
119
+ async runContent(content, name = "inline", options = {}) {
120
+ const flow = parseFlowContent(content, name);
121
+ return this.runFlow(flow, options);
122
+ }
123
+ /**
124
+ * Run a parsed flow
125
+ */
126
+ async runFlow(flow, options = {}) {
127
+ const runner = this.createRunner();
128
+ if (options.onTestStart) {
129
+ options.onTestStart(flow.name, flow.steps.length);
130
+ }
131
+ const result = await runner.runFlow(flow, (stepResult) => {
132
+ if (options.onStep) {
133
+ options.onStep(stepResult, flow.name);
134
+ }
135
+ });
136
+ if (options.onTestComplete) {
137
+ options.onTestComplete(result);
138
+ }
139
+ return result;
140
+ }
141
+ /**
142
+ * Run multiple flow files
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * // Sequential
147
+ * const results = await pilot.runMultiple(['tests/login.flow', 'tests/checkout.flow']);
148
+ *
149
+ * // Parallel with 4 workers
150
+ * const results = await pilot.runMultiple(['tests/*.flow'], { parallel: true, workers: 4 });
151
+ * ```
152
+ */
153
+ async runMultiple(patterns, options = {}) {
154
+ // Expand patterns to file paths
155
+ const files = [];
156
+ for (const pattern of patterns) {
157
+ if (pattern.includes("*")) {
158
+ // It's a glob pattern - find matching files
159
+ const found = await findFlowFiles(pattern.replace(/\/\*.*$/, ""));
160
+ files.push(...found);
161
+ }
162
+ else {
163
+ const fs = await import("fs");
164
+ if (fs.statSync(pattern).isDirectory()) {
165
+ const found = await findFlowFiles(pattern);
166
+ files.push(...found);
167
+ }
168
+ else {
169
+ files.push(pattern);
170
+ }
171
+ }
172
+ }
173
+ if (files.length === 0) {
174
+ return [];
175
+ }
176
+ const results = [];
177
+ if (options.parallel && files.length > 1) {
178
+ // Parallel execution
179
+ const workers = options.workers || 4;
180
+ const pending = [...files];
181
+ const running = new Map();
182
+ while (pending.length > 0 || running.size > 0) {
183
+ // Start new tasks up to worker limit
184
+ while (pending.length > 0 && running.size < workers) {
185
+ const file = pending.shift();
186
+ const promise = this.runFile(file, options)
187
+ .then((result) => {
188
+ results.push(result);
189
+ running.delete(file);
190
+ })
191
+ .catch(() => {
192
+ running.delete(file);
193
+ });
194
+ running.set(file, promise);
195
+ }
196
+ // Wait for at least one to complete
197
+ if (running.size > 0) {
198
+ await Promise.race(running.values());
199
+ }
200
+ }
201
+ }
202
+ else {
203
+ // Sequential execution
204
+ for (const file of files) {
205
+ const result = await this.runFile(file, options);
206
+ results.push(result);
207
+ }
208
+ }
209
+ return results;
210
+ }
211
+ /**
212
+ * Run all flow files in a directory
213
+ *
214
+ * @example
215
+ * ```typescript
216
+ * const results = await pilot.runAll('tests/', { parallel: true });
217
+ * ```
218
+ */
219
+ async runAll(directory = "tests", options = {}) {
220
+ return this.runMultiple([directory], options);
221
+ }
222
+ /**
223
+ * Generate a report from results
224
+ */
225
+ generateReport(result) {
226
+ return this.reporter.generate(result);
227
+ }
228
+ /**
229
+ * Generate a suite report from multiple results
230
+ */
231
+ generateSuiteReport(results) {
232
+ return this.reporter.generateSuiteReport(results);
233
+ }
234
+ /**
235
+ * Save a report to file/folder
236
+ */
237
+ saveReport(result, filename) {
238
+ return this.reporter.saveAsFolder(result);
239
+ }
240
+ /**
241
+ * Save a suite report to folder
242
+ */
243
+ saveSuiteReport(results) {
244
+ return this.reporter.saveSuiteAsFolder(results);
245
+ }
246
+ /**
247
+ * Print summary to console
248
+ */
249
+ printSummary(result) {
250
+ this.reporter.printSummary(result);
251
+ }
252
+ /**
253
+ * Get the current configuration
254
+ */
255
+ getConfig() {
256
+ return this.config;
257
+ }
258
+ }
259
+ export default Slapify;
260
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { FlowFile } from "../types.js";
2
+ /**
3
+ * Parse a .flow file into a FlowFile object
4
+ */
5
+ export declare function parseFlowFile(filePath: string): FlowFile;
6
+ /**
7
+ * Parse flow content from a string (for inline tests)
8
+ */
9
+ export declare function parseFlowContent(content: string, name?: string): FlowFile;
10
+ /**
11
+ * Find all .flow files in a directory
12
+ */
13
+ export declare function findFlowFiles(dir: string): Promise<string[]>;
14
+ /**
15
+ * Validate a flow file for common issues
16
+ */
17
+ export declare function validateFlowFile(flow: FlowFile): string[];
18
+ /**
19
+ * Get a summary of a flow file
20
+ */
21
+ export declare function getFlowSummary(flow: FlowFile): {
22
+ totalSteps: number;
23
+ requiredSteps: number;
24
+ optionalSteps: number;
25
+ conditionalSteps: number;
26
+ };
27
+ //# sourceMappingURL=flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/parser/flow.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAY,MAAM,aAAa,CAAC;AA0CjD;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAuBxD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAiB,GACtB,QAAQ,CAiBV;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGlE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAmBzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAOA"}
@@ -0,0 +1,117 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { glob } from "glob";
4
+ /**
5
+ * Parse a single line into a FlowStep
6
+ */
7
+ function parseLine(line, lineNumber) {
8
+ const trimmed = line.trim();
9
+ // Skip empty lines and comments
10
+ if (!trimmed || trimmed.startsWith("#")) {
11
+ return null;
12
+ }
13
+ // Check for [Optional] prefix
14
+ const optionalMatch = trimmed.match(/^\[Optional\]\s*(.+)$/i);
15
+ const isOptional = !!optionalMatch;
16
+ const stepText = optionalMatch ? optionalMatch[1] : trimmed;
17
+ // Check for conditional (If ... appears, ...)
18
+ const conditionalMatch = stepText.match(/^If\s+(.+?)\s*,\s*(.+)$/i);
19
+ const isConditional = !!conditionalMatch;
20
+ return {
21
+ line: lineNumber,
22
+ text: stepText,
23
+ optional: isOptional,
24
+ conditional: isConditional,
25
+ condition: conditionalMatch ? conditionalMatch[1] : undefined,
26
+ action: conditionalMatch ? conditionalMatch[2] : undefined,
27
+ };
28
+ }
29
+ /**
30
+ * Extract comments from a flow file
31
+ */
32
+ function extractComments(content) {
33
+ return content
34
+ .split("\n")
35
+ .filter((line) => line.trim().startsWith("#"))
36
+ .map((line) => line.trim().substring(1).trim());
37
+ }
38
+ /**
39
+ * Parse a .flow file into a FlowFile object
40
+ */
41
+ export function parseFlowFile(filePath) {
42
+ if (!fs.existsSync(filePath)) {
43
+ throw new Error(`Flow file not found: ${filePath}`);
44
+ }
45
+ const content = fs.readFileSync(filePath, "utf-8");
46
+ const lines = content.split("\n");
47
+ const steps = [];
48
+ for (let i = 0; i < lines.length; i++) {
49
+ const step = parseLine(lines[i], i + 1);
50
+ if (step) {
51
+ steps.push(step);
52
+ }
53
+ }
54
+ return {
55
+ path: filePath,
56
+ name: path.basename(filePath, ".flow"),
57
+ steps,
58
+ comments: extractComments(content),
59
+ };
60
+ }
61
+ /**
62
+ * Parse flow content from a string (for inline tests)
63
+ */
64
+ export function parseFlowContent(content, name = "inline") {
65
+ const lines = content.split("\n");
66
+ const steps = [];
67
+ for (let i = 0; i < lines.length; i++) {
68
+ const step = parseLine(lines[i], i + 1);
69
+ if (step) {
70
+ steps.push(step);
71
+ }
72
+ }
73
+ return {
74
+ path: "",
75
+ name,
76
+ steps,
77
+ comments: extractComments(content),
78
+ };
79
+ }
80
+ /**
81
+ * Find all .flow files in a directory
82
+ */
83
+ export async function findFlowFiles(dir) {
84
+ const pattern = path.join(dir, "**/*.flow");
85
+ return glob(pattern, { nodir: true });
86
+ }
87
+ /**
88
+ * Validate a flow file for common issues
89
+ */
90
+ export function validateFlowFile(flow) {
91
+ const warnings = [];
92
+ if (flow.steps.length === 0) {
93
+ warnings.push("Flow file has no steps");
94
+ }
95
+ // Check for steps that might be incomplete
96
+ for (const step of flow.steps) {
97
+ if (step.text.length < 3) {
98
+ warnings.push(`Line ${step.line}: Step seems too short: "${step.text}"`);
99
+ }
100
+ if (step.conditional && !step.action) {
101
+ warnings.push(`Line ${step.line}: Conditional step missing action`);
102
+ }
103
+ }
104
+ return warnings;
105
+ }
106
+ /**
107
+ * Get a summary of a flow file
108
+ */
109
+ export function getFlowSummary(flow) {
110
+ return {
111
+ totalSteps: flow.steps.length,
112
+ requiredSteps: flow.steps.filter((s) => !s.optional).length,
113
+ optionalSteps: flow.steps.filter((s) => s.optional).length,
114
+ conditionalSteps: flow.steps.filter((s) => s.conditional).length,
115
+ };
116
+ }
117
+ //# sourceMappingURL=flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/parser/flow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import { TestResult, ReportConfig } from "../types.js";
2
+ /**
3
+ * Generate test reports in various formats
4
+ */
5
+ export declare class ReportGenerator {
6
+ private config;
7
+ constructor(config?: ReportConfig);
8
+ /**
9
+ * Generate a report from test results
10
+ */
11
+ generate(result: TestResult): string;
12
+ /**
13
+ * Generate a suite report from multiple test results
14
+ */
15
+ generateSuiteReport(results: TestResult[]): string;
16
+ /**
17
+ * Save report to file
18
+ */
19
+ save(result: TestResult, filename?: string): string;
20
+ /**
21
+ * Save report as a folder with embedded images
22
+ */
23
+ saveAsFolder(result: TestResult): string;
24
+ /**
25
+ * Save suite report as a folder
26
+ */
27
+ saveSuiteAsFolder(results: TestResult[]): string;
28
+ /**
29
+ * Generate Markdown report
30
+ */
31
+ private generateMarkdown;
32
+ /**
33
+ * Generate HTML report with Tailwind CSS
34
+ */
35
+ private generateHTML;
36
+ /**
37
+ * Format a single step for HTML with Tailwind
38
+ */
39
+ private formatStepHTML;
40
+ /**
41
+ * Generate suite report HTML with Tailwind
42
+ */
43
+ private generateSuiteHTML;
44
+ /**
45
+ * Format a test item for suite report with Tailwind
46
+ */
47
+ private formatTestItemHTML;
48
+ /**
49
+ * Format duration in human-readable form
50
+ */
51
+ private formatDuration;
52
+ /**
53
+ * Get icon for action type
54
+ */
55
+ private getActionIcon;
56
+ /**
57
+ * Print summary to console
58
+ */
59
+ printSummary(result: TestResult): void;
60
+ }
61
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAc,YAAY,EAAE,MAAM,aAAa,CAAC;AAEnE;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,GAAE,YAAiB;IASrC;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM;IAapC;;OAEG;IACH,mBAAmB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM;IAIlD;;OAEG;IACH,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;IA0BnD;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM;IAgDxC;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM;IA6ChD;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAmExB;;OAEG;IACH,OAAO,CAAC,YAAY;IAyHpB;;OAEG;IACH,OAAO,CAAC,cAAc;IAiGtB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAsFzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkE1B;;OAEG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;IACH,OAAO,CAAC,aAAa;IAmBrB;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;CAgBvC"}