diff --git a/background/steps/create-plus-checkout.js b/background/steps/create-plus-checkout.js index 6e5d150..905e874 100644 --- a/background/steps/create-plus-checkout.js +++ b/background/steps/create-plus-checkout.js @@ -210,13 +210,42 @@ return Number.isFinite(numeric) ? Math.max(0, Math.floor(numeric)) : null; } - function isGpcAutoModeEnabled(payload = {}) { - const rootScope = typeof self !== 'undefined' ? self : globalThis; - if (rootScope.GoPayUtils?.isGpcAutoModeEnabled) { - return rootScope.GoPayUtils.isGpcAutoModeEnabled(payload); + function normalizeGpcAutoModePermissionValue(value) { + if (typeof value === 'boolean') { + return value; } + if (typeof value === 'number') { + if (value === 1) return true; + if (value === 0) return false; + } + const normalized = String(value ?? '').trim().toLowerCase(); + if (!normalized) { + return null; + } + if (['true', '1', 'yes', 'y', 'on', 'enabled', 'enable'].includes(normalized)) { + return true; + } + if (['false', '0', 'no', 'n', 'off', 'disabled', 'disable'].includes(normalized)) { + return false; + } + return null; + } + + function getGpcAutoModePermission(payload = {}) { const data = unwrapGpcResponse(payload); - return data?.auto_mode_enabled === true || data?.autoModeEnabled === true; + if (!data || typeof data !== 'object' || Array.isArray(data)) { + return null; + } + return normalizeGpcAutoModePermissionValue( + data.auto_mode_enabled + ?? data.autoModeEnabled + ?? data.auto_enabled + ?? data.autoEnabled + ); + } + + function isGpcAutoModePermissionDenied(payload = {}) { + return getGpcAutoModePermission(payload) === false; } async function assertGpcApiKeyReadyForCreate(state = {}, phoneMode = GPC_HELPER_PHONE_MODE_MANUAL, apiKey = '') { @@ -244,7 +273,7 @@ if (remainingUses !== null && remainingUses <= 0) { throw new Error('创建 GPC 订单失败:API Key 剩余次数不足。'); } - if (phoneMode === GPC_HELPER_PHONE_MODE_AUTO && !isGpcAutoModeEnabled(balanceData)) { + if (phoneMode === GPC_HELPER_PHONE_MODE_AUTO && isGpcAutoModePermissionDenied(balanceData)) { throw new Error('创建 GPC 订单失败:当前 GPC API Key 未开通自动模式。'); } } diff --git a/sidepanel/sidepanel.js b/sidepanel/sidepanel.js index 2760ce9..d32e7e0 100644 --- a/sidepanel/sidepanel.js +++ b/sidepanel/sidepanel.js @@ -2167,22 +2167,55 @@ function getGpcHelperAutoModeEnabled(state = latestState) { return Boolean(state?.gopayHelperAutoModeEnabled); } -function hasGpcAutoModePermissionField(payload = {}) { - if (!payload || typeof payload !== 'object' || Array.isArray(payload)) { +function normalizeGpcAutoModePermissionValue(value) { + if (typeof value === 'boolean') { + return value; + } + if (typeof value === 'number') { + if (value === 1) return true; + if (value === 0) return false; + } + const normalized = String(value ?? '').trim().toLowerCase(); + if (!normalized) { + return null; + } + if (['true', '1', 'yes', 'y', 'on', 'enabled', 'enable'].includes(normalized)) { + return true; + } + if (['false', '0', 'no', 'n', 'off', 'disabled', 'disable'].includes(normalized)) { return false; } - return payload.auto_mode_enabled !== undefined - || payload.autoModeEnabled !== undefined - || payload.auto_enabled !== undefined - || payload.autoEnabled !== undefined - || (payload.data && typeof payload.data === 'object' && !Array.isArray(payload.data) && hasGpcAutoModePermissionField(payload.data)); + return null; +} + +function getGpcAutoModePermissionFromPayload(payload = {}) { + if (!payload || typeof payload !== 'object' || Array.isArray(payload)) { + return null; + } + for (const key of ['auto_mode_enabled', 'autoModeEnabled', 'auto_enabled', 'autoEnabled']) { + if (payload[key] !== undefined) { + return normalizeGpcAutoModePermissionValue(payload[key]); + } + } + if (payload.data && typeof payload.data === 'object' && !Array.isArray(payload.data)) { + return getGpcAutoModePermissionFromPayload(payload.data); + } + return null; +} + +function shouldPreserveSelectedGpcAutoMode(state = latestState) { + const payloadPermission = getGpcAutoModePermissionFromPayload(state?.gopayHelperBalancePayload); + return normalizeGpcHelperPhoneModeValue(state?.gopayHelperPhoneMode) === GPC_HELPER_PHONE_MODE_AUTO + && (Boolean(state?.gopayHelperAutoModeEnabled) || payloadPermission === true); +} + +function hasGpcAutoModePermissionField(payload = {}) { + return getGpcAutoModePermissionFromPayload(payload) !== null; } function isGpcAutoModePermissionDenied(state = latestState) { - if (getGpcHelperAutoModeEnabled(state)) { - return false; - } - return hasGpcAutoModePermissionField(state?.gopayHelperBalancePayload); + const payloadPermission = getGpcAutoModePermissionFromPayload(state?.gopayHelperBalancePayload); + return payloadPermission === false; } function normalizeGpcRemainingUsesValue(value) { @@ -3389,7 +3422,10 @@ function collectSettingsPayload() { ? selectGpcHelperPhoneMode.value : (latestState?.gopayHelperPhoneMode || 'manual') ); - const effectiveGpcPhoneMode = (typeof isGpcAutoModePermissionDenied === 'function' && isGpcAutoModePermissionDenied(latestState)) + const preserveSelectedGpcAutoMode = typeof shouldPreserveSelectedGpcAutoMode === 'function' + ? shouldPreserveSelectedGpcAutoMode(latestState) + : false; + const effectiveGpcPhoneMode = (!preserveSelectedGpcAutoMode && typeof isGpcAutoModePermissionDenied === 'function' && isGpcAutoModePermissionDenied(latestState)) ? 'manual' : selectedGpcPhoneMode; const selectedGpcOtpChannel = normalizeGpcOtpChannelSafe( @@ -7370,7 +7406,11 @@ function updatePlusModeUI() { ); const gpcAutoModeDenied = isGpcAutoModePermissionDenied(latestState); const gpcAutoModeEnabled = getGpcHelperAutoModeEnabled(latestState); - const isGpcAutoMode = !gpcAutoModeDenied && gpcPhoneMode === GPC_HELPER_PHONE_MODE_AUTO; + const preserveSelectedGpcAutoMode = typeof shouldPreserveSelectedGpcAutoMode === 'function' + ? shouldPreserveSelectedGpcAutoMode(latestState) + : false; + const effectiveGpcAutoModeDenied = gpcAutoModeDenied && !preserveSelectedGpcAutoMode; + const isGpcAutoMode = !effectiveGpcAutoModeDenied && gpcPhoneMode === GPC_HELPER_PHONE_MODE_AUTO; const gpcOtpChannel = normalizeGpcOtpChannelValue( typeof selectGpcHelperOtpChannel !== 'undefined' && selectGpcHelperOtpChannel ? selectGpcHelperOtpChannel.value @@ -7385,7 +7425,7 @@ function updatePlusModeUI() { ? normalizePlusPaymentMethod(selectPlusPaymentMethod.value) : method; const gpcRowsVisible = enabled && selectedMethod === gpcValue; - const canShowGpcModeSelector = gpcRowsVisible && (gpcAutoModeEnabled || !gpcAutoModeDenied); + const canShowGpcModeSelector = gpcRowsVisible && (gpcAutoModeEnabled || !effectiveGpcAutoModeDenied); const localSmsControlsVisible = gpcRowsVisible && !isGpcAutoMode; const effectiveLocalSmsEnabled = !isGpcAutoMode && localSmsEnabled; if (typeof selectPlusPaymentMethod !== 'undefined' && selectPlusPaymentMethod) { @@ -7430,7 +7470,7 @@ function updatePlusModeUI() { rowGpcHelperPhoneMode.style.display = canShowGpcModeSelector ? '' : 'none'; } if (typeof selectGpcHelperPhoneMode !== 'undefined' && selectGpcHelperPhoneMode) { - selectGpcHelperPhoneMode.value = gpcAutoModeDenied ? GPC_HELPER_PHONE_MODE_MANUAL : gpcPhoneMode; + selectGpcHelperPhoneMode.value = effectiveGpcAutoModeDenied ? GPC_HELPER_PHONE_MODE_MANUAL : gpcPhoneMode; } [ typeof rowGpcHelperCountryCode !== 'undefined' ? rowGpcHelperCountryCode : null, @@ -7735,7 +7775,7 @@ async function ensureGpcApiKeyReadyForStart(options = {}) { return false; } - if (selectedMode === GPC_HELPER_PHONE_MODE_AUTO && !balanceState.gopayHelperAutoModeEnabled) { + if (selectedMode === GPC_HELPER_PHONE_MODE_AUTO && isGpcAutoModePermissionDenied(balanceState)) { if (typeof selectGpcHelperPhoneMode !== 'undefined' && selectGpcHelperPhoneMode) { selectGpcHelperPhoneMode.value = GPC_HELPER_PHONE_MODE_MANUAL; } @@ -11765,14 +11805,22 @@ btnGpcHelperBalance?.addEventListener('click', async () => { gopayHelperAutoModeEnabled: getGpcAutoModeEnabledFromResponse(response), gopayHelperApiKeyStatus: response?.apiKeyStatus || response?.data?.status || response?.payload?.data?.status || response?.payload?.status || '', }; + const nextAutoModePermission = getGpcAutoModePermissionFromPayload(nextState.gopayHelperBalancePayload); + const nextAutoModeDenied = nextAutoModePermission === false; + const nextAutoModeConfirmed = nextAutoModePermission === true || nextState.gopayHelperAutoModeEnabled; + const selectedModeBeforeBalanceState = getSelectedGpcHelperPhoneMode(); syncLatestState(nextState); - if (!nextState.gopayHelperAutoModeEnabled && getSelectedGpcHelperPhoneMode() === GPC_HELPER_PHONE_MODE_AUTO) { + if (nextAutoModeDenied && selectedModeBeforeBalanceState === GPC_HELPER_PHONE_MODE_AUTO) { selectGpcHelperPhoneMode.value = GPC_HELPER_PHONE_MODE_MANUAL; syncLatestState({ gopayHelperPhoneMode: GPC_HELPER_PHONE_MODE_MANUAL }); await saveSettings({ silent: true, force: true }).catch(() => {}); showToast('当前 API Key 未开通自动模式,已切回手动模式。', 'warn'); + } else if (nextAutoModeDenied) { + showToast('GPC 余额已更新,当前 API Key 只能使用手动模式。', 'success'); + } else if (nextAutoModeConfirmed) { + showToast('GPC 余额已更新,自动模式可用。', 'success'); } else { - showToast(nextState.gopayHelperAutoModeEnabled ? 'GPC 余额已更新,自动模式可用。' : 'GPC 余额已更新,当前 API Key 只能使用手动模式。', 'success'); + showToast('GPC 余额已更新,当前接口未返回自动模式权限,已保留所选模式。', 'success'); } updatePlusModeUI(); } catch (error) { @@ -13728,7 +13776,9 @@ chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => { if (message.payload.gopayHelperPhoneMode !== undefined && selectGpcHelperPhoneMode) { selectGpcHelperPhoneMode.value = normalizeGpcHelperPhoneModeValue(message.payload.gopayHelperPhoneMode); } - if (message.payload.gopayHelperAutoModeEnabled === false && selectGpcHelperPhoneMode?.value === GPC_HELPER_PHONE_MODE_AUTO) { + if (message.payload.gopayHelperAutoModeEnabled === false + && selectGpcHelperPhoneMode?.value === GPC_HELPER_PHONE_MODE_AUTO + && isGpcAutoModePermissionDenied(latestState)) { selectGpcHelperPhoneMode.value = GPC_HELPER_PHONE_MODE_MANUAL; syncLatestState({ gopayHelperPhoneMode: GPC_HELPER_PHONE_MODE_MANUAL }); showToast('当前 API Key 未开通自动模式,已切回手动模式。', 'warn', 2200); diff --git a/tests/plus-checkout-create-wait.test.js b/tests/plus-checkout-create-wait.test.js index 9b3d01a..6c13520 100644 --- a/tests/plus-checkout-create-wait.test.js +++ b/tests/plus-checkout-create-wait.test.js @@ -510,6 +510,63 @@ test('GPC auto checkout only sends access token and API Key', async () => { assert.equal(events.find((event) => event.type === 'complete')?.step, 6); }); +test('GPC auto checkout keeps running when balance payload omits auto mode permission', async () => { + const events = []; + const fetchCalls = []; + const executor = api.createPlusCheckoutCreateExecutor({ + addLog: async () => {}, + chrome: { + tabs: { + create: async () => { + throw new Error('should not open token tab when direct access token exists'); + }, + remove: async () => {}, + }, + }, + completeStepFromBackground: async (step, payload) => events.push({ type: 'complete', step, payload }), + ensureContentScriptReadyOnTabUntilStopped: async () => {}, + fetch: async (url, options = {}) => { + fetchCalls.push({ url, options }); + return { + ok: true, + status: 200, + json: async () => url.endsWith('/api/gp/balance') + ? createGpcBalanceResponse({ auto_mode_enabled: undefined, remaining_uses: 998 }) + : createGpcTaskResponse({ + task_id: 'task_auto_unknown_permission', + status: 'queued', + status_text: '排队中', + phone_mode: 'auto', + api_waiting_for: '', + }), + }; + }, + registerTab: async () => {}, + sendTabMessageUntilStopped: async () => ({}), + setState: async (payload) => events.push({ type: 'set-state', payload }), + sleepWithStop: async () => {}, + waitForTabCompleteUntilStopped: async () => {}, + }); + + await executor.executePlusCheckoutCreate({ + plusPaymentMethod: 'gpc-helper', + gopayHelperPhoneMode: 'auto', + gopayHelperApiUrl: 'https://gpc.qlhazycoder.top/', + chatgptAccessToken: 'state-access-token', + gopayHelperApiKey: 'gpc_auto_123', + }); + + assert.equal(fetchCalls.length, 2); + assert.equal(fetchCalls[0].url, 'https://gpc.qlhazycoder.top/api/gp/balance'); + assert.equal(fetchCalls[1].url, 'https://gpc.qlhazycoder.top/api/gp/tasks'); + const helperPayload = JSON.parse(fetchCalls[1].options.body); + assert.equal(helperPayload.phone_mode, 'auto'); + const statePayload = events.find((event) => event.type === 'set-state')?.payload || {}; + assert.equal(statePayload.gopayHelperTaskId, 'task_auto_unknown_permission'); + assert.equal(statePayload.gopayHelperPhoneMode, 'auto'); + assert.equal(events.find((event) => event.type === 'complete')?.step, 6); +}); + test('GPC auto checkout blocks API Keys without auto mode permission', async () => { const fetchCalls = []; const executor = api.createPlusCheckoutCreateExecutor({ diff --git a/tests/sidepanel-plus-payment-method.test.js b/tests/sidepanel-plus-payment-method.test.js index ecf00ef..fdd8e6d 100644 --- a/tests/sidepanel-plus-payment-method.test.js +++ b/tests/sidepanel-plus-payment-method.test.js @@ -134,6 +134,9 @@ test('sidepanel Plus UI hides PayPal account selector while GoPay is selected', extractFunction('getSelectedPlusPaymentMethod'), extractFunction('normalizeGpcHelperPhoneModeValue'), extractFunction('getGpcHelperAutoModeEnabled'), + extractFunction('normalizeGpcAutoModePermissionValue'), + extractFunction('getGpcAutoModePermissionFromPayload'), + extractFunction('shouldPreserveSelectedGpcAutoMode'), extractFunction('hasGpcAutoModePermissionField'), extractFunction('isGpcAutoModePermissionDenied'), extractFunction('normalizeGpcOtpChannelValue'), @@ -217,6 +220,9 @@ test('sidepanel Plus UI shows GPC fields and purchase button only for GPC', () = extractFunction('getSelectedPlusPaymentMethod'), extractFunction('normalizeGpcHelperPhoneModeValue'), extractFunction('getGpcHelperAutoModeEnabled'), + extractFunction('normalizeGpcAutoModePermissionValue'), + extractFunction('getGpcAutoModePermissionFromPayload'), + extractFunction('shouldPreserveSelectedGpcAutoMode'), extractFunction('hasGpcAutoModePermissionField'), extractFunction('isGpcAutoModePermissionDenied'), extractFunction('normalizeGpcOtpChannelValue'), @@ -310,6 +316,9 @@ test('sidepanel hides GPC auto mode selector when API Key has no auto permission extractFunction('getSelectedPlusPaymentMethod'), extractFunction('normalizeGpcHelperPhoneModeValue'), extractFunction('getGpcHelperAutoModeEnabled'), + extractFunction('normalizeGpcAutoModePermissionValue'), + extractFunction('getGpcAutoModePermissionFromPayload'), + extractFunction('shouldPreserveSelectedGpcAutoMode'), extractFunction('hasGpcAutoModePermissionField'), extractFunction('isGpcAutoModePermissionDenied'), extractFunction('normalizeGpcOtpChannelValue'), @@ -353,12 +362,104 @@ return { updatePlusModeUI, selectGpcHelperPhoneMode, plusPaymentMethodCaption, r assert.match(api.plusPaymentMethodCaption.textContent, /手动/); }); +test('sidepanel keeps selected GPC auto mode when persisted permission survives stop refresh', () => { + const bundle = [ + extractFunction('normalizePlusPaymentMethod'), + extractFunction('getSelectedPlusPaymentMethod'), + extractFunction('normalizeGpcHelperPhoneModeValue'), + extractFunction('getGpcHelperAutoModeEnabled'), + extractFunction('normalizeGpcAutoModePermissionValue'), + extractFunction('getGpcAutoModePermissionFromPayload'), + extractFunction('shouldPreserveSelectedGpcAutoMode'), + extractFunction('hasGpcAutoModePermissionField'), + extractFunction('isGpcAutoModePermissionDenied'), + extractFunction('normalizeGpcOtpChannelValue'), + extractFunction('updatePlusModeUI'), + ].join('\n'); + + const api = new Function(` +let latestState = { + plusPaymentMethod: 'gpc-helper', + gopayHelperPhoneMode: 'auto', + gopayHelperAutoModeEnabled: true, + gopayHelperBalancePayload: { auto_mode_enabled: true }, +}; +let currentPlusPaymentMethod = 'gpc-helper'; +const inputPlusModeEnabled = { checked: true }; +const selectPlusPaymentMethod = { value: 'gpc-helper', style: { display: 'none' } }; +const GPC_HELPER_PHONE_MODE_AUTO = 'auto'; +const GPC_HELPER_PHONE_MODE_MANUAL = 'manual'; +const plusPaymentMethodCaption = { textContent: '' }; +const rowPayPalAccount = { style: { display: '' } }; +const rowPlusPaymentMethod = { style: { display: 'none' } }; +const rowGpcHelperApi = { style: { display: 'none' } }; +const rowGpcHelperCardKey = { style: { display: 'none' } }; +const rowGpcHelperPhoneMode = { style: { display: 'none' } }; +const selectGpcHelperPhoneMode = { value: 'auto' }; +const rowGpcHelperCountryCode = { style: { display: 'none' } }; +const rowGpcHelperPhone = { style: { display: 'none' } }; +const rowGpcHelperOtpChannel = { style: { display: 'none' } }; +const selectGpcHelperOtpChannel = { value: 'whatsapp' }; +const rowGpcHelperLocalSmsEnabled = { style: { display: 'none' } }; +const inputGpcHelperLocalSmsEnabled = { checked: false }; +const rowGpcHelperLocalSmsUrl = { style: { display: 'none' } }; +const rowGpcHelperPin = { style: { display: 'none' } }; +${bundle} +function syncLatestState(nextState) { latestState = { ...latestState, ...nextState }; } +return { + updatePlusModeUI, + selectGpcHelperPhoneMode, + getSelectedPhoneMode() { return selectGpcHelperPhoneMode.value; }, + getPayloadPhoneMode() { + return (() => { + const selectedGpcPhoneMode = normalizeGpcHelperPhoneModeValue(selectGpcHelperPhoneMode.value); + const preserveSelectedGpcAutoMode = shouldPreserveSelectedGpcAutoMode(latestState); + return (!preserveSelectedGpcAutoMode && isGpcAutoModePermissionDenied(latestState)) ? 'manual' : selectedGpcPhoneMode; + })(); + }, + applyDataUpdated(payload) { + syncLatestState(payload); + if (payload.gopayHelperPhoneMode !== undefined) { + selectGpcHelperPhoneMode.value = normalizeGpcHelperPhoneModeValue(payload.gopayHelperPhoneMode); + } + if (payload.gopayHelperAutoModeEnabled === false + && selectGpcHelperPhoneMode?.value === GPC_HELPER_PHONE_MODE_AUTO + && isGpcAutoModePermissionDenied(latestState)) { + selectGpcHelperPhoneMode.value = GPC_HELPER_PHONE_MODE_MANUAL; + syncLatestState({ gopayHelperPhoneMode: GPC_HELPER_PHONE_MODE_MANUAL }); + } + updatePlusModeUI(); + }, + rows: { rowGpcHelperPhoneMode, rowGpcHelperPhone, rowGpcHelperOtpChannel, rowGpcHelperPin }, +}; +`)(); + + api.updatePlusModeUI(); + assert.equal(api.getSelectedPhoneMode(), 'auto'); + assert.equal(api.getPayloadPhoneMode(), 'auto'); + assert.equal(api.rows.rowGpcHelperPhoneMode.style.display, ''); + assert.equal(api.rows.rowGpcHelperPhone.style.display, 'none'); + + api.applyDataUpdated({ + autoRunning: false, + autoRunPhase: 'stopped', + gopayHelperAutoModeEnabled: false, + }); + + assert.equal(api.getSelectedPhoneMode(), 'auto'); + assert.equal(api.getPayloadPhoneMode(), 'auto'); + assert.equal(api.rows.rowGpcHelperPhone.style.display, 'none'); +}); + test('sidepanel keeps selected GPC auto mode before permission has been queried', () => { const bundle = [ extractFunction('normalizePlusPaymentMethod'), extractFunction('getSelectedPlusPaymentMethod'), extractFunction('normalizeGpcHelperPhoneModeValue'), extractFunction('getGpcHelperAutoModeEnabled'), + extractFunction('normalizeGpcAutoModePermissionValue'), + extractFunction('getGpcAutoModePermissionFromPayload'), + extractFunction('shouldPreserveSelectedGpcAutoMode'), extractFunction('hasGpcAutoModePermissionField'), extractFunction('isGpcAutoModePermissionDenied'), extractFunction('normalizeGpcOtpChannelValue'), @@ -401,6 +502,70 @@ return { updatePlusModeUI, selectGpcHelperPhoneMode, plusPaymentMethodCaption, r assert.match(api.plusPaymentMethodCaption.textContent, /自动/); }); +test('sidepanel start check keeps GPC auto mode when balance payload omits permission field', async () => { + const bundle = [ + extractFunction('normalizeGpcAutoModePermissionValue'), + extractFunction('getGpcAutoModePermissionFromPayload'), + extractFunction('isGpcAutoModePermissionDenied'), + extractFunction('normalizeGpcRemainingUsesValue'), + extractFunction('ensureGpcApiKeyReadyForStart'), + ].join('\n'); + + const api = new Function(` +let latestState = { gopayHelperPhoneMode: 'auto' }; +const GPC_HELPER_PHONE_MODE_AUTO = 'auto'; +const GPC_HELPER_PHONE_MODE_MANUAL = 'manual'; +const selectGpcHelperPhoneMode = { value: 'auto' }; +const dialogs = []; +let saveCalls = 0; +let updateCalls = 0; +${bundle} +function isGpcHelperCheckoutSelected() { return true; } +function getSelectedGpcHelperPhoneMode() { return selectGpcHelperPhoneMode.value; } +async function refreshGpcBalanceForStart() { + return { + gopayHelperRemainingUses: 998, + gopayHelperApiKeyStatus: 'active', + gopayHelperAutoModeEnabled: false, + gopayHelperBalancePayload: { + status: 'active', + remaining_uses: 998, + }, + }; +} +async function showGpcStartBlockedDialog(message) { + dialogs.push(message); +} +function syncLatestState(nextState) { + latestState = { ...latestState, ...nextState }; +} +function updatePlusModeUI() { + updateCalls += 1; +} +async function saveSettings() { + saveCalls += 1; +} +function showToast() {} +return { + ensureGpcApiKeyReadyForStart, + selectGpcHelperPhoneMode, + getDialogs: () => dialogs.slice(), + getSaveCalls: () => saveCalls, + getUpdateCalls: () => updateCalls, + getPersistedPhoneMode: () => latestState.gopayHelperPhoneMode, +}; +`)(); + + const allowed = await api.ensureGpcApiKeyReadyForStart(); + + assert.equal(allowed, true); + assert.equal(api.selectGpcHelperPhoneMode.value, 'auto'); + assert.equal(api.getPersistedPhoneMode(), 'auto'); + assert.equal(api.getSaveCalls(), 0); + assert.equal(api.getUpdateCalls(), 0); + assert.deepEqual(api.getDialogs(), []); +}); + test('sidepanel resolves pending GoPay manual confirmation from DATA_UPDATED state', async () => { const bundle = [ extractFunction('openPlusManualConfirmationDialog'),