feat: add support for deferring Step 9 callback timeout during auth security verification
This commit is contained in:
@@ -182,3 +182,175 @@ return {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('step9 defers callback timeout while auth security verification is still redirecting', async () => {
|
||||
const api = new Function('step9ModuleSource', `
|
||||
const self = {};
|
||||
let webNavListener = null;
|
||||
let webNavCommittedListener = null;
|
||||
let step8TabUpdatedListener = null;
|
||||
let cleanupCalls = 0;
|
||||
let deferCalls = 0;
|
||||
let completePayload = null;
|
||||
const callbackUrl = 'http://localhost:1455/auth/callback?code=abc&state=xyz';
|
||||
|
||||
const chrome = {
|
||||
webNavigation: {
|
||||
onBeforeNavigate: {
|
||||
addListener(listener) {
|
||||
webNavListener = listener;
|
||||
setTimeout(() => {
|
||||
if (typeof webNavListener === 'function') {
|
||||
webNavListener({ tabId: 123, url: callbackUrl });
|
||||
}
|
||||
}, 25);
|
||||
},
|
||||
removeListener() {},
|
||||
},
|
||||
onCommitted: {
|
||||
addListener(listener) {
|
||||
webNavCommittedListener = listener;
|
||||
},
|
||||
removeListener() {},
|
||||
},
|
||||
},
|
||||
tabs: {
|
||||
onUpdated: {
|
||||
addListener(listener) {
|
||||
step8TabUpdatedListener = listener;
|
||||
},
|
||||
removeListener() {},
|
||||
},
|
||||
async update() {},
|
||||
},
|
||||
};
|
||||
|
||||
async function addLog() {}
|
||||
function cleanupStep8NavigationListeners() {
|
||||
cleanupCalls += 1;
|
||||
webNavListener = null;
|
||||
webNavCommittedListener = null;
|
||||
step8TabUpdatedListener = null;
|
||||
}
|
||||
function throwIfStep8SettledOrStopped(resolved) {
|
||||
if (resolved) throw new Error('already resolved');
|
||||
}
|
||||
async function getTabId() { return 123; }
|
||||
async function isTabAlive() { return true; }
|
||||
async function ensureStep8SignupPageReady() {}
|
||||
async function getOAuthFlowStepTimeoutMs(defaultTimeoutMs, options = {}) {
|
||||
if (options.actionLabel === 'OAuth localhost 回调') {
|
||||
return 1;
|
||||
}
|
||||
return defaultTimeoutMs;
|
||||
}
|
||||
async function shouldDeferStep9CallbackTimeout(details = {}) {
|
||||
deferCalls += 1;
|
||||
return Number(details.tabId) === 123;
|
||||
}
|
||||
async function waitForStep8Ready() {
|
||||
return {
|
||||
consentReady: true,
|
||||
url: 'https://auth.openai.com/sign-in-with-chatgpt/codex/consent',
|
||||
};
|
||||
}
|
||||
async function triggerStep8ContentStrategy() {}
|
||||
async function waitForStep8ClickEffect() {
|
||||
return {
|
||||
progressed: true,
|
||||
reason: 'url_changed',
|
||||
url: 'https://auth.openai.com/api/oauth/oauth2/auth?client_id=app_test',
|
||||
};
|
||||
}
|
||||
function getStep8CallbackUrlFromNavigation(details, signupTabId) {
|
||||
return Number(details?.tabId) === Number(signupTabId) ? details.url : '';
|
||||
}
|
||||
function getStep8CallbackUrlFromTabUpdate() { return ''; }
|
||||
function getStep8EffectLabel() { return 'URL 已变化'; }
|
||||
async function prepareStep8DebuggerClick() { return { rect: { centerX: 10, centerY: 10 } }; }
|
||||
async function clickWithDebugger() {}
|
||||
async function reloadStep8ConsentPage() {}
|
||||
async function reuseOrCreateTab() { return 123; }
|
||||
async function sleepWithStop() {}
|
||||
function setWebNavListener(listener) { webNavListener = listener; }
|
||||
function getWebNavListener() { return webNavListener; }
|
||||
function setWebNavCommittedListener(listener) { webNavCommittedListener = listener; }
|
||||
function getWebNavCommittedListener() { return webNavCommittedListener; }
|
||||
function setStep8TabUpdatedListener(listener) { step8TabUpdatedListener = listener; }
|
||||
function getStep8TabUpdatedListener() { return step8TabUpdatedListener; }
|
||||
function setStep8PendingReject() {}
|
||||
async function completeStepFromBackground(step, payload) {
|
||||
completePayload = { step, payload };
|
||||
}
|
||||
|
||||
const STEP8_CLICK_RETRY_DELAY_MS = 1;
|
||||
const STEP8_READY_WAIT_TIMEOUT_MS = 5;
|
||||
const STEP8_MAX_ROUNDS = 1;
|
||||
const STEP8_STRATEGIES = [
|
||||
{ mode: 'content', strategy: 'requestSubmit', label: 'form.requestSubmit' },
|
||||
];
|
||||
|
||||
${step9ModuleSource}
|
||||
|
||||
const executor = self.MultiPageBackgroundStep9.createStep9Executor({
|
||||
addLog,
|
||||
chrome,
|
||||
cleanupStep8NavigationListeners,
|
||||
clickWithDebugger,
|
||||
completeStepFromBackground,
|
||||
ensureStep8SignupPageReady,
|
||||
getOAuthFlowStepTimeoutMs,
|
||||
getStep8CallbackUrlFromNavigation,
|
||||
getStep8CallbackUrlFromTabUpdate,
|
||||
getStep8EffectLabel,
|
||||
getTabId,
|
||||
getWebNavCommittedListener,
|
||||
getWebNavListener,
|
||||
getStep8TabUpdatedListener,
|
||||
isTabAlive,
|
||||
prepareStep8DebuggerClick,
|
||||
reloadStep8ConsentPage,
|
||||
reuseOrCreateTab,
|
||||
setStep8PendingReject,
|
||||
setStep8TabUpdatedListener,
|
||||
setWebNavCommittedListener,
|
||||
setWebNavListener,
|
||||
shouldDeferStep9CallbackTimeout,
|
||||
sleepWithStop,
|
||||
STEP8_CLICK_RETRY_DELAY_MS,
|
||||
STEP8_MAX_ROUNDS,
|
||||
STEP8_READY_WAIT_TIMEOUT_MS,
|
||||
STEP8_STRATEGIES,
|
||||
throwIfStep8SettledOrStopped,
|
||||
triggerStep8ContentStrategy,
|
||||
waitForStep8ClickEffect,
|
||||
waitForStep8Ready,
|
||||
});
|
||||
|
||||
return {
|
||||
executeStep9: executor.executeStep9,
|
||||
snapshot() {
|
||||
return {
|
||||
cleanupCalls,
|
||||
deferCalls,
|
||||
completePayload,
|
||||
};
|
||||
},
|
||||
};
|
||||
`)(step9ModuleSource);
|
||||
|
||||
await api.executeStep9({
|
||||
oauthUrl: 'https://auth.openai.com/original-oauth',
|
||||
visibleStep: 12,
|
||||
});
|
||||
|
||||
const snapshot = api.snapshot();
|
||||
assert.equal(snapshot.deferCalls >= 1, true);
|
||||
assert.equal(snapshot.cleanupCalls >= 1, true);
|
||||
assert.deepEqual(snapshot.completePayload, {
|
||||
step: 12,
|
||||
payload: {
|
||||
localhostUrl: 'http://localhost:1455/auth/callback?code=abc&state=xyz',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user