Skip to content

Commit

Permalink
feat(payments-plugin): E2e test fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
martijnvdbrug committed Feb 27, 2024
1 parent 07d9b4d commit 1e65032
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 31 deletions.
27 changes: 26 additions & 1 deletion packages/payments-plugin/e2e/mollie-payment.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ describe('Mollie payments with useDynamicRedirectUrl=false', () => {
},
},
);
expect(result.message).toContain('The following variants are out of stock');
expect(result.message).toContain('insufficient stock of Pinelab stickers');
// Set stock back to not tracking
({ updateProductVariants } = await adminClient.query(UPDATE_PRODUCT_VARIANTS, {
input: {
Expand Down Expand Up @@ -335,6 +335,31 @@ describe('Mollie payments with useDynamicRedirectUrl=false', () => {
});
});

it('Should reuse payment url when amount is the same', async () => {
// Should only fetch the order from Mollie, not create a new one
nock('https://api.mollie.com/')
.get('/v2/orders/ord_mockId')
.reply(200, {
...mockData.mollieOrderResponse,
amount: {
value: '1009.90',
currency: 'USD',
},
_links: {
// Mock a new checkout url, to test that this one is actually reused
checkout: {
href: 'https://this-means-reuse-succeeded',
},
},
});
const { createMolliePaymentIntent } = await shopClient.query(CREATE_MOLLIE_PAYMENT_INTENT, {
input: {
paymentMethodCode: mockData.methodCode,
},
});
expect(createMolliePaymentIntent).toEqual({ url: 'https://this-means-reuse-succeeded' });
});

it('Should get payment url with deducted amount if a payment is already made', async () => {
let mollieRequest: any | undefined;
nock('https://api.mollie.com/')
Expand Down
48 changes: 18 additions & 30 deletions packages/payments-plugin/src/mollie/mollie.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,30 +113,27 @@ export class MollieService {
'payments',
],
});
if (!order.lines?.length) {
return new PaymentIntentError('Cannot create payment intent for empty order');
}
if (!order.customer) {
return new PaymentIntentError('Cannot create payment intent for order without customer');
if (order.state !== 'ArrangingPayment' && order.state !== 'ArrangingAdditionalPayment') {
// Pre-check if order is transitionable to ArrangingPayment, because that will happen after Mollie payment
try {
await this.canTransitionTo(ctx, order.id, 'ArrangingPayment');
} catch (e) {
if ((e as Error).message) {
return new PaymentIntentError((e as Error).message);
}
throw e;
}
}
if (!order.customer.firstName.length) {
if (!order.customer?.firstName.length) {
return new PaymentIntentError(
'Cannot create payment intent for order with customer that has no firstName set',
);
}
if (!order.customer.lastName.length) {
if (!order.customer?.lastName.length) {
return new PaymentIntentError(
'Cannot create payment intent for order with customer that has no lastName set',
);
}
if (!order.customer.emailAddress.length) {
return new PaymentIntentError(
'Cannot create payment intent for order with customer that has no emailAddress set',
);
}
if (!order.shippingLines?.length) {
return new PaymentIntentError('Cannot create payment intent for order without shippingMethod');
}
if (!paymentMethod) {
return new PaymentIntentError(`No paymentMethod found with code ${paymentMethodCode}`);
}
Expand All @@ -156,19 +153,6 @@ export class MollieService {
}
redirectUrl = paymentMethodRedirectUrl;
}
// FIXME: The manual checks above can be removed, now that we do a canTransition check?
if (order.state !== 'ArrangingPayment' && order.state !== 'ArrangingAdditionalPayment') {
// Check if order is transitionable to ArrangingPayment, because that will happen after Mollie payment
await this.canTransitionTo(ctx, order.id, 'ArrangingPayment');
}
const variantsWithInsufficientSaleableStock = await this.getVariantsWithInsufficientStock(ctx, order);
if (variantsWithInsufficientSaleableStock.length) {
return new PaymentIntentError(
`The following variants are out of stock: ${variantsWithInsufficientSaleableStock
.map(v => v.name)
.join(', ')}`,
);
}
const apiKey = paymentMethod.handler.args.find(arg => arg.name === 'apiKey')?.value;
if (!apiKey) {
Logger.warn(
Expand Down Expand Up @@ -487,11 +471,15 @@ export class MollieService {
amountToPay,
existingMollieOrder.amount,
);
if (checkoutUrl && amountsMatch) {
return checkoutUrl;
if (amountsMatch) {
return checkoutUrl ?? undefined;
}
}

/**
* Dry run a transition to a given state.
* As long as we don't call 'finalize', the transition never completes.
*/
private async canTransitionTo(ctx: RequestContext, orderId: ID, state: OrderState) {
// Fetch new order object, because `transition()` mutates the order object
const orderCopy = await assertFound(this.orderService.findOne(ctx, orderId));
Expand Down

0 comments on commit 1e65032

Please sign in to comment.