Split PayPal hosted checkout flow
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const vm = require('node:vm');
|
||||
|
||||
const source = fs.readFileSync('content/paypal-flow.js', 'utf8');
|
||||
|
||||
@@ -308,3 +309,332 @@ test('PayPal email submit refills a prefilled email before clicking next', async
|
||||
awaiting: 'password_page',
|
||||
});
|
||||
});
|
||||
|
||||
function createHostedPayPalHarness(options = {}) {
|
||||
const events = [];
|
||||
const attrs = new Map();
|
||||
const elementsById = new Map();
|
||||
let elements = [];
|
||||
let listener = null;
|
||||
const body = { innerText: '', textContent: '' };
|
||||
const location = {
|
||||
href: 'https://www.paypal.com/checkoutweb/signup',
|
||||
host: 'www.paypal.com',
|
||||
pathname: '/checkoutweb/signup',
|
||||
};
|
||||
|
||||
function createDomElement({
|
||||
tagName = 'DIV',
|
||||
id = '',
|
||||
type = '',
|
||||
name = '',
|
||||
text = '',
|
||||
value = '',
|
||||
attrs: initialAttrs = {},
|
||||
options: selectOptions = [],
|
||||
} = {}) {
|
||||
const attrMap = new Map(Object.entries(initialAttrs));
|
||||
const element = {
|
||||
nodeType: 1,
|
||||
tagName,
|
||||
id,
|
||||
type,
|
||||
name,
|
||||
textContent: text,
|
||||
innerText: text,
|
||||
value,
|
||||
checked: false,
|
||||
disabled: false,
|
||||
hidden: false,
|
||||
options: selectOptions,
|
||||
parentElement: null,
|
||||
style: { display: 'block', visibility: 'visible', opacity: '1' },
|
||||
getAttribute(key) {
|
||||
if (key === 'id') return this.id;
|
||||
if (key === 'type') return this.type;
|
||||
if (key === 'name') return this.name;
|
||||
if (key === 'placeholder') return attrMap.get('placeholder') || '';
|
||||
return attrMap.has(key) ? attrMap.get(key) : null;
|
||||
},
|
||||
setAttribute(key, nextValue) {
|
||||
attrMap.set(key, String(nextValue));
|
||||
},
|
||||
dispatchEvent() {
|
||||
return true;
|
||||
},
|
||||
focus() {},
|
||||
blur() {},
|
||||
click() {
|
||||
events.push({ type: 'native-click', id: this.id, text: this.textContent });
|
||||
},
|
||||
getBoundingClientRect() {
|
||||
return { left: 10, top: 10, width: 180, height: 44 };
|
||||
},
|
||||
};
|
||||
if (id) elementsById.set(id, element);
|
||||
return element;
|
||||
}
|
||||
|
||||
const countrySelect = createDomElement({ tagName: 'SELECT', id: 'country', value: 'US' });
|
||||
const emailInput = createDomElement({ tagName: 'INPUT', id: 'email', type: 'email', name: 'email' });
|
||||
const phoneInput = createDomElement({ tagName: 'INPUT', id: 'phone', type: 'tel', name: 'phone' });
|
||||
const cardNumberInput = createDomElement({ tagName: 'INPUT', id: 'cardNumber', type: 'text' });
|
||||
const cardExpiryInput = createDomElement({ tagName: 'INPUT', id: 'cardExpiry', type: 'text' });
|
||||
const cardCvvInput = createDomElement({ tagName: 'INPUT', id: 'cardCvv', type: 'text' });
|
||||
const passwordInput = createDomElement({ tagName: 'INPUT', id: 'password', type: 'password' });
|
||||
const firstNameInput = createDomElement({ tagName: 'INPUT', id: 'firstName', type: 'text' });
|
||||
const lastNameInput = createDomElement({ tagName: 'INPUT', id: 'lastName', type: 'text' });
|
||||
const billingLine1Input = createDomElement({ tagName: 'INPUT', id: 'billingLine1', type: 'text' });
|
||||
const billingCityInput = createDomElement({ tagName: 'INPUT', id: 'billingCity', type: 'text' });
|
||||
const billingPostalCodeInput = createDomElement({ tagName: 'INPUT', id: 'billingPostalCode', type: 'text' });
|
||||
const billingStateSelect = createDomElement({
|
||||
tagName: 'SELECT',
|
||||
id: 'billingState',
|
||||
value: '',
|
||||
options: [
|
||||
{ textContent: 'New York', label: 'New York', value: 'NY' },
|
||||
{ textContent: 'California', label: 'California', value: 'CA' },
|
||||
],
|
||||
});
|
||||
const submitButton = createDomElement({
|
||||
tagName: 'BUTTON',
|
||||
id: 'hostedSubmit',
|
||||
text: 'Agree & Create Account',
|
||||
attrs: { 'data-testid': 'submit-button' },
|
||||
});
|
||||
const createAccountButton = createDomElement({
|
||||
tagName: 'BUTTON',
|
||||
id: 'createAccountButton',
|
||||
text: 'Agree & Create Account',
|
||||
attrs: { 'data-testid': 'createAccountButton' },
|
||||
});
|
||||
|
||||
function setElements(nextElements) {
|
||||
elements = nextElements;
|
||||
elementsById.clear();
|
||||
for (const element of nextElements) {
|
||||
if (element.id) elementsById.set(element.id, element);
|
||||
}
|
||||
}
|
||||
|
||||
function showGuestCheckout() {
|
||||
location.href = 'https://www.paypal.com/checkoutweb/signup';
|
||||
location.host = 'www.paypal.com';
|
||||
location.pathname = '/checkoutweb/signup';
|
||||
body.innerText = 'Pay with debit or credit card';
|
||||
body.textContent = body.innerText;
|
||||
setElements([
|
||||
countrySelect,
|
||||
emailInput,
|
||||
phoneInput,
|
||||
cardNumberInput,
|
||||
cardExpiryInput,
|
||||
cardCvvInput,
|
||||
passwordInput,
|
||||
firstNameInput,
|
||||
lastNameInput,
|
||||
billingLine1Input,
|
||||
billingCityInput,
|
||||
billingPostalCodeInput,
|
||||
billingStateSelect,
|
||||
submitButton,
|
||||
]);
|
||||
}
|
||||
|
||||
function showCreateAccount() {
|
||||
location.href = 'https://www.paypal.com/checkoutweb/create-account';
|
||||
location.host = 'www.paypal.com';
|
||||
location.pathname = '/checkoutweb/create-account';
|
||||
body.innerText = 'Create your PayPal account. Agree & Create Account';
|
||||
body.textContent = body.innerText;
|
||||
setElements([createAccountButton]);
|
||||
}
|
||||
|
||||
const context = {
|
||||
console: { log() {}, warn() {}, error() {}, info() {} },
|
||||
location,
|
||||
window: {},
|
||||
Event: class TestEvent { constructor(type) { this.type = type; } },
|
||||
MouseEvent: class TestMouseEvent { constructor(type) { this.type = type; } },
|
||||
PointerEvent: class TestPointerEvent { constructor(type) { this.type = type; } },
|
||||
document: {
|
||||
readyState: 'complete',
|
||||
body,
|
||||
documentElement: {
|
||||
getAttribute(name) {
|
||||
return attrs.get(name) || null;
|
||||
},
|
||||
setAttribute(name, nextValue) {
|
||||
attrs.set(name, String(nextValue));
|
||||
},
|
||||
},
|
||||
getElementById(id) {
|
||||
return elementsById.get(id) || null;
|
||||
},
|
||||
querySelector(selector) {
|
||||
const text = String(selector || '');
|
||||
if (text.includes('createAccountButton') || text.includes('create-account-button')) {
|
||||
return elements.includes(createAccountButton) ? createAccountButton : null;
|
||||
}
|
||||
if (text.includes('submit-button') || text.includes('hosted-payment-submit-button')) {
|
||||
return elements.includes(submitButton) ? submitButton : null;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
querySelectorAll(selector) {
|
||||
const text = String(selector || '');
|
||||
if (text === 'input') return elements.filter((element) => element.tagName === 'INPUT');
|
||||
if (text === 'input[type="email"]') return elements.filter((element) => element.type === 'email');
|
||||
if (text === 'input[type="password"]') return elements.filter((element) => element.type === 'password');
|
||||
if (text.includes('button') || text.includes('[role="button"]')) {
|
||||
return elements.filter((element) => element.tagName === 'BUTTON');
|
||||
}
|
||||
return [];
|
||||
},
|
||||
},
|
||||
chrome: {
|
||||
runtime: {
|
||||
onMessage: {
|
||||
addListener(fn) {
|
||||
listener = fn;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
CodexOperationDelay: {
|
||||
async performOperationWithDelay(metadata, operation) {
|
||||
events.push({ type: 'operation', metadata });
|
||||
const result = await operation();
|
||||
events.push({ type: 'delay', metadata });
|
||||
return result;
|
||||
},
|
||||
},
|
||||
resetStopState() {},
|
||||
isStopError() { return false; },
|
||||
throwIfStopped() {},
|
||||
sleep() { return Promise.resolve(); },
|
||||
fillInput(element, value) {
|
||||
if (element === phoneInput && typeof options.renderPhone === 'function') {
|
||||
element.value = options.renderPhone(value);
|
||||
} else {
|
||||
element.value = value;
|
||||
}
|
||||
events.push({ type: 'fill', id: element.id, value: element.value });
|
||||
},
|
||||
simulateClick(element) {
|
||||
events.push({ type: 'click', id: element.id, text: element.textContent });
|
||||
},
|
||||
};
|
||||
context.window = context;
|
||||
context.window.getComputedStyle = (element) => element?.style || { display: 'block', visibility: 'visible', opacity: '1' };
|
||||
|
||||
vm.createContext(context);
|
||||
vm.runInContext(source, context);
|
||||
assert.equal(typeof listener, 'function');
|
||||
|
||||
async function send(message) {
|
||||
return await new Promise((resolve) => {
|
||||
listener(message, {}, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
events,
|
||||
send,
|
||||
showCreateAccount,
|
||||
showGuestCheckout,
|
||||
};
|
||||
}
|
||||
|
||||
test('PayPal hosted guest checkout verifies configured local phone before submit', async () => {
|
||||
const harness = createHostedPayPalHarness({
|
||||
renderPhone: (value) => `+1 ${value}`,
|
||||
});
|
||||
harness.showGuestCheckout();
|
||||
|
||||
const result = await harness.send({
|
||||
type: 'PAYPAL_RUN_HOSTED_CHECKOUT_STEP',
|
||||
source: 'test',
|
||||
payload: {
|
||||
expectedStage: 'guest_checkout',
|
||||
email: 'guest@example.com',
|
||||
phone: '4155551234',
|
||||
cardNumber: '4147200000000000',
|
||||
cardExpiry: '12 / 29',
|
||||
cardCvv: '123',
|
||||
password: 'Aa1!example',
|
||||
firstName: 'James',
|
||||
lastName: 'Smith',
|
||||
address: {
|
||||
street: '1 Main St',
|
||||
city: 'New York',
|
||||
state: 'New York',
|
||||
zip: '10001',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.submitted, true);
|
||||
assert.equal(result.phoneMatched, true);
|
||||
assert.equal(result.payloadPhoneDigits, '4155551234');
|
||||
assert.equal(result.renderedPhoneDigits, '14155551234');
|
||||
assert.equal(harness.events.some((event) => event.type === 'click' && event.id === 'hostedSubmit'), true);
|
||||
assert.deepEqual(
|
||||
JSON.parse(JSON.stringify(harness.events.filter((event) => event.type === 'operation').map((event) => event.metadata))),
|
||||
[{ stepKey: 'paypal-hosted-card', kind: 'click', label: 'hosted-paypal-card-submit' }]
|
||||
);
|
||||
});
|
||||
|
||||
test('PayPal hosted guest checkout blocks submit when rendered phone differs from config', async () => {
|
||||
const harness = createHostedPayPalHarness({
|
||||
renderPhone: () => '9999999999',
|
||||
});
|
||||
harness.showGuestCheckout();
|
||||
|
||||
const result = await harness.send({
|
||||
type: 'PAYPAL_RUN_HOSTED_CHECKOUT_STEP',
|
||||
source: 'test',
|
||||
payload: {
|
||||
expectedStage: 'guest_checkout',
|
||||
phone: '4155551234',
|
||||
cardNumber: '4147200000000000',
|
||||
cardExpiry: '12 / 29',
|
||||
cardCvv: '123',
|
||||
password: 'Aa1!example',
|
||||
address: { street: '1 Main St', city: 'New York', state: 'New York', zip: '10001' },
|
||||
},
|
||||
});
|
||||
|
||||
assert.match(result.error, /电话不一致/);
|
||||
assert.equal(harness.events.some((event) => event.type === 'click' && event.id === 'hostedSubmit'), false);
|
||||
});
|
||||
|
||||
test('PayPal hosted create account page is detected and handled as its own step', async () => {
|
||||
const harness = createHostedPayPalHarness();
|
||||
harness.showCreateAccount();
|
||||
|
||||
const state = await harness.send({
|
||||
type: 'PAYPAL_HOSTED_GET_STATE',
|
||||
source: 'test',
|
||||
payload: {},
|
||||
});
|
||||
assert.equal(state.ok, true);
|
||||
assert.equal(state.hostedStage, 'create_account');
|
||||
assert.equal(state.createAccountReady, true);
|
||||
|
||||
const result = await harness.send({
|
||||
type: 'PAYPAL_RUN_HOSTED_CHECKOUT_STEP',
|
||||
source: 'test',
|
||||
payload: { expectedStage: 'create_account' },
|
||||
});
|
||||
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.stage, 'create_account');
|
||||
assert.equal(result.submitted, true);
|
||||
assert.equal(harness.events.some((event) => event.type === 'click' && event.id === 'createAccountButton'), true);
|
||||
assert.deepEqual(
|
||||
JSON.parse(JSON.stringify(harness.events.filter((event) => event.type === 'operation').map((event) => event.metadata))),
|
||||
[{ stepKey: 'paypal-hosted-create-account', kind: 'click', label: 'hosted-paypal-create-account' }]
|
||||
);
|
||||
});
|
||||
|
||||
@@ -288,7 +288,7 @@ test('GoPay plus checkout create forwards gopay payment method to the checkout c
|
||||
assert.deepStrictEqual(events[0]?.payload, { paymentMethod: 'gopay' });
|
||||
});
|
||||
|
||||
test('PayPal no-card binding create waits for hosted success and does not use the old PayPal tail', async () => {
|
||||
test('PayPal no-card binding create only opens hosted checkout and leaves page steps to later nodes', async () => {
|
||||
const events = [];
|
||||
let currentUrl = 'https://chatgpt.com/';
|
||||
const executor = api.createPlusCheckoutCreateExecutor({
|
||||
@@ -315,21 +315,8 @@ test('PayPal no-card binding create waits for hosted success and does not use th
|
||||
ensureContentScriptReadyOnTabUntilStopped: async (source, tabId, options) => {
|
||||
events.push({ type: 'ready', source, tabId, options });
|
||||
},
|
||||
fetch: async (url) => {
|
||||
events.push({ type: 'fetch', url });
|
||||
assert.equal(url, 'https://www.meiguodizhi.com/api/v1/dz');
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
json: async () => ({
|
||||
address: {
|
||||
Address: '1 Main St',
|
||||
City: 'New York',
|
||||
State: 'New York',
|
||||
Zip_Code: '10001',
|
||||
},
|
||||
}),
|
||||
};
|
||||
fetch: async () => {
|
||||
throw new Error('create node should not fetch address or run PayPal page automation');
|
||||
},
|
||||
registerTab: async (source, tabId) => {
|
||||
events.push({ type: 'register', source, tabId });
|
||||
@@ -345,13 +332,6 @@ test('PayPal no-card binding create waits for hosted success and does not use th
|
||||
currency: 'USD',
|
||||
};
|
||||
}
|
||||
if (message.type === 'RUN_PAYPAL_HOSTED_OPENAI_CHECKOUT_STEP') {
|
||||
currentUrl = 'https://chatgpt.com/backend-api/payments/success?session_id=cs_hosted';
|
||||
return { clicked: true };
|
||||
}
|
||||
if (message.type === 'PLUS_CHECKOUT_GET_STATE') {
|
||||
return { hostedVerificationVisible: false };
|
||||
}
|
||||
throw new Error(`unexpected message type ${message.type}`);
|
||||
},
|
||||
setState: async (payload) => {
|
||||
@@ -384,13 +364,105 @@ test('PayPal no-card binding create waits for hosted success and does not use th
|
||||
assert.equal(statePayload.plusCheckoutCurrency, 'USD');
|
||||
assert.equal(statePayload.plusReturnUrl, '');
|
||||
assert.equal(events.some((event) => event.type === 'tab-message' && event.message.type === 'FILL_PLUS_BILLING_AND_SUBMIT'), false);
|
||||
assert.equal(events.some((event) => event.type === 'tab-message' && event.message.type === 'RUN_PAYPAL_HOSTED_OPENAI_CHECKOUT_STEP'), false);
|
||||
assert.deepStrictEqual(events.find((event) => event.type === 'complete'), {
|
||||
type: 'complete',
|
||||
step: 'plus-checkout-create',
|
||||
payload: {
|
||||
plusCheckoutCountry: 'US',
|
||||
plusCheckoutCurrency: 'USD',
|
||||
plusCheckoutSource: 'paypal-hosted',
|
||||
plusCheckoutUrl: 'https://pay.openai.com/c/pay/cs_hosted',
|
||||
plusReturnUrl: '',
|
||||
plusHostedCheckoutCompleted: false,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('PayPal no-card binding OpenAI checkout node submits hosted page and completes after success transition', async () => {
|
||||
const events = [];
|
||||
let currentUrl = 'https://pay.openai.com/c/pay/cs_hosted';
|
||||
const executor = api.createPlusCheckoutCreateExecutor({
|
||||
addLog: async (message, level = 'info') => {
|
||||
events.push({ type: 'log', message, level });
|
||||
},
|
||||
chrome: {
|
||||
tabs: {
|
||||
get: async (tabId) => ({ id: tabId, url: currentUrl, status: 'complete' }),
|
||||
},
|
||||
},
|
||||
completeNodeFromBackground: async (step, payload) => {
|
||||
events.push({ type: 'complete', step, payload });
|
||||
},
|
||||
ensureContentScriptReadyOnTabUntilStopped: async (source, tabId, options) => {
|
||||
events.push({ type: 'ready', source, tabId, options });
|
||||
},
|
||||
fetch: async (url) => {
|
||||
events.push({ type: 'fetch', url });
|
||||
assert.equal(url, 'https://www.meiguodizhi.com/api/v1/dz');
|
||||
return {
|
||||
ok: true,
|
||||
status: 200,
|
||||
json: async () => ({
|
||||
address: {
|
||||
Address: '1 Main St',
|
||||
City: 'New York',
|
||||
State: 'New York',
|
||||
Zip_Code: '10001',
|
||||
},
|
||||
}),
|
||||
};
|
||||
},
|
||||
getState: async () => ({
|
||||
hostedCheckoutPhoneNumber: '(415) 555-1234',
|
||||
}),
|
||||
registerTab: async (source, tabId) => {
|
||||
events.push({ type: 'register', source, tabId });
|
||||
},
|
||||
sendTabMessageUntilStopped: async (tabId, source, message) => {
|
||||
events.push({ type: 'tab-message', tabId, source, message });
|
||||
if (message.type === 'RUN_PAYPAL_HOSTED_OPENAI_CHECKOUT_STEP') {
|
||||
currentUrl = 'https://chatgpt.com/backend-api/payments/success?session_id=cs_hosted';
|
||||
return { clicked: true };
|
||||
}
|
||||
if (message.type === 'PLUS_CHECKOUT_GET_STATE') {
|
||||
return { hostedVerificationVisible: false };
|
||||
}
|
||||
throw new Error(`unexpected message type ${message.type}`);
|
||||
},
|
||||
setState: async (payload) => {
|
||||
events.push({ type: 'set-state', payload });
|
||||
},
|
||||
sleepWithStop: async (ms) => {
|
||||
events.push({ type: 'sleep', ms });
|
||||
},
|
||||
waitForTabCompleteUntilStopped: async () => {
|
||||
events.push({ type: 'tab-complete' });
|
||||
},
|
||||
});
|
||||
|
||||
await executor.executePayPalHostedOpenAiCheckout({
|
||||
plusCheckoutTabId: 55,
|
||||
plusPaymentMethod: 'paypal-hosted',
|
||||
hostedCheckoutPhoneNumber: '2125550000',
|
||||
plusHostedCheckoutOauthDelaySeconds: 0,
|
||||
});
|
||||
|
||||
const profileState = events.find((event) => event.type === 'set-state' && event.payload.plusHostedCheckoutGuestProfile)?.payload || {};
|
||||
assert.equal(profileState.plusHostedCheckoutGuestProfile.phone, '4155551234');
|
||||
assert.equal(profileState.plusHostedCheckoutPhoneDigits, '4155551234');
|
||||
assert.equal(
|
||||
events.find((event) => event.type === 'tab-message' && event.message.type === 'RUN_PAYPAL_HOSTED_OPENAI_CHECKOUT_STEP')?.message?.payload?.address?.street,
|
||||
'1 Main St'
|
||||
);
|
||||
assert.deepStrictEqual(events.find((event) => event.type === 'complete'), {
|
||||
type: 'complete',
|
||||
step: 'paypal-hosted-openai-checkout',
|
||||
payload: {
|
||||
plusCheckoutUrl: 'https://chatgpt.com/backend-api/payments/success?session_id=cs_hosted',
|
||||
plusCheckoutSource: 'paypal-hosted',
|
||||
plusReturnUrl: 'https://chatgpt.com/backend-api/payments/success?session_id=cs_hosted',
|
||||
plusHostedCheckoutCompleted: true,
|
||||
plusHostedCheckoutOauthDelaySeconds: 0,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -221,6 +221,12 @@ test('step definitions module exposes ordered normal and Plus step metadata', ()
|
||||
'fetch-signup-code',
|
||||
'fill-profile',
|
||||
'plus-checkout-create',
|
||||
'paypal-hosted-openai-checkout',
|
||||
'paypal-hosted-email',
|
||||
'paypal-hosted-verification',
|
||||
'paypal-hosted-card',
|
||||
'paypal-hosted-create-account',
|
||||
'paypal-hosted-review',
|
||||
'oauth-login',
|
||||
'fetch-login-code',
|
||||
'confirm-oauth',
|
||||
@@ -230,8 +236,10 @@ test('step definitions module exposes ordered normal and Plus step metadata', ()
|
||||
assert.equal(hostedSteps.some((step) => step.key === 'plus-checkout-billing'), false);
|
||||
assert.equal(hostedSteps.some((step) => step.key === 'paypal-approve'), false);
|
||||
assert.equal(hostedSteps.some((step) => step.key === 'plus-checkout-return'), false);
|
||||
assert.deepStrictEqual(api.getStepIds({ plusModeEnabled: true, plusPaymentMethod: 'paypal-hosted' }), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
assert.equal(api.getLastStepId({ plusModeEnabled: true, plusPaymentMethod: 'paypal-hosted' }), 10);
|
||||
assert.equal(hostedSteps.find((step) => step.key === 'paypal-hosted-openai-checkout')?.title, '无卡直绑提交 OpenAI Checkout');
|
||||
assert.equal(hostedSteps.find((step) => step.key === 'paypal-hosted-card')?.title, '无卡直绑填写 PayPal 资料');
|
||||
assert.deepStrictEqual(api.getStepIds({ plusModeEnabled: true, plusPaymentMethod: 'paypal-hosted' }), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
|
||||
assert.equal(api.getLastStepId({ plusModeEnabled: true, plusPaymentMethod: 'paypal-hosted' }), 16);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
goPaySteps.map((step) => step.key),
|
||||
@@ -308,8 +316,8 @@ test('Plus session strategy swaps the OAuth tail for a single SUB2API import nod
|
||||
plusPaymentMethod: 'paypal-hosted',
|
||||
plusAccountAccessStrategy: 'sub2api_codex_session',
|
||||
},
|
||||
previousNodeId: 'plus-checkout-create',
|
||||
expectedStepIds: [1, 2, 3, 4, 5, 6, 7],
|
||||
previousNodeId: 'paypal-hosted-review',
|
||||
expectedStepIds: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
|
||||
},
|
||||
{
|
||||
label: 'gopay',
|
||||
@@ -399,8 +407,8 @@ test('Plus session strategy swaps the OAuth tail for a single CPA import node',
|
||||
plusPaymentMethod: 'paypal-hosted',
|
||||
plusAccountAccessStrategy: 'cpa_codex_session',
|
||||
},
|
||||
previousNodeId: 'plus-checkout-create',
|
||||
expectedStepIds: [1, 2, 3, 4, 5, 6, 7],
|
||||
previousNodeId: 'paypal-hosted-review',
|
||||
expectedStepIds: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
|
||||
},
|
||||
{
|
||||
label: 'gopay',
|
||||
|
||||
Reference in New Issue
Block a user