fix flow-specific manual step execution
This commit is contained in:
@@ -288,23 +288,6 @@
|
|||||||
return appendAccountRunRecord(status, state, reason);
|
return appendAccountRunRecord(status, state, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ensureManualStepPrerequisites(step) {
|
|
||||||
if (step !== 4) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const signupTabId = typeof getTabId === 'function'
|
|
||||||
? await getTabId('openai-auth')
|
|
||||||
: null;
|
|
||||||
const signupTabAlive = signupTabId && typeof isTabAlive === 'function'
|
|
||||||
? await isTabAlive('openai-auth')
|
|
||||||
: Boolean(signupTabId);
|
|
||||||
|
|
||||||
if (!signupTabId || !signupTabAlive) {
|
|
||||||
throw new Error('手动执行步骤 4 前,请先执行步骤 1 或步骤 2,确保认证页仍然打开并停留在验证码页。');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEFAULT_OPENAI_NODE_BY_STEP = Object.freeze({
|
const DEFAULT_OPENAI_NODE_BY_STEP = Object.freeze({
|
||||||
1: 'open-chatgpt',
|
1: 'open-chatgpt',
|
||||||
2: 'submit-signup-email',
|
2: 'submit-signup-email',
|
||||||
@@ -1278,9 +1261,6 @@
|
|||||||
if (typeof assertNodeExecutionAllowedForState === 'function') {
|
if (typeof assertNodeExecutionAllowedForState === 'function') {
|
||||||
assertNodeExecutionAllowedForState(nodeId, requestState, '手动执行节点');
|
assertNodeExecutionAllowedForState(nodeId, requestState, '手动执行节点');
|
||||||
}
|
}
|
||||||
if (message.source === 'sidepanel') {
|
|
||||||
await ensureManualStepPrerequisites(resolvedStep);
|
|
||||||
}
|
|
||||||
if (message.source === 'sidepanel') {
|
if (message.source === 'sidepanel') {
|
||||||
await invalidateDownstreamAfterStepRestart(resolvedStep, { logLabel: `节点 ${nodeId} 重新执行` });
|
await invalidateDownstreamAfterStepRestart(resolvedStep, { logLabel: `节点 ${nodeId} 重新执行` });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ function createRouter(overrides = {}) {
|
|||||||
executedSteps: [],
|
executedSteps: [],
|
||||||
accountRecords: [],
|
accountRecords: [],
|
||||||
};
|
};
|
||||||
const nodeByStep = {
|
const nodeByStep = overrides.nodeByStep || {
|
||||||
1: 'open-chatgpt',
|
1: 'open-chatgpt',
|
||||||
2: 'submit-signup-email',
|
2: 'submit-signup-email',
|
||||||
3: 'fill-password',
|
3: 'fill-password',
|
||||||
@@ -42,6 +42,7 @@ function createRouter(overrides = {}) {
|
|||||||
12: 'confirm-oauth',
|
12: 'confirm-oauth',
|
||||||
13: 'platform-verify',
|
13: 'platform-verify',
|
||||||
};
|
};
|
||||||
|
const stepByNode = overrides.stepByNode || null;
|
||||||
const normalStepByNode = {
|
const normalStepByNode = {
|
||||||
'open-chatgpt': 1,
|
'open-chatgpt': 1,
|
||||||
'submit-signup-email': 2,
|
'submit-signup-email': 2,
|
||||||
@@ -67,6 +68,12 @@ function createRouter(overrides = {}) {
|
|||||||
};
|
};
|
||||||
const getStepForNode = (nodeId) => {
|
const getStepForNode = (nodeId) => {
|
||||||
const state = normalizeState(overrides.state || {});
|
const state = normalizeState(overrides.state || {});
|
||||||
|
if (typeof overrides.getStepIdByNodeIdForState === 'function') {
|
||||||
|
return overrides.getStepIdByNodeIdForState(nodeId, state) || 0;
|
||||||
|
}
|
||||||
|
if (stepByNode && Object.prototype.hasOwnProperty.call(stepByNode, nodeId)) {
|
||||||
|
return stepByNode[nodeId] || 0;
|
||||||
|
}
|
||||||
return (state.plusModeEnabled ? plusStepByNode : normalStepByNode)[nodeId] || 0;
|
return (state.plusModeEnabled ? plusStepByNode : normalStepByNode)[nodeId] || 0;
|
||||||
};
|
};
|
||||||
const normalizeState = (state = {}) => {
|
const normalizeState = (state = {}) => {
|
||||||
@@ -133,8 +140,10 @@ function createRouter(overrides = {}) {
|
|||||||
getPendingAutoRunTimerPlan: () => null,
|
getPendingAutoRunTimerPlan: () => null,
|
||||||
getSourceLabel: () => '',
|
getSourceLabel: () => '',
|
||||||
getState: async () => normalizeState(overrides.state || { nodeStatuses: { 'fill-password': 'pending' } }),
|
getState: async () => normalizeState(overrides.state || { nodeStatuses: { 'fill-password': 'pending' } }),
|
||||||
getNodeIdsForState: () => ['open-chatgpt', 'submit-signup-email', 'fill-password', 'fetch-signup-code', 'fill-profile', 'wait-registration-success', 'oauth-login', 'fetch-login-code', 'confirm-oauth', 'platform-verify'],
|
getNodeIdsForState: overrides.getNodeIdsForState || (() => ['open-chatgpt', 'submit-signup-email', 'fill-password', 'fetch-signup-code', 'fill-profile', 'wait-registration-success', 'oauth-login', 'fetch-login-code', 'confirm-oauth', 'platform-verify']),
|
||||||
getStepIdByNodeIdForState: (nodeId, state = {}) => (state.plusModeEnabled ? plusStepByNode : normalStepByNode)[nodeId] || 0,
|
getStepIdByNodeIdForState: overrides.getStepIdByNodeIdForState || ((nodeId, state = {}) => (stepByNode && Object.prototype.hasOwnProperty.call(stepByNode, nodeId))
|
||||||
|
? stepByNode[nodeId] || 0
|
||||||
|
: (state.plusModeEnabled ? plusStepByNode : normalStepByNode)[nodeId] || 0),
|
||||||
getStepDefinitionForState: overrides.getStepDefinitionForState,
|
getStepDefinitionForState: overrides.getStepDefinitionForState,
|
||||||
getStepIdsForState: overrides.getStepIdsForState,
|
getStepIdsForState: overrides.getStepIdsForState,
|
||||||
getLastStepIdForState: overrides.getLastStepIdForState,
|
getLastStepIdForState: overrides.getLastStepIdForState,
|
||||||
@@ -624,24 +633,75 @@ test('message router stops the flow and surfaces cloudflare security block error
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('message router blocks manual step 4 execution when signup page tab is missing', async () => {
|
test('message router delegates OpenAI manual step 4 to the OpenAI node executor', async () => {
|
||||||
const { router, events } = createRouter({
|
const { router, events } = createRouter({
|
||||||
getTabId: async () => null,
|
getTabId: async () => null,
|
||||||
isTabAlive: async () => false,
|
isTabAlive: async () => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
await assert.rejects(
|
await router.handleMessage({
|
||||||
() => router.handleMessage({
|
type: 'EXECUTE_NODE',
|
||||||
type: 'EXECUTE_NODE',
|
source: 'sidepanel',
|
||||||
source: 'sidepanel',
|
nodeId: 'fetch-signup-code',
|
||||||
nodeId: 'fetch-signup-code',
|
payload: { nodeId: 'fetch-signup-code' },
|
||||||
payload: { nodeId: 'fetch-signup-code' },
|
}, {});
|
||||||
}, {}),
|
|
||||||
/手动执行步骤 4 前,请先执行步骤 1 或步骤 2/
|
|
||||||
);
|
|
||||||
|
|
||||||
assert.deepStrictEqual(events.invalidations, []);
|
assert.deepStrictEqual(events.invalidations, [
|
||||||
assert.deepStrictEqual(events.executedSteps, []);
|
{ step: 4, options: { logLabel: '节点 fetch-signup-code 重新执行' } },
|
||||||
|
]);
|
||||||
|
assert.deepStrictEqual(events.executedSteps, [4]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('message router delegates Kiro manual step 4 without OpenAI auth-tab prerequisites', async () => {
|
||||||
|
const kiroNodeByStep = {
|
||||||
|
1: 'kiro-open-register-page',
|
||||||
|
2: 'kiro-submit-email',
|
||||||
|
3: 'kiro-submit-name',
|
||||||
|
4: 'kiro-submit-verification-code',
|
||||||
|
5: 'kiro-submit-password',
|
||||||
|
6: 'kiro-complete-register-consent',
|
||||||
|
7: 'kiro-start-desktop-authorize',
|
||||||
|
8: 'kiro-complete-desktop-authorize',
|
||||||
|
9: 'kiro-upload-credential',
|
||||||
|
};
|
||||||
|
const kiroStepByNode = Object.fromEntries(
|
||||||
|
Object.entries(kiroNodeByStep).map(([step, nodeId]) => [nodeId, Number(step)])
|
||||||
|
);
|
||||||
|
const { router, events } = createRouter({
|
||||||
|
state: {
|
||||||
|
activeFlowId: 'kiro',
|
||||||
|
flowId: 'kiro',
|
||||||
|
nodeStatuses: {
|
||||||
|
'kiro-open-register-page': 'completed',
|
||||||
|
'kiro-submit-email': 'completed',
|
||||||
|
'kiro-submit-name': 'completed',
|
||||||
|
'kiro-submit-verification-code': 'failed',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nodeByStep: kiroNodeByStep,
|
||||||
|
stepByNode: kiroStepByNode,
|
||||||
|
getNodeIdsForState: () => Object.values(kiroNodeByStep),
|
||||||
|
getTabId: async (sourceId) => {
|
||||||
|
assert.notEqual(sourceId, 'openai-auth');
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
isTabAlive: async (sourceId) => {
|
||||||
|
assert.notEqual(sourceId, 'openai-auth');
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await router.handleMessage({
|
||||||
|
type: 'EXECUTE_NODE',
|
||||||
|
source: 'sidepanel',
|
||||||
|
nodeId: 'kiro-submit-verification-code',
|
||||||
|
payload: { nodeId: 'kiro-submit-verification-code' },
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
assert.deepStrictEqual(events.invalidations, [
|
||||||
|
{ step: 4, options: { logLabel: '节点 kiro-submit-verification-code 重新执行' } },
|
||||||
|
]);
|
||||||
|
assert.deepStrictEqual(events.executedSteps, [4]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('message router resolves GPC OTP manual confirmation without completing step early', async () => {
|
test('message router resolves GPC OTP manual confirmation without completing step early', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user