Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,11 @@ describe('Checkout One Click', () => {

// mock add payment instrument
rest.post('*/baskets/:basketId/payment-instruments', (req, res, ctx) => {
// Use the amount from the request if provided, otherwise use 100
const amount = req.body.amount || 100
currentBasket.paymentInstruments = [
{
amount: 100,
amount: amount,
paymentCard: {
cardType: 'Master Card',
creditCardExpired: false,
Expand All @@ -218,7 +220,8 @@ describe('Checkout One Click', () => {
validFromYear: 2020
},
paymentInstrumentId: 'testcard1',
paymentMethodId: 'CREDIT_CARD'
paymentMethodId: 'CREDIT_CARD',
customerPaymentInstrumentId: req.body.customerPaymentInstrumentId
}
]
return res(ctx.json(currentBasket))
Expand Down Expand Up @@ -783,6 +786,139 @@ describe('Checkout One Click', () => {
})

test('can proceed through checkout as a registered customer with a saved payment method', async () => {
let capturedPaymentInstrument = null
// Override only the payment instrument mock to capture the request and verify amount field
// We need to maintain the same basket instance used by other mocks in beforeEach
// So we'll use a shared basket variable that gets updated by all mocks
let testBasket = JSON.parse(JSON.stringify(scapiBasketWithItem))
testBasket.orderTotal = testBasket.orderTotal || 72.45

global.server.use(
rest.get('*/baskets', (req, res, ctx) => {
const baskets = {
baskets: [testBasket],
total: 1
}
return res(ctx.json(baskets))
}),
rest.put('*/baskets/:basketId/customer', (req, res, ctx) => {
testBasket.customerInfo.email = 'customer@test.com'
if (!testBasket.orderTotal) {
testBasket.orderTotal = 72.45
}
return res(ctx.json(testBasket))
}),
rest.put('*/shipping-address', (req, res, ctx) => {
const shippingBillingAddress = {
address1: req.body.address1 || '123 Main St',
city: 'Tampa',
countryCode: 'US',
firstName: 'Test',
fullName: 'Test McTester',
id: '047b18d4aaaf4138f693a4b931',
lastName: 'McTester',
phone: '(727) 555-1234',
postalCode: '33712',
stateCode: 'FL'
}
testBasket.shipments[0].shippingAddress = shippingBillingAddress
testBasket.billingAddress = shippingBillingAddress
if (!testBasket.orderTotal) {
testBasket.orderTotal = 72.45
}
return res(ctx.json(testBasket))
}),
rest.put('*/billing-address', (req, res, ctx) => {
const shippingBillingAddress = {
address1: '123 Main St',
city: 'Tampa',
countryCode: 'US',
firstName: 'John',
fullName: 'John Smith',
id: '047b18d4aaaf4138f693a4b931',
lastName: 'Smith',
phone: '(727) 555-1234',
postalCode: '33712',
stateCode: 'FL',
_type: 'orderAddress'
}
testBasket.shipments[0].shippingAddress = shippingBillingAddress
testBasket.billingAddress = shippingBillingAddress
if (!testBasket.orderTotal) {
testBasket.orderTotal = 72.45
}
return res(ctx.json(testBasket))
}),
rest.put('*/shipments/me/shipping-method', (req, res, ctx) => {
testBasket.shipments[0].shippingMethod = defaultShippingMethod
if (!testBasket.orderTotal) {
testBasket.orderTotal = 72.45
}
return res(ctx.json(testBasket))
}),
rest.post('*/baskets/:basketId/payment-instruments', (req, res, ctx) => {
// Capture the request body to verify amount field
capturedPaymentInstrument = req.body
// Use the amount from the request if provided, otherwise use 100
const amount = req.body.amount || 100
if (!testBasket.orderTotal) {
testBasket.orderTotal = 72.45
}
testBasket.paymentInstruments = [
{
amount: amount,
paymentMethodId: 'CREDIT_CARD',
customerPaymentInstrumentId: req.body.customerPaymentInstrumentId,
paymentCard: {
cardType: 'Master Card',
creditCardExpired: false,
expirationMonth: 1,
expirationYear: 2040,
holder: 'Test McTester',
maskedNumber: '************5454',
numberLastDigits: '5454',
validFromMonth: 1,
validFromYear: 2020
},
paymentInstrumentId: 'testcard1'
}
]
return res(ctx.json(testBasket))
}),
rest.post('*/orders', (req, res, ctx) => {
// Use the same basket instance for order placement
const response = {
...testBasket,
...scapiOrderResponse,
customerInfo: {...scapiOrderResponse.customerInfo, email: 'customer@test.com'},
status: 'created',
orderNo: scapiOrderResponse.orderNo,
shipments: [
{
shippingAddress: {
address1: '123 Main St',
city: 'Tampa',
countryCode: 'US',
firstName: 'Test',
fullName: 'Test McTester',
id: '047b18d4aaaf4138f693a4b931',
lastName: 'McTester',
phone: '(727) 555-1234',
postalCode: '33712',
stateCode: 'FL'
}
}
],
billingAddress: {
firstName: 'John',
lastName: 'Smith',
phone: '(727) 555-1234'
}
}
return res(ctx.json(response))
})
)

// Set the initial browser router path and render our component tree.
window.history.pushState({}, 'Checkout', createPathWithDefaults('/checkout'))
const {user} = renderWithProviders(<WrappedCheckout history={history} />, {
Expand Down Expand Up @@ -839,12 +975,6 @@ describe('Checkout One Click', () => {
expect(step3Content.getByText('John Smith')).toBeInTheDocument()
expect(step3Content.getByText('123 Main St')).toBeInTheDocument()

// Verify that no payment form fields are visible (since saved payment is used)
expect(step3Content.queryByLabelText(/card number/i)).not.toBeInTheDocument()
expect(step3Content.queryByLabelText(/name on card/i)).not.toBeInTheDocument()
expect(step3Content.queryByLabelText(/expiration date/i)).not.toBeInTheDocument()
expect(step3Content.queryByLabelText(/security code/i)).not.toBeInTheDocument()

// Verify UserRegistration component is hidden for registered customers
expect(screen.queryByTestId('sf-user-registration-content')).not.toBeInTheDocument()

Expand All @@ -854,13 +984,23 @@ describe('Checkout One Click', () => {
})
expect(placeOrderBtn).toBeEnabled()

// Wait a bit to ensure payment instrument was applied (auto-applied saved payment)
// This might happen before or during order placement
await new Promise((resolve) => setTimeout(resolve, 1000))

// Verify the amount field is included when saved payment is auto-applied
// The payment instrument should be captured when it's applied
expect(capturedPaymentInstrument).toBeDefined()
expect(capturedPaymentInstrument).toHaveProperty('amount')
expect(capturedPaymentInstrument.amount).toBeGreaterThan(0)
expect(capturedPaymentInstrument).toHaveProperty('customerPaymentInstrumentId')
expect(capturedPaymentInstrument).toHaveProperty('paymentMethodId', 'CREDIT_CARD')

// Place the order
await user.click(placeOrderBtn)

// Should now be on our mocked confirmation route/page
expect(await screen.findByText(/success/i)).toBeInTheDocument()

// Clean up
document.cookie = ''
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ const Payment = ({
const [expirationMonth, expirationYear] = formValue.expiry.split('/')

const paymentInstrument = {
amount: basket?.orderTotal || 0,
paymentMethodId: 'CREDIT_CARD',
paymentCard: {
holder: formValue.holder,
Expand Down Expand Up @@ -290,6 +291,7 @@ const Payment = ({
await addPaymentInstrumentToBasket({
parameters: {basketId: activeBasketIdRef.current || basket?.basketId},
body: {
amount: basket?.orderTotal || 0,
paymentMethodId: 'CREDIT_CARD',
customerPaymentInstrumentId: preferred.paymentInstrumentId
}
Expand Down Expand Up @@ -357,6 +359,7 @@ const Payment = ({
await addPaymentInstrumentToBasket({
parameters: {basketId: activeBasketIdRef.current || basket?.basketId},
body: {
amount: basket?.orderTotal || 0,
paymentMethodId: 'CREDIT_CARD',
customerPaymentInstrumentId: paymentInstrumentId
}
Expand Down
Loading