@specwise/runner 0.1.0 → 0.2.1
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/api.d.ts +2 -0
- package/dist/api.js +6 -0
- package/dist/api.js.map +1 -1
- package/dist/cli.js +42 -18
- package/dist/cli.js.map +1 -1
- package/dist/discoverer.d.ts +6 -0
- package/dist/discoverer.js +267 -0
- package/dist/discoverer.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
package/dist/api.js
CHANGED
|
@@ -29,5 +29,11 @@ export class SpecwiseAPI {
|
|
|
29
29
|
results,
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
+
async submitPage(projectId, data) {
|
|
33
|
+
await this.request("POST", `/api/v1/discovery/projects/${projectId}/pages`, data);
|
|
34
|
+
}
|
|
35
|
+
async submitFlow(projectId, data) {
|
|
36
|
+
await this.request("POST", `/api/v1/discovery/projects/${projectId}/flows`, data);
|
|
37
|
+
}
|
|
32
38
|
}
|
|
33
39
|
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,WAAW;IAEZ;IACA;IAFV,YACU,OAAe,EACf,KAAa;QADb,YAAO,GAAP,OAAO,CAAQ;QACf,UAAK,GAAL,KAAK,CAAQ;IACpB,CAAC;IAEI,KAAK,CAAC,OAAO,CACnB,MAAc,EACd,IAAY,EACZ,IAAc;QAEd,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM;YACN,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;aACtC;YACD,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC9C,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,OAAO,MAAM,IAAI,IAAI,YAAY,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;QAC3E,CAAC;QAED,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,OAAO,CAAe,MAAM,EAAE,mCAAmC,CAAC,CAAC;IACjF,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAyB;QACpC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,qCAAqC,EAAE;YAChE,OAAO;SACR,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,WAAW;IAEZ;IACA;IAFV,YACU,OAAe,EACf,KAAa;QADb,YAAO,GAAP,OAAO,CAAQ;QACf,UAAK,GAAL,KAAK,CAAQ;IACpB,CAAC;IAEI,KAAK,CAAC,OAAO,CACnB,MAAc,EACd,IAAY,EACZ,IAAc;QAEd,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM;YACN,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;aACtC;YACD,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC9C,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,OAAO,MAAM,IAAI,IAAI,YAAY,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;QAC3E,CAAC;QAED,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,OAAO,CAAe,MAAM,EAAE,mCAAmC,CAAC,CAAC;IACjF,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAyB;QACpC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,qCAAqC,EAAE;YAChE,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB,EAAE,IAAa;QAC/C,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,8BAA8B,SAAS,QAAQ,EAAE,IAAI,CAAC,CAAC;IACpF,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB,EAAE,IAAa;QAC/C,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,8BAA8B,SAAS,QAAQ,EAAE,IAAI,CAAC,CAAC;IACpF,CAAC;CACF"}
|
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { SpecwiseAPI } from "./api.js";
|
|
3
3
|
import { executeTestRun } from "./runner.js";
|
|
4
|
+
import { runDiscovery } from "./discoverer.js";
|
|
4
5
|
import { log } from "./log.js";
|
|
5
6
|
function parseArgs(argv) {
|
|
6
7
|
let token = "";
|
|
7
8
|
let api = "";
|
|
8
9
|
let headed = false;
|
|
10
|
+
let discover = false;
|
|
11
|
+
let projectId = "";
|
|
12
|
+
let url = "";
|
|
9
13
|
for (const arg of argv.slice(2)) {
|
|
10
14
|
if (arg.startsWith("--token=")) {
|
|
11
15
|
token = arg.slice("--token=".length);
|
|
@@ -13,43 +17,68 @@ function parseArgs(argv) {
|
|
|
13
17
|
else if (arg.startsWith("--api=")) {
|
|
14
18
|
api = arg.slice("--api=".length);
|
|
15
19
|
}
|
|
20
|
+
else if (arg.startsWith("--project=")) {
|
|
21
|
+
projectId = arg.slice("--project=".length);
|
|
22
|
+
}
|
|
23
|
+
else if (arg.startsWith("--url=")) {
|
|
24
|
+
url = arg.slice("--url=".length);
|
|
25
|
+
}
|
|
16
26
|
else if (arg === "--headed") {
|
|
17
27
|
headed = true;
|
|
18
28
|
}
|
|
29
|
+
else if (arg === "--discover") {
|
|
30
|
+
discover = true;
|
|
31
|
+
}
|
|
19
32
|
else if (arg === "--help" || arg === "-h") {
|
|
20
33
|
console.log(`
|
|
21
|
-
@specwise/runner -
|
|
34
|
+
@specwise/runner - Test runner and app discovery for Specwise
|
|
22
35
|
|
|
23
36
|
Usage:
|
|
24
|
-
npx @specwise/runner --token=<token> --api=<api_url>
|
|
37
|
+
npx @specwise/runner --token=<token> --api=<api_url> Run tests
|
|
38
|
+
npx @specwise/runner --discover --token=<token> --api=<url> \\
|
|
39
|
+
--project=<id> --url=<app_url> Discover app
|
|
40
|
+
|
|
41
|
+
Modes:
|
|
42
|
+
(default) Execute test cases from a test run
|
|
43
|
+
--discover Open browser, navigate your app, capture pages & elements
|
|
25
44
|
|
|
26
45
|
Options:
|
|
27
|
-
--token=<token>
|
|
28
|
-
--api=<url>
|
|
29
|
-
--
|
|
30
|
-
--
|
|
46
|
+
--token=<token> Auth token (agent token for tests, access token for discovery)
|
|
47
|
+
--api=<url> Specwise API URL (e.g. http://localhost:8000)
|
|
48
|
+
--project=<id> Project ID (required for --discover)
|
|
49
|
+
--url=<url> Start URL for discovery (e.g. https://myapp.com)
|
|
50
|
+
--headed Show browser window (default for discover, optional for tests)
|
|
51
|
+
--help Show this help
|
|
31
52
|
`);
|
|
32
53
|
process.exit(0);
|
|
33
54
|
}
|
|
34
55
|
}
|
|
35
56
|
if (!token) {
|
|
36
|
-
console.error("Error: --token is required.
|
|
57
|
+
console.error("Error: --token is required.");
|
|
37
58
|
process.exit(1);
|
|
38
59
|
}
|
|
39
60
|
if (!api) {
|
|
40
61
|
console.error("Error: --api is required. e.g. --api=http://localhost:8000");
|
|
41
62
|
process.exit(1);
|
|
42
63
|
}
|
|
43
|
-
|
|
64
|
+
if (discover && !projectId) {
|
|
65
|
+
console.error("Error: --project is required for discovery mode.");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
return { token, api: api.replace(/\/$/, ""), headed, discover, projectId, url };
|
|
44
69
|
}
|
|
45
70
|
async function main() {
|
|
46
|
-
const
|
|
71
|
+
const args = parseArgs(process.argv);
|
|
47
72
|
console.log("");
|
|
48
|
-
console.log(" \x1b[1m@specwise/runner\x1b[0m v0.
|
|
73
|
+
console.log(" \x1b[1m@specwise/runner\x1b[0m v0.2.0");
|
|
49
74
|
console.log(" ─────────────────────────");
|
|
50
75
|
console.log("");
|
|
51
|
-
const client = new SpecwiseAPI(api, token);
|
|
52
|
-
|
|
76
|
+
const client = new SpecwiseAPI(args.api, args.token);
|
|
77
|
+
if (args.discover) {
|
|
78
|
+
await runDiscovery(client, args.projectId, args.url);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// ── Test execution mode ──────────────────────────────────────────────
|
|
53
82
|
log("Pulling test cases from Specwise...");
|
|
54
83
|
let data;
|
|
55
84
|
try {
|
|
@@ -66,18 +95,15 @@ async function main() {
|
|
|
66
95
|
log("No test cases to execute.");
|
|
67
96
|
process.exit(0);
|
|
68
97
|
}
|
|
69
|
-
// Resolve test account
|
|
70
98
|
const account = data.test_accounts[0] ?? null;
|
|
71
99
|
if (account) {
|
|
72
100
|
log(`Using account: ${account.label || account.email} (${account.role})`);
|
|
73
101
|
}
|
|
74
|
-
// Execute
|
|
75
102
|
const reports = await executeTestRun(data.test_cases, {
|
|
76
103
|
targetUrl: data.target_url,
|
|
77
104
|
account,
|
|
78
105
|
authConfig: data.auth_config,
|
|
79
|
-
}, !headed);
|
|
80
|
-
// Summary
|
|
106
|
+
}, !args.headed);
|
|
81
107
|
const passed = reports.filter((r) => r.status === "passed").length;
|
|
82
108
|
const failed = reports.filter((r) => r.status === "failed").length;
|
|
83
109
|
const blocked = reports.filter((r) => r.status === "blocked").length;
|
|
@@ -88,7 +114,6 @@ async function main() {
|
|
|
88
114
|
console.log(` \x1b[32m${passed} passed\x1b[0m \x1b[31m${failed} failed\x1b[0m ${blocked} blocked`);
|
|
89
115
|
console.log(` Total time: ${(totalMs / 1000).toFixed(1)}s`);
|
|
90
116
|
console.log("");
|
|
91
|
-
// Report back
|
|
92
117
|
log("Reporting results to Specwise...");
|
|
93
118
|
try {
|
|
94
119
|
await client.report(reports);
|
|
@@ -98,7 +123,6 @@ async function main() {
|
|
|
98
123
|
log(`\x1b[31mFailed to report results: ${err instanceof Error ? err.message : err}\x1b[0m`);
|
|
99
124
|
process.exit(1);
|
|
100
125
|
}
|
|
101
|
-
// Exit with error code if any failed
|
|
102
126
|
process.exit(failed > 0 ? 1 : 0);
|
|
103
127
|
}
|
|
104
128
|
main().catch((err) => {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discovery mode — opens a headed browser, lets user navigate,
|
|
3
|
+
* captures page elements and user actions in real time.
|
|
4
|
+
*/
|
|
5
|
+
import type { SpecwiseAPI } from "./api.js";
|
|
6
|
+
export declare function runDiscovery(api: SpecwiseAPI, projectId: string, startUrl: string): Promise<void>;
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discovery mode — opens a headed browser, lets user navigate,
|
|
3
|
+
* captures page elements and user actions in real time.
|
|
4
|
+
*/
|
|
5
|
+
import { chromium } from "playwright";
|
|
6
|
+
import { log } from "./log.js";
|
|
7
|
+
const EXTRACT_ELEMENTS_JS = `() => {
|
|
8
|
+
const results = [];
|
|
9
|
+
const selectors = 'a, button, input, select, textarea, [role="button"], [role="link"], [role="tab"], [onclick], [data-testid], [type="submit"]';
|
|
10
|
+
const elements = document.querySelectorAll(selectors);
|
|
11
|
+
|
|
12
|
+
for (const el of elements) {
|
|
13
|
+
if (!el.offsetParent && el.tagName !== 'INPUT' && el.tagName !== 'SELECT') continue;
|
|
14
|
+
|
|
15
|
+
const tag = el.tagName.toLowerCase();
|
|
16
|
+
const inputType = el.getAttribute('type') || '';
|
|
17
|
+
const id = el.id || '';
|
|
18
|
+
const name = el.getAttribute('name') || '';
|
|
19
|
+
const testId = el.getAttribute('data-testid') || '';
|
|
20
|
+
const ariaLabel = el.getAttribute('aria-label') || '';
|
|
21
|
+
|
|
22
|
+
let elementType = 'other';
|
|
23
|
+
if (tag === 'input') {
|
|
24
|
+
const t = inputType.toLowerCase();
|
|
25
|
+
if (t === 'checkbox') elementType = 'checkbox';
|
|
26
|
+
else if (t === 'radio') elementType = 'radio';
|
|
27
|
+
else if (t === 'file') elementType = 'file';
|
|
28
|
+
else if (t === 'submit' || t === 'button') elementType = 'button';
|
|
29
|
+
else elementType = 'input';
|
|
30
|
+
} else if (tag === 'button' || el.getAttribute('role') === 'button') {
|
|
31
|
+
elementType = 'button';
|
|
32
|
+
} else if (tag === 'a' || el.getAttribute('role') === 'link') {
|
|
33
|
+
elementType = 'link';
|
|
34
|
+
} else if (tag === 'select') {
|
|
35
|
+
elementType = 'select';
|
|
36
|
+
} else if (tag === 'textarea') {
|
|
37
|
+
elementType = 'textarea';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let css = tag;
|
|
41
|
+
if (id) css = '#' + id;
|
|
42
|
+
else if (testId) css = '[data-testid="' + testId + '"]';
|
|
43
|
+
else if (name) css = tag + '[name="' + name + '"]';
|
|
44
|
+
else if (ariaLabel) css = tag + '[aria-label="' + ariaLabel + '"]';
|
|
45
|
+
else if (inputType) css = tag + '[type="' + inputType + '"]';
|
|
46
|
+
|
|
47
|
+
let xpath = '';
|
|
48
|
+
if (id) xpath = '//*[@id="' + id + '"]';
|
|
49
|
+
else if (name) xpath = '//' + tag + '[@name="' + name + '"]';
|
|
50
|
+
else if (testId) xpath = '//*[@data-testid="' + testId + '"]';
|
|
51
|
+
|
|
52
|
+
let formGroup = '';
|
|
53
|
+
const form = el.closest('form');
|
|
54
|
+
if (form) formGroup = form.id || form.getAttribute('name') || form.getAttribute('action') || 'form';
|
|
55
|
+
|
|
56
|
+
const options = [];
|
|
57
|
+
if (tag === 'select') {
|
|
58
|
+
for (const opt of el.options) {
|
|
59
|
+
if (opt.value) options.push(opt.value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
results.push({
|
|
64
|
+
tag,
|
|
65
|
+
element_type: elementType,
|
|
66
|
+
input_type: inputType,
|
|
67
|
+
id,
|
|
68
|
+
name,
|
|
69
|
+
css_selector: css,
|
|
70
|
+
xpath,
|
|
71
|
+
text: (el.textContent || '').trim().slice(0, 80),
|
|
72
|
+
placeholder: el.getAttribute('placeholder') || '',
|
|
73
|
+
aria_label: ariaLabel,
|
|
74
|
+
data_testid: testId,
|
|
75
|
+
role: el.getAttribute('role') || '',
|
|
76
|
+
href: tag === 'a' ? (el.getAttribute('href') || '').slice(0, 200) : '',
|
|
77
|
+
options: options.slice(0, 10),
|
|
78
|
+
is_required: el.required || el.getAttribute('aria-required') === 'true',
|
|
79
|
+
form_group: formGroup,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return results.slice(0, 100);
|
|
83
|
+
}`;
|
|
84
|
+
const EXTRACT_LINKS_JS = `() => {
|
|
85
|
+
const links = new Set();
|
|
86
|
+
for (const a of document.querySelectorAll('a[href]')) {
|
|
87
|
+
const href = a.href;
|
|
88
|
+
if (href && href.startsWith('http') && !href.includes('javascript:')) {
|
|
89
|
+
links.add(href.split('#')[0].split('?')[0]);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return [...links];
|
|
93
|
+
}`;
|
|
94
|
+
export async function runDiscovery(api, projectId, startUrl) {
|
|
95
|
+
log("Starting discovery mode...");
|
|
96
|
+
log("A browser will open. Navigate your app — each page's elements will be captured.");
|
|
97
|
+
log("Press Ctrl+C when you're done.\n");
|
|
98
|
+
const browser = await chromium.launch({ headless: false });
|
|
99
|
+
const context = await browser.newContext({ viewport: { width: 1280, height: 720 } });
|
|
100
|
+
const page = await context.newPage();
|
|
101
|
+
const capturedUrls = new Set();
|
|
102
|
+
const recordedActions = [];
|
|
103
|
+
let pagesCaptured = 0;
|
|
104
|
+
// Capture elements on every navigation
|
|
105
|
+
async function capturePage(p) {
|
|
106
|
+
const url = p.url();
|
|
107
|
+
if (url === "about:blank" || capturedUrls.has(url))
|
|
108
|
+
return;
|
|
109
|
+
try {
|
|
110
|
+
// Wait for SPA to fully render — network idle + DOM has interactive elements
|
|
111
|
+
await p.waitForLoadState("networkidle", { timeout: 15000 }).catch(() => { });
|
|
112
|
+
await p.waitForTimeout(2000); // extra buffer for JS frameworks to render
|
|
113
|
+
// Wait until at least one interactive element exists (SPA content loaded)
|
|
114
|
+
await p.waitForSelector("input, button, a[href], select, textarea, [role='button']", { timeout: 10000 }).catch(() => { });
|
|
115
|
+
// Retry element extraction — some SPAs render in multiple passes
|
|
116
|
+
let elements = [];
|
|
117
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
118
|
+
elements = await p.evaluate(EXTRACT_ELEMENTS_JS);
|
|
119
|
+
if (elements.length > 0)
|
|
120
|
+
break;
|
|
121
|
+
await p.waitForTimeout(1500);
|
|
122
|
+
}
|
|
123
|
+
const links = await p.evaluate(EXTRACT_LINKS_JS);
|
|
124
|
+
const title = await p.title();
|
|
125
|
+
await api.submitPage(projectId, {
|
|
126
|
+
url,
|
|
127
|
+
title,
|
|
128
|
+
elements,
|
|
129
|
+
links,
|
|
130
|
+
});
|
|
131
|
+
capturedUrls.add(url);
|
|
132
|
+
pagesCaptured++;
|
|
133
|
+
log(` Captured: ${title || url} (${elements.length} elements)`);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
// Page might have navigated away already
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Record user actions via CDP
|
|
140
|
+
const client = await context.newCDPSession(page);
|
|
141
|
+
// Track navigations
|
|
142
|
+
page.on("framenavigated", async (frame) => {
|
|
143
|
+
if (frame === page.mainFrame()) {
|
|
144
|
+
const url = frame.url();
|
|
145
|
+
recordedActions.push({
|
|
146
|
+
action: "navigate",
|
|
147
|
+
url,
|
|
148
|
+
page_title: await page.title().catch(() => ""),
|
|
149
|
+
selector: "",
|
|
150
|
+
xpath: "",
|
|
151
|
+
text: "",
|
|
152
|
+
value: "",
|
|
153
|
+
element_tag: "",
|
|
154
|
+
element_type: "",
|
|
155
|
+
element_name: "",
|
|
156
|
+
timestamp: new Date().toISOString(),
|
|
157
|
+
});
|
|
158
|
+
await capturePage(page);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
// Inject action recorder into every page
|
|
162
|
+
await context.addInitScript(() => {
|
|
163
|
+
// Record clicks
|
|
164
|
+
document.addEventListener("click", (e) => {
|
|
165
|
+
const el = e.target?.closest("a, button, [role='button'], input[type='submit']");
|
|
166
|
+
if (!el)
|
|
167
|
+
return;
|
|
168
|
+
const data = {
|
|
169
|
+
action: "click",
|
|
170
|
+
selector: buildSel(el),
|
|
171
|
+
text: (el.textContent || "").trim().slice(0, 80),
|
|
172
|
+
element_tag: el.tagName.toLowerCase(),
|
|
173
|
+
};
|
|
174
|
+
window.__specwise_actions = window.__specwise_actions || [];
|
|
175
|
+
window.__specwise_actions.push(data);
|
|
176
|
+
}, true);
|
|
177
|
+
// Record input changes
|
|
178
|
+
document.addEventListener("change", (e) => {
|
|
179
|
+
const el = e.target;
|
|
180
|
+
if (!el || !["INPUT", "TEXTAREA", "SELECT"].includes(el.tagName))
|
|
181
|
+
return;
|
|
182
|
+
const action = el.tagName === "SELECT" ? "select" : el.type === "checkbox" || el.type === "radio" ? "check" : "fill";
|
|
183
|
+
const data = {
|
|
184
|
+
action,
|
|
185
|
+
selector: buildSel(el),
|
|
186
|
+
value: el.value,
|
|
187
|
+
element_tag: el.tagName.toLowerCase(),
|
|
188
|
+
element_type: el.type || "",
|
|
189
|
+
element_name: el.name || "",
|
|
190
|
+
};
|
|
191
|
+
window.__specwise_actions = window.__specwise_actions || [];
|
|
192
|
+
window.__specwise_actions.push(data);
|
|
193
|
+
}, true);
|
|
194
|
+
function buildSel(el) {
|
|
195
|
+
if (el.id)
|
|
196
|
+
return "#" + el.id;
|
|
197
|
+
const testId = el.getAttribute("data-testid");
|
|
198
|
+
if (testId)
|
|
199
|
+
return `[data-testid="${testId}"]`;
|
|
200
|
+
const name = el.getAttribute("name");
|
|
201
|
+
if (name)
|
|
202
|
+
return `${el.tagName.toLowerCase()}[name="${name}"]`;
|
|
203
|
+
return el.tagName.toLowerCase();
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
// Poll for recorded actions from the page
|
|
207
|
+
const actionPollInterval = setInterval(async () => {
|
|
208
|
+
try {
|
|
209
|
+
const actions = await page.evaluate(() => {
|
|
210
|
+
const acts = window.__specwise_actions || [];
|
|
211
|
+
window.__specwise_actions = [];
|
|
212
|
+
return acts;
|
|
213
|
+
});
|
|
214
|
+
for (const act of actions) {
|
|
215
|
+
recordedActions.push({
|
|
216
|
+
...act,
|
|
217
|
+
url: page.url(),
|
|
218
|
+
page_title: await page.title().catch(() => ""),
|
|
219
|
+
xpath: "",
|
|
220
|
+
timestamp: new Date().toISOString(),
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// page might be navigating
|
|
226
|
+
}
|
|
227
|
+
}, 1000);
|
|
228
|
+
// Navigate to start URL
|
|
229
|
+
if (startUrl) {
|
|
230
|
+
await page.goto(startUrl, { waitUntil: "domcontentloaded", timeout: 15000 });
|
|
231
|
+
}
|
|
232
|
+
await capturePage(page);
|
|
233
|
+
// Wait for user to close browser or Ctrl+C
|
|
234
|
+
log("\nBrowse your app now. Each page will be captured automatically.");
|
|
235
|
+
log("Close the browser window or press Ctrl+C when done.\n");
|
|
236
|
+
await new Promise((resolve) => {
|
|
237
|
+
browser.on("disconnected", () => resolve());
|
|
238
|
+
process.on("SIGINT", async () => {
|
|
239
|
+
log("\nStopping discovery...");
|
|
240
|
+
clearInterval(actionPollInterval);
|
|
241
|
+
await browser.close().catch(() => { });
|
|
242
|
+
resolve();
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
clearInterval(actionPollInterval);
|
|
246
|
+
// Submit recorded flow
|
|
247
|
+
if (recordedActions.length > 0) {
|
|
248
|
+
log(`\nSaving recorded flow (${recordedActions.length} actions)...`);
|
|
249
|
+
try {
|
|
250
|
+
await api.submitFlow(projectId, {
|
|
251
|
+
steps: recordedActions,
|
|
252
|
+
start_url: startUrl || recordedActions[0]?.url || "",
|
|
253
|
+
});
|
|
254
|
+
log("\x1b[32mFlow saved!\x1b[0m");
|
|
255
|
+
}
|
|
256
|
+
catch (err) {
|
|
257
|
+
log(`\x1b[31mFailed to save flow: ${err instanceof Error ? err.message : err}\x1b[0m`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
console.log("");
|
|
261
|
+
console.log(" ─────────────────────────");
|
|
262
|
+
console.log(` \x1b[1mDiscovery complete\x1b[0m`);
|
|
263
|
+
console.log(` \x1b[32m${pagesCaptured} pages captured\x1b[0m`);
|
|
264
|
+
console.log(` ${recordedActions.length} actions recorded`);
|
|
265
|
+
console.log("");
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=discoverer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discoverer.js","sourceRoot":"","sources":["../src/discoverer.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|