完善手机接码逻辑
This commit is contained in:
@@ -81,6 +81,7 @@ test('background account history settings are normalized independently from hotm
|
||||
extractFunction('normalizeSub2ApiGroupNames'),
|
||||
extractFunction('normalizeBoundedIntegerSetting'),
|
||||
extractFunction('normalizeLocalHttpBaseUrl'),
|
||||
extractFunction('buildPersistentSettingsPayload'),
|
||||
extractFunction('normalizePersistentSettingValue'),
|
||||
].join('\n');
|
||||
|
||||
@@ -181,10 +182,16 @@ function normalizeCloudflareTempEmailReceiveMailbox(value) { return String(value
|
||||
function normalizeCloudflareTempEmailDomain(value) { return String(value || '').trim(); }
|
||||
function normalizeCloudflareTempEmailDomains(value) { return Array.isArray(value) ? value : []; }
|
||||
function normalizeHotmailAccounts(value) { return Array.isArray(value) ? value : []; }
|
||||
function resolveLegacyAutoStepDelaySeconds(value) {
|
||||
return value && Object.prototype.hasOwnProperty.call(value, 'autoStepDelaySeconds')
|
||||
? value.autoStepDelaySeconds
|
||||
: undefined;
|
||||
}
|
||||
${bundle}
|
||||
return {
|
||||
normalizeAccountRunHistoryHelperBaseUrl,
|
||||
normalizePersistentSettingValue,
|
||||
buildPersistentSettingsPayload,
|
||||
};
|
||||
`)();
|
||||
|
||||
@@ -243,6 +250,8 @@ return {
|
||||
assert.equal(api.normalizePersistentSettingValue('phoneSmsProvider', 'NEXSMS'), 'nexsms');
|
||||
assert.equal(api.normalizePersistentSettingValue('phoneSmsProvider', 'unknown'), 'hero-sms');
|
||||
assert.deepStrictEqual(api.normalizePersistentSettingValue('phoneSmsProviderOrder', ['nexsms', '5sim', 'nexsms']), ['nexsms', '5sim']);
|
||||
assert.equal(api.normalizePersistentSettingValue('phoneSmsReuseEnabled', false), false);
|
||||
assert.equal(api.normalizePersistentSettingValue('phoneSmsReuseEnabled', true), true);
|
||||
assert.equal(api.normalizePersistentSettingValue('fiveSimApiKey', ' demo-five '), ' demo-five ');
|
||||
assert.equal(api.normalizePersistentSettingValue('fiveSimProduct', ' OpenAI! '), 'openai');
|
||||
assert.equal(api.normalizePersistentSettingValue('fiveSimCountryId', ' England! '), 'england');
|
||||
@@ -335,4 +344,26 @@ return {
|
||||
countryLabel: '',
|
||||
}
|
||||
);
|
||||
const legacyReusePayload = api.buildPersistentSettingsPayload({
|
||||
heroSmsReuseEnabled: false,
|
||||
});
|
||||
assert.equal(legacyReusePayload.phoneSmsReuseEnabled, false);
|
||||
assert.equal(legacyReusePayload.heroSmsReuseEnabled, false);
|
||||
const fiveSimReusePayload = api.buildPersistentSettingsPayload({
|
||||
fiveSimReuseEnabled: false,
|
||||
});
|
||||
assert.equal(fiveSimReusePayload.phoneSmsReuseEnabled, false);
|
||||
assert.equal(fiveSimReusePayload.heroSmsReuseEnabled, false);
|
||||
const conflictingReusePayload = api.buildPersistentSettingsPayload({
|
||||
heroSmsReuseEnabled: true,
|
||||
fiveSimReuseEnabled: false,
|
||||
});
|
||||
assert.equal(conflictingReusePayload.phoneSmsReuseEnabled, true);
|
||||
assert.equal(conflictingReusePayload.heroSmsReuseEnabled, true);
|
||||
const newReusePayload = api.buildPersistentSettingsPayload({
|
||||
phoneSmsReuseEnabled: false,
|
||||
heroSmsReuseEnabled: true,
|
||||
});
|
||||
assert.equal(newReusePayload.phoneSmsReuseEnabled, false);
|
||||
assert.equal(newReusePayload.heroSmsReuseEnabled, false);
|
||||
});
|
||||
|
||||
@@ -15,6 +15,7 @@ test('background defaults enable free phone reuse switches', () => {
|
||||
|
||||
assert.match(defaultsBlock, /freePhoneReuseEnabled:\s*true/);
|
||||
assert.match(defaultsBlock, /freePhoneReuseAutoEnabled:\s*true/);
|
||||
assert.match(defaultsBlock, /phoneSmsReuseEnabled:\s*DEFAULT_HERO_SMS_REUSE_ENABLED/);
|
||||
});
|
||||
|
||||
test('background free reusable phone setter does not depend on module-scoped phone flow constants', () => {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
const source = fs.readFileSync('phone-sms/providers/registry.js', 'utf8');
|
||||
|
||||
function loadRegistry(root = {}) {
|
||||
return new Function('self', `${source}; return self.PhoneSmsProviderRegistry;`)(root);
|
||||
}
|
||||
|
||||
test('phone sms provider registry normalizes ids, order and labels consistently', () => {
|
||||
const registry = loadRegistry({
|
||||
PhoneSmsHeroSmsProvider: {
|
||||
createProvider: (deps = {}) => ({ provider: 'hero-sms', deps }),
|
||||
},
|
||||
PhoneSmsFiveSimProvider: {
|
||||
createProvider: (deps = {}) => ({ provider: '5sim', deps }),
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(registry.getProviderIds(), ['hero-sms', '5sim', 'nexsms']);
|
||||
assert.equal(registry.normalizeProviderId(' NEXSMS '), 'nexsms');
|
||||
assert.equal(registry.normalizeProviderId('unknown-provider'), 'hero-sms');
|
||||
assert.equal(registry.getProviderLabel('nexsms'), 'NexSMS');
|
||||
assert.equal(registry.getProviderDefinition('nexsms').moduleKey, 'PhoneSmsNexSmsProvider');
|
||||
assert.deepStrictEqual(
|
||||
registry.normalizeProviderOrder([
|
||||
{ provider: 'nexsms' },
|
||||
{ id: '5sim' },
|
||||
{ value: 'hero-sms' },
|
||||
'NEXSMS',
|
||||
]),
|
||||
['nexsms', '5sim', 'hero-sms']
|
||||
);
|
||||
assert.deepStrictEqual(
|
||||
registry.normalizeProviderOrder([], ['nexsms', '5sim', 'nexsms']),
|
||||
['nexsms', '5sim']
|
||||
);
|
||||
assert.deepStrictEqual(
|
||||
registry.createProvider('5sim', { foo: 1 }),
|
||||
{ provider: '5sim', deps: { foo: 1 } }
|
||||
);
|
||||
assert.throws(() => registry.createProvider('nexsms'), /Phone SMS provider module is not loaded: nexsms/);
|
||||
});
|
||||
@@ -1948,9 +1948,181 @@ test('phone verification helper acquires a number from 5sim with fallback countr
|
||||
assert.equal(requests[3].pathname, '/v1/user/buy/activation/england/any/openai');
|
||||
});
|
||||
|
||||
test('phone verification helper rejects 5sim maxPrice with custom operator before buying', async () => {
|
||||
const requests = [];
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
test('phone verification helper prefers phoneSmsReuseEnabled over legacy heroSmsReuseEnabled for 5sim acquisition', async () => {
|
||||
const requests = [];
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
fetchImpl: async (url, options = {}) => {
|
||||
const parsedUrl = new URL(url);
|
||||
requests.push({
|
||||
pathname: parsedUrl.pathname,
|
||||
search: parsedUrl.searchParams,
|
||||
headers: options?.headers || {},
|
||||
});
|
||||
if (parsedUrl.pathname === '/v1/guest/prices') {
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => JSON.stringify({
|
||||
openai: {
|
||||
thailand: {
|
||||
any: {
|
||||
cost: 0.08,
|
||||
count: 12,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
if (parsedUrl.pathname === '/v1/user/buy/activation/thailand/any/openai') {
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => JSON.stringify({
|
||||
id: 1234567,
|
||||
phone: '+66880000000',
|
||||
country: 'thailand',
|
||||
country_name: 'Thailand',
|
||||
product: 'openai',
|
||||
}),
|
||||
};
|
||||
}
|
||||
throw new Error(`Unexpected 5sim request: ${parsedUrl.pathname}`);
|
||||
},
|
||||
getState: async () => ({
|
||||
phoneSmsProvider: '5sim',
|
||||
fiveSimApiKey: 'five-token',
|
||||
fiveSimCountryOrder: ['thailand'],
|
||||
fiveSimOperator: 'any',
|
||||
fiveSimProduct: 'openai',
|
||||
phoneSmsReuseEnabled: false,
|
||||
heroSmsReuseEnabled: true,
|
||||
heroSmsActivationRetryRounds: 1,
|
||||
}),
|
||||
sendToContentScriptResilient: async () => ({}),
|
||||
setState: async () => {},
|
||||
sleepWithStop: async () => {},
|
||||
throwIfStopped: () => {},
|
||||
});
|
||||
|
||||
const activation = await helpers.requestPhoneActivation({
|
||||
phoneSmsProvider: '5sim',
|
||||
fiveSimApiKey: 'five-token',
|
||||
fiveSimCountryOrder: ['thailand'],
|
||||
fiveSimOperator: 'any',
|
||||
fiveSimProduct: 'openai',
|
||||
phoneSmsReuseEnabled: false,
|
||||
heroSmsReuseEnabled: true,
|
||||
heroSmsActivationRetryRounds: 1,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(activation, {
|
||||
activationId: '1234567',
|
||||
phoneNumber: '+66880000000',
|
||||
provider: '5sim',
|
||||
serviceCode: 'openai',
|
||||
countryId: 'thailand',
|
||||
countryCode: 'thailand',
|
||||
countryLabel: 'Thailand',
|
||||
successfulUses: 0,
|
||||
maxUses: 3,
|
||||
});
|
||||
assert.equal(requests[0].pathname, '/v1/guest/prices');
|
||||
assert.equal(requests[1].pathname, '/v1/user/buy/activation/thailand/any/openai');
|
||||
assert.equal(requests[1].search.get('reuse'), null);
|
||||
});
|
||||
|
||||
test('phone verification helper treats fiveSimReuseEnabled as legacy-only when phoneSmsReuseEnabled is absent', async () => {
|
||||
const requests = [];
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
fetchImpl: async (url, options = {}) => {
|
||||
const parsedUrl = new URL(url);
|
||||
requests.push({
|
||||
pathname: parsedUrl.pathname,
|
||||
search: parsedUrl.searchParams,
|
||||
headers: options?.headers || {},
|
||||
});
|
||||
if (parsedUrl.pathname === '/v1/guest/prices') {
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => JSON.stringify({
|
||||
openai: {
|
||||
thailand: {
|
||||
any: {
|
||||
cost: 0.08,
|
||||
count: 12,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
if (parsedUrl.pathname === '/v1/user/buy/activation/thailand/any/openai') {
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => JSON.stringify({
|
||||
id: 1234568,
|
||||
phone: '+66880000001',
|
||||
country: 'thailand',
|
||||
country_name: 'Thailand',
|
||||
product: 'openai',
|
||||
}),
|
||||
};
|
||||
}
|
||||
throw new Error(`Unexpected 5sim request: ${parsedUrl.pathname}`);
|
||||
},
|
||||
getState: async () => ({
|
||||
phoneSmsProvider: '5sim',
|
||||
fiveSimApiKey: 'five-token',
|
||||
fiveSimCountryOrder: ['thailand'],
|
||||
fiveSimOperator: 'any',
|
||||
fiveSimProduct: 'openai',
|
||||
heroSmsReuseEnabled: true,
|
||||
fiveSimReuseEnabled: false,
|
||||
heroSmsActivationRetryRounds: 1,
|
||||
}),
|
||||
sendToContentScriptResilient: async () => ({}),
|
||||
setState: async () => {},
|
||||
sleepWithStop: async () => {},
|
||||
throwIfStopped: () => {},
|
||||
});
|
||||
|
||||
const activation = await helpers.requestPhoneActivation({
|
||||
phoneSmsProvider: '5sim',
|
||||
fiveSimApiKey: 'five-token',
|
||||
fiveSimCountryOrder: ['thailand'],
|
||||
fiveSimOperator: 'any',
|
||||
fiveSimProduct: 'openai',
|
||||
heroSmsReuseEnabled: true,
|
||||
fiveSimReuseEnabled: false,
|
||||
heroSmsActivationRetryRounds: 1,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(activation, {
|
||||
activationId: '1234568',
|
||||
phoneNumber: '+66880000001',
|
||||
provider: '5sim',
|
||||
serviceCode: 'openai',
|
||||
countryId: 'thailand',
|
||||
countryCode: 'thailand',
|
||||
countryLabel: 'Thailand',
|
||||
successfulUses: 0,
|
||||
maxUses: 3,
|
||||
});
|
||||
assert.equal(requests[0].pathname, '/v1/guest/prices');
|
||||
assert.equal(requests[1].pathname, '/v1/user/buy/activation/thailand/any/openai');
|
||||
assert.equal(requests[1].search.get('reuse'), '1');
|
||||
});
|
||||
|
||||
test('phone verification helper rejects 5sim maxPrice with custom operator before buying', async () => {
|
||||
const requests = [];
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
fetchImpl: async (url) => {
|
||||
|
||||
@@ -943,6 +943,7 @@ 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);
|
||||
|
||||
Reference in New Issue
Block a user