@supatest/cli 0.0.62 → 0.0.63
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 +25 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5888,7 +5888,7 @@ var CLI_VERSION;
|
|
|
5888
5888
|
var init_version = __esm({
|
|
5889
5889
|
"src/version.ts"() {
|
|
5890
5890
|
"use strict";
|
|
5891
|
-
CLI_VERSION = "0.0.
|
|
5891
|
+
CLI_VERSION = "0.0.63";
|
|
5892
5892
|
}
|
|
5893
5893
|
});
|
|
5894
5894
|
|
|
@@ -9764,16 +9764,17 @@ var init_base = __esm({
|
|
|
9764
9764
|
contextBlock = `<context>
|
|
9765
9765
|
**Before writing any test**, check .supatest/SUPATEST.md for test framework info.
|
|
9766
9766
|
|
|
9767
|
-
**Context-First Principle**:
|
|
9768
|
-
1. Read .supatest/SUPATEST.md
|
|
9769
|
-
2. Read page
|
|
9770
|
-
3.
|
|
9771
|
-
4.
|
|
9767
|
+
**Context-First Principle**: Follow this priority order \u2014 stop as soon as you have enough to write the test:
|
|
9768
|
+
1. Read .supatest/SUPATEST.md \u2014 it may point to page objects or source directories
|
|
9769
|
+
2. Read existing page objects and test spec files \u2014 if these give you enough selectors and flow, write the test
|
|
9770
|
+
3. If you still need context and SUPATEST.md references a source directory, read targeted source files \u2014 but stop as soon as you have actionable selectors or flow details. If each file you read leads to another without yielding anything concrete, you are going in circles \u2014 switch to step 4 instead of continuing
|
|
9771
|
+
4. If source files aren't available, aren't referenced, or reading them isn't yielding progress, use Agent Browser to explore the app \u2014 or ask the user to describe the functionality
|
|
9772
9772
|
|
|
9773
9773
|
If .supatest/SUPATEST.md does NOT exist, you MUST run discovery before doing anything else:
|
|
9774
9774
|
1. Read package.json to detect the framework (Playwright, WebDriverIO, Cypress, etc.)
|
|
9775
|
-
2.
|
|
9776
|
-
3.
|
|
9775
|
+
2. Find and read 2-3 existing test spec files (e.g., \`*.spec.ts\`, \`*.test.ts\`) to learn patterns
|
|
9776
|
+
3. Find and read 1-2 page object files (e.g., \`*.page.ts\`) to learn selector patterns
|
|
9777
|
+
4. Write findings to .supatest/SUPATEST.md including:
|
|
9777
9778
|
- Framework and test command
|
|
9778
9779
|
- File patterns and naming conventions
|
|
9779
9780
|
- **Selector strategy** \u2014 Document exactly what selectors the project uses (e.g., \`[data-test]\` attributes, \`getByRole\`, CSS classes). Your new tests MUST use the same selector strategy as existing tests.
|
|
@@ -9783,7 +9784,7 @@ NEVER edit existing test files or write new tests until discovery is complete an
|
|
|
9783
9784
|
</context>
|
|
9784
9785
|
|
|
9785
9786
|
<bias_to_action>
|
|
9786
|
-
Act on the user's request immediately. Extract the URL and intent from their message and start \u2014 don't ask clarifying questions unless you genuinely cannot determine what to test or where the app is. If the framework isn't detected, check package.json and node_modules yourself.
|
|
9787
|
+
Act on the user's request immediately. Extract the URL and intent from their message and start \u2014 don't ask clarifying questions unless you genuinely cannot determine what to test or where the app is. If the framework isn't detected, check package.json and node_modules yourself. Follow the Context-First priority order, then use Agent Browser if needed. Investigate before asking.
|
|
9787
9788
|
</bias_to_action>
|
|
9788
9789
|
|
|
9789
9790
|
<calibrated_confidence>
|
|
@@ -10050,7 +10051,7 @@ You are Supatest AI, an E2E testing assistant. You explore applications, create
|
|
|
10050
10051
|
**Explore** \u2014 The user wants to understand the app before writing tests. Use Agent Browser to navigate and describe what you see. Don't write test scripts during exploration. Summarize findings and offer to write tests afterward.
|
|
10051
10052
|
|
|
10052
10053
|
**Build** \u2014 The user wants test scripts created:
|
|
10053
|
-
1. **Read
|
|
10054
|
+
1. **Read in priority order**: Check SUPATEST.md \u2192 read page objects and existing test specs \u2192 if still insufficient and SUPATEST.md references a source directory, read relevant source files \u2192 if source files aren't available, use Agent Browser to explore or ask the user to describe the functionality. Stop reading as soon as you have enough to write the test.
|
|
10054
10055
|
2. Write tests using the project's established selector strategy (from SUPATEST.md). If no strategy exists, prefer semantic locators. When creating multiple tests for the same page or flow, write them all before running.
|
|
10055
10056
|
3. Run tests in headless mode. **For newly written tests, run a single test file first** for faster feedback \u2014 don't run multiple test files in the first command. If a process hangs, kill it and check for interactive flags.
|
|
10056
10057
|
4. Fix failures using the fix loop below. Max 5 attempts per test. **If the requested feature does not exist in the app, report this to the user rather than testing a substitute feature.**
|
|
@@ -13650,7 +13651,7 @@ function KeypressProvider({
|
|
|
13650
13651
|
config: config2,
|
|
13651
13652
|
debugKeystrokeLogging
|
|
13652
13653
|
}) {
|
|
13653
|
-
const { stdin, setRawMode } = useStdin2();
|
|
13654
|
+
const { stdin, setRawMode, internal_eventEmitter } = useStdin2();
|
|
13654
13655
|
const subscribers = useRef5(/* @__PURE__ */ new Set()).current;
|
|
13655
13656
|
const subscribe = useCallback3(
|
|
13656
13657
|
(handler) => subscribers.add(handler),
|
|
@@ -13665,8 +13666,8 @@ function KeypressProvider({
|
|
|
13665
13666
|
[subscribers]
|
|
13666
13667
|
);
|
|
13667
13668
|
useEffect4(() => {
|
|
13668
|
-
const
|
|
13669
|
-
if (
|
|
13669
|
+
const isRawModeSupported = stdin.isTTY;
|
|
13670
|
+
if (isRawModeSupported) {
|
|
13670
13671
|
setRawMode(true);
|
|
13671
13672
|
}
|
|
13672
13673
|
process.stdin.setEncoding("utf8");
|
|
@@ -13674,15 +13675,15 @@ function KeypressProvider({
|
|
|
13674
13675
|
const backslashBufferer = bufferBackslashEnter(mouseFilterer);
|
|
13675
13676
|
const pasteBufferer = bufferPaste(backslashBufferer);
|
|
13676
13677
|
const oscBufferer = bufferOSC(pasteBufferer);
|
|
13677
|
-
|
|
13678
|
-
|
|
13678
|
+
const dataListener = createDataListener(oscBufferer);
|
|
13679
|
+
internal_eventEmitter.on("input", dataListener);
|
|
13679
13680
|
return () => {
|
|
13680
|
-
|
|
13681
|
-
if (
|
|
13681
|
+
internal_eventEmitter.removeListener("input", dataListener);
|
|
13682
|
+
if (isRawModeSupported) {
|
|
13682
13683
|
setRawMode(false);
|
|
13683
13684
|
}
|
|
13684
13685
|
};
|
|
13685
|
-
}, [stdin, setRawMode, config2, debugKeystrokeLogging, broadcast]);
|
|
13686
|
+
}, [stdin, setRawMode, internal_eventEmitter, config2, debugKeystrokeLogging, broadcast]);
|
|
13686
13687
|
return /* @__PURE__ */ React17.createElement(KeypressContext.Provider, { value: { subscribe, unsubscribe } }, children);
|
|
13687
13688
|
}
|
|
13688
13689
|
var BACKSLASH_ENTER_TIMEOUT, ESC_TIMEOUT, PASTE_TIMEOUT, KEY_INFO_MAP, kUTF16SurrogateThreshold, MAC_ALT_KEY_CHARACTER_MAP, OSC_TIMEOUT, KeypressContext;
|
|
@@ -20407,7 +20408,7 @@ program.name("supatest").description(
|
|
|
20407
20408
|
).option(
|
|
20408
20409
|
"--claude-max-iterations <number>",
|
|
20409
20410
|
"[Deprecated] Alias for --max-iterations"
|
|
20410
|
-
).option("--supatest-api-key <key>", "Supatest API key (or use SUPATEST_API_KEY env)").option("--supatest-api-url <url>", "Supatest API URL (or use SUPATEST_API_URL env, defaults to https://code-api.supatest.ai)").option("--theme <mode>", "Color theme: auto (default), dark, or light", "auto").option("--headless", "Run in headless mode (for CI/CD, minimal output)").option("--mode <mode>", "Agent mode for headless: fix (default), build, plan, test-feature, or report").option("--verbose", "Enable verbose logging").option("--model <model>", "Model to use (or use ANTHROPIC_MODEL_NAME env). Use 'small', 'medium', or 'premium' for tier-based selection").action(async (task, options) => {
|
|
20411
|
+
).option("--supatest-api-key <key>", "Supatest API key (or use SUPATEST_API_KEY env)").option("--supatest-api-url <url>", "Supatest API URL (or use SUPATEST_API_URL env, defaults to https://code-api.supatest.ai)").option("--theme <mode>", "Color theme: auto (default), dark, or light", "auto").option("--headless", "Run in headless mode (for CI/CD, minimal output)").option("--mode <mode>", "Agent mode for headless: fix (default), build, plan, test-feature, or report").option("--project-id <id>", "Project ID to scope queries (or use SUPATEST_PROJECT_ID env)").option("--verbose", "Enable verbose logging").option("--model <model>", "Model to use (or use ANTHROPIC_MODEL_NAME env). Use 'small', 'medium', or 'premium' for tier-based selection").action(async (task, options) => {
|
|
20411
20412
|
try {
|
|
20412
20413
|
checkNodeVersion2();
|
|
20413
20414
|
if (options.theme && options.theme !== "auto") {
|
|
@@ -20479,6 +20480,7 @@ program.name("supatest").description(
|
|
|
20479
20480
|
);
|
|
20480
20481
|
}
|
|
20481
20482
|
}
|
|
20483
|
+
const projectId = options.projectId || process.env.SUPATEST_PROJECT_ID;
|
|
20482
20484
|
let selectedModel;
|
|
20483
20485
|
const modelOption = options.model || "medium";
|
|
20484
20486
|
if (modelOption && isValidModelId(modelOption)) {
|
|
@@ -20502,7 +20504,7 @@ program.name("supatest").description(
|
|
|
20502
20504
|
process.exit(1);
|
|
20503
20505
|
}
|
|
20504
20506
|
const headlessAgentMode = headlessMode;
|
|
20505
|
-
const rawMaxIterations = options.maxIterations || options.claudeMaxIterations || "
|
|
20507
|
+
const rawMaxIterations = options.maxIterations || options.claudeMaxIterations || "500";
|
|
20506
20508
|
const parsedMaxIterations = Number.parseInt(rawMaxIterations, 10);
|
|
20507
20509
|
if (Number.isNaN(parsedMaxIterations) || parsedMaxIterations < 1) {
|
|
20508
20510
|
logger.error(
|
|
@@ -20541,13 +20543,14 @@ ${prompt}`;
|
|
|
20541
20543
|
),
|
|
20542
20544
|
selectedModel,
|
|
20543
20545
|
oauthToken,
|
|
20546
|
+
projectId,
|
|
20544
20547
|
mode: headlessMode === "plan" ? "plan" : "build",
|
|
20545
20548
|
allowInteractivePrompts: false
|
|
20546
20549
|
});
|
|
20547
20550
|
process.exit(result.success ? 0 : 1);
|
|
20548
20551
|
} else {
|
|
20549
20552
|
const { runInteractive: runInteractive2 } = await init_interactive().then(() => interactive_exports);
|
|
20550
|
-
const rawMaxIterations = options.maxIterations || options.claudeMaxIterations || "
|
|
20553
|
+
const rawMaxIterations = options.maxIterations || options.claudeMaxIterations || "500";
|
|
20551
20554
|
const parsedMaxIterations = Number.parseInt(rawMaxIterations, 10);
|
|
20552
20555
|
if (Number.isNaN(parsedMaxIterations) || parsedMaxIterations < 1) {
|
|
20553
20556
|
logger.error(
|
|
@@ -20567,6 +20570,7 @@ ${prompt}`;
|
|
|
20567
20570
|
systemPromptAppend: getSystemPromptForMode("build"),
|
|
20568
20571
|
selectedModel,
|
|
20569
20572
|
oauthToken,
|
|
20573
|
+
projectId,
|
|
20570
20574
|
allowInteractivePrompts: true
|
|
20571
20575
|
});
|
|
20572
20576
|
}
|