From 54e5668d1ac450b07887155e452046cda7762215 Mon Sep 17 00:00:00 2001 From: Robert Field Date: Tue, 14 Nov 2023 17:02:19 +0000 Subject: [PATCH] feat: added manual gateway to d2c schematics for mocking out a checkout flow --- packages/d2c-schematics/collection.json | 5 + .../enter-payment-information.ts.template | 10 ++ .../files/e2e/util/gateway-check.ts.template | 13 ++ .../payments/CheckoutForm.tsx.template | 137 ++++++++++++++++++ .../manual-payment-gateway/index.ts | 35 +++++ .../manual-payment-gateway/schema.json | 50 +++++++ packages/d2c-schematics/tsup.config.ts | 5 + 7 files changed, 255 insertions(+) create mode 100644 packages/d2c-schematics/manual-payment-gateway/files/e2e/util/enter-payment-information.ts.template create mode 100644 packages/d2c-schematics/manual-payment-gateway/files/e2e/util/gateway-check.ts.template create mode 100644 packages/d2c-schematics/manual-payment-gateway/files/src/components/checkout/payments/CheckoutForm.tsx.template create mode 100644 packages/d2c-schematics/manual-payment-gateway/index.ts create mode 100644 packages/d2c-schematics/manual-payment-gateway/schema.json diff --git a/packages/d2c-schematics/collection.json b/packages/d2c-schematics/collection.json index f0080a1b..2cde2635 100644 --- a/packages/d2c-schematics/collection.json +++ b/packages/d2c-schematics/collection.json @@ -97,6 +97,11 @@ "factory": "./ep-payments-payment-gateway", "schema": "./ep-payments-payment-gateway/schema.json", "description": "Create components for EP Payments payment gateway." + }, + "manual-payment-gateway": { + "factory": "./manual-payment-gateway", + "schema": "./manual-payment-gateway/schema.json", + "description": "Create components for EP Payments payment gateway." } } } diff --git a/packages/d2c-schematics/manual-payment-gateway/files/e2e/util/enter-payment-information.ts.template b/packages/d2c-schematics/manual-payment-gateway/files/e2e/util/enter-payment-information.ts.template new file mode 100644 index 00000000..738196b7 --- /dev/null +++ b/packages/d2c-schematics/manual-payment-gateway/files/e2e/util/enter-payment-information.ts.template @@ -0,0 +1,10 @@ +import { Page } from "@playwright/test"; +import { fillAllFormFields, FormInput } from "./fill-form-field"; + +export async function enterPaymentInformation(page: Page, values: FormInput) { + const paymentIframe = await page + .locator('[id="payment-element"]') + .frameLocator("iframe"); + + await fillAllFormFields(paymentIframe, values); +} diff --git a/packages/d2c-schematics/manual-payment-gateway/files/e2e/util/gateway-check.ts.template b/packages/d2c-schematics/manual-payment-gateway/files/e2e/util/gateway-check.ts.template new file mode 100644 index 00000000..b1ecf29c --- /dev/null +++ b/packages/d2c-schematics/manual-payment-gateway/files/e2e/util/gateway-check.ts.template @@ -0,0 +1,13 @@ +import type { Moltin as EPCCClient } from "@moltin/sdk"; + +export async function gatewayCheck(client: EPCCClient): Promise { + try { + const gateways = await client.Gateways.All(); + const epPaymentGateway = gateways.data.find( + (gateway) => gateway.slug === "elastic_path_payments_stripe", + )?.enabled; + return !!epPaymentGateway; + } catch (err) { + return false; + } +} diff --git a/packages/d2c-schematics/manual-payment-gateway/files/src/components/checkout/payments/CheckoutForm.tsx.template b/packages/d2c-schematics/manual-payment-gateway/files/src/components/checkout/payments/CheckoutForm.tsx.template new file mode 100644 index 00000000..0878af72 --- /dev/null +++ b/packages/d2c-schematics/manual-payment-gateway/files/src/components/checkout/payments/CheckoutForm.tsx.template @@ -0,0 +1,137 @@ +import { Form, Formik } from "formik"; +import { + CheckoutForm as CheckoutFormType, + checkoutFormSchema, +} from "../form-schema/checkout-form-schema"; +import { PaymentRequestBody } from "@moltin/sdk"; +import ShippingForm from "../ShippingForm"; +import CustomFormControl from "../CustomFormControl"; +import BillingForm from "../BillingForm"; +import { useCart, useStore } from "@elasticpath/react-shopper-hooks"; +import { CheckoutFormComponent } from "../types/checkout-form"; +import { toFormikValidationSchema } from "zod-formik-adapter"; + +const initialValues: Partial = { + personal: { + email: "", + }, + sameAsShipping: true, + shippingAddress: { + first_name: "", + last_name: "", + line_1: "", + country: "", + region: "", + postcode: "", + }, +}; + +const CheckoutForm: CheckoutFormComponent = ({ + showCompletedOrder, +}): JSX.Element => { + const { client } = useStore(); + const { checkout } = useCart(); + + return ( + <> + { + const { + personal, + shippingAddress, + billingAddress, + sameAsShipping, + } = validatedValues; + + const payment: PaymentRequestBody = { + gateway: "manual", + method: "purchase", + }; + + const orderResponse = await checkout( + personal.email, + shippingAddress, + payment, + sameAsShipping, + billingAddress ?? undefined, + ); + + showCompletedOrder(orderResponse, validatedValues); + }} + > + {({ handleChange, values, isSubmitting }) => ( +
+
+
+

+ {" "} + Contact Information +

+ +
+
+

Shipping Address

+ + +
+ {!values.sameAsShipping && } + + +
+
+ )} +
+ + ); +}; + +export default CheckoutForm; diff --git a/packages/d2c-schematics/manual-payment-gateway/index.ts b/packages/d2c-schematics/manual-payment-gateway/index.ts new file mode 100644 index 00000000..feec072d --- /dev/null +++ b/packages/d2c-schematics/manual-payment-gateway/index.ts @@ -0,0 +1,35 @@ +import { + MergeStrategy, + Rule, + Tree, + apply, + applyTemplates, + chain, + mergeWith, + move, + strings, + url, + noop, + filter, +} from "@angular-devkit/schematics" +import { Schema as ManualPaymentGatewayOptions } from "./schema" + +export default function (options: ManualPaymentGatewayOptions): Rule { + return async (_host: Tree) => { + return chain([ + mergeWith( + apply(url("./files"), [ + options.skipTests + ? filter((path) => !path.endsWith(".spec.ts.template")) + : noop(), + applyTemplates({ + utils: strings, + ...options, + }), + move(options.path || ""), + ]), + MergeStrategy.Overwrite, + ), + ]) + } +} diff --git a/packages/d2c-schematics/manual-payment-gateway/schema.json b/packages/d2c-schematics/manual-payment-gateway/schema.json new file mode 100644 index 00000000..390cddf7 --- /dev/null +++ b/packages/d2c-schematics/manual-payment-gateway/schema.json @@ -0,0 +1,50 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "ManualPaymentGatewayCheckout", + "title": "Manual Payment Gateway Options Schema", + "type": "object", + "description": "Generates checkout page and supporting functionality in the workspace.", + "additionalProperties": true, + "properties": { + "skipTests": { + "description": "Do not create \"spec.ts\" test files for the application.", + "type": "boolean", + "default": false, + "alias": "S" + }, + "skipConfig": { + "description": "Do not configure Checkout in Elastic Path Commerce Cloud.", + "type": "boolean", + "default": false + }, + "directory": { + "type": "string", + "description": "The directory name to create the workspace in." + }, + "path": { + "type": "string", + "format": "path", + "$default": { + "$source": "workingDirectory" + }, + "description": "The path at which to create the component file, relative to the current workspace. Default is a folder with the same name as the component in the project root.", + "visible": false + }, + "epccClientId": { + "description": "The client id value for an Elastic Path Commerce Cloud store.", + "type": "string", + "visible": "false" + }, + "epccClientSecret": { + "description": "The client secret value for an Elastic Path Commerce Cloud store.", + "type": "string", + "visible": "false" + }, + "epccEndpointUrl": { + "description": "The geographical endpoint url for an Elastic Path Commerce Cloud store.", + "type": "string", + "visible": "false" + } + }, + "required": ["epccClientId", "epccClientSecret", "epccEndpointUrl", "directory"] +} diff --git a/packages/d2c-schematics/tsup.config.ts b/packages/d2c-schematics/tsup.config.ts index 474575a3..6aa46fe4 100644 --- a/packages/d2c-schematics/tsup.config.ts +++ b/packages/d2c-schematics/tsup.config.ts @@ -29,6 +29,7 @@ export default defineConfig(() => { "checkout/index": "./checkout/index.ts", "ep-payments-payment-gateway/index": "./ep-payments-payment-gateway/index.ts", + "manual-payment-gateway/index": "./manual-payment-gateway/index.ts", }, format: ["cjs"], clean: false, @@ -127,6 +128,10 @@ export default defineConfig(() => { from: ["./ep-payments-payment-gateway/**/*"], to: ["./dist/ep-payments-payment-gateway"], }, + { + from: ["./manual-payment-gateway/**/*"], + to: ["./dist/manual-payment-gateway"], + }, ], }), ],