限制手机号注册流程使用号码复用

This commit is contained in:
QLHazyCoder
2026-05-15 18:23:41 +08:00
parent 81fc40706a
commit 4c2ab31b07
9 changed files with 929 additions and 26 deletions
@@ -47,6 +47,20 @@ test('background free reusable phone setter can recover local HeroSMS activation
assert.match(setterBlock, /manualOnly:\s*!activationId/);
});
test('background blocks free reusable phone mutations while phone signup owns the identity', () => {
const source = fs.readFileSync('background.js', 'utf8');
const clearStart = source.indexOf('async function clearFreeReusablePhoneActivation');
const setterStart = source.indexOf('async function setFreeReusablePhoneActivation');
const setterEnd = source.indexOf('// ============================================================\n// Tab Registry', setterStart);
const clearBlock = source.slice(clearStart, setterStart);
const setterBlock = source.slice(setterStart, setterEnd);
assert.match(source, /function isPhoneSignupIdentityStateForReuse\(/);
assert.match(source, /function hasSignupPhoneActivationState\(/);
assert.match(clearBlock, /isPhoneSignupIdentityStateForReuse\(state\)/);
assert.match(setterBlock, /isPhoneSignupIdentityStateForReuse\(state\)/);
});
test('background HeroSMS phone prefix inference covers built-in major countries', () => {
const source = fs.readFileSync('background.js', 'utf8');
const supportedStart = source.indexOf('const HERO_SMS_SUPPORTED_COUNTRY_IDS = [');
@@ -132,6 +146,124 @@ test('SAVE_SETTING broadcasts free phone reuse setting updates for realtime side
);
});
test('SAVE_SETTING preserves phone reuse preferences while phone signup is selected', async () => {
const source = fs.readFileSync('background/message-router.js', 'utf8');
const globalScope = { console };
const api = new Function('self', `${source}; return self.MultiPageBackgroundMessageRouter;`)(globalScope);
const persistedPayloads = [];
let state = {
signupMethod: 'phone',
phoneVerificationEnabled: true,
plusModeEnabled: false,
phoneSmsReuseEnabled: true,
heroSmsReuseEnabled: true,
freePhoneReuseEnabled: true,
freePhoneReuseAutoEnabled: true,
phonePreferredActivation: {
provider: 'hero-sms',
activationId: 'stored',
phoneNumber: '66950001111',
},
};
const router = api.createMessageRouter({
addLog: async () => {},
buildLuckmailSessionSettingsPayload: () => ({}),
buildPersistentSettingsPayload: (input = {}) => ({
signupMethod: String(input.signupMethod || state.signupMethod),
phoneSmsReuseEnabled: Boolean(input.phoneSmsReuseEnabled),
heroSmsReuseEnabled: Boolean(input.heroSmsReuseEnabled),
freePhoneReuseEnabled: Boolean(input.freePhoneReuseEnabled),
freePhoneReuseAutoEnabled: Boolean(input.freePhoneReuseAutoEnabled),
phonePreferredActivation: input.phonePreferredActivation ?? null,
}),
broadcastDataUpdate: () => {},
getState: async () => ({ ...state }),
setPersistentSettings: async (updates) => {
persistedPayloads.push({ ...updates });
},
setState: async (updates) => {
state = { ...state, ...updates };
},
});
const response = await router.handleMessage({
type: 'SAVE_SETTING',
payload: {
signupMethod: 'phone',
phoneSmsReuseEnabled: false,
heroSmsReuseEnabled: false,
freePhoneReuseEnabled: false,
freePhoneReuseAutoEnabled: false,
phonePreferredActivation: null,
},
});
assert.equal(response.ok, true);
assert.equal(state.phoneSmsReuseEnabled, true);
assert.equal(state.heroSmsReuseEnabled, true);
assert.equal(state.freePhoneReuseEnabled, true);
assert.equal(state.freePhoneReuseAutoEnabled, true);
assert.deepStrictEqual(state.phonePreferredActivation, {
provider: 'hero-sms',
activationId: 'stored',
phoneNumber: '66950001111',
});
assert.equal(persistedPayloads[0].phoneSmsReuseEnabled, true);
assert.equal(persistedPayloads[0].freePhoneReuseEnabled, true);
});
test('SAVE_SETTING allows phone reuse preferences after switching back to email signup', async () => {
const source = fs.readFileSync('background/message-router.js', 'utf8');
const globalScope = { console };
const api = new Function('self', `${source}; return self.MultiPageBackgroundMessageRouter;`)(globalScope);
let state = {
signupMethod: 'phone',
phoneVerificationEnabled: true,
plusModeEnabled: false,
phoneSmsReuseEnabled: true,
heroSmsReuseEnabled: true,
freePhoneReuseEnabled: true,
freePhoneReuseAutoEnabled: true,
};
const router = api.createMessageRouter({
addLog: async () => {},
buildLuckmailSessionSettingsPayload: () => ({}),
buildPersistentSettingsPayload: (input = {}) => ({
signupMethod: String(input.signupMethod || state.signupMethod),
phoneSmsReuseEnabled: Boolean(input.phoneSmsReuseEnabled),
heroSmsReuseEnabled: Boolean(input.heroSmsReuseEnabled),
freePhoneReuseEnabled: Boolean(input.freePhoneReuseEnabled),
freePhoneReuseAutoEnabled: Boolean(input.freePhoneReuseAutoEnabled),
}),
broadcastDataUpdate: () => {},
getState: async () => ({ ...state }),
setPersistentSettings: async () => {},
setState: async (updates) => {
state = { ...state, ...updates };
},
});
const response = await router.handleMessage({
type: 'SAVE_SETTING',
payload: {
signupMethod: 'email',
phoneSmsReuseEnabled: false,
heroSmsReuseEnabled: false,
freePhoneReuseEnabled: false,
freePhoneReuseAutoEnabled: false,
},
});
assert.equal(response.ok, true);
assert.equal(state.signupMethod, 'email');
assert.equal(state.phoneSmsReuseEnabled, false);
assert.equal(state.heroSmsReuseEnabled, false);
assert.equal(state.freePhoneReuseEnabled, false);
assert.equal(state.freePhoneReuseAutoEnabled, false);
});
test('SAVE_SETTING broadcasts operation delay setting without background success log', async () => {
const source = fs.readFileSync('background/message-router.js', 'utf8');
const globalScope = { console };
+235
View File
@@ -140,6 +140,67 @@ test('signup phone helper persists signup runtime state without touching add-pho
assert.ok(!setStateCalls.some((updates) => Object.prototype.hasOwnProperty.call(updates, 'currentPhoneActivation')));
});
test('signup phone helper buys a fresh number instead of using reuse entries', async () => {
const actions = [];
let currentState = {
heroSmsApiKey: 'demo-key',
signupMethod: 'phone',
phoneSmsReuseEnabled: true,
heroSmsReuseEnabled: true,
phonePreferredActivation: {
activationId: 'preferred-activation',
phoneNumber: '66950002222',
provider: 'hero-sms',
serviceCode: 'dr',
countryId: 52,
successfulUses: 0,
maxUses: 3,
},
reusablePhoneActivation: {
activationId: 'paid-reuse',
phoneNumber: '66950003333',
provider: 'hero-sms',
serviceCode: 'dr',
countryId: 52,
successfulUses: 1,
maxUses: 3,
},
};
const helpers = api.createPhoneVerificationHelpers({
addLog: async () => {},
ensureStep8SignupPageReady: async () => {},
fetchImpl: async (url) => {
const parsedUrl = new URL(url);
const action = parsedUrl.searchParams.get('action');
actions.push(action);
if (action === 'reactivate') {
throw new Error('phone signup should not reactivate reusable numbers');
}
if (action === 'getPrices') {
return { ok: true, text: async () => buildHeroSmsPricesPayload() };
}
if (action === 'getNumber') {
return { ok: true, text: async () => 'ACCESS_NUMBER:signup-fresh:66959916439' };
}
throw new Error(`Unexpected HeroSMS action: ${action}`);
},
getState: async () => currentState,
sendToContentScriptResilient: async () => ({}),
setState: async (updates) => {
currentState = { ...currentState, ...updates };
},
sleepWithStop: async () => {},
throwIfStopped: () => {},
});
const activation = await helpers.prepareSignupPhoneActivation(currentState);
assert.equal(activation.activationId, 'signup-fresh');
assert.deepStrictEqual(actions, ['getPrices', 'getNumber']);
assert.equal(currentState.signupPhoneNumber, '66959916439');
assert.equal(currentState.reusablePhoneActivation.activationId, 'paid-reuse');
});
test('signup phone helper polls signup SMS code and keeps activation purpose isolated', async () => {
const setStateCalls = [];
let currentState = {
@@ -274,6 +335,82 @@ test('signup phone helper finalizes or cancels signup activation without clearin
assert.ok(!setStateCalls.some((updates) => Object.prototype.hasOwnProperty.call(updates, 'currentPhoneActivation')));
});
test('signup phone helper does not store signup numbers into the reusable pool', async () => {
const setStateCalls = [];
let currentState = {
heroSmsApiKey: 'demo-key',
signupMethod: 'phone',
phoneSmsReuseEnabled: true,
heroSmsReuseEnabled: true,
signupPhoneActivation: {
activationId: 'signup-123',
phoneNumber: '66959916439',
provider: 'hero-sms',
serviceCode: 'dr',
countryId: 52,
successfulUses: 0,
maxUses: 3,
},
reusablePhoneActivation: {
activationId: 'paid-reuse',
phoneNumber: '66950003333',
provider: 'hero-sms',
serviceCode: 'dr',
countryId: 52,
successfulUses: 1,
maxUses: 3,
},
phoneReusableActivationPool: [
{
activationId: 'pool-reuse',
phoneNumber: '66950004444',
provider: 'hero-sms',
serviceCode: 'dr',
countryId: 52,
successfulUses: 1,
maxUses: 3,
},
],
};
const helpers = api.createPhoneVerificationHelpers({
addLog: async () => {},
ensureStep8SignupPageReady: async () => {},
fetchImpl: async (url) => {
const parsedUrl = new URL(url);
const action = parsedUrl.searchParams.get('action');
if (action === 'setStatus') {
return { ok: true, text: async () => 'ACCESS_READY' };
}
throw new Error(`Unexpected HeroSMS action: ${action}`);
},
getState: async () => currentState,
sendToContentScriptResilient: async () => ({}),
setState: async (updates) => {
setStateCalls.push(updates);
currentState = { ...currentState, ...updates };
},
sleepWithStop: async () => {},
throwIfStopped: () => {},
});
await helpers.finalizeSignupPhoneActivationAfterSuccess(currentState, currentState.signupPhoneActivation);
assert.equal(currentState.reusablePhoneActivation.activationId, 'paid-reuse');
assert.deepStrictEqual(
currentState.phoneReusableActivationPool.map((entry) => entry.activationId),
['pool-reuse']
);
assert.equal(
setStateCalls.some((updates) => updates?.reusablePhoneActivation?.activationId === 'signup-123'),
false
);
assert.equal(
setStateCalls.some((updates) => Array.isArray(updates?.phoneReusableActivationPool)
&& updates.phoneReusableActivationPool.some((entry) => entry.activationId === 'signup-123')),
false
);
});
test('signup phone helper completes signup SMS verification without touching add-phone activation', async () => {
const setStateCalls = [];
const contentMessages = [];
@@ -4953,6 +5090,104 @@ test('phone verification helper gives automatic free reuse priority over paid re
assert.equal(currentState.reusablePhoneActivation.activationId, 'paid-reuse');
});
test('phone verification helper ignores reuse entries for phone signup identity', async () => {
const requests = [];
let currentState = {
heroSmsApiKey: 'demo-key',
signupMethod: 'phone',
accountIdentifierType: 'phone',
accountIdentifier: '66959916439',
phoneSmsReuseEnabled: true,
heroSmsReuseEnabled: true,
freePhoneReuseEnabled: true,
freePhoneReuseAutoEnabled: true,
verificationResendCount: 0,
currentPhoneActivation: null,
reusablePhoneActivation: {
activationId: 'paid-reuse',
phoneNumber: '66950003333',
provider: 'hero-sms',
serviceCode: 'dr',
countryId: 52,
countryLabel: 'Thailand',
successfulUses: 0,
maxUses: 3,
},
freeReusablePhoneActivation: {
activationId: 'free-priority',
phoneNumber: '66950004444',
provider: 'hero-sms',
serviceCode: 'dr',
countryId: 52,
countryLabel: 'Thailand',
successfulUses: 0,
maxUses: 3,
source: 'free-manual-reuse',
},
};
const helpers = api.createPhoneVerificationHelpers({
addLog: async () => {},
ensureStep8SignupPageReady: async () => {},
fetchImpl: async (url) => {
const parsedUrl = new URL(url);
requests.push(parsedUrl);
const action = parsedUrl.searchParams.get('action');
const id = parsedUrl.searchParams.get('id');
if (action === 'reactivate' || id === 'free-priority') {
throw new Error(`phone signup identity should not use reusable activation: ${action}:${id || ''}`);
}
if (action === 'getPrices') {
return { ok: true, text: async () => buildHeroSmsPricesPayload() };
}
if (action === 'getNumber') {
return { ok: true, text: async () => 'ACCESS_NUMBER:fresh-phone:66950008888' };
}
if (action === 'getStatus' && id === 'fresh-phone') {
return { ok: true, text: async () => 'STATUS_OK:445566' };
}
if (action === 'setStatus' && id === 'fresh-phone') {
return { ok: true, text: async () => 'ACCESS_ACTIVATION' };
}
throw new Error(`Unexpected HeroSMS action: ${action}:${id || ''}`);
},
getOAuthFlowStepTimeoutMs: async (defaultTimeoutMs) => defaultTimeoutMs,
getState: async () => ({ ...currentState }),
sendToContentScriptResilient: async (_source, message) => {
if (message.type === 'SUBMIT_PHONE_NUMBER') {
return { phoneVerificationPage: true, url: 'https://auth.openai.com/phone-verification' };
}
if (message.type === 'SUBMIT_PHONE_VERIFICATION_CODE') {
return { success: true, consentReady: true, url: 'https://auth.openai.com/authorize' };
}
throw new Error(`Unexpected content-script message: ${message.type}`);
},
setState: async (updates) => {
currentState = { ...currentState, ...updates };
},
sleepWithStop: async () => {},
throwIfStopped: () => {},
});
const result = await helpers.completePhoneVerificationFlow(1, {
addPhonePage: true,
phoneVerificationPage: false,
url: 'https://auth.openai.com/add-phone',
});
assert.deepStrictEqual(result, {
success: true,
consentReady: true,
url: 'https://auth.openai.com/authorize',
});
assert.deepStrictEqual(
requests.map((requestUrl) => requestUrl.searchParams.get('action')),
['getPrices', 'getNumber', 'getStatus', 'setStatus']
);
assert.equal(currentState.freeReusablePhoneActivation.activationId, 'free-priority');
assert.equal(currentState.reusablePhoneActivation.activationId, 'paid-reuse');
});
test('phone verification helper hands off manual-only free reuse even when automatic free reuse is enabled', async () => {
const requests = [];
const messages = [];
@@ -519,6 +519,28 @@ test('updatePhoneVerificationSettingsUI toggles SMS rows from the sms switch and
const api = new Function(`
let phoneVerificationSectionExpanded = false;
let latestState = {};
let phoneSignupReuseUiWasLocked = false;
const PHONE_SIGNUP_REUSE_LOCK_TITLE = '手机号注册流程不使用号码复用,切回邮箱注册后会恢复原设置';
const SIGNUP_METHOD_EMAIL = 'email';
const SIGNUP_METHOD_PHONE = 'phone';
const DEFAULT_SIGNUP_METHOD = SIGNUP_METHOD_EMAIL;
const DEFAULT_HERO_SMS_REUSE_ENABLED = true;
function createMockClassList() {
const values = new Set();
return {
toggle(name, force) {
const enabled = force === undefined ? !values.has(name) : Boolean(force);
if (enabled) values.add(name);
else values.delete(name);
},
contains(name) {
return values.has(name);
},
};
}
function createMockRow() {
return { style: { display: 'none' }, classList: createMockClassList(), title: '' };
}
const inputPhoneVerificationEnabled = { checked: false };
const rowPhoneVerificationEnabled = { style: { display: 'none' } };
const rowPhoneVerificationFold = { style: { display: 'none' } };
@@ -583,13 +605,24 @@ const rowHeroSmsCurrentNumber = { style: { display: 'none' } };
const rowHeroSmsCurrentCountdown = { style: { display: 'none' } };
const rowHeroSmsPriceTiers = { style: { display: 'none' } };
const rowHeroSmsCurrentCode = { style: { display: 'none' } };
const rowHeroSmsPreferredActivation = { style: { display: 'none' } };
const rowHeroSmsPreferredActivation = createMockRow();
const rowPhoneVerificationResendCount = { style: { display: 'none' } };
const rowPhoneReplacementLimit = { style: { display: 'none' } };
const rowPhoneCodeWaitSeconds = { style: { display: 'none' } };
const rowPhoneCodeTimeoutWindows = { style: { display: 'none' } };
const rowPhoneCodePollIntervalSeconds = { style: { display: 'none' } };
const rowPhoneCodePollMaxRounds = { style: { display: 'none' } };
const rowFreePhoneReuseEnabled = createMockRow();
const rowFreePhoneReuseAutoEnabled = createMockRow();
const rowFreeReusablePhone = createMockRow();
const heroSmsReuseRow = createMockRow();
const inputHeroSmsReuseEnabled = { checked: true, disabled: false, closest: () => heroSmsReuseRow };
const inputFreePhoneReuseEnabled = { checked: true, disabled: false };
const inputFreePhoneReuseAutoEnabled = { checked: true, disabled: false };
const selectHeroSmsPreferredActivation = { disabled: false };
const inputFreeReusablePhone = { disabled: false };
const btnSaveFreeReusablePhone = { disabled: false };
const btnClearFreeReusablePhone = { disabled: false };
const PHONE_SMS_PROVIDER_HERO_SMS = 'hero-sms';
const PHONE_SMS_PROVIDER_FIVE_SIM = '5sim';
const PHONE_SMS_PROVIDER_NEXSMS = 'nexsms';
@@ -602,10 +635,23 @@ function updateSignupMethodUI() {
function syncSignupPhoneInputFromState() {
rowSignupPhone.style.display = inputPhoneVerificationEnabled.checked && latestState.signupPhoneNumber ? '' : 'none';
}
function setFreePhoneReuseControlsLocked() {}
function setFreePhoneReuseControlsLocked(locked) {
inputFreePhoneReuseEnabled.disabled = Boolean(locked);
inputFreePhoneReuseAutoEnabled.disabled = Boolean(locked)
|| !Boolean(inputFreePhoneReuseEnabled.checked)
|| !Boolean(inputPhoneVerificationEnabled.checked && phoneVerificationSectionExpanded);
}
function isAutoRunLockedPhase() { return false; }
function isAutoRunScheduledPhase() { return false; }
${extractFunction('normalizeSignupMethod')}
${extractFunction('normalizeHeroSmsReuseEnabledValue')}
${extractFunction('isPhoneSignupReuseLocked')}
${extractFunction('getStoredPhoneSmsReuseEnabled')}
${extractFunction('getStoredFreePhoneReuseEnabled')}
${extractFunction('getStoredFreePhoneReuseAutoEnabled')}
${extractFunction('restorePhoneReuseControlsFromState')}
${extractFunction('setElementReuseLockedState')}
${extractFunction('updatePhoneVerificationSettingsUI')}
return {
@@ -642,12 +688,23 @@ return {
rowHeroSmsPriceTiers,
rowHeroSmsCurrentCode,
rowHeroSmsPreferredActivation,
rowFreePhoneReuseEnabled,
rowFreePhoneReuseAutoEnabled,
rowFreeReusablePhone,
rowPhoneVerificationResendCount,
rowPhoneReplacementLimit,
rowPhoneCodeWaitSeconds,
rowPhoneCodeTimeoutWindows,
rowPhoneCodePollIntervalSeconds,
rowPhoneCodePollMaxRounds,
heroSmsReuseRow,
inputHeroSmsReuseEnabled,
inputFreePhoneReuseEnabled,
inputFreePhoneReuseAutoEnabled,
selectHeroSmsPreferredActivation,
inputFreeReusablePhone,
btnSaveFreeReusablePhone,
btnClearFreeReusablePhone,
setSelectedPhoneSmsProvider(value) { selectPhoneSmsProvider.value = value; },
updatePhoneVerificationSettingsUI,
};
@@ -733,6 +790,46 @@ return {
assert.equal(api.rowPhoneCodePollIntervalSeconds.style.display, '');
assert.equal(api.rowPhoneCodePollMaxRounds.style.display, '');
api.setLatestState({
signupMethod: 'phone',
signupPhoneNumber: '66959916439',
phoneSmsReuseEnabled: true,
freePhoneReuseEnabled: true,
freePhoneReuseAutoEnabled: true,
});
api.updatePhoneVerificationSettingsUI();
assert.equal(api.inputHeroSmsReuseEnabled.checked, false);
assert.equal(api.inputHeroSmsReuseEnabled.disabled, true);
assert.equal(api.inputFreePhoneReuseEnabled.checked, false);
assert.equal(api.inputFreePhoneReuseEnabled.disabled, true);
assert.equal(api.inputFreePhoneReuseAutoEnabled.checked, false);
assert.equal(api.inputFreePhoneReuseAutoEnabled.disabled, true);
assert.equal(api.selectHeroSmsPreferredActivation.disabled, true);
assert.equal(api.inputFreeReusablePhone.disabled, true);
assert.equal(api.btnSaveFreeReusablePhone.disabled, true);
assert.equal(api.btnClearFreeReusablePhone.disabled, true);
assert.equal(api.rowFreePhoneReuseEnabled.classList.contains('is-disabled'), true);
assert.equal(api.rowFreeReusablePhone.classList.contains('is-disabled'), true);
api.setLatestState({
signupMethod: 'email',
signupPhoneNumber: '',
phoneSmsReuseEnabled: true,
freePhoneReuseEnabled: true,
freePhoneReuseAutoEnabled: true,
});
api.updatePhoneVerificationSettingsUI();
assert.equal(api.inputHeroSmsReuseEnabled.checked, true);
assert.equal(api.inputHeroSmsReuseEnabled.disabled, false);
assert.equal(api.inputFreePhoneReuseEnabled.checked, true);
assert.equal(api.inputFreePhoneReuseEnabled.disabled, false);
assert.equal(api.inputFreePhoneReuseAutoEnabled.checked, true);
assert.equal(api.inputFreePhoneReuseAutoEnabled.disabled, false);
assert.equal(api.selectHeroSmsPreferredActivation.disabled, false);
assert.equal(api.inputFreeReusablePhone.disabled, false);
assert.equal(api.btnSaveFreeReusablePhone.disabled, false);
assert.equal(api.btnClearFreeReusablePhone.disabled, false);
api.setSelectedPhoneSmsProvider('5sim');
api.updatePhoneVerificationSettingsUI();
assert.equal(api.rowFiveSimApiKey.style.display, '');
@@ -759,6 +856,19 @@ let latestState = {
fiveSimCountryOrder: ['thailand', 'england'],
heroSmsMinPrice: '0.0444',
fiveSimMinPrice: '0.3333',
phoneSmsReuseEnabled: false,
heroSmsReuseEnabled: false,
freePhoneReuseEnabled: false,
freePhoneReuseAutoEnabled: false,
phonePreferredActivation: {
provider: 'hero-sms',
activationId: 'stored-activation',
phoneNumber: '66950001111',
countryId: 52,
countryLabel: 'Thailand',
successfulUses: 2,
maxUses: 3,
},
};
let cloudflareDomainEditMode = false;
let cloudflareTempEmailDomainEditMode = false;
@@ -857,6 +967,9 @@ const PHONE_SMS_PROVIDER_HERO_SMS = 'hero-sms';
const PHONE_SMS_PROVIDER_FIVE_SIM = '5sim';
const PHONE_SMS_PROVIDER_NEXSMS = 'nexsms';
const DEFAULT_PHONE_SMS_PROVIDER = PHONE_SMS_PROVIDER_HERO_SMS;
const SIGNUP_METHOD_EMAIL = 'email';
const SIGNUP_METHOD_PHONE = 'phone';
const DEFAULT_SIGNUP_METHOD = SIGNUP_METHOD_EMAIL;
const DEFAULT_FIVE_SIM_COUNTRY_ID = 'vietnam';
const DEFAULT_FIVE_SIM_COUNTRY_LABEL = '越南 (Vietnam)';
const DEFAULT_FIVE_SIM_OPERATOR = 'any';
@@ -916,6 +1029,11 @@ ${extractFunction('normalizeHeroSmsAcquirePriority')}
${extractFunction('normalizeHeroSmsCountryId')}
${extractFunction('normalizeHeroSmsCountryLabel')}
${extractFunction('getSelectedHeroSmsCountryOption')}
${extractFunction('normalizeSignupMethod')}
${extractFunction('isPhoneSignupReuseLocked')}
${extractFunction('getStoredPhoneSmsReuseEnabled')}
${extractFunction('getStoredFreePhoneReuseEnabled')}
${extractFunction('getStoredFreePhoneReuseAutoEnabled')}
function syncHeroSmsFallbackSelectionOrderFromSelect() {
return [{ id: 52, label: 'Thailand' }, { id: 16, label: 'United Kingdom' }];
}
@@ -948,21 +1066,21 @@ return { collectSettingsPayload };
assert.equal(payload.nexSmsApiKey, 'nex-key');
assert.deepStrictEqual(payload.nexSmsCountryOrder, [1]);
assert.equal(payload.nexSmsServiceCode, 'ot');
assert.equal(payload.phoneSmsReuseEnabled, true);
assert.equal(payload.heroSmsReuseEnabled, true);
assert.equal(payload.freePhoneReuseEnabled, true);
assert.equal(payload.freePhoneReuseAutoEnabled, true);
assert.equal(payload.phoneSmsReuseEnabled, false);
assert.equal(payload.heroSmsReuseEnabled, false);
assert.equal(payload.freePhoneReuseEnabled, false);
assert.equal(payload.freePhoneReuseAutoEnabled, false);
assert.equal(payload.heroSmsAcquirePriority, 'price');
assert.equal(payload.heroSmsMinPrice, '0.03');
assert.equal(payload.heroSmsMaxPrice, '0.12');
assert.equal(payload.heroSmsPreferredPrice, '0.0512');
assert.deepStrictEqual(payload.phonePreferredActivation, {
provider: 'hero-sms',
activationId: 'demo-activation',
phoneNumber: '66958889999',
activationId: 'stored-activation',
phoneNumber: '66950001111',
countryId: 52,
countryLabel: 'Thailand',
successfulUses: 0,
successfulUses: 2,
maxUses: 3,
});
assert.equal(payload.phoneVerificationReplacementLimit, 5);