@validate.qa/runner 1.0.93 → 1.0.94
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/cli.js +77 -9
- package/dist/cli.mjs +77 -9
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8566,10 +8566,13 @@ var require_google_signin = __commonJS({
|
|
|
8566
8566
|
exports2.googleSignInGuidanceOpts = googleSignInGuidanceOpts;
|
|
8567
8567
|
exports2.googleSignInAllowedEmails = googleSignInAllowedEmails;
|
|
8568
8568
|
exports2.collectGoogleSignInEnv = collectGoogleSignInEnv;
|
|
8569
|
+
exports2.isGoogleAccountsUrl = isGoogleAccountsUrl;
|
|
8570
|
+
exports2.googleSignInCredentialMismatch = googleSignInCredentialMismatch;
|
|
8569
8571
|
exports2.generateTotp = generateTotp;
|
|
8570
8572
|
exports2.buildGoogleSignInPromptSection = buildGoogleSignInPromptSection;
|
|
8571
8573
|
var node_crypto_1 = require("crypto");
|
|
8572
8574
|
exports2.GOOGLE_SIGNIN_PASSWORD_KEY = "GOOGLE_SIGNIN_PASSWORD";
|
|
8575
|
+
var APP_REGISTER_CREDENTIAL_KEYS = /^(TEST_|E2E_|QA_)?(USER_?EMAIL|USER_?PASSWORD|USER_?NAME|USERNAME)$/i;
|
|
8573
8576
|
exports2.GOOGLE_SIGNIN_ENV_KEYS = [
|
|
8574
8577
|
"GOOGLE_SIGNIN_PASSWORD",
|
|
8575
8578
|
"GOOGLE_SIGNIN_EMAIL",
|
|
@@ -8626,6 +8629,34 @@ var require_google_signin = __commonJS({
|
|
|
8626
8629
|
}
|
|
8627
8630
|
return out;
|
|
8628
8631
|
}
|
|
8632
|
+
function isGoogleAccountsUrl(url) {
|
|
8633
|
+
if (!url)
|
|
8634
|
+
return false;
|
|
8635
|
+
try {
|
|
8636
|
+
const host = new URL(url).hostname.toLowerCase();
|
|
8637
|
+
return host === "accounts.google.com" || host.endsWith(".google.com") && host.includes("accounts");
|
|
8638
|
+
} catch {
|
|
8639
|
+
return /accounts\.google\.com/i.test(url);
|
|
8640
|
+
}
|
|
8641
|
+
}
|
|
8642
|
+
function googleSignInCredentialMismatch(pageUrl, credentialKey, opts) {
|
|
8643
|
+
const configured = opts?.configured ?? !!loadGoogleSignInConfig(opts?.env);
|
|
8644
|
+
if (!configured)
|
|
8645
|
+
return null;
|
|
8646
|
+
const onGoogle = isGoogleAccountsUrl(pageUrl);
|
|
8647
|
+
if (onGoogle) {
|
|
8648
|
+
if (credentialKey === exports2.GOOGLE_SIGNIN_PASSWORD_KEY)
|
|
8649
|
+
return null;
|
|
8650
|
+
if (APP_REGISTER_CREDENTIAL_KEYS.test(credentialKey)) {
|
|
8651
|
+
return `fill_credential: this is Google account login (accounts.google.com), not app email signup. Do not use ${credentialKey}. Type the BARE Google email with browser_type, then fill_credential with credentialKey ${exports2.GOOGLE_SIGNIN_PASSWORD_KEY}. Do not click Continue with phone / SMS OTP when Continue with Google is available.`;
|
|
8652
|
+
}
|
|
8653
|
+
return null;
|
|
8654
|
+
}
|
|
8655
|
+
if (credentialKey === exports2.GOOGLE_SIGNIN_PASSWORD_KEY) {
|
|
8656
|
+
return `fill_credential: ${exports2.GOOGLE_SIGNIN_PASSWORD_KEY} is only for accounts.google.com. Click Continue with Google first (not Continue with phone). Phone / "Mobile or email" is not app email signup.`;
|
|
8657
|
+
}
|
|
8658
|
+
return null;
|
|
8659
|
+
}
|
|
8629
8660
|
function generateTotp(secret, atMs = Date.now(), stepSeconds = 30, digits = 6) {
|
|
8630
8661
|
const key = decodeBase32(secret);
|
|
8631
8662
|
const counter = Math.floor(atMs / 1e3 / stepSeconds);
|
|
@@ -8664,10 +8695,14 @@ var require_google_signin = __commonJS({
|
|
|
8664
8695
|
const fill = variant === "cli" ? `fill_credential with credentialKey \`${opts.googlePasswordKey}\`` : `\`fill_credential\` (credentialKey \`${opts.googlePasswordKey}\`)`;
|
|
8665
8696
|
const plainProvision = variant === "cli" ? "`inbox_provision_identity` with `plain: true`" : "`provision_identity` with `plain: true`";
|
|
8666
8697
|
return `
|
|
8667
|
-
Google / Gmail SSO
|
|
8668
|
-
-
|
|
8669
|
-
-
|
|
8670
|
-
-
|
|
8698
|
+
Google / Gmail SSO (use this when the APP has no Create-account email form):
|
|
8699
|
+
- App email+password SIGNUP means a form ON THIS APP to create an account (Sign up / Create account / Register, including after "Sign up with email"). That is FIRST. Do not use Google if that form exists.
|
|
8700
|
+
- These are NOT app email signup \u2014 do not treat them as the email playbook, and do not fill TEST_USER_EMAIL / TEST_USER_PASSWORD into them when Continue with Google is available:
|
|
8701
|
+
- "Continue with phone" / SMS / OTP
|
|
8702
|
+
- "Mobile or email" / phone-number identity on a Sign in page
|
|
8703
|
+
- Google's own email and password fields on accounts.google.com
|
|
8704
|
+
- If Sign in offers Continue with Google (and there is no app Create-account email form): click Continue with Google. Do NOT click Continue with phone for this registration.
|
|
8705
|
+
- If a Google popup or tab opens, switch to it. On accounts.google.com, type the BARE Google account email \`${opts.googleEmail}\` (no plus-tag) with browser_type, click Next, then fill the Google password with ${fill}. NEVER type the Google password as text, NEVER use TEST_USER_PASSWORD here, NEVER use the IMAP app password.
|
|
8671
8706
|
- Click Next.${totp}
|
|
8672
8707
|
- Click Continue / Allow on any consent screen, then return to the app tab.
|
|
8673
8708
|
- If the app then emails a verification code/link, first call ${plainProvision} (Google SSO uses the bare inbox address, not the +tag), then complete it with the inbox tools as usual.
|
|
@@ -8699,7 +8734,7 @@ var require_credential_tools = __commonJS({
|
|
|
8699
8734
|
type: "function",
|
|
8700
8735
|
function: {
|
|
8701
8736
|
name: "fill_credential",
|
|
8702
|
-
description: 'Fill a stored credential VALUE into a form field. ALWAYS use this instead of `browser_type` for ANY email/password/token/auth field. You pass the variable KEY (e.g. "TEST_USER_EMAIL") and the runner injects the real value server-side \u2014 you never see the secret. The list of available credential keys is in the system prompt.',
|
|
8737
|
+
description: 'Fill a stored credential VALUE into a form field. ALWAYS use this instead of `browser_type` for ANY email/password/token/auth field. You pass the variable KEY (e.g. "TEST_USER_EMAIL") and the runner injects the real value server-side \u2014 you never see the secret. On accounts.google.com use GOOGLE_SIGNIN_PASSWORD (never TEST_USER_PASSWORD). The list of available credential keys is in the system prompt.',
|
|
8703
8738
|
parameters: {
|
|
8704
8739
|
type: "object",
|
|
8705
8740
|
properties: {
|
|
@@ -8861,6 +8896,22 @@ CREDENTIAL ROTATION (required when the STORED user's secret changes \u2014 read
|
|
|
8861
8896
|
return entries.map(([k, v]) => `- **${k}**: \`${v}\``).join("\n");
|
|
8862
8897
|
}
|
|
8863
8898
|
var DEFAULT_MAX_RESULT_CHARS = 15e3;
|
|
8899
|
+
var PAGE_URL_RE = /Page URL:\s*(\S+)/i;
|
|
8900
|
+
async function peekPageUrl(mcpClient) {
|
|
8901
|
+
try {
|
|
8902
|
+
const mcpResult = await mcpClient.callTool({ name: "browser_snapshot", arguments: {} });
|
|
8903
|
+
const { text } = parseMcpContent(mcpResult);
|
|
8904
|
+
const match = text.match(PAGE_URL_RE);
|
|
8905
|
+
return match?.[1]?.replace(/[),.;]+$/, "");
|
|
8906
|
+
} catch {
|
|
8907
|
+
return void 0;
|
|
8908
|
+
}
|
|
8909
|
+
}
|
|
8910
|
+
function googleFillBlocked(pageUrl, credentialKey, credentials) {
|
|
8911
|
+
return (0, google_signin_js_1.googleSignInCredentialMismatch)(pageUrl, credentialKey, {
|
|
8912
|
+
configured: !!credentials[google_signin_js_1.GOOGLE_SIGNIN_PASSWORD_KEY]
|
|
8913
|
+
});
|
|
8914
|
+
}
|
|
8864
8915
|
async function handleFillCredential(toolArgs, ctx) {
|
|
8865
8916
|
const key = typeof toolArgs.credentialKey === "string" ? toolArgs.credentialKey : "";
|
|
8866
8917
|
const element = typeof toolArgs.element === "string" ? toolArgs.element : "";
|
|
@@ -8882,6 +8933,13 @@ CREDENTIAL ROTATION (required when the STORED user's secret changes \u2014 read
|
|
|
8882
8933
|
didMutate: false
|
|
8883
8934
|
};
|
|
8884
8935
|
}
|
|
8936
|
+
if (ctx.credentials[google_signin_js_1.GOOGLE_SIGNIN_PASSWORD_KEY]) {
|
|
8937
|
+
const pageUrl = await peekPageUrl(ctx.mcpClient);
|
|
8938
|
+
const blocked = googleFillBlocked(pageUrl, key, ctx.credentials);
|
|
8939
|
+
if (blocked) {
|
|
8940
|
+
return { content: JSON.stringify({ error: blocked }), didMutate: false };
|
|
8941
|
+
}
|
|
8942
|
+
}
|
|
8885
8943
|
const underlyingArgs = { element, ref, text: value, submit };
|
|
8886
8944
|
const mcpResult = await ctx.mcpClient.callTool({ name: "browser_type", arguments: underlyingArgs });
|
|
8887
8945
|
const mcpFailed = mcpResultIsError(mcpResult);
|
|
@@ -8920,6 +8978,16 @@ CREDENTIAL ROTATION (required when the STORED user's secret changes \u2014 read
|
|
|
8920
8978
|
}
|
|
8921
8979
|
resolved.push({ field, value });
|
|
8922
8980
|
}
|
|
8981
|
+
if (ctx.credentials[google_signin_js_1.GOOGLE_SIGNIN_PASSWORD_KEY]) {
|
|
8982
|
+
const pageUrl = await peekPageUrl(ctx.mcpClient);
|
|
8983
|
+
for (const f of fields) {
|
|
8984
|
+
const key = typeof f.credentialKey === "string" ? f.credentialKey : typeof f.key === "string" ? f.key : "";
|
|
8985
|
+
const blocked = googleFillBlocked(pageUrl, key, ctx.credentials);
|
|
8986
|
+
if (blocked) {
|
|
8987
|
+
return { content: JSON.stringify({ error: blocked }), didMutate: false };
|
|
8988
|
+
}
|
|
8989
|
+
}
|
|
8990
|
+
}
|
|
8923
8991
|
if (missing.length > 0) {
|
|
8924
8992
|
const available = Object.keys(ctx.credentials).filter((k) => ctx.credentials[k]).join(", ") || "(none configured)";
|
|
8925
8993
|
return {
|
|
@@ -74749,7 +74817,7 @@ var require_inbox_tools = __commonJS({
|
|
|
74749
74817
|
${where} You register using ONE real, monitored email (\`${opts.email}\`) and can complete email-verification (OTP code or confirmation link) end-to-end. This OVERRIDES the general "do not submit forms" rule for the signup/registration form ONLY.
|
|
74750
74818
|
|
|
74751
74819
|
Steps:
|
|
74752
|
-
1. Navigate to the Sign Up / Register page (click the link in the UI). FIRST look for an email+password
|
|
74820
|
+
1. Navigate to the Sign Up / Register / Sign in page (click the link in the UI). FIRST look for an app Create-account email+password form (including after "Sign up with email").${opts.googleEmail && opts.googlePasswordKey ? ' "Continue with phone", SMS OTP, and "Mobile or email" on a Sign in page are NOT that form \u2014 if Continue with Google is offered and there is no app Create-account email form, use the Google / Gmail SSO playbook below (do not click Continue with phone).' : ""}
|
|
74753
74821
|
2. Call \`provision_identity\` \u2192 it returns the email to register with (\`${opts.email}\`). The \`+\` part is a normal sub-address that still lands in our inbox.
|
|
74754
74822
|
3. Fill the signup form: type that email into the email field with \`browser_type\` (this generated inbox email is intentionally visible and is allowed for registration); fill the password field with single-field \`fill_credential\` (credentialKey \`${opts.passwordKey}\`); fill any name/other required fields with simple test values. Do NOT use \`fill_credential_form\` for registration.
|
|
74755
74823
|
- If the form REJECTS the email (says "invalid email" / will not accept the "+"), call \`provision_identity\` again with \`plain: true\` and use the bare address it returns instead.
|
|
@@ -74931,7 +74999,7 @@ This project asked to REGISTER a new account, but this runner CANNOT receive ema
|
|
|
74931
74999
|
return `## Account registration & email verification (ENABLED)
|
|
74932
75000
|
This run registers a new account using our ONE real, monitored inbox (the address \`${email}\` \u2014 the "+" part is a normal sub-address that still lands in our inbox) and can complete email verification end-to-end. This overrides any "do not submit forms" guidance for the signup form only.
|
|
74933
75001
|
|
|
74934
|
-
1. Go to the Sign Up / Register page. FIRST look for an email+password
|
|
75002
|
+
1. Go to the Sign Up / Register / Sign in page. FIRST look for an app Create-account email+password form (including after "Sign up with email").${google ? ' "Continue with phone", SMS OTP, and "Mobile or email" on a Sign in page are NOT that form \u2014 if Continue with Google is offered and there is no app Create-account email form, use the Google / Gmail SSO playbook below (do not click Continue with phone).' : ""}
|
|
74935
75003
|
2. Call \`inbox_provision_identity\` \u2192 it returns the email to register with (\`${email}\`). Type that email into the email field.
|
|
74936
75004
|
- If the form REJECTS the email (says "invalid email" / will not accept the "+"), call \`inbox_provision_identity\` with \`plain: true\` and use the bare address it returns instead.
|
|
74937
75005
|
3. Fill the password with the \`${passwordKey}\` credential (use fill_credential). Submit the signup form.
|
|
@@ -333344,7 +333412,7 @@ ${keyLines || "- (none provided)"}
|
|
|
333344
333412
|
## EXACTLY what to do
|
|
333345
333413
|
1. Navigate to ${baseUrl} and take a \`browser_snapshot\`.
|
|
333346
333414
|
2. Find the Sign Up / Register / Create account affordance (match by PURPOSE, in the app's own language) and open the signup form. If a reveal button hides the fields ("Sign up with Email"), click it first.
|
|
333347
|
-
3. Follow the "Account Registration (verification inbox is ENABLED)" steps below EXACTLY: call \`provision_identity\` for the email, type that email, fill the password with \`fill_credential\`, fill any other required fields with simple test values, and submit. If there is
|
|
333415
|
+
3. Follow the "Account Registration (verification inbox is ENABLED)" steps below EXACTLY: call \`provision_identity\` for the email, type that email, fill the password with \`fill_credential\`, fill any other required fields with simple test values, and submit. If there is no app Create-account email form (phone / "Mobile or email" / SMS do not count) and Sign in offers "Continue with Google", follow the Google / Gmail SSO playbook (bare Google account email, \`fill_credential\` with \`GOOGLE_SIGNIN_PASSWORD\` on accounts.google.com, never TEST_USER_PASSWORD, never Continue with phone).
|
|
333348
333416
|
4. Complete email verification using the inbox tools (\`wait_for_verification\` \u2192 enter the code or \`open_verification_link\`). Re-poll if the email is slow; resend AT MOST once; NEVER register a second account.
|
|
333349
333417
|
5. Confirm you are signed in \u2014 a redirect to an authenticated route, or an in-place change to authenticated content. Take a \`browser_snapshot\`.
|
|
333350
333418
|
6. \`capture_page\` the authenticated landing page in its DEFAULT state, then call \`finish_exploration\`. Do this the MOMENT the account is verified and you are signed in.
|
|
@@ -356286,7 +356354,7 @@ var require_package4 = __commonJS({
|
|
|
356286
356354
|
"package.json"(exports2, module2) {
|
|
356287
356355
|
module2.exports = {
|
|
356288
356356
|
name: "@validate.qa/runner",
|
|
356289
|
-
version: "1.0.
|
|
356357
|
+
version: "1.0.94",
|
|
356290
356358
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
356291
356359
|
bin: {
|
|
356292
356360
|
"validate-runner": "dist/cli.js"
|
package/dist/cli.mjs
CHANGED
|
@@ -8571,10 +8571,13 @@ var require_google_signin = __commonJS({
|
|
|
8571
8571
|
exports.googleSignInGuidanceOpts = googleSignInGuidanceOpts;
|
|
8572
8572
|
exports.googleSignInAllowedEmails = googleSignInAllowedEmails;
|
|
8573
8573
|
exports.collectGoogleSignInEnv = collectGoogleSignInEnv;
|
|
8574
|
+
exports.isGoogleAccountsUrl = isGoogleAccountsUrl;
|
|
8575
|
+
exports.googleSignInCredentialMismatch = googleSignInCredentialMismatch;
|
|
8574
8576
|
exports.generateTotp = generateTotp;
|
|
8575
8577
|
exports.buildGoogleSignInPromptSection = buildGoogleSignInPromptSection;
|
|
8576
8578
|
var node_crypto_1 = __require("crypto");
|
|
8577
8579
|
exports.GOOGLE_SIGNIN_PASSWORD_KEY = "GOOGLE_SIGNIN_PASSWORD";
|
|
8580
|
+
var APP_REGISTER_CREDENTIAL_KEYS = /^(TEST_|E2E_|QA_)?(USER_?EMAIL|USER_?PASSWORD|USER_?NAME|USERNAME)$/i;
|
|
8578
8581
|
exports.GOOGLE_SIGNIN_ENV_KEYS = [
|
|
8579
8582
|
"GOOGLE_SIGNIN_PASSWORD",
|
|
8580
8583
|
"GOOGLE_SIGNIN_EMAIL",
|
|
@@ -8631,6 +8634,34 @@ var require_google_signin = __commonJS({
|
|
|
8631
8634
|
}
|
|
8632
8635
|
return out;
|
|
8633
8636
|
}
|
|
8637
|
+
function isGoogleAccountsUrl(url) {
|
|
8638
|
+
if (!url)
|
|
8639
|
+
return false;
|
|
8640
|
+
try {
|
|
8641
|
+
const host = new URL(url).hostname.toLowerCase();
|
|
8642
|
+
return host === "accounts.google.com" || host.endsWith(".google.com") && host.includes("accounts");
|
|
8643
|
+
} catch {
|
|
8644
|
+
return /accounts\.google\.com/i.test(url);
|
|
8645
|
+
}
|
|
8646
|
+
}
|
|
8647
|
+
function googleSignInCredentialMismatch(pageUrl, credentialKey, opts) {
|
|
8648
|
+
const configured = opts?.configured ?? !!loadGoogleSignInConfig(opts?.env);
|
|
8649
|
+
if (!configured)
|
|
8650
|
+
return null;
|
|
8651
|
+
const onGoogle = isGoogleAccountsUrl(pageUrl);
|
|
8652
|
+
if (onGoogle) {
|
|
8653
|
+
if (credentialKey === exports.GOOGLE_SIGNIN_PASSWORD_KEY)
|
|
8654
|
+
return null;
|
|
8655
|
+
if (APP_REGISTER_CREDENTIAL_KEYS.test(credentialKey)) {
|
|
8656
|
+
return `fill_credential: this is Google account login (accounts.google.com), not app email signup. Do not use ${credentialKey}. Type the BARE Google email with browser_type, then fill_credential with credentialKey ${exports.GOOGLE_SIGNIN_PASSWORD_KEY}. Do not click Continue with phone / SMS OTP when Continue with Google is available.`;
|
|
8657
|
+
}
|
|
8658
|
+
return null;
|
|
8659
|
+
}
|
|
8660
|
+
if (credentialKey === exports.GOOGLE_SIGNIN_PASSWORD_KEY) {
|
|
8661
|
+
return `fill_credential: ${exports.GOOGLE_SIGNIN_PASSWORD_KEY} is only for accounts.google.com. Click Continue with Google first (not Continue with phone). Phone / "Mobile or email" is not app email signup.`;
|
|
8662
|
+
}
|
|
8663
|
+
return null;
|
|
8664
|
+
}
|
|
8634
8665
|
function generateTotp(secret, atMs = Date.now(), stepSeconds = 30, digits = 6) {
|
|
8635
8666
|
const key = decodeBase32(secret);
|
|
8636
8667
|
const counter = Math.floor(atMs / 1e3 / stepSeconds);
|
|
@@ -8669,10 +8700,14 @@ var require_google_signin = __commonJS({
|
|
|
8669
8700
|
const fill = variant === "cli" ? `fill_credential with credentialKey \`${opts.googlePasswordKey}\`` : `\`fill_credential\` (credentialKey \`${opts.googlePasswordKey}\`)`;
|
|
8670
8701
|
const plainProvision = variant === "cli" ? "`inbox_provision_identity` with `plain: true`" : "`provision_identity` with `plain: true`";
|
|
8671
8702
|
return `
|
|
8672
|
-
Google / Gmail SSO
|
|
8673
|
-
-
|
|
8674
|
-
-
|
|
8675
|
-
-
|
|
8703
|
+
Google / Gmail SSO (use this when the APP has no Create-account email form):
|
|
8704
|
+
- App email+password SIGNUP means a form ON THIS APP to create an account (Sign up / Create account / Register, including after "Sign up with email"). That is FIRST. Do not use Google if that form exists.
|
|
8705
|
+
- These are NOT app email signup \u2014 do not treat them as the email playbook, and do not fill TEST_USER_EMAIL / TEST_USER_PASSWORD into them when Continue with Google is available:
|
|
8706
|
+
- "Continue with phone" / SMS / OTP
|
|
8707
|
+
- "Mobile or email" / phone-number identity on a Sign in page
|
|
8708
|
+
- Google's own email and password fields on accounts.google.com
|
|
8709
|
+
- If Sign in offers Continue with Google (and there is no app Create-account email form): click Continue with Google. Do NOT click Continue with phone for this registration.
|
|
8710
|
+
- If a Google popup or tab opens, switch to it. On accounts.google.com, type the BARE Google account email \`${opts.googleEmail}\` (no plus-tag) with browser_type, click Next, then fill the Google password with ${fill}. NEVER type the Google password as text, NEVER use TEST_USER_PASSWORD here, NEVER use the IMAP app password.
|
|
8676
8711
|
- Click Next.${totp}
|
|
8677
8712
|
- Click Continue / Allow on any consent screen, then return to the app tab.
|
|
8678
8713
|
- If the app then emails a verification code/link, first call ${plainProvision} (Google SSO uses the bare inbox address, not the +tag), then complete it with the inbox tools as usual.
|
|
@@ -8704,7 +8739,7 @@ var require_credential_tools = __commonJS({
|
|
|
8704
8739
|
type: "function",
|
|
8705
8740
|
function: {
|
|
8706
8741
|
name: "fill_credential",
|
|
8707
|
-
description: 'Fill a stored credential VALUE into a form field. ALWAYS use this instead of `browser_type` for ANY email/password/token/auth field. You pass the variable KEY (e.g. "TEST_USER_EMAIL") and the runner injects the real value server-side \u2014 you never see the secret. The list of available credential keys is in the system prompt.',
|
|
8742
|
+
description: 'Fill a stored credential VALUE into a form field. ALWAYS use this instead of `browser_type` for ANY email/password/token/auth field. You pass the variable KEY (e.g. "TEST_USER_EMAIL") and the runner injects the real value server-side \u2014 you never see the secret. On accounts.google.com use GOOGLE_SIGNIN_PASSWORD (never TEST_USER_PASSWORD). The list of available credential keys is in the system prompt.',
|
|
8708
8743
|
parameters: {
|
|
8709
8744
|
type: "object",
|
|
8710
8745
|
properties: {
|
|
@@ -8866,6 +8901,22 @@ CREDENTIAL ROTATION (required when the STORED user's secret changes \u2014 read
|
|
|
8866
8901
|
return entries.map(([k, v]) => `- **${k}**: \`${v}\``).join("\n");
|
|
8867
8902
|
}
|
|
8868
8903
|
var DEFAULT_MAX_RESULT_CHARS = 15e3;
|
|
8904
|
+
var PAGE_URL_RE = /Page URL:\s*(\S+)/i;
|
|
8905
|
+
async function peekPageUrl(mcpClient) {
|
|
8906
|
+
try {
|
|
8907
|
+
const mcpResult = await mcpClient.callTool({ name: "browser_snapshot", arguments: {} });
|
|
8908
|
+
const { text } = parseMcpContent(mcpResult);
|
|
8909
|
+
const match = text.match(PAGE_URL_RE);
|
|
8910
|
+
return match?.[1]?.replace(/[),.;]+$/, "");
|
|
8911
|
+
} catch {
|
|
8912
|
+
return void 0;
|
|
8913
|
+
}
|
|
8914
|
+
}
|
|
8915
|
+
function googleFillBlocked(pageUrl, credentialKey, credentials) {
|
|
8916
|
+
return (0, google_signin_js_1.googleSignInCredentialMismatch)(pageUrl, credentialKey, {
|
|
8917
|
+
configured: !!credentials[google_signin_js_1.GOOGLE_SIGNIN_PASSWORD_KEY]
|
|
8918
|
+
});
|
|
8919
|
+
}
|
|
8869
8920
|
async function handleFillCredential(toolArgs, ctx) {
|
|
8870
8921
|
const key = typeof toolArgs.credentialKey === "string" ? toolArgs.credentialKey : "";
|
|
8871
8922
|
const element = typeof toolArgs.element === "string" ? toolArgs.element : "";
|
|
@@ -8887,6 +8938,13 @@ CREDENTIAL ROTATION (required when the STORED user's secret changes \u2014 read
|
|
|
8887
8938
|
didMutate: false
|
|
8888
8939
|
};
|
|
8889
8940
|
}
|
|
8941
|
+
if (ctx.credentials[google_signin_js_1.GOOGLE_SIGNIN_PASSWORD_KEY]) {
|
|
8942
|
+
const pageUrl = await peekPageUrl(ctx.mcpClient);
|
|
8943
|
+
const blocked = googleFillBlocked(pageUrl, key, ctx.credentials);
|
|
8944
|
+
if (blocked) {
|
|
8945
|
+
return { content: JSON.stringify({ error: blocked }), didMutate: false };
|
|
8946
|
+
}
|
|
8947
|
+
}
|
|
8890
8948
|
const underlyingArgs = { element, ref, text: value, submit };
|
|
8891
8949
|
const mcpResult = await ctx.mcpClient.callTool({ name: "browser_type", arguments: underlyingArgs });
|
|
8892
8950
|
const mcpFailed = mcpResultIsError(mcpResult);
|
|
@@ -8925,6 +8983,16 @@ CREDENTIAL ROTATION (required when the STORED user's secret changes \u2014 read
|
|
|
8925
8983
|
}
|
|
8926
8984
|
resolved.push({ field, value });
|
|
8927
8985
|
}
|
|
8986
|
+
if (ctx.credentials[google_signin_js_1.GOOGLE_SIGNIN_PASSWORD_KEY]) {
|
|
8987
|
+
const pageUrl = await peekPageUrl(ctx.mcpClient);
|
|
8988
|
+
for (const f of fields) {
|
|
8989
|
+
const key = typeof f.credentialKey === "string" ? f.credentialKey : typeof f.key === "string" ? f.key : "";
|
|
8990
|
+
const blocked = googleFillBlocked(pageUrl, key, ctx.credentials);
|
|
8991
|
+
if (blocked) {
|
|
8992
|
+
return { content: JSON.stringify({ error: blocked }), didMutate: false };
|
|
8993
|
+
}
|
|
8994
|
+
}
|
|
8995
|
+
}
|
|
8928
8996
|
if (missing.length > 0) {
|
|
8929
8997
|
const available = Object.keys(ctx.credentials).filter((k) => ctx.credentials[k]).join(", ") || "(none configured)";
|
|
8930
8998
|
return {
|
|
@@ -74754,7 +74822,7 @@ var require_inbox_tools = __commonJS({
|
|
|
74754
74822
|
${where} You register using ONE real, monitored email (\`${opts.email}\`) and can complete email-verification (OTP code or confirmation link) end-to-end. This OVERRIDES the general "do not submit forms" rule for the signup/registration form ONLY.
|
|
74755
74823
|
|
|
74756
74824
|
Steps:
|
|
74757
|
-
1. Navigate to the Sign Up / Register page (click the link in the UI). FIRST look for an email+password
|
|
74825
|
+
1. Navigate to the Sign Up / Register / Sign in page (click the link in the UI). FIRST look for an app Create-account email+password form (including after "Sign up with email").${opts.googleEmail && opts.googlePasswordKey ? ' "Continue with phone", SMS OTP, and "Mobile or email" on a Sign in page are NOT that form \u2014 if Continue with Google is offered and there is no app Create-account email form, use the Google / Gmail SSO playbook below (do not click Continue with phone).' : ""}
|
|
74758
74826
|
2. Call \`provision_identity\` \u2192 it returns the email to register with (\`${opts.email}\`). The \`+\` part is a normal sub-address that still lands in our inbox.
|
|
74759
74827
|
3. Fill the signup form: type that email into the email field with \`browser_type\` (this generated inbox email is intentionally visible and is allowed for registration); fill the password field with single-field \`fill_credential\` (credentialKey \`${opts.passwordKey}\`); fill any name/other required fields with simple test values. Do NOT use \`fill_credential_form\` for registration.
|
|
74760
74828
|
- If the form REJECTS the email (says "invalid email" / will not accept the "+"), call \`provision_identity\` again with \`plain: true\` and use the bare address it returns instead.
|
|
@@ -74936,7 +75004,7 @@ This project asked to REGISTER a new account, but this runner CANNOT receive ema
|
|
|
74936
75004
|
return `## Account registration & email verification (ENABLED)
|
|
74937
75005
|
This run registers a new account using our ONE real, monitored inbox (the address \`${email}\` \u2014 the "+" part is a normal sub-address that still lands in our inbox) and can complete email verification end-to-end. This overrides any "do not submit forms" guidance for the signup form only.
|
|
74938
75006
|
|
|
74939
|
-
1. Go to the Sign Up / Register page. FIRST look for an email+password
|
|
75007
|
+
1. Go to the Sign Up / Register / Sign in page. FIRST look for an app Create-account email+password form (including after "Sign up with email").${google ? ' "Continue with phone", SMS OTP, and "Mobile or email" on a Sign in page are NOT that form \u2014 if Continue with Google is offered and there is no app Create-account email form, use the Google / Gmail SSO playbook below (do not click Continue with phone).' : ""}
|
|
74940
75008
|
2. Call \`inbox_provision_identity\` \u2192 it returns the email to register with (\`${email}\`). Type that email into the email field.
|
|
74941
75009
|
- If the form REJECTS the email (says "invalid email" / will not accept the "+"), call \`inbox_provision_identity\` with \`plain: true\` and use the bare address it returns instead.
|
|
74942
75010
|
3. Fill the password with the \`${passwordKey}\` credential (use fill_credential). Submit the signup form.
|
|
@@ -333349,7 +333417,7 @@ ${keyLines || "- (none provided)"}
|
|
|
333349
333417
|
## EXACTLY what to do
|
|
333350
333418
|
1. Navigate to ${baseUrl} and take a \`browser_snapshot\`.
|
|
333351
333419
|
2. Find the Sign Up / Register / Create account affordance (match by PURPOSE, in the app's own language) and open the signup form. If a reveal button hides the fields ("Sign up with Email"), click it first.
|
|
333352
|
-
3. Follow the "Account Registration (verification inbox is ENABLED)" steps below EXACTLY: call \`provision_identity\` for the email, type that email, fill the password with \`fill_credential\`, fill any other required fields with simple test values, and submit. If there is
|
|
333420
|
+
3. Follow the "Account Registration (verification inbox is ENABLED)" steps below EXACTLY: call \`provision_identity\` for the email, type that email, fill the password with \`fill_credential\`, fill any other required fields with simple test values, and submit. If there is no app Create-account email form (phone / "Mobile or email" / SMS do not count) and Sign in offers "Continue with Google", follow the Google / Gmail SSO playbook (bare Google account email, \`fill_credential\` with \`GOOGLE_SIGNIN_PASSWORD\` on accounts.google.com, never TEST_USER_PASSWORD, never Continue with phone).
|
|
333353
333421
|
4. Complete email verification using the inbox tools (\`wait_for_verification\` \u2192 enter the code or \`open_verification_link\`). Re-poll if the email is slow; resend AT MOST once; NEVER register a second account.
|
|
333354
333422
|
5. Confirm you are signed in \u2014 a redirect to an authenticated route, or an in-place change to authenticated content. Take a \`browser_snapshot\`.
|
|
333355
333423
|
6. \`capture_page\` the authenticated landing page in its DEFAULT state, then call \`finish_exploration\`. Do this the MOMENT the account is verified and you are signed in.
|
|
@@ -356291,7 +356359,7 @@ var require_package4 = __commonJS({
|
|
|
356291
356359
|
"package.json"(exports, module) {
|
|
356292
356360
|
module.exports = {
|
|
356293
356361
|
name: "@validate.qa/runner",
|
|
356294
|
-
version: "1.0.
|
|
356362
|
+
version: "1.0.94",
|
|
356295
356363
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
356296
356364
|
bin: {
|
|
356297
356365
|
"validate-runner": "dist/cli.js"
|
package/package.json
CHANGED