修复资料页提交重试判定
This commit is contained in:
+59
-4
@@ -6544,10 +6544,65 @@ async function waitForStep5SubmitButton(timeout = 5000) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isStep5SubmitButtonClickable(button) {
|
function isStep5SubmitButtonClickable(button) {
|
||||||
return Boolean(button)
|
if (
|
||||||
&& isVisibleElement(button)
|
!button
|
||||||
&& !button.disabled
|
|| !isVisibleElement(button)
|
||||||
&& button.getAttribute?.('aria-disabled') !== 'true';
|
|| button.disabled
|
||||||
|
|| button.getAttribute?.('aria-disabled') === 'true'
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ariaBusy = String(button.getAttribute?.('aria-busy') || '').trim().toLowerCase();
|
||||||
|
if (ariaBusy === 'true') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pendingAttr = [
|
||||||
|
button.getAttribute?.('data-loading'),
|
||||||
|
button.getAttribute?.('data-pending'),
|
||||||
|
button.getAttribute?.('data-submitting'),
|
||||||
|
button.getAttribute?.('data-state'),
|
||||||
|
]
|
||||||
|
.map((value) => String(value || '').trim().toLowerCase())
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' ');
|
||||||
|
if (/\b(?:true|loading|pending|submitting|busy)\b/.test(pendingAttr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pendingAncestor = button.closest?.([
|
||||||
|
'[aria-busy="true"]',
|
||||||
|
'[data-loading="true"]',
|
||||||
|
'[data-pending="true"]',
|
||||||
|
'[data-submitting="true"]',
|
||||||
|
'[data-state="loading"]',
|
||||||
|
'[data-state="pending"]',
|
||||||
|
'[data-state="submitting"]',
|
||||||
|
].join(', '));
|
||||||
|
if (pendingAncestor) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let style = null;
|
||||||
|
try {
|
||||||
|
style = typeof window !== 'undefined' && window.getComputedStyle
|
||||||
|
? window.getComputedStyle(button)
|
||||||
|
: null;
|
||||||
|
} catch {
|
||||||
|
style = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (style?.pointerEvents === 'none') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const opacity = Number.parseFloat(style?.opacity || '');
|
||||||
|
if (Number.isFinite(opacity) && opacity < 0.8) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isStep5ProfileStillVisible() {
|
function isStep5ProfileStillVisible() {
|
||||||
|
|||||||
@@ -814,6 +814,91 @@ return {
|
|||||||
assert.equal(snapshot.logs.some(({ message }) => /仍停留在资料页,正在重新点击/.test(message)), true);
|
assert.equal(snapshot.logs.some(({ message }) => /仍停留在资料页,正在重新点击/.test(message)), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('step 5 waits instead of retrying while profile submit is pending', async () => {
|
||||||
|
const api = new Function(`
|
||||||
|
const realDateNow = Date.now;
|
||||||
|
let now = 0;
|
||||||
|
const clicks = [];
|
||||||
|
const completeButton = {
|
||||||
|
tagName: 'BUTTON',
|
||||||
|
type: 'submit',
|
||||||
|
textContent: 'Complete account creation',
|
||||||
|
hidden: false,
|
||||||
|
disabled: false,
|
||||||
|
getAttribute(name) {
|
||||||
|
if (name === 'aria-disabled') return 'false';
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
closest() {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const location = { href: 'https://auth.openai.com/u/signup/profile' };
|
||||||
|
const document = {
|
||||||
|
querySelector(selector) {
|
||||||
|
if (selector === 'button[type="submit"], input[type="submit"]') return completeButton;
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
querySelectorAll(selector) {
|
||||||
|
if (selector === 'button, [role="button"], input[type="button"], input[type="submit"]') return [completeButton];
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const window = {
|
||||||
|
getComputedStyle() {
|
||||||
|
return { opacity: '0.5', pointerEvents: 'auto' };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Date.now = () => now;
|
||||||
|
function throwIfStopped() {}
|
||||||
|
function log() {}
|
||||||
|
async function sleep(ms = 0) { now += ms || 250; }
|
||||||
|
async function humanPause() {}
|
||||||
|
function simulateClick(el) { clicks.push(el?.textContent || 'clicked'); }
|
||||||
|
function isVisibleElement(el) { return Boolean(el) && !el.hidden; }
|
||||||
|
function isActionEnabled(el) { return Boolean(el) && !el.disabled && el.getAttribute?.('aria-disabled') !== 'true'; }
|
||||||
|
function getActionText(el) { return el?.textContent || ''; }
|
||||||
|
function getSignupAuthRetryPathPatterns() { return []; }
|
||||||
|
function getAuthTimeoutErrorPageState() { return null; }
|
||||||
|
async function recoverCurrentAuthRetryPage() { throw new Error('should not recover retry page'); }
|
||||||
|
function createSignupUserAlreadyExistsError() { return new Error('user already exists'); }
|
||||||
|
function createAuthMaxCheckAttemptsError() { return new Error('max_check_attempts'); }
|
||||||
|
function getStep5ErrorText() { return ''; }
|
||||||
|
function isStep5Ready() { return true; }
|
||||||
|
function isLikelyLoggedInChatgptHomeUrl() { return false; }
|
||||||
|
function isOAuthConsentPage() { return false; }
|
||||||
|
function isAddPhonePageReady() { return false; }
|
||||||
|
|
||||||
|
${extractFunction('isSignupProfilePageUrl')}
|
||||||
|
${getStep5OutcomeBundle()}
|
||||||
|
|
||||||
|
return {
|
||||||
|
run() {
|
||||||
|
return waitForStep5SubmitOutcome({ timeoutMs: 4000, retryClickIntervalMs: 3500 });
|
||||||
|
},
|
||||||
|
snapshot() {
|
||||||
|
return { clicks, now };
|
||||||
|
},
|
||||||
|
restore() {
|
||||||
|
Date.now = realDateNow;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
`)();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await assert.rejects(
|
||||||
|
() => api.run(),
|
||||||
|
/已点击提交 1\/3 次/
|
||||||
|
);
|
||||||
|
const snapshot = api.snapshot();
|
||||||
|
assert.deepStrictEqual(snapshot.clicks, []);
|
||||||
|
assert.ok(snapshot.now >= 4000);
|
||||||
|
} finally {
|
||||||
|
api.restore();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('step 5 recovers auth retry page after profile submit', async () => {
|
test('step 5 recovers auth retry page after profile submit', async () => {
|
||||||
const api = new Function(`
|
const api = new Function(`
|
||||||
let retryVisible = true;
|
let retryVisible = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user