@supatest/cli 0.0.27 → 0.0.28
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 +72 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19,15 +19,15 @@ You are Supatest AI, an E2E test builder that iteratively creates, runs, and fix
|
|
|
19
19
|
</role>
|
|
20
20
|
|
|
21
21
|
<context>
|
|
22
|
-
First, check if SUPATEST.md contains test framework information.
|
|
22
|
+
First, check if .supatest/SUPATEST.md contains test framework information.
|
|
23
23
|
|
|
24
24
|
If yes: Read it and use the documented framework, patterns, and conventions.
|
|
25
25
|
|
|
26
|
-
If no: Run discovery once, then write findings to SUPATEST.md:
|
|
26
|
+
If no: Run discovery once, then write findings to .supatest/SUPATEST.md:
|
|
27
27
|
- Detect framework from package.json dependencies
|
|
28
28
|
- Find test command from package.json scripts
|
|
29
29
|
- Read 2-3 existing tests to learn patterns (structure, page objects, selectors, test data setup)
|
|
30
|
-
- Write a "Test Framework" section to SUPATEST.md with your findings
|
|
30
|
+
- Write a "Test Framework" section to .supatest/SUPATEST.md with your findings
|
|
31
31
|
|
|
32
32
|
This ensures discovery happens once and persists across sessions.
|
|
33
33
|
</context>
|
|
@@ -82,6 +82,66 @@ A test is complete when it passes 2+ times consistently with resilient selectors
|
|
|
82
82
|
}
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
+
// src/prompts/discover.ts
|
|
86
|
+
var discoverPrompt;
|
|
87
|
+
var init_discover = __esm({
|
|
88
|
+
"src/prompts/discover.ts"() {
|
|
89
|
+
"use strict";
|
|
90
|
+
discoverPrompt = `Discover and document the test framework setup for this project.
|
|
91
|
+
|
|
92
|
+
**Your task:**
|
|
93
|
+
1. Read package.json to identify the test framework (Playwright, WebDriverIO, Cypress, Cucumber, etc.)
|
|
94
|
+
2. Find the test command in package.json scripts
|
|
95
|
+
3. Locate existing tests and read 3-5 files to understand:
|
|
96
|
+
- Test file structure and naming conventions
|
|
97
|
+
- Page objects, fixtures, or helper utilities
|
|
98
|
+
- Selector strategies used (data-testid, roles, CSS, XPath)
|
|
99
|
+
- Test data setup patterns (API calls vs UI setup)
|
|
100
|
+
- Assertion patterns and custom matchers
|
|
101
|
+
- Wait strategies and timing patterns
|
|
102
|
+
4. Identify best practices and patterns used in the codebase:
|
|
103
|
+
- How are tests organized (by feature, by page, by user flow)?
|
|
104
|
+
- Are there shared utilities or custom commands?
|
|
105
|
+
- How is authentication handled in tests?
|
|
106
|
+
- Are there environment-specific configurations?
|
|
107
|
+
5. Write your findings to .supatest/SUPATEST.md in a "Test Framework" section
|
|
108
|
+
|
|
109
|
+
**Example SUPATEST.md output:**
|
|
110
|
+
|
|
111
|
+
## Test Framework
|
|
112
|
+
|
|
113
|
+
- **Framework:** WebDriverIO + Cucumber
|
|
114
|
+
- **Config:** wdio.conf.js
|
|
115
|
+
- **Test command:** \`yarn start -- --provider browser --tags @tag_name\`
|
|
116
|
+
|
|
117
|
+
### Project Structure
|
|
118
|
+
- Features: src/features/
|
|
119
|
+
- Step definitions: src/step_definitions/ui/
|
|
120
|
+
- Page objects: src/pages/common/
|
|
121
|
+
- API utilities: src/utils/endpoints/
|
|
122
|
+
|
|
123
|
+
### Conventions
|
|
124
|
+
- Selectors: data-testid preferred, fallback to aria selectors
|
|
125
|
+
- Test data: Created via API endpoints before tests run
|
|
126
|
+
- Naming: snake_case for feature files, camelCase for step definitions
|
|
127
|
+
- Tags: @smoke for critical paths, @regression for full suite
|
|
128
|
+
|
|
129
|
+
### Patterns
|
|
130
|
+
- Page Object Model with lazy element initialization
|
|
131
|
+
- API helpers for test data setup/teardown
|
|
132
|
+
- Custom wait utilities in src/utils/waits.js
|
|
133
|
+
- Shared authentication flow via login.task.js
|
|
134
|
+
|
|
135
|
+
### Best Practices
|
|
136
|
+
- Each test creates isolated test data
|
|
137
|
+
- Cleanup in afterEach hooks
|
|
138
|
+
- No hard-coded waits, use explicit element conditions
|
|
139
|
+
- Screenshots on failure via reporter config
|
|
140
|
+
|
|
141
|
+
If .supatest/SUPATEST.md already has a "Test Framework" section, report what's there and ask if the user wants to refresh it.`;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
85
145
|
// src/prompts/fixer.ts
|
|
86
146
|
var fixerPrompt;
|
|
87
147
|
var init_fixer = __esm({
|
|
@@ -228,6 +288,7 @@ var init_prompts = __esm({
|
|
|
228
288
|
"src/prompts/index.ts"() {
|
|
229
289
|
"use strict";
|
|
230
290
|
init_builder();
|
|
291
|
+
init_discover();
|
|
231
292
|
init_fixer();
|
|
232
293
|
init_planner();
|
|
233
294
|
}
|
|
@@ -5233,7 +5294,7 @@ var CLI_VERSION;
|
|
|
5233
5294
|
var init_version = __esm({
|
|
5234
5295
|
"src/version.ts"() {
|
|
5235
5296
|
"use strict";
|
|
5236
|
-
CLI_VERSION = "0.0.
|
|
5297
|
+
CLI_VERSION = "0.0.28";
|
|
5237
5298
|
}
|
|
5238
5299
|
});
|
|
5239
5300
|
|
|
@@ -10028,7 +10089,7 @@ var init_HelpMenu = __esm({
|
|
|
10028
10089
|
/* @__PURE__ */ React22.createElement(Text17, { bold: true, color: theme.text.accent }, "\u{1F4D6} Supatest AI CLI - Help"),
|
|
10029
10090
|
/* @__PURE__ */ React22.createElement(Box19, { marginTop: 1 }),
|
|
10030
10091
|
/* @__PURE__ */ React22.createElement(Text17, { bold: true, color: theme.text.secondary }, "Slash Commands:"),
|
|
10031
|
-
/* @__PURE__ */ React22.createElement(Box19, { flexDirection: "column", marginLeft: 2, marginTop: 0 }, /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/help"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " or "), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/?"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Toggle this help menu")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/resume"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Resume a previous session")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/clear"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Clear message history")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/model"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Cycle through available models")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/setup"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Initial setup for Supatest CLI")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/feedback"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Report an issue or request a feature")), isAuthenticated ? /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/logout"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Log out of Supatest")) : /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/login"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Authenticate with Supatest")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/exit"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Exit the CLI"))),
|
|
10092
|
+
/* @__PURE__ */ React22.createElement(Box19, { flexDirection: "column", marginLeft: 2, marginTop: 0 }, /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/help"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " or "), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/?"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Toggle this help menu")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/resume"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Resume a previous session")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/clear"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Clear message history")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/model"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Cycle through available models")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/setup"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Initial setup for Supatest CLI")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/discover"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Discover test framework and write to SUPATEST.md")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/feedback"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Report an issue or request a feature")), isAuthenticated ? /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/logout"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Log out of Supatest")) : /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/login"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Authenticate with Supatest")), /* @__PURE__ */ React22.createElement(Text17, null, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/exit"), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, " - Exit the CLI"))),
|
|
10032
10093
|
customCommands.length > 0 && /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(Box19, { marginTop: 1 }), /* @__PURE__ */ React22.createElement(Text17, { bold: true, color: theme.text.secondary }, "Project Commands:"), /* @__PURE__ */ React22.createElement(Box19, { flexDirection: "column", marginLeft: 2, marginTop: 0 }, customCommands.slice(0, 5).map((cmd) => /* @__PURE__ */ React22.createElement(Text17, { key: cmd.name }, /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.accent }, "/", cmd.name), /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, cmd.description ? ` - ${cmd.description}` : ""))), customCommands.length > 5 && /* @__PURE__ */ React22.createElement(Text17, { color: theme.text.dim }, "...and ", customCommands.length - 5, " more (use Tab to autocomplete)"))),
|
|
10033
10094
|
/* @__PURE__ */ React22.createElement(Box19, { marginTop: 1 }),
|
|
10034
10095
|
/* @__PURE__ */ React22.createElement(Text17, { bold: true, color: theme.text.secondary }, "Keyboard Shortcuts:"),
|
|
@@ -10227,6 +10288,7 @@ var init_InputPrompt = __esm({
|
|
|
10227
10288
|
{ name: "/fix", desc: "Fix failing tests" },
|
|
10228
10289
|
{ name: "/feedback", desc: "Report an issue" },
|
|
10229
10290
|
{ name: "/setup", desc: "Install Playwright browsers" },
|
|
10291
|
+
{ name: "/discover", desc: "Discover test framework" },
|
|
10230
10292
|
{ name: "/login", desc: "Authenticate with Supatest" },
|
|
10231
10293
|
{ name: "/logout", desc: "Log out" },
|
|
10232
10294
|
{ name: "/exit", desc: "Exit CLI" }
|
|
@@ -10681,6 +10743,7 @@ var init_App = __esm({
|
|
|
10681
10743
|
init_shared_es();
|
|
10682
10744
|
init_login();
|
|
10683
10745
|
init_setup();
|
|
10746
|
+
init_prompts();
|
|
10684
10747
|
init_command_discovery();
|
|
10685
10748
|
init_stdio();
|
|
10686
10749
|
init_token_storage();
|
|
@@ -10918,6 +10981,10 @@ var init_App = __esm({
|
|
|
10918
10981
|
}
|
|
10919
10982
|
return;
|
|
10920
10983
|
}
|
|
10984
|
+
if (command === "/discover") {
|
|
10985
|
+
onSubmitTask?.(discoverPrompt);
|
|
10986
|
+
return;
|
|
10987
|
+
}
|
|
10921
10988
|
const projectDir = config2.cwd || process.cwd();
|
|
10922
10989
|
const spaceIndex = trimmedTask.indexOf(" ");
|
|
10923
10990
|
const commandName = spaceIndex > 0 ? trimmedTask.slice(1, spaceIndex) : trimmedTask.slice(1);
|