Merge pull request #293 from netcookies/fix/madao-country-iso-dev
fix(madao): 适配国家中文标签和线路归一化
This commit is contained in:
@@ -71,6 +71,7 @@ test('background account history settings are normalized independently from hotm
|
||||
extractFunction('normalizeMaDaoIdentifier'),
|
||||
extractFunction('normalizeMaDaoProviderId'),
|
||||
extractFunction('normalizeMaDaoCountry'),
|
||||
extractFunction('normalizeMaDaoOperator'),
|
||||
extractFunction('normalizeMaDaoPrice'),
|
||||
extractFunction('normalizePhonePreferredActivation'),
|
||||
extractFunction('normalizePhoneVerificationReplacementLimit'),
|
||||
@@ -382,6 +383,7 @@ return {
|
||||
assert.equal(api.normalizePersistentSettingValue('madaoProviderId', ' Upstream A! '), 'upstreama');
|
||||
assert.equal(api.normalizePersistentSettingValue('madaoCountry', ' gb '), 'GB');
|
||||
assert.equal(api.normalizePersistentSettingValue('madaoCountry', 'ANY'), 'any');
|
||||
assert.equal(api.normalizePersistentSettingValue('madaoOperator', ' Operator A! '), 'operatora');
|
||||
assert.equal(api.normalizePersistentSettingValue('madaoAutoPickCountry', 1), true);
|
||||
assert.equal(api.normalizePersistentSettingValue('madaoReusePhone', 0), false);
|
||||
assert.equal(api.normalizePersistentSettingValue('madaoMinPrice', '0.123456'), '0.1235');
|
||||
|
||||
@@ -419,6 +419,7 @@ return {
|
||||
madaoRoutingPlanId: 'rp-openai',
|
||||
madaoProviderId: 'upstream-a',
|
||||
madaoCountry: 'GB',
|
||||
madaoOperator: 'operator-a',
|
||||
madaoAutoPickCountry: false,
|
||||
madaoReusePhone: true,
|
||||
madaoMinPrice: '0.12',
|
||||
@@ -452,6 +453,7 @@ return {
|
||||
assert.equal(api.getPayloadInput().madaoRoutingPlanId, 'rp-openai');
|
||||
assert.equal(api.getPayloadInput().madaoProviderId, 'upstream-a');
|
||||
assert.equal(api.getPayloadInput().madaoCountry, 'GB');
|
||||
assert.equal(api.getPayloadInput().madaoOperator, 'operator-a');
|
||||
assert.equal(api.getPayloadInput().madaoAutoPickCountry, false);
|
||||
assert.equal(api.getPayloadInput().madaoReusePhone, true);
|
||||
assert.equal(api.getPayloadInput().madaoMinPrice, '0.12');
|
||||
|
||||
@@ -118,6 +118,7 @@ const PERSISTED_SETTING_DEFAULTS = {
|
||||
madaoRoutingPlanId: '',
|
||||
madaoProviderId: '',
|
||||
madaoCountry: '',
|
||||
madaoOperator: '',
|
||||
madaoAutoPickCountry: true,
|
||||
madaoReusePhone: true,
|
||||
madaoMinPrice: '',
|
||||
@@ -219,6 +220,7 @@ function normalizeMaDaoBaseUrl(value = '') {
|
||||
function normalizeMaDaoMode(value = '') { return String(value || '').trim().toLowerCase() === 'direct' ? 'direct' : DEFAULT_MADAO_MODE; }
|
||||
function normalizeMaDaoIdentifier(value = '') { return String(value || '').trim(); }
|
||||
function normalizeMaDaoProviderId(value = '') { return String(value || '').trim().toLowerCase().replace(/[^a-z0-9_-]+/g, ''); }
|
||||
function normalizeMaDaoOperator(value = '') { return String(value || '').trim().toLowerCase().replace(/[^a-z0-9_-]+/g, ''); }
|
||||
function normalizeMaDaoCountry(value = '') {
|
||||
const trimmed = String(value || '').trim();
|
||||
if (!trimmed) return '';
|
||||
@@ -306,6 +308,7 @@ test('buildPersistentSettingsPayload writes canonical settings schema into persi
|
||||
assert.equal(payload.phoneSmsProvider, 'hero-sms');
|
||||
assert.equal(payload.madaoBaseUrl, DEFAULT_MADAO_BASE_URL_FOR_TEST);
|
||||
assert.equal(payload.madaoMode, DEFAULT_MADAO_MODE_FOR_TEST);
|
||||
assert.equal(payload.madaoOperator, '');
|
||||
assert.equal(payload.madaoAutoPickCountry, true);
|
||||
assert.equal(payload.madaoReusePhone, true);
|
||||
assert.equal(Object.prototype.hasOwnProperty.call(payload, 'kiroRegion'), false);
|
||||
@@ -724,6 +727,7 @@ test('buildPersistentSettingsPayload persists normalized MaDao flat settings out
|
||||
madaoRoutingPlanId: ' rp-openai ',
|
||||
madaoProviderId: ' Upstream A! ',
|
||||
madaoCountry: ' gb ',
|
||||
madaoOperator: ' Operator A! ',
|
||||
madaoAutoPickCountry: 0,
|
||||
madaoReusePhone: 1,
|
||||
madaoMinPrice: '0.123456',
|
||||
@@ -737,6 +741,7 @@ test('buildPersistentSettingsPayload persists normalized MaDao flat settings out
|
||||
assert.equal(payload.madaoRoutingPlanId, 'rp-openai');
|
||||
assert.equal(payload.madaoProviderId, 'upstreama');
|
||||
assert.equal(payload.madaoCountry, 'GB');
|
||||
assert.equal(payload.madaoOperator, 'operatora');
|
||||
assert.equal(payload.madaoAutoPickCountry, false);
|
||||
assert.equal(payload.madaoReusePhone, true);
|
||||
assert.equal(payload.madaoMinPrice, '0.1235');
|
||||
|
||||
@@ -38,6 +38,7 @@ test('MaDao direct acquire sends only direct fields and normalizes activation da
|
||||
madaoRoutingPlanId: 'route-plan-should-not-be-sent',
|
||||
madaoProviderId: 'Upstream A!',
|
||||
madaoCountry: 'gb',
|
||||
madaoOperator: 'Operator A!',
|
||||
madaoAutoPickCountry: 'false',
|
||||
madaoReusePhone: '1',
|
||||
madaoMinPrice: '0.01',
|
||||
@@ -54,6 +55,9 @@ test('MaDao direct acquire sends only direct fields and normalizes activation da
|
||||
auto_pick_country: false,
|
||||
reuse_phone: true,
|
||||
country: 'GB',
|
||||
metadata: {
|
||||
operator: 'operatora',
|
||||
},
|
||||
min_price: 0.01,
|
||||
max_price: 0.2,
|
||||
});
|
||||
@@ -100,6 +104,37 @@ test('MaDao routing acquire sends routing plan only', async () => {
|
||||
assert.equal(activation.madaoRoutingItemId, 'route-1');
|
||||
});
|
||||
|
||||
test('MaDao direct acquire treats any operator as default route', async () => {
|
||||
const requests = [];
|
||||
const provider = api.createProvider({
|
||||
fetchImpl: async (_url, options = {}) => {
|
||||
requests.push({ body: JSON.parse(options.body) });
|
||||
return createJsonResponse({
|
||||
ticket_id: 'ticket-any',
|
||||
phone_number: '+66111111111',
|
||||
country: 'TH',
|
||||
provider: 'fivesim',
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
await provider.acquireActivation({
|
||||
madaoMode: 'direct',
|
||||
madaoProviderId: 'fivesim',
|
||||
madaoCountry: 'TH',
|
||||
madaoOperator: 'Any operator',
|
||||
});
|
||||
|
||||
assert.equal(requests.length, 1);
|
||||
assert.deepEqual(requests[0].body, {
|
||||
provider: 'fivesim',
|
||||
service: 'openai',
|
||||
auto_pick_country: true,
|
||||
reuse_phone: true,
|
||||
country: 'TH',
|
||||
});
|
||||
});
|
||||
|
||||
test('MaDao poll extracts codes from nested messages and reports pending status', async () => {
|
||||
const statusEvents = [];
|
||||
const provider = api.createProvider({
|
||||
|
||||
@@ -356,6 +356,68 @@ test('phone auth can auto-select country by dial code even when number has no pl
|
||||
}
|
||||
});
|
||||
|
||||
test('phone auth rejects stale selected country when it does not match phone dial code', async () => {
|
||||
const originalDocument = global.document;
|
||||
const originalEvent = global.Event;
|
||||
const originalLocation = global.location;
|
||||
|
||||
const dom = createFakeAddPhoneDom({
|
||||
options: [
|
||||
{ value: 'TH', textContent: 'Thailand (+66)', buttonText: 'Thailand (+66)' },
|
||||
{ value: 'GB', textContent: 'United Kingdom (+44)', buttonText: 'United Kingdom (+44)' },
|
||||
],
|
||||
selectedIndex: 0,
|
||||
});
|
||||
|
||||
global.document = dom.document;
|
||||
global.Event = class Event {
|
||||
constructor(type) {
|
||||
this.type = type;
|
||||
}
|
||||
};
|
||||
global.location = { href: 'https://auth.openai.com/add-phone' };
|
||||
|
||||
try {
|
||||
const helpers = api.createPhoneAuthHelpers({
|
||||
fillInput: (element, value) => {
|
||||
element.value = value;
|
||||
},
|
||||
getActionText: () => '',
|
||||
getPageTextSnapshot: () => '',
|
||||
getVerificationErrorText: () => '',
|
||||
humanPause: async () => {},
|
||||
isActionEnabled: () => true,
|
||||
isAddPhonePageReady: () => true,
|
||||
isConsentReady: () => false,
|
||||
isPhoneVerificationPageReady: () => false,
|
||||
isVisibleElement: () => true,
|
||||
simulateClick: (element) => {
|
||||
element.click?.();
|
||||
},
|
||||
sleep: async () => {},
|
||||
throwIfStopped: () => {},
|
||||
waitForElement: async () => null,
|
||||
});
|
||||
|
||||
await assert.rejects(
|
||||
() => helpers.submitPhoneNumber({
|
||||
countryLabel: 'Country #10',
|
||||
phoneNumber: '+84943328460',
|
||||
}),
|
||||
/Failed to select "Country #10" on the add-phone page\./
|
||||
);
|
||||
|
||||
assert.equal(dom.select.value, 'TH');
|
||||
assert.equal(dom.phoneInput.value, '');
|
||||
assert.equal(dom.hiddenPhoneInput.value, '');
|
||||
assert.equal(dom.wasSubmitClicked(), false);
|
||||
} finally {
|
||||
global.document = originalDocument;
|
||||
global.Event = originalEvent;
|
||||
global.location = originalLocation;
|
||||
}
|
||||
});
|
||||
|
||||
test('phone auth resend stops with PHONE_ROUTE_405_RECOVERY_FAILED instead of endless Try-again loop', async () => {
|
||||
const originalDocument = global.document;
|
||||
const originalLocation = global.location;
|
||||
|
||||
@@ -3,6 +3,8 @@ const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
const source = fs.readFileSync('phone-sms/providers/registry.js', 'utf8');
|
||||
const maDaoSource = fs.readFileSync('phone-sms/providers/madao.js', 'utf8');
|
||||
const nexSmsSource = fs.readFileSync('phone-sms/providers/nexsms.js', 'utf8');
|
||||
|
||||
function loadRegistry(root = {}) {
|
||||
return new Function('self', `${source}; return self.PhoneSmsProviderRegistry;`)(root);
|
||||
@@ -16,6 +18,9 @@ test('phone sms provider registry normalizes ids, order and labels consistently'
|
||||
PhoneSmsFiveSimProvider: {
|
||||
createProvider: (deps = {}) => ({ provider: '5sim', deps }),
|
||||
},
|
||||
PhoneSmsNexSmsProvider: {
|
||||
createProvider: (deps = {}) => ({ provider: 'nexsms', deps }),
|
||||
},
|
||||
PhoneSmsMaDaoProvider: {
|
||||
createProvider: (deps = {}) => ({ provider: 'madao', deps }),
|
||||
},
|
||||
@@ -52,5 +57,43 @@ test('phone sms provider registry normalizes ids, order and labels consistently'
|
||||
registry.createProvider('madao', { foo: 2 }),
|
||||
{ provider: 'madao', deps: { foo: 2 } }
|
||||
);
|
||||
assert.throws(() => registry.createProvider('nexsms'), /接码平台模块未加载:nexsms/);
|
||||
assert.deepStrictEqual(
|
||||
registry.createProvider('nexsms', { foo: 3 }),
|
||||
{ provider: 'nexsms', deps: { foo: 3 } }
|
||||
);
|
||||
});
|
||||
|
||||
test('phone sms provider registry can create the real MaDao provider module', () => {
|
||||
const maDaoModule = new Function('self', `${maDaoSource}; return self.PhoneSmsMaDaoProvider;`)({});
|
||||
const registry = loadRegistry({
|
||||
PhoneSmsMaDaoProvider: maDaoModule,
|
||||
});
|
||||
|
||||
const provider = registry.createProvider('madao', { fetchImpl: 'demo-fetch' });
|
||||
|
||||
assert.equal(provider.id, 'madao');
|
||||
assert.equal(provider.label, 'MaDao');
|
||||
assert.equal(provider.defaultProduct, 'openai');
|
||||
assert.equal(typeof provider.acquireActivation, 'function');
|
||||
assert.equal(typeof provider.pollActivation, 'function');
|
||||
assert.equal(typeof provider.releaseActivation, 'function');
|
||||
assert.equal(provider.mapTicketStatus('waiting_code'), 'waiting_code');
|
||||
});
|
||||
|
||||
test('phone sms provider registry can create the real NexSMS provider module', () => {
|
||||
const nexSmsModule = new Function('self', `${nexSmsSource}; return self.PhoneSmsNexSmsProvider;`)({});
|
||||
const registry = loadRegistry({
|
||||
PhoneSmsNexSmsProvider: nexSmsModule,
|
||||
});
|
||||
|
||||
const provider = registry.createProvider('nexsms', { fetchImpl: 'demo-fetch' });
|
||||
|
||||
assert.equal(provider.id, 'nexsms');
|
||||
assert.equal(provider.label, 'NexSMS');
|
||||
assert.equal(provider.defaultProduct, 'OpenAI');
|
||||
assert.equal(provider.defaultServiceCode, 'ot');
|
||||
assert.equal(typeof provider.fetchBalance, 'function');
|
||||
assert.equal(typeof provider.fetchPrices, 'function');
|
||||
assert.equal(provider.normalizeCountryId('8'), 8);
|
||||
assert.equal(provider.normalizeServiceCode(' OT '), 'ot');
|
||||
});
|
||||
|
||||
@@ -3,10 +3,19 @@ const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
const source = fs.readFileSync('background/phone-verification-flow.js', 'utf8');
|
||||
const globalScope = {};
|
||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundPhoneVerification;`)(globalScope);
|
||||
const heroSmsSource = fs.readFileSync('phone-sms/providers/hero-sms.js', 'utf8');
|
||||
const fiveSimSource = fs.readFileSync('phone-sms/providers/five-sim.js', 'utf8');
|
||||
const nexSmsSource = fs.readFileSync('phone-sms/providers/nexsms.js', 'utf8');
|
||||
const maDaoSource = fs.readFileSync('phone-sms/providers/madao.js', 'utf8');
|
||||
const maDaoModule = new Function('self', `${maDaoSource}; return self.PhoneSmsMaDaoProvider;`)({});
|
||||
const registrySource = fs.readFileSync('phone-sms/providers/registry.js', 'utf8');
|
||||
const globalScope = {};
|
||||
new Function('self', `${heroSmsSource}; return self.PhoneSmsHeroSmsProvider;`)(globalScope);
|
||||
new Function('self', `${fiveSimSource}; return self.PhoneSmsFiveSimProvider;`)(globalScope);
|
||||
new Function('self', `${nexSmsSource}; return self.PhoneSmsNexSmsProvider;`)(globalScope);
|
||||
new Function('self', `${maDaoSource}; return self.PhoneSmsMaDaoProvider;`)(globalScope);
|
||||
new Function('self', `${registrySource}; return self.PhoneSmsProviderRegistry;`)(globalScope);
|
||||
const api = new Function('self', `${source}; return self.MultiPageBackgroundPhoneVerification;`)(globalScope);
|
||||
const maDaoModule = globalScope.PhoneSmsMaDaoProvider;
|
||||
|
||||
function buildHeroSmsPricesPayload({ country = '52', service = 'dr', cost = 0.08, count = 25370, physicalCount = 14528 } = {}) {
|
||||
return JSON.stringify({
|
||||
@@ -157,6 +166,110 @@ test('phone verification helper reads latest HeroSMS operator from persistent st
|
||||
assert.equal(getNumberRequest.searchParams.get('operator'), 'dtac');
|
||||
});
|
||||
|
||||
test('phone verification helper creates 5sim adapter through provider registry when available', async () => {
|
||||
const createCalls = [];
|
||||
const root = {
|
||||
PhoneSmsProviderRegistry: {
|
||||
createProvider: (providerId, deps = {}) => {
|
||||
createCalls.push({ providerId, deps });
|
||||
return {
|
||||
requestActivation: async () => ({
|
||||
activationId: '5sim-registry-1',
|
||||
phoneNumber: '+447700900001',
|
||||
provider: '5sim',
|
||||
serviceCode: 'openai',
|
||||
countryId: 'england',
|
||||
}),
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
const registryApi = new Function('self', `${source}; return self.MultiPageBackgroundPhoneVerification;`)(root);
|
||||
const helpers = registryApi.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
fetchImpl: async () => {
|
||||
throw new Error('5sim registry adapter should own network access');
|
||||
},
|
||||
getState: async () => ({ phoneSmsProvider: '5sim' }),
|
||||
sendToContentScriptResilient: async () => ({}),
|
||||
setState: async () => {},
|
||||
sleepWithStop: async () => {},
|
||||
throwIfStopped: () => {},
|
||||
});
|
||||
|
||||
const activation = await helpers.requestPhoneActivation({ phoneSmsProvider: '5sim' });
|
||||
|
||||
assert.equal(createCalls.length, 1);
|
||||
assert.equal(createCalls[0].providerId, '5sim');
|
||||
assert.equal(typeof createCalls[0].deps.fetchImpl, 'function');
|
||||
assert.equal(activation.activationId, '5sim-registry-1');
|
||||
});
|
||||
|
||||
test('phone verification helper creates MaDao adapter through provider registry when available', async () => {
|
||||
const createCalls = [];
|
||||
const requests = [];
|
||||
const root = {
|
||||
PhoneSmsProviderRegistry: {
|
||||
createProvider: (providerId, deps = {}) => {
|
||||
createCalls.push({ providerId, deps });
|
||||
return maDaoModule.createProvider(deps);
|
||||
},
|
||||
},
|
||||
};
|
||||
const registryApi = new Function('self', `${source}; return self.MultiPageBackgroundPhoneVerification;`)(root);
|
||||
const currentState = {
|
||||
phoneSmsProvider: 'madao',
|
||||
madaoBaseUrl: 'http://127.0.0.1:7822/',
|
||||
madaoHttpSecret: 'secret-token',
|
||||
madaoMode: 'routing_plan',
|
||||
madaoRoutingPlanId: 'rp-openai',
|
||||
};
|
||||
const helpers = registryApi.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
fetchImpl: async (url, options = {}) => {
|
||||
const parsedUrl = new URL(url);
|
||||
requests.push({ url: parsedUrl, options, body: options.body ? JSON.parse(options.body) : null });
|
||||
if (parsedUrl.pathname === '/api/acquire') {
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => JSON.stringify({
|
||||
ticket_id: 'madao-registry-1',
|
||||
phone_number: '+14155550123',
|
||||
service: 'openai',
|
||||
country: 'CA',
|
||||
provider: 'upstream-a',
|
||||
routing_plan_id: 'rp-openai',
|
||||
routing_item_id: 'route-1',
|
||||
status: 'waiting_code',
|
||||
}),
|
||||
};
|
||||
}
|
||||
throw new Error(`Unexpected MaDao path: ${parsedUrl.pathname}`);
|
||||
},
|
||||
getState: async () => ({ ...currentState }),
|
||||
sendToContentScriptResilient: async () => ({}),
|
||||
setState: async () => {},
|
||||
sleepWithStop: async () => {},
|
||||
throwIfStopped: () => {},
|
||||
});
|
||||
|
||||
const activation = await helpers.requestPhoneActivation(currentState);
|
||||
|
||||
assert.equal(createCalls.length, 1);
|
||||
assert.equal(createCalls[0].providerId, 'madao');
|
||||
assert.equal(typeof createCalls[0].deps.fetchImpl, 'function');
|
||||
assert.equal(activation.activationId, 'madao-registry-1');
|
||||
assert.equal(activation.countryId, 'CA');
|
||||
assert.deepStrictEqual(requests[0].body, {
|
||||
provider: 'auto',
|
||||
service: 'openai',
|
||||
routing_plan_id: 'rp-openai',
|
||||
});
|
||||
});
|
||||
|
||||
test('phone verification helper acquires, polls and releases MaDao activation through provider adapter', async () => {
|
||||
const requests = [];
|
||||
let currentState = {
|
||||
@@ -172,7 +285,6 @@ test('phone verification helper acquires, polls and releases MaDao activation th
|
||||
};
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
createMaDaoProvider: maDaoModule.createProvider,
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
fetchImpl: async (url, options = {}) => {
|
||||
const parsedUrl = new URL(url);
|
||||
@@ -252,6 +364,161 @@ test('phone verification helper acquires, polls and releases MaDao activation th
|
||||
assert.deepStrictEqual(requests[2].body, { ticket_id: 'madao-1', action: 'finish' });
|
||||
});
|
||||
|
||||
test('phone verification helper keeps MaDao routing replacement country as ISO code on resubmit', async () => {
|
||||
const requests = [];
|
||||
const messages = [];
|
||||
let currentState = {
|
||||
phoneSmsProvider: 'madao',
|
||||
madaoBaseUrl: 'http://127.0.0.1:7822/',
|
||||
madaoHttpSecret: 'secret-token',
|
||||
madaoMode: 'routing_plan',
|
||||
madaoRoutingPlanId: 'rp-openai',
|
||||
verificationResendCount: 0,
|
||||
phoneVerificationReplacementLimit: 2,
|
||||
phoneCodeWaitSeconds: 15,
|
||||
phoneCodeTimeoutWindows: 1,
|
||||
phoneCodePollIntervalSeconds: 1,
|
||||
phoneCodePollMaxRounds: 1,
|
||||
currentPhoneActivation: null,
|
||||
reusablePhoneActivation: null,
|
||||
};
|
||||
let acquireCalls = 0;
|
||||
let replaceCalls = 0;
|
||||
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
fetchImpl: async (url, options = {}) => {
|
||||
const parsedUrl = new URL(url);
|
||||
const body = options.body ? JSON.parse(options.body) : null;
|
||||
requests.push({ url: parsedUrl, options, body });
|
||||
if (parsedUrl.pathname === '/api/acquire') {
|
||||
acquireCalls += 1;
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => JSON.stringify({
|
||||
ticket_id: 'madao-ticket-routing-1',
|
||||
provider: 'herosms',
|
||||
service: 'openai',
|
||||
country: 'TH',
|
||||
phone_number: '+66950002222',
|
||||
routing_plan_id: 'rp-openai',
|
||||
routing_plan_name: 'OpenAI Plan',
|
||||
routing_item_id: 'route-1',
|
||||
status: 'waiting_code',
|
||||
}),
|
||||
};
|
||||
}
|
||||
if (parsedUrl.pathname === '/api/poll') {
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => JSON.stringify({
|
||||
ticket_id: body.ticket_id,
|
||||
provider: body.ticket_id === 'madao-ticket-routing-1' ? 'herosms' : 'smsbower',
|
||||
status: body.ticket_id === 'madao-ticket-routing-1' ? 'waiting_code' : 'code_received',
|
||||
code: body.ticket_id === 'madao-ticket-routing-1' ? null : '654321',
|
||||
}),
|
||||
};
|
||||
}
|
||||
if (parsedUrl.pathname === '/api/routing/replace') {
|
||||
replaceCalls += 1;
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => JSON.stringify({
|
||||
current_ticket_id: 'madao-ticket-routing-1',
|
||||
current_ticket_release: {
|
||||
ticket_id: 'madao-ticket-routing-1',
|
||||
provider: 'herosms',
|
||||
status: 'cancelled',
|
||||
},
|
||||
next_ticket: {
|
||||
ticket_id: 'madao-ticket-routing-2',
|
||||
provider: 'smsbower',
|
||||
service: 'openai',
|
||||
country: 'VN',
|
||||
phone_number: '+84943328460',
|
||||
routing_plan_id: 'rp-openai',
|
||||
routing_plan_name: 'OpenAI Plan',
|
||||
routing_item_id: 'route-2',
|
||||
status: 'waiting_code',
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
if (parsedUrl.pathname === '/api/release') {
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
text: async () => JSON.stringify({ ok: true }),
|
||||
};
|
||||
}
|
||||
throw new Error(`Unexpected MaDao path: ${parsedUrl.pathname}`);
|
||||
},
|
||||
getOAuthFlowStepTimeoutMs: async (defaultTimeoutMs) => defaultTimeoutMs,
|
||||
getState: async () => ({ ...currentState }),
|
||||
sendToContentScriptResilient: async (_source, message) => {
|
||||
messages.push(message);
|
||||
if (message.type === 'STEP8_GET_STATE') {
|
||||
return {
|
||||
addPhonePage: true,
|
||||
phoneVerificationPage: false,
|
||||
url: 'https://auth.openai.com/add-phone',
|
||||
};
|
||||
}
|
||||
if (message.type === 'SUBMIT_PHONE_NUMBER') {
|
||||
return {
|
||||
phoneVerificationPage: true,
|
||||
url: 'https://auth.openai.com/phone-verification',
|
||||
};
|
||||
}
|
||||
if (message.type === 'RETURN_TO_ADD_PHONE') {
|
||||
return {
|
||||
addPhonePage: true,
|
||||
url: 'https://auth.openai.com/add-phone',
|
||||
};
|
||||
}
|
||||
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.equal(acquireCalls, 1);
|
||||
assert.equal(replaceCalls, 1);
|
||||
const phoneSubmissions = messages.filter((message) => message.type === 'SUBMIT_PHONE_NUMBER');
|
||||
assert.equal(phoneSubmissions.length, 2);
|
||||
assert.equal(phoneSubmissions[0].payload.phoneNumber, '+66950002222');
|
||||
assert.equal(phoneSubmissions[0].payload.countryId, 'TH');
|
||||
assert.equal(phoneSubmissions[0].payload.countryLabel, 'Thailand');
|
||||
assert.equal(phoneSubmissions[1].payload.phoneNumber, '+84943328460');
|
||||
assert.equal(phoneSubmissions[1].payload.countryId, 'VN');
|
||||
assert.equal(phoneSubmissions[1].payload.countryLabel, 'Vietnam');
|
||||
});
|
||||
|
||||
test('signup phone helper persists signup runtime state without touching add-phone activation', async () => {
|
||||
const setStateCalls = [];
|
||||
let currentState = {
|
||||
@@ -974,8 +1241,6 @@ test('signup phone helper does not let a hung page-state probe stall HeroSMS pol
|
||||
});
|
||||
|
||||
test('signup phone helper fails stale email-verification on 5sim RECEIVED without code during SMS polling', async () => {
|
||||
const fiveSimSource = fs.readFileSync('phone-sms/providers/five-sim.js', 'utf8');
|
||||
const fiveSimModule = new Function('self', `${fiveSimSource}; return self.PhoneSmsFiveSimProvider;`)({});
|
||||
let checkCount = 0;
|
||||
let pageStateReads = 0;
|
||||
const contentMessages = [];
|
||||
@@ -1005,7 +1270,6 @@ test('signup phone helper fails stale email-verification on 5sim RECEIVED withou
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
createFiveSimProvider: fiveSimModule.createProvider,
|
||||
fetchImpl: async (url) => {
|
||||
const parsedUrl = new URL(url);
|
||||
if (parsedUrl.pathname === '/v1/user/check/5001') {
|
||||
@@ -2352,29 +2616,28 @@ test('phone verification helper acquires a number from 5sim with fallback countr
|
||||
heroSmsActivationRetryRounds: 1,
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(activation, {
|
||||
activationId: '9876543',
|
||||
phoneNumber: '+447911123456',
|
||||
provider: '5sim',
|
||||
serviceCode: 'openai',
|
||||
countryId: 'england',
|
||||
countryCode: 'england',
|
||||
countryLabel: 'England',
|
||||
successfulUses: 0,
|
||||
maxUses: 3,
|
||||
});
|
||||
assert.equal(requests.length, 4);
|
||||
assert.equal(requests[0].pathname, '/v1/guest/prices');
|
||||
assert.equal(requests[0].search.get('country'), 'thailand');
|
||||
assert.equal(requests[0].search.get('product'), 'openai');
|
||||
assert.equal(requests[1].pathname, '/v1/user/buy/activation/thailand/any/openai');
|
||||
assert.equal(requests[1].search.get('maxPrice'), '0.08');
|
||||
assert.equal(requests[1].search.get('reuse'), '1');
|
||||
assert.equal(requests[1].headers.Authorization, 'Bearer five-token');
|
||||
assert.equal(requests[2].pathname, '/v1/guest/prices');
|
||||
assert.equal(requests[2].search.get('country'), 'england');
|
||||
assert.equal(requests[2].search.get('product'), 'openai');
|
||||
assert.equal(requests[3].pathname, '/v1/user/buy/activation/england/any/openai');
|
||||
assert.equal(activation.activationId, '9876543');
|
||||
assert.equal(activation.phoneNumber, '+447911123456');
|
||||
assert.equal(activation.provider, '5sim');
|
||||
assert.equal(activation.serviceCode, 'openai');
|
||||
assert.equal(activation.countryId, 'england');
|
||||
assert.equal(activation.countryCode, 'england');
|
||||
assert.equal(activation.successfulUses, 0);
|
||||
assert.equal(activation.maxUses, 3);
|
||||
assert.equal(requests.length, 6);
|
||||
assert.equal(requests[0].pathname, '/v1/guest/products/thailand/any');
|
||||
assert.equal(requests[1].pathname, '/v1/guest/prices');
|
||||
assert.equal(requests[1].search.get('country'), 'thailand');
|
||||
assert.equal(requests[1].search.get('product'), 'openai');
|
||||
assert.equal(requests[2].pathname, '/v1/user/buy/activation/thailand/any/openai');
|
||||
assert.equal(requests[2].search.get('maxPrice'), '0.08');
|
||||
assert.equal(requests[2].search.get('reuse'), '1');
|
||||
assert.equal(requests[2].headers.Authorization, 'Bearer five-token');
|
||||
assert.equal(requests[3].pathname, '/v1/guest/products/england/any');
|
||||
assert.equal(requests[4].pathname, '/v1/guest/prices');
|
||||
assert.equal(requests[4].search.get('country'), 'england');
|
||||
assert.equal(requests[4].search.get('product'), 'openai');
|
||||
assert.equal(requests[5].pathname, '/v1/user/buy/activation/england/any/openai');
|
||||
});
|
||||
|
||||
test('phone verification helper preserves fallback provider while refreshing latest settings', async () => {
|
||||
@@ -2514,13 +2777,14 @@ test('phone verification helper preserves fallback provider while refreshing lat
|
||||
assert.deepStrictEqual(
|
||||
fiveSimRequests.map((entry) => entry.url.pathname),
|
||||
[
|
||||
'/v1/guest/products/vietnam/any',
|
||||
'/v1/guest/prices',
|
||||
'/v1/user/buy/activation/vietnam/any/openai',
|
||||
'/v1/user/check/5020',
|
||||
'/v1/user/finish/5020',
|
||||
]
|
||||
);
|
||||
assert.equal(fiveSimRequests[1].options.headers.Authorization, 'Bearer five-token');
|
||||
assert.equal(fiveSimRequests[2].options.headers.Authorization, 'Bearer five-token');
|
||||
});
|
||||
|
||||
test('phone verification helper prefers phoneSmsReuseEnabled over legacy heroSmsReuseEnabled for 5sim acquisition', async () => {
|
||||
@@ -2593,20 +2857,18 @@ test('phone verification helper prefers phoneSmsReuseEnabled over legacy heroSms
|
||||
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);
|
||||
assert.equal(activation.activationId, '1234567');
|
||||
assert.equal(activation.phoneNumber, '+66880000000');
|
||||
assert.equal(activation.provider, '5sim');
|
||||
assert.equal(activation.serviceCode, 'openai');
|
||||
assert.equal(activation.countryId, 'thailand');
|
||||
assert.equal(activation.countryCode, 'thailand');
|
||||
assert.equal(activation.successfulUses, 0);
|
||||
assert.equal(activation.maxUses, 3);
|
||||
assert.equal(requests[0].pathname, '/v1/guest/products/thailand/any');
|
||||
assert.equal(requests[1].pathname, '/v1/guest/prices');
|
||||
assert.equal(requests[2].pathname, '/v1/user/buy/activation/thailand/any/openai');
|
||||
assert.equal(requests[2].search.get('reuse'), null);
|
||||
});
|
||||
|
||||
test('phone verification helper treats fiveSimReuseEnabled as legacy-only when phoneSmsReuseEnabled is absent', async () => {
|
||||
@@ -2679,20 +2941,18 @@ test('phone verification helper treats fiveSimReuseEnabled as legacy-only when p
|
||||
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');
|
||||
assert.equal(activation.activationId, '1234568');
|
||||
assert.equal(activation.phoneNumber, '+66880000001');
|
||||
assert.equal(activation.provider, '5sim');
|
||||
assert.equal(activation.serviceCode, 'openai');
|
||||
assert.equal(activation.countryId, 'thailand');
|
||||
assert.equal(activation.countryCode, 'thailand');
|
||||
assert.equal(activation.successfulUses, 0);
|
||||
assert.equal(activation.maxUses, 3);
|
||||
assert.equal(requests[0].pathname, '/v1/guest/products/thailand/any');
|
||||
assert.equal(requests[1].pathname, '/v1/guest/prices');
|
||||
assert.equal(requests[2].pathname, '/v1/user/buy/activation/thailand/any/openai');
|
||||
assert.equal(requests[2].search.get('reuse'), '1');
|
||||
});
|
||||
|
||||
test('phone verification helper rejects 5sim maxPrice with custom operator before buying', async () => {
|
||||
@@ -3115,7 +3375,7 @@ test('phone verification helper polls and parses 5sim verification codes', async
|
||||
|
||||
assert.equal(code, '246810');
|
||||
assert.equal(checkCount, 2);
|
||||
assert.deepStrictEqual(statusUpdates, ['PENDING']);
|
||||
assert.deepStrictEqual(statusUpdates, ['PENDING', 'RECEIVED']);
|
||||
});
|
||||
|
||||
test('phone verification helper treats HeroSMS STATUS_WAIT_RETRY payload status as pending', async () => {
|
||||
@@ -3242,18 +3502,16 @@ test('phone verification helper reuses 5sim by keeping the original activation',
|
||||
}
|
||||
);
|
||||
|
||||
assert.deepStrictEqual(nextActivation, {
|
||||
activationId: '600001',
|
||||
phoneNumber: '+44 7911-123-456',
|
||||
provider: '5sim',
|
||||
serviceCode: 'openai',
|
||||
countryId: 'england',
|
||||
countryCode: 'england',
|
||||
successfulUses: 0,
|
||||
maxUses: 1,
|
||||
source: '5sim-retained-reuse',
|
||||
ignoredPhoneCodeKeys: ['old::111111'],
|
||||
});
|
||||
assert.equal(nextActivation.activationId, '600001');
|
||||
assert.equal(nextActivation.phoneNumber, '+44 7911-123-456');
|
||||
assert.equal(nextActivation.provider, '5sim');
|
||||
assert.equal(nextActivation.serviceCode, 'openai');
|
||||
assert.equal(nextActivation.countryId, 'england');
|
||||
assert.equal(nextActivation.countryCode, 'england');
|
||||
assert.equal(nextActivation.successfulUses, 0);
|
||||
assert.equal(nextActivation.maxUses, 1);
|
||||
assert.equal(nextActivation.source, '5sim-retained-reuse');
|
||||
assert.deepStrictEqual(nextActivation.ignoredPhoneCodeKeys, ['old::111111']);
|
||||
assert.deepStrictEqual(requests, ['/v1/user/check/600001']);
|
||||
});
|
||||
|
||||
@@ -6448,12 +6706,9 @@ test('phone verification helper auto free-reuses 5sim by polling the retained or
|
||||
},
|
||||
};
|
||||
|
||||
const fiveSimSource = fs.readFileSync('phone-sms/providers/five-sim.js', 'utf8');
|
||||
const fiveSimModule = new Function('self', `${fiveSimSource}; return self.PhoneSmsFiveSimProvider;`)({});
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
createFiveSimProvider: fiveSimModule.createProvider,
|
||||
fetchImpl: async (url) => {
|
||||
const parsedUrl = new URL(url);
|
||||
requests.push(parsedUrl);
|
||||
@@ -6547,12 +6802,9 @@ test('phone verification helper retires failed 5sim free-reuse record instead of
|
||||
},
|
||||
};
|
||||
|
||||
const fiveSimSource = fs.readFileSync('phone-sms/providers/five-sim.js', 'utf8');
|
||||
const fiveSimModule = new Function('self', `${fiveSimSource}; return self.PhoneSmsFiveSimProvider;`)({});
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
createFiveSimProvider: fiveSimModule.createProvider,
|
||||
fetchImpl: async (url) => {
|
||||
const parsedUrl = new URL(url);
|
||||
requests.push(parsedUrl);
|
||||
@@ -8724,12 +8976,9 @@ test('phone verification helper routes 5sim buy, check, and finish by current ac
|
||||
reusablePhoneActivation: null,
|
||||
};
|
||||
|
||||
const fiveSimSource = fs.readFileSync('phone-sms/providers/five-sim.js', 'utf8');
|
||||
const fiveSimModule = new Function('self', `${fiveSimSource}; return self.PhoneSmsFiveSimProvider;`)({});
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
createFiveSimProvider: fiveSimModule.createProvider,
|
||||
fetchImpl: async (url, options = {}) => {
|
||||
const parsedUrl = new URL(url);
|
||||
requests.push({ url: parsedUrl, options });
|
||||
@@ -8838,7 +9087,6 @@ test('phone verification helper uses MaDao routing replace when add-phone reject
|
||||
};
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
createMaDaoProvider: maDaoModule.createProvider,
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
fetchImpl: async (url, options = {}) => {
|
||||
const parsedUrl = new URL(url);
|
||||
@@ -8966,6 +9214,7 @@ test('phone verification helper reacquires MaDao direct numbers after releasing
|
||||
madaoRoutingPlanId: 'rp-stale',
|
||||
madaoProviderId: 'upstream-a',
|
||||
madaoCountry: 'gb',
|
||||
madaoOperator: 'operator-a',
|
||||
madaoAutoPickCountry: false,
|
||||
madaoReusePhone: true,
|
||||
madaoMinPrice: '0.01',
|
||||
@@ -8981,7 +9230,6 @@ test('phone verification helper reacquires MaDao direct numbers after releasing
|
||||
};
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
createMaDaoProvider: maDaoModule.createProvider,
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
fetchImpl: async (url, options = {}) => {
|
||||
const parsedUrl = new URL(url);
|
||||
@@ -9076,6 +9324,9 @@ test('phone verification helper reacquires MaDao direct numbers after releasing
|
||||
auto_pick_country: false,
|
||||
reuse_phone: true,
|
||||
country: 'GB',
|
||||
metadata: {
|
||||
operator: 'operator-a',
|
||||
},
|
||||
min_price: 0.01,
|
||||
max_price: 0.2,
|
||||
});
|
||||
@@ -9114,12 +9365,9 @@ test('phone verification helper keeps 5sim reusable activation on the original o
|
||||
},
|
||||
};
|
||||
|
||||
const fiveSimSource = fs.readFileSync('phone-sms/providers/five-sim.js', 'utf8');
|
||||
const fiveSimModule = new Function('self', `${fiveSimSource}; return self.PhoneSmsFiveSimProvider;`)({});
|
||||
const helpers = api.createPhoneVerificationHelpers({
|
||||
addLog: async () => {},
|
||||
ensureStep8SignupPageReady: async () => {},
|
||||
createFiveSimProvider: fiveSimModule.createProvider,
|
||||
fetchImpl: async (url) => {
|
||||
const parsedUrl = new URL(url);
|
||||
requests.push(parsedUrl);
|
||||
|
||||
@@ -156,15 +156,28 @@ test('sidepanel html exposes phone verification toggle and multi-provider SMS ro
|
||||
assert.match(html, /id="row-madao-mode"/);
|
||||
assert.match(html, /id="select-madao-mode"/);
|
||||
assert.match(html, /id="row-madao-routing-plan-id"/);
|
||||
assert.match(html, /id="input-madao-routing-plan-id"/);
|
||||
assert.match(html, /id="select-madao-routing-plan-id"/);
|
||||
assert.match(html, /id="btn-madao-refresh-routing-plans"/);
|
||||
assert.doesNotMatch(html, /id="input-madao-routing-plan-id"/);
|
||||
assert.match(html, /id="row-madao-provider-id"/);
|
||||
assert.match(html, /id="input-madao-provider-id"/);
|
||||
assert.match(html, /id="select-madao-provider-id"/);
|
||||
assert.match(html, /id="btn-madao-refresh-providers"/);
|
||||
assert.doesNotMatch(html, /id="input-madao-provider-id"/);
|
||||
assert.match(html, /id="row-madao-country"/);
|
||||
assert.match(html, /id="input-madao-country"/);
|
||||
assert.match(html, /id="row-madao-auto-pick-country"/);
|
||||
assert.match(html, /id="input-madao-auto-pick-country"/);
|
||||
assert.match(html, /id="row-madao-reuse-phone"/);
|
||||
assert.match(html, /id="input-madao-reuse-phone"/);
|
||||
assert.match(html, /id="select-madao-country"/);
|
||||
assert.match(html, /id="btn-madao-refresh-countries"/);
|
||||
assert.doesNotMatch(html, /id="input-madao-country"/);
|
||||
assert.match(html, /id="row-madao-operator"/);
|
||||
assert.match(html, /id="select-madao-operator"/);
|
||||
assert.match(html, /id="btn-madao-refresh-operators"/);
|
||||
assert.doesNotMatch(html, /id="row-madao-auto-pick-country"/);
|
||||
assert.doesNotMatch(html, /id="input-madao-auto-pick-country"/);
|
||||
assert.doesNotMatch(html, /id="row-madao-reuse-phone"/);
|
||||
assert.doesNotMatch(html, /id="input-madao-reuse-phone"/);
|
||||
assert.doesNotMatch(html, /直连平台/);
|
||||
assert.doesNotMatch(html, /直连国家/);
|
||||
assert.doesNotMatch(html, /自动选国家/);
|
||||
assert.doesNotMatch(html, /MaDao 复用/);
|
||||
assert.match(html, /id="row-madao-price-range"/);
|
||||
assert.match(html, /id="input-madao-min-price"/);
|
||||
assert.match(html, /id="input-madao-max-price"/);
|
||||
@@ -190,6 +203,228 @@ test('sidepanel loads live SMS country lists silently during startup', () => {
|
||||
assert.doesNotMatch(sidepanelSource, /console\.error\('加载 (?:HeroSMS|5sim|NexSMS) 国家列表失败:'/);
|
||||
});
|
||||
|
||||
test('MaDao routing plan select loads options from helper API and preserves saved plan', async () => {
|
||||
const requests = [];
|
||||
const fetchImpl = async (url, options = {}) => {
|
||||
requests.push({ url, options });
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
async text() {
|
||||
return JSON.stringify({
|
||||
plans: [
|
||||
{ id: 'openai-plan', name: 'OpenAI Plan', service: 'openai', enabled: true },
|
||||
{ id: 'kiro-plan', name: 'Kiro Plan', service: 'kiro', enabled: true },
|
||||
{ id: 'disabled-plan', name: 'Disabled Plan', service: 'openai', enabled: false },
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const api = new Function('fetch', `
|
||||
const DEFAULT_MADAO_BASE_URL = 'http://127.0.0.1:7822';
|
||||
let latestState = {
|
||||
madaoBaseUrl: 'http://madao.local/api/acquire',
|
||||
madaoHttpSecret: 'madao-secret',
|
||||
madaoRoutingPlanId: 'stored-plan',
|
||||
};
|
||||
let maDaoRoutingPlanOptions = [];
|
||||
let displayText = '';
|
||||
let toastText = '';
|
||||
const inputMaDaoBaseUrl = { value: 'http://madao.local/api/acquire' };
|
||||
const inputMaDaoHttpSecret = { value: 'madao-secret' };
|
||||
const selectMaDaoRoutingPlanId = {
|
||||
value: 'stored-plan',
|
||||
options: [],
|
||||
replaceChildren(...children) {
|
||||
this.options = children;
|
||||
},
|
||||
};
|
||||
function updateHeroSmsPlatformDisplay() {
|
||||
displayText = getSelectedMaDaoRoutingPlanLabel();
|
||||
}
|
||||
function showToast(message) {
|
||||
toastText = message;
|
||||
}
|
||||
${extractFunction('normalizeMaDaoBaseUrlValue')}
|
||||
${extractFunction('normalizeMaDaoIdentifierValue')}
|
||||
${extractFunction('normalizeMaDaoRoutingPlanIdValue')}
|
||||
${extractFunction('createSelectOptionElement')}
|
||||
${extractFunction('setSelectOptions')}
|
||||
${extractFunction('buildMaDaoRoutingPlanOptions')}
|
||||
${extractFunction('setMaDaoRoutingPlanSelectOptions')}
|
||||
${extractFunction('buildMaDaoRequestUrl')}
|
||||
${extractFunction('buildMaDaoRequestHeaders')}
|
||||
${extractFunction('fetchMaDaoJson')}
|
||||
${extractFunction('getMaDaoRoutingPlansFromPayload')}
|
||||
${extractFunction('loadMaDaoRoutingPlans')}
|
||||
${extractFunction('getSelectedMaDaoRoutingPlanLabel')}
|
||||
return {
|
||||
loadMaDaoRoutingPlans,
|
||||
selectMaDaoRoutingPlanId,
|
||||
get options() { return selectMaDaoRoutingPlanId.options.map((option) => ({ value: option.value, label: option.textContent, selected: option.selected })); },
|
||||
get displayText() { return displayText; },
|
||||
get toastText() { return toastText; },
|
||||
};
|
||||
`)(fetchImpl);
|
||||
|
||||
const plans = await api.loadMaDaoRoutingPlans();
|
||||
|
||||
assert.deepStrictEqual(plans.map((plan) => plan.value), ['openai-plan']);
|
||||
assert.equal(api.selectMaDaoRoutingPlanId.value, 'stored-plan');
|
||||
assert.deepStrictEqual(api.options.map((option) => option.value), ['', 'stored-plan', 'openai-plan']);
|
||||
assert.equal(api.options.find((option) => option.value === 'stored-plan').selected, true);
|
||||
assert.equal(api.displayText, 'stored-plan');
|
||||
assert.equal(api.toastText, '已刷新 MaDao 路由计划。');
|
||||
assert.equal(requests[0].url, 'http://madao.local/api/routing-plans');
|
||||
assert.equal(requests[0].options.headers.Authorization, 'Bearer madao-secret');
|
||||
});
|
||||
|
||||
test('MaDao direct selects load provider country and operator options from daemon API', async () => {
|
||||
const requests = [];
|
||||
const fetchImpl = async (url, options = {}) => {
|
||||
const parsedUrl = new URL(url);
|
||||
requests.push({
|
||||
pathname: parsedUrl.pathname,
|
||||
options,
|
||||
body: options.body ? JSON.parse(options.body) : null,
|
||||
});
|
||||
if (parsedUrl.pathname === '/api/providers') {
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
async text() {
|
||||
return JSON.stringify({
|
||||
providers: [
|
||||
{ id: 'stored-provider', name: 'Stored Provider', enabled: true, protocol_label: 'REST' },
|
||||
{ id: 'disabled-provider', name: 'Disabled Provider', enabled: false },
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
if (parsedUrl.pathname === '/api/providers/stored-provider/countries') {
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
async text() {
|
||||
return JSON.stringify({
|
||||
provider: 'stored-provider',
|
||||
items: [
|
||||
{ value: 'GB', label: 'United Kingdom', label_zh: '英国', provider_value: 'england' },
|
||||
{ value: 'TH', label: 'Thailand', label_zh: '泰国', provider_value: '52' },
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
if (parsedUrl.pathname === '/api/providers/stored-provider/operators') {
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
async text() {
|
||||
return JSON.stringify({
|
||||
provider: 'stored-provider',
|
||||
items: [
|
||||
{ value: 'any', label: 'Any operator' },
|
||||
{ value: 'operator-a', label: 'Operator A' },
|
||||
{ value: 'operator-b', label: 'Operator B' },
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
throw new Error(`Unexpected MaDao path: ${parsedUrl.pathname}`);
|
||||
};
|
||||
|
||||
const api = new Function('fetch', `
|
||||
const DEFAULT_MADAO_BASE_URL = 'http://127.0.0.1:7822';
|
||||
let latestState = {
|
||||
madaoBaseUrl: 'http://madao.local/api/acquire',
|
||||
madaoHttpSecret: 'madao-secret',
|
||||
madaoProviderId: 'stored-provider',
|
||||
madaoCountry: 'england',
|
||||
madaoOperator: 'operator-a',
|
||||
};
|
||||
let maDaoProviderOptions = [];
|
||||
let maDaoCountryOptions = [];
|
||||
let maDaoOperatorOptions = [];
|
||||
let displayText = '';
|
||||
let toastText = '';
|
||||
const inputMaDaoBaseUrl = { value: 'http://madao.local/api/acquire' };
|
||||
const inputMaDaoHttpSecret = { value: 'madao-secret' };
|
||||
const selectMaDaoProviderId = { value: 'stored-provider', options: [], replaceChildren(...children) { this.options = children; } };
|
||||
const selectMaDaoCountry = { value: 'england', options: [], replaceChildren(...children) { this.options = children; } };
|
||||
const selectMaDaoOperator = { value: 'operator-a', options: [], replaceChildren(...children) { this.options = children; } };
|
||||
function updateHeroSmsPlatformDisplay() {
|
||||
displayText = [selectMaDaoProviderId.value, selectMaDaoCountry.value, selectMaDaoOperator.value].filter(Boolean).join('/');
|
||||
}
|
||||
function showToast(message) {
|
||||
toastText = message;
|
||||
}
|
||||
${extractFunction('normalizeMaDaoBaseUrlValue')}
|
||||
${extractFunction('normalizeMaDaoIdentifierValue')}
|
||||
${extractFunction('normalizeMaDaoProviderIdValue')}
|
||||
${extractFunction('normalizeMaDaoOperatorValue')}
|
||||
${extractFunction('normalizeMaDaoCountry')}
|
||||
${extractFunction('formatMaDaoCountryDisplayLabel')}
|
||||
${extractFunction('createSelectOptionElement')}
|
||||
${extractFunction('setSelectOptions')}
|
||||
${extractFunction('normalizeMaDaoOptionListItems')}
|
||||
${extractFunction('resolveMaDaoOptionSelectedValue')}
|
||||
${extractFunction('setMaDaoProviderSelectOptions')}
|
||||
${extractFunction('setMaDaoCountrySelectOptions')}
|
||||
${extractFunction('setMaDaoOperatorSelectOptions')}
|
||||
${extractFunction('buildMaDaoRequestUrl')}
|
||||
${extractFunction('buildMaDaoRequestHeaders')}
|
||||
${extractFunction('fetchMaDaoJson')}
|
||||
${extractFunction('getMaDaoProvidersFromPayload')}
|
||||
${extractFunction('getMaDaoOptionItemsFromPayload')}
|
||||
${extractFunction('getSelectedMaDaoProviderId')}
|
||||
${extractFunction('getSelectedMaDaoCountry')}
|
||||
${extractFunction('loadMaDaoProviders')}
|
||||
${extractFunction('loadMaDaoCountries')}
|
||||
${extractFunction('loadMaDaoOperators')}
|
||||
return {
|
||||
loadMaDaoProviders,
|
||||
selectMaDaoProviderId,
|
||||
selectMaDaoCountry,
|
||||
selectMaDaoOperator,
|
||||
get providerOptions() { return selectMaDaoProviderId.options.map((option) => ({ value: option.value, label: option.textContent, selected: option.selected })); },
|
||||
get countryOptions() { return selectMaDaoCountry.options.map((option) => ({ value: option.value, label: option.textContent, selected: option.selected })); },
|
||||
get operatorOptions() { return selectMaDaoOperator.options.map((option) => ({ value: option.value, label: option.textContent, selected: option.selected })); },
|
||||
get displayText() { return displayText; },
|
||||
get toastText() { return toastText; },
|
||||
};
|
||||
`)(fetchImpl);
|
||||
|
||||
const providers = await api.loadMaDaoProviders();
|
||||
|
||||
assert.deepStrictEqual(providers.map((provider) => provider.value), ['stored-provider']);
|
||||
assert.equal(api.selectMaDaoProviderId.value, 'stored-provider');
|
||||
assert.equal(api.selectMaDaoCountry.value, 'GB');
|
||||
assert.equal(api.selectMaDaoOperator.value, 'operator-a');
|
||||
assert.deepStrictEqual(api.providerOptions.map((option) => option.value), ['', 'stored-provider']);
|
||||
assert.deepStrictEqual(api.countryOptions.map((option) => option.value), ['', 'GB', 'TH']);
|
||||
assert.deepStrictEqual(api.countryOptions.map((option) => option.label), ['请先选择服务商', '英国', '泰国']);
|
||||
assert.deepStrictEqual(api.operatorOptions.map((option) => option.value), ['', 'operator-a', 'operator-b']);
|
||||
assert.deepStrictEqual(api.operatorOptions.map((option) => option.label), ['任意线路', 'Operator A', 'Operator B']);
|
||||
assert.equal(api.displayText, 'stored-provider/GB/operator-a');
|
||||
assert.equal(api.toastText, '已刷新 MaDao 服务商。');
|
||||
assert.deepStrictEqual(requests.map((request) => request.pathname), [
|
||||
'/api/providers',
|
||||
'/api/providers/stored-provider/countries',
|
||||
'/api/providers/stored-provider/operators',
|
||||
]);
|
||||
assert.deepStrictEqual(requests[2].body, { country: 'GB' });
|
||||
assert.equal(requests[0].options.headers.Authorization, 'Bearer madao-secret');
|
||||
});
|
||||
|
||||
test('HeroSMS country parser accepts keyed country maps from the live API', () => {
|
||||
const api = new Function(`
|
||||
${extractFunction('normalizeHeroSmsCountryPayloadEntries')}
|
||||
@@ -704,6 +939,7 @@ const rowMaDaoMode = { style: { display: 'none' } };
|
||||
const rowMaDaoRoutingPlanId = { style: { display: 'none' } };
|
||||
const rowMaDaoProviderId = { style: { display: 'none' } };
|
||||
const rowMaDaoCountry = { style: { display: 'none' } };
|
||||
const rowMaDaoOperator = { style: { display: 'none' } };
|
||||
const rowMaDaoAutoPickCountry = { style: { display: 'none' } };
|
||||
const rowMaDaoReusePhone = { style: { display: 'none' } };
|
||||
const rowMaDaoPriceRange = { style: { display: 'none' } };
|
||||
@@ -785,8 +1021,7 @@ const PHONE_SMS_PROVIDER_UI_DESCRIPTORS = ${JSON.stringify({
|
||||
directRowKeys: [
|
||||
'rowMaDaoProviderId',
|
||||
'rowMaDaoCountry',
|
||||
'rowMaDaoAutoPickCountry',
|
||||
'rowMaDaoReusePhone',
|
||||
'rowMaDaoOperator',
|
||||
'rowMaDaoPriceRange',
|
||||
],
|
||||
},
|
||||
@@ -862,6 +1097,7 @@ return {
|
||||
rowMaDaoRoutingPlanId,
|
||||
rowMaDaoProviderId,
|
||||
rowMaDaoCountry,
|
||||
rowMaDaoOperator,
|
||||
rowMaDaoAutoPickCountry,
|
||||
rowMaDaoReusePhone,
|
||||
rowMaDaoPriceRange,
|
||||
@@ -941,6 +1177,7 @@ return {
|
||||
assert.equal(api.rowMaDaoRoutingPlanId.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoProviderId.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoCountry.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoOperator.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoAutoPickCountry.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoReusePhone.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoPriceRange.style.display, 'none');
|
||||
@@ -1057,6 +1294,7 @@ return {
|
||||
assert.equal(api.rowMaDaoRoutingPlanId.style.display, '');
|
||||
assert.equal(api.rowMaDaoProviderId.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoCountry.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoOperator.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoAutoPickCountry.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoReusePhone.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoPriceRange.style.display, 'none');
|
||||
@@ -1069,8 +1307,9 @@ return {
|
||||
assert.equal(api.rowMaDaoRoutingPlanId.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoProviderId.style.display, '');
|
||||
assert.equal(api.rowMaDaoCountry.style.display, '');
|
||||
assert.equal(api.rowMaDaoAutoPickCountry.style.display, '');
|
||||
assert.equal(api.rowMaDaoReusePhone.style.display, '');
|
||||
assert.equal(api.rowMaDaoOperator.style.display, '');
|
||||
assert.equal(api.rowMaDaoAutoPickCountry.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoReusePhone.style.display, 'none');
|
||||
assert.equal(api.rowMaDaoPriceRange.style.display, '');
|
||||
});
|
||||
|
||||
@@ -1160,9 +1399,10 @@ const inputNexSmsServiceCode = { value: 'ot' };
|
||||
const inputMaDaoBaseUrl = { value: 'http://127.0.0.1:7822/api/acquire' };
|
||||
const inputMaDaoHttpSecret = { value: 'madao-secret' };
|
||||
const selectMaDaoMode = { value: 'direct' };
|
||||
const inputMaDaoRoutingPlanId = { value: 'plan-1' };
|
||||
const inputMaDaoProviderId = { value: 'Local Provider!!' };
|
||||
const inputMaDaoCountry = { value: 'th' };
|
||||
const selectMaDaoRoutingPlanId = { value: 'plan-1' };
|
||||
const selectMaDaoProviderId = { value: 'Local Provider!!' };
|
||||
const selectMaDaoCountry = { value: 'th' };
|
||||
const selectMaDaoOperator = { value: 'Operator A!' };
|
||||
const inputMaDaoAutoPickCountry = { checked: false };
|
||||
const inputMaDaoReusePhone = { checked: true };
|
||||
const inputMaDaoMinPrice = { value: '0.02' };
|
||||
@@ -1266,7 +1506,9 @@ ${extractFunction('normalizeMaDaoBaseUrlValue')}
|
||||
${extractFunction('normalizeMaDaoModeValue')}
|
||||
${extractFunction('normalizeMaDaoIdentifierValue')}
|
||||
${extractFunction('normalizeMaDaoProviderIdValue')}
|
||||
${extractFunction('normalizeMaDaoOperatorValue')}
|
||||
${extractFunction('normalizeMaDaoCountry')}
|
||||
${extractFunction('formatMaDaoCountryDisplayLabel')}
|
||||
${extractFunction('normalizeMaDaoPriceValue')}
|
||||
${extractFunction('normalizeFiveSimCountryCode')}
|
||||
${extractFunction('normalizeFiveSimCountryOrderValue')}
|
||||
@@ -1338,6 +1580,7 @@ return { collectSettingsPayload };
|
||||
assert.equal(payload.madaoRoutingPlanId, 'plan-1');
|
||||
assert.equal(payload.madaoProviderId, 'localprovider');
|
||||
assert.equal(payload.madaoCountry, 'TH');
|
||||
assert.equal(payload.madaoOperator, 'operatora');
|
||||
assert.equal(payload.madaoAutoPickCountry, false);
|
||||
assert.equal(payload.madaoReusePhone, true);
|
||||
assert.equal(payload.madaoMinPrice, '0.02');
|
||||
@@ -1389,6 +1632,7 @@ let latestState = {
|
||||
madaoRoutingPlanId: 'plan-old',
|
||||
madaoProviderId: 'provider-old',
|
||||
madaoCountry: 'TH',
|
||||
madaoOperator: 'operator-old',
|
||||
madaoAutoPickCountry: true,
|
||||
madaoReusePhone: true,
|
||||
madaoMinPrice: '0.01',
|
||||
@@ -1434,9 +1678,34 @@ const inputNexSmsServiceCode = { value: 'ot' };
|
||||
const inputMaDaoBaseUrl = { value: 'http://127.0.0.1:7822/api/poll' };
|
||||
const inputMaDaoHttpSecret = { value: 'madao-live-secret' };
|
||||
const selectMaDaoMode = { value: 'direct' };
|
||||
const inputMaDaoRoutingPlanId = { value: 'plan-live' };
|
||||
const inputMaDaoProviderId = { value: 'Provider Live!' };
|
||||
const inputMaDaoCountry = { value: 'local' };
|
||||
const selectMaDaoRoutingPlanId = {
|
||||
value: 'plan-live',
|
||||
options: [],
|
||||
replaceChildren(...children) {
|
||||
this.options = children;
|
||||
},
|
||||
};
|
||||
const selectMaDaoProviderId = {
|
||||
value: 'Provider Live!',
|
||||
options: [],
|
||||
replaceChildren(...children) {
|
||||
this.options = children;
|
||||
},
|
||||
};
|
||||
const selectMaDaoCountry = {
|
||||
value: 'local',
|
||||
options: [],
|
||||
replaceChildren(...children) {
|
||||
this.options = children;
|
||||
},
|
||||
};
|
||||
const selectMaDaoOperator = {
|
||||
value: 'Operator Live!',
|
||||
options: [],
|
||||
replaceChildren(...children) {
|
||||
this.options = children;
|
||||
},
|
||||
};
|
||||
const inputMaDaoAutoPickCountry = { checked: false };
|
||||
const inputMaDaoReusePhone = { checked: false };
|
||||
const inputMaDaoMinPrice = { value: '0.02' };
|
||||
@@ -1454,6 +1723,10 @@ let heroSmsCountrySelectionOrder = [];
|
||||
let phoneSmsProviderOrderSelection = ['hero-sms', '5sim'];
|
||||
let lastPhoneSmsProviderBeforeChange = null;
|
||||
let savedPayload = null;
|
||||
let maDaoRoutingPlanOptions = [];
|
||||
let maDaoProviderOptions = [];
|
||||
let maDaoCountryOptions = [];
|
||||
let maDaoOperatorOptions = [];
|
||||
|
||||
${extractFunction('normalizePhoneSmsProvider')}
|
||||
${extractFunction('normalizePhoneSmsProviderValue')}
|
||||
@@ -1483,9 +1756,21 @@ ${extractFunction('normalizeNexSmsServiceCodeValue')}
|
||||
${extractFunction('normalizeMaDaoBaseUrlValue')}
|
||||
${extractFunction('normalizeMaDaoModeValue')}
|
||||
${extractFunction('normalizeMaDaoIdentifierValue')}
|
||||
${extractFunction('normalizeMaDaoRoutingPlanIdValue')}
|
||||
${extractFunction('normalizeMaDaoProviderIdValue')}
|
||||
${extractFunction('normalizeMaDaoOperatorValue')}
|
||||
${extractFunction('normalizeMaDaoCountry')}
|
||||
${extractFunction('normalizeMaDaoPriceValue')}
|
||||
${extractFunction('formatMaDaoCountryDisplayLabel')}
|
||||
${extractFunction('createSelectOptionElement')}
|
||||
${extractFunction('setSelectOptions')}
|
||||
${extractFunction('normalizeMaDaoOptionListItems')}
|
||||
${extractFunction('resolveMaDaoOptionSelectedValue')}
|
||||
${extractFunction('buildMaDaoRoutingPlanOptions')}
|
||||
${extractFunction('setMaDaoRoutingPlanSelectOptions')}
|
||||
${extractFunction('setMaDaoProviderSelectOptions')}
|
||||
${extractFunction('setMaDaoCountrySelectOptions')}
|
||||
${extractFunction('setMaDaoOperatorSelectOptions')}
|
||||
${extractFunction('normalizePhoneSmsMinPriceValue')}
|
||||
${extractFunction('normalizePhoneSmsMaxPriceValue')}
|
||||
${extractFunction('normalizeHeroSmsCountryId')}
|
||||
@@ -1508,6 +1793,7 @@ function syncLatestState(patch) { latestState = { ...latestState, ...patch }; }
|
||||
function loadHeroSmsCountries() { return Promise.resolve(); }
|
||||
function loadFiveSimCountries() { return Promise.resolve(); }
|
||||
function loadNexSmsCountries() { return Promise.resolve(); }
|
||||
function loadMaDaoProviders() { return Promise.resolve(); }
|
||||
function applyHeroSmsFallbackSelection() {}
|
||||
function applyFiveSimCountrySelection() {}
|
||||
function applyNexSmsCountrySelection() {}
|
||||
@@ -1564,6 +1850,71 @@ return {
|
||||
assert.equal(api.savedPayload.fiveSimMinPrice, '0.88');
|
||||
});
|
||||
|
||||
test('buildPhoneSmsProviderStatePatch preserves MaDao hidden reuse defaults when controls are absent', () => {
|
||||
const api = new Function(`
|
||||
let latestState = {
|
||||
phoneSmsProvider: 'madao',
|
||||
madaoBaseUrl: 'http://127.0.0.1:7822',
|
||||
madaoHttpSecret: 'secret-old',
|
||||
madaoMode: 'direct',
|
||||
madaoRoutingPlanId: 'plan-old',
|
||||
madaoProviderId: 'provider-old',
|
||||
madaoCountry: 'TH',
|
||||
madaoOperator: 'any',
|
||||
madaoAutoPickCountry: true,
|
||||
madaoReusePhone: true,
|
||||
madaoMinPrice: '0.01',
|
||||
madaoMaxPrice: '0.09',
|
||||
};
|
||||
const PHONE_SMS_PROVIDER_HERO_SMS = 'hero-sms';
|
||||
const PHONE_SMS_PROVIDER_HERO = PHONE_SMS_PROVIDER_HERO_SMS;
|
||||
const PHONE_SMS_PROVIDER_FIVE_SIM = '5sim';
|
||||
const PHONE_SMS_PROVIDER_NEXSMS = 'nexsms';
|
||||
const PHONE_SMS_PROVIDER_MADAO = 'madao';
|
||||
const DEFAULT_PHONE_SMS_PROVIDER = PHONE_SMS_PROVIDER_HERO_SMS;
|
||||
const DEFAULT_FIVE_SIM_COUNTRY_ID = 'vietnam';
|
||||
const DEFAULT_FIVE_SIM_COUNTRY_LABEL = '越南 (Vietnam)';
|
||||
const DEFAULT_FIVE_SIM_OPERATOR = 'any';
|
||||
const DEFAULT_FIVE_SIM_PRODUCT = 'openai';
|
||||
const DEFAULT_NEX_SMS_SERVICE_CODE = 'ot';
|
||||
const DEFAULT_MADAO_BASE_URL = 'http://127.0.0.1:7822';
|
||||
const MADAO_MODE_ROUTING_PLAN = 'routing_plan';
|
||||
const MADAO_MODE_DIRECT = 'direct';
|
||||
const DEFAULT_MADAO_MODE = MADAO_MODE_ROUTING_PLAN;
|
||||
const selectMaDaoMode = { value: 'direct' };
|
||||
const selectMaDaoRoutingPlanId = { value: 'plan-live' };
|
||||
const selectMaDaoProviderId = { value: 'provider-live' };
|
||||
const selectMaDaoCountry = { value: 'GB' };
|
||||
const selectMaDaoOperator = { value: 'Any operator' };
|
||||
const inputMaDaoBaseUrl = { value: 'http://127.0.0.1:7822/api/acquire' };
|
||||
const inputMaDaoHttpSecret = { value: 'secret-live' };
|
||||
const inputMaDaoMinPrice = { value: '0.02' };
|
||||
const inputMaDaoMaxPrice = { value: '0.20' };
|
||||
|
||||
${extractFunction('normalizePhoneSmsProvider')}
|
||||
${extractFunction('normalizeMaDaoBaseUrlValue')}
|
||||
${extractFunction('normalizeMaDaoModeValue')}
|
||||
${extractFunction('normalizeMaDaoIdentifierValue')}
|
||||
${extractFunction('normalizeMaDaoRoutingPlanIdValue')}
|
||||
${extractFunction('normalizeMaDaoProviderIdValue')}
|
||||
${extractFunction('normalizeMaDaoOperatorValue')}
|
||||
${extractFunction('normalizeMaDaoCountry')}
|
||||
${extractFunction('normalizeMaDaoPriceValue')}
|
||||
${extractFunction('normalizePhoneSmsMinPriceValue')}
|
||||
${extractFunction('normalizePhoneSmsMaxPriceValue')}
|
||||
${extractFunction('buildPhoneSmsProviderStatePatch')}
|
||||
return { buildPhoneSmsProviderStatePatch };
|
||||
`)();
|
||||
|
||||
const patch = api.buildPhoneSmsProviderStatePatch('madao');
|
||||
|
||||
assert.equal(patch.madaoAutoPickCountry, true);
|
||||
assert.equal(patch.madaoReusePhone, true);
|
||||
assert.equal(patch.madaoOperator, '');
|
||||
assert.equal(patch.madaoProviderId, 'provider-live');
|
||||
assert.equal(patch.madaoCountry, 'GB');
|
||||
});
|
||||
|
||||
test('HeroSMS operator helpers normalize keyed operator payloads', () => {
|
||||
const api = new Function(`
|
||||
const DEFAULT_HERO_SMS_OPERATOR = 'any';
|
||||
|
||||
Reference in New Issue
Block a user