feat(order): name the fields an order still lacks for a checkout
missingCheckoutFields returns which of email, invoiceAddress and delivery an order lacks, so the checkout can answer 400 before it creates a PayPal order. Refs libretech/mp#71
This commit is contained in:
2 files changed
+49
-2
No files matched your search
@@ -8,3 +8,20 @@ export type OrderLockState = {
|
|||||||
* so the customer can no longer change its contact details, addresses, delivery method or cart.
|
* so the customer can no longer change its contact details, addresses, delivery method or cart.
|
||||||
*/
|
*/
|
||||||
export const isLockedForCustomer = (order: OrderLockState): boolean => Boolean(order.paymentAuthorised);
|
export const isLockedForCustomer = (order: OrderLockState): boolean => Boolean(order.paymentAuthorised);
|
||||||
|
|
||||||
|
/** The fields of an order a checkout needs: the contact and address steps of the shop's checkout, and a delivery method. */
|
||||||
|
export type CheckoutFields = {
|
||||||
|
email?: string | null;
|
||||||
|
invoiceAddress?: string | null;
|
||||||
|
/** The populated delivery method, or null. */
|
||||||
|
delivery?: unknown;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The names of the fields the order still lacks for a checkout, in this order: email, invoiceAddress, delivery. [] if none. */
|
||||||
|
export const missingCheckoutFields = (order: CheckoutFields): string[] => {
|
||||||
|
const missing: string[] = [];
|
||||||
|
if (typeof order.email !== "string" || order.email.trim() === "") missing.push("email");
|
||||||
|
if (typeof order.invoiceAddress !== "string" || order.invoiceAddress.trim() === "") missing.push("invoiceAddress");
|
||||||
|
if (order.delivery === null || order.delivery === undefined) missing.push("delivery");
|
||||||
|
return missing;
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { test } from "node:test";
|
import { test } from "node:test";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import { isLockedForCustomer } from "../../src/checkout/order-state.ts";
|
import { isLockedForCustomer, missingCheckoutFields } from "../../src/checkout/order-state.ts";
|
||||||
|
|
||||||
// Shaped like the row PUT /orders/:uuid/cart reads with strapi.db.query("api::order.order").findOne before it updates.
|
// Shaped like the row PUT /orders/:uuid/cart reads with strapi.db.query("api::order.order").findOne before it updates.
|
||||||
const order = (overrides = {}) => ({
|
const order = (overrides = {}) => ({
|
||||||
@@ -21,6 +21,36 @@ test("an order is open for the customer until its payment is authorised", () =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("an order is locked once its payment is authorised", () => {
|
test("an order is locked once its payment is authorised", () => {
|
||||||
// what capturePayment writes once PayPal reports the capture COMPLETED
|
// what capturePayment writes once the capture is verified (src/checkout/capture-payment.ts)
|
||||||
|
assert.equal(isLockedForCustomer(order({ paymentAuthorised: true, paymentStatus: "captured" })), true);
|
||||||
|
// what it wrote before
|
||||||
assert.equal(isLockedForCustomer(order({ paymentAuthorised: true, paymentStatus: "authorised" })), true);
|
assert.equal(isLockedForCustomer(order({ paymentAuthorised: true, paymentStatus: "authorised" })), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Shaped like the row POST /orders/:uuid/checkout reads (strapi.db.query findOne with orderDefaultParams), after both checkout steps.
|
||||||
|
const readyForCheckout = (overrides = {}) =>
|
||||||
|
order({
|
||||||
|
invoiceAddress: "Erika Mustermann\nMusterstraße 1\n70190 Stuttgart",
|
||||||
|
deliveryAddress: "Erika Mustermann\nMusterstraße 1\n70190 Stuttgart",
|
||||||
|
delivery: { id: 1, name: "DHL", price: 4.95 },
|
||||||
|
...overrides
|
||||||
|
});
|
||||||
|
|
||||||
|
test("an order that went through both checkout steps lacks nothing for the checkout", () => {
|
||||||
|
assert.deepEqual(missingCheckoutFields(readyForCheckout()), []);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("names the email, invoice address and delivery method an order still lacks for the checkout", () => {
|
||||||
|
// a new order: POST /orders creates it empty
|
||||||
|
assert.deepEqual(missingCheckoutFields({ email: null, invoiceAddress: null, delivery: null }), ["email", "invoiceAddress", "delivery"]);
|
||||||
|
assert.deepEqual(missingCheckoutFields({}), ["email", "invoiceAddress", "delivery"]);
|
||||||
|
// after step 1 alone
|
||||||
|
assert.deepEqual(missingCheckoutFields(readyForCheckout({ invoiceAddress: null, deliveryAddress: null, delivery: null })), [
|
||||||
|
"invoiceAddress",
|
||||||
|
"delivery"
|
||||||
|
]);
|
||||||
|
assert.deepEqual(missingCheckoutFields(readyForCheckout({ email: " " })), ["email"]);
|
||||||
|
assert.deepEqual(missingCheckoutFields(readyForCheckout({ invoiceAddress: "" })), ["invoiceAddress"]);
|
||||||
|
// a delivery method that was deleted is populated as null
|
||||||
|
assert.deepEqual(missingCheckoutFields(readyForCheckout({ delivery: null })), ["delivery"]);
|
||||||
|
});
|
||||||
Reference in new issue
Block a user