修复问题
This commit is contained in:
@@ -181,6 +181,34 @@ test('message router syncs signup phone runtime state from step 2 payload immedi
|
||||
assert.deepStrictEqual(events.signupPhoneStates, []);
|
||||
});
|
||||
|
||||
test('message router clears stale signup phone runtime when step 2 resolves email identity', async () => {
|
||||
const { router, events } = createRouter({
|
||||
state: {
|
||||
stepStatuses: { 3: 'pending' },
|
||||
accountIdentifierType: 'phone',
|
||||
accountIdentifier: '+66959916439',
|
||||
signupPhoneNumber: '+66959916439',
|
||||
signupPhoneActivation: { activationId: 'old', phoneNumber: '+66959916439' },
|
||||
},
|
||||
});
|
||||
|
||||
await router.handleStepData(2, {
|
||||
email: 'user@example.com',
|
||||
accountIdentifierType: 'email',
|
||||
accountIdentifier: 'user@example.com',
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(events.emailStates, ['user@example.com']);
|
||||
assert.deepStrictEqual(events.signupPhoneSilentStates, [null]);
|
||||
assert.ok(events.stateUpdates.some((updates) => (
|
||||
updates.accountIdentifierType === 'email'
|
||||
&& updates.accountIdentifier === 'user@example.com'
|
||||
&& updates.signupPhoneNumber === ''
|
||||
&& updates.signupPhoneActivation === null
|
||||
&& updates.signupPhoneCompletedActivation === null
|
||||
)));
|
||||
});
|
||||
|
||||
test('message router does not overwrite a completed step 3 when step 2 is replayed', async () => {
|
||||
const { router, events } = createRouter({
|
||||
state: { stepStatuses: { 3: 'completed' } },
|
||||
|
||||
@@ -180,6 +180,146 @@ test('step 2 uses phone activation when resolved signup method is phone', async
|
||||
]);
|
||||
});
|
||||
|
||||
test('step 2 reuses existing signup phone activation without acquiring a new number', async () => {
|
||||
const completedPayloads = [];
|
||||
const sequence = [];
|
||||
const sentPayloads = [];
|
||||
const activation = {
|
||||
activationId: 'existing-signup-activation',
|
||||
phoneNumber: '+446700000001',
|
||||
provider: 'hero-sms',
|
||||
serviceCode: 'dr',
|
||||
countryId: 16,
|
||||
countryLabel: 'United Kingdom',
|
||||
};
|
||||
|
||||
const executor = step2Api.createStep2Executor({
|
||||
addLog: async () => {},
|
||||
chrome: { tabs: { update: async () => {} } },
|
||||
completeStepFromBackground: async (step, payload) => {
|
||||
completedPayloads.push({ step, payload });
|
||||
},
|
||||
ensureContentScriptReadyOnTab: async () => {},
|
||||
ensureSignupEntryPageReady: async () => ({ tabId: 15 }),
|
||||
ensureSignupPostIdentityPageReadyInTab: async () => ({
|
||||
state: 'phone_verification_page',
|
||||
url: 'https://auth.openai.com/phone-verification',
|
||||
}),
|
||||
getTabId: async () => 15,
|
||||
isTabAlive: async () => true,
|
||||
phoneVerificationHelpers: {
|
||||
normalizeActivation: (record) => record,
|
||||
prepareSignupPhoneActivation: async () => {
|
||||
throw new Error('prepareSignupPhoneActivation should not run when signup activation already exists');
|
||||
},
|
||||
cancelSignupPhoneActivation: async () => {
|
||||
throw new Error('activation should not be cancelled on success');
|
||||
},
|
||||
},
|
||||
resolveSignupMethod: () => 'phone',
|
||||
resolveSignupEmailForFlow: async () => {
|
||||
throw new Error('email resolver should not run for phone signup');
|
||||
},
|
||||
sendToContentScriptResilient: async (_source, message) => {
|
||||
if (message.type === 'ENSURE_SIGNUP_PHONE_ENTRY_READY') {
|
||||
sequence.push('ensureSignupPhoneEntryReady');
|
||||
return { ready: true, state: 'phone_entry' };
|
||||
}
|
||||
sequence.push('submitSignupPhone');
|
||||
sentPayloads.push(message.payload);
|
||||
return { submitted: true };
|
||||
},
|
||||
SIGNUP_PAGE_INJECT_FILES: [],
|
||||
});
|
||||
|
||||
await executor.executeStep2({
|
||||
signupMethod: 'phone',
|
||||
signupPhoneActivation: activation,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(sequence, [
|
||||
'ensureSignupPhoneEntryReady',
|
||||
'submitSignupPhone',
|
||||
]);
|
||||
assert.deepStrictEqual(sentPayloads, [
|
||||
{
|
||||
signupMethod: 'phone',
|
||||
phoneNumber: '+446700000001',
|
||||
countryId: 16,
|
||||
countryLabel: 'United Kingdom',
|
||||
},
|
||||
]);
|
||||
assert.equal(completedPayloads[0].payload.signupPhoneActivation, activation);
|
||||
});
|
||||
|
||||
test('step 2 submits manual signup phone without acquiring a number', async () => {
|
||||
const completedPayloads = [];
|
||||
const sentPayloads = [];
|
||||
|
||||
const executor = step2Api.createStep2Executor({
|
||||
addLog: async () => {},
|
||||
chrome: { tabs: { update: async () => {} } },
|
||||
completeStepFromBackground: async (step, payload) => {
|
||||
completedPayloads.push({ step, payload });
|
||||
},
|
||||
ensureContentScriptReadyOnTab: async () => {},
|
||||
ensureSignupEntryPageReady: async () => ({ tabId: 16 }),
|
||||
ensureSignupPostIdentityPageReadyInTab: async () => ({
|
||||
state: 'phone_verification_page',
|
||||
url: 'https://auth.openai.com/phone-verification',
|
||||
}),
|
||||
getTabId: async () => 16,
|
||||
isTabAlive: async () => true,
|
||||
phoneVerificationHelpers: {
|
||||
prepareSignupPhoneActivation: async () => {
|
||||
throw new Error('prepareSignupPhoneActivation should not run for manual signup phone');
|
||||
},
|
||||
},
|
||||
resolveSignupMethod: () => 'phone',
|
||||
resolveSignupEmailForFlow: async () => {
|
||||
throw new Error('email resolver should not run for phone signup');
|
||||
},
|
||||
sendToContentScriptResilient: async (_source, message) => {
|
||||
if (message.type === 'ENSURE_SIGNUP_PHONE_ENTRY_READY') {
|
||||
return { ready: true, state: 'phone_entry' };
|
||||
}
|
||||
sentPayloads.push(message.payload);
|
||||
return { submitted: true };
|
||||
},
|
||||
SIGNUP_PAGE_INJECT_FILES: [],
|
||||
});
|
||||
|
||||
await executor.executeStep2({
|
||||
signupMethod: 'phone',
|
||||
signupPhoneNumber: '+446700000002',
|
||||
accountIdentifierType: 'phone',
|
||||
accountIdentifier: '+446700000002',
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(sentPayloads, [
|
||||
{
|
||||
signupMethod: 'phone',
|
||||
phoneNumber: '+446700000002',
|
||||
countryId: null,
|
||||
countryLabel: '',
|
||||
},
|
||||
]);
|
||||
assert.deepStrictEqual(completedPayloads, [
|
||||
{
|
||||
step: 2,
|
||||
payload: {
|
||||
accountIdentifierType: 'phone',
|
||||
accountIdentifier: '+446700000002',
|
||||
signupPhoneNumber: '+446700000002',
|
||||
signupPhoneActivation: null,
|
||||
nextSignupState: 'phone_verification_page',
|
||||
nextSignupUrl: 'https://auth.openai.com/phone-verification',
|
||||
skippedPasswordStep: true,
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('step 2 stops with an explicit error instead of silently skipping 3/4/5 on chatgpt home', async () => {
|
||||
const completedPayloads = [];
|
||||
const logs = [];
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
function loadPhoneCountryUtils() {
|
||||
const source = fs.readFileSync('content/phone-country-utils.js', 'utf8');
|
||||
const root = {};
|
||||
return new Function('self', `${source}; return self.MultiPagePhoneCountryUtils;`)(root);
|
||||
}
|
||||
|
||||
test('phone country utils extracts dial codes from current OpenAI country labels', () => {
|
||||
const utils = loadPhoneCountryUtils();
|
||||
|
||||
assert.equal(utils.extractDialCodeFromText('United Kingdom (+44)'), '44');
|
||||
assert.equal(utils.extractDialCodeFromText('United Kingdom +(44)'), '44');
|
||||
assert.equal(utils.extractDialCodeFromText('United Kingdom +44'), '44');
|
||||
});
|
||||
|
||||
test('phone country utils resolves country dial code from provider phone numbers', () => {
|
||||
const utils = loadPhoneCountryUtils();
|
||||
|
||||
assert.equal(utils.resolveDialCodeFromPhoneNumber('447423278610'), '44');
|
||||
assert.equal(utils.resolveDialCodeFromPhoneNumber('+8613800138000'), '86');
|
||||
assert.equal(utils.resolveDialCodeFromPhoneNumber('12461234567'), '1246');
|
||||
});
|
||||
|
||||
test('phone country utils finds country options by phone dial code and country aliases', () => {
|
||||
const utils = loadPhoneCountryUtils();
|
||||
const options = [
|
||||
{ value: 'ID', textContent: 'Indonesia +(62)' },
|
||||
{ value: 'GB', textContent: 'United Kingdom +(44)' },
|
||||
];
|
||||
|
||||
assert.equal(utils.findOptionByPhoneNumber(options, '447423278610'), options[1]);
|
||||
assert.equal(utils.findOptionByCountryLabel(options, 'England'), options[1]);
|
||||
});
|
||||
|
||||
test('phone country utils is loaded before phone auth content scripts', () => {
|
||||
const manifest = JSON.parse(fs.readFileSync('manifest.json', 'utf8'));
|
||||
const authScript = manifest.content_scripts.find((entry) => (
|
||||
Array.isArray(entry.matches)
|
||||
&& entry.matches.some((match) => match.includes('auth.openai.com'))
|
||||
));
|
||||
|
||||
assert.ok(authScript, 'missing auth content script');
|
||||
assert.ok(authScript.js.includes('content/phone-country-utils.js'));
|
||||
assert.ok(
|
||||
authScript.js.indexOf('content/phone-country-utils.js') < authScript.js.indexOf('content/phone-auth.js'),
|
||||
'phone-country-utils.js must load before phone-auth.js'
|
||||
);
|
||||
assert.ok(
|
||||
authScript.js.indexOf('content/phone-country-utils.js') < authScript.js.indexOf('content/signup-page.js'),
|
||||
'phone-country-utils.js must load before signup-page.js'
|
||||
);
|
||||
|
||||
const background = fs.readFileSync('background.js', 'utf8');
|
||||
const injectLine = background.match(/const\s+SIGNUP_PAGE_INJECT_FILES\s*=\s*\[[^\n]+\]/)?.[0] || '';
|
||||
assert.ok(injectLine.includes("'content/phone-country-utils.js'"));
|
||||
assert.ok(
|
||||
injectLine.indexOf("'content/phone-country-utils.js'") < injectLine.indexOf("'content/phone-auth.js'"),
|
||||
'dynamic signup injection must load phone-country-utils.js before phone-auth.js'
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user