From 5a17eaf211973416ef70b1326e5b9b64df876f3b Mon Sep 17 00:00:00 2001 From: Yassin Date: Wed, 25 Sep 2024 16:51:59 +0200 Subject: [PATCH] Gherkin use case for cart features with Cypress + Cumcumber + typescript Gherkin use case for cart features with Cypress + Cumcumber + typescript --- .cypress-cucumber-preprocessorrc.json | 7 + .gitignore | 3 + README.md | 1 + Test-Design.md | 85 + app/product/[handle]/page.tsx | 15 +- components/carousel.tsx | 10 +- components/cart/actions.ts | 5 + components/cart/add-to-cart.tsx | 49 +- components/cart/cart-context.tsx | 24 +- components/cart/delete-item-button.tsx | 4 +- components/cart/edit-item-quantity-button.tsx | 5 +- components/cart/modal.tsx | 40 +- components/grid/three-items.tsx | 17 +- components/grid/tile.tsx | 2 + components/label.tsx | 13 +- components/layout/footer.tsx | 2 +- components/layout/navbar/index.tsx | 3 +- components/layout/navbar/mobile-menu.tsx | 1 + components/layout/navbar/search.tsx | 1 + components/layout/search/filter/item.tsx | 1 + components/price.tsx | 9 +- components/product/product-description.tsx | 9 +- components/product/variant-selector.tsx | 1 + cypress.config.ts | 24 +- cypress/e2e/common-step-definitions/common.ts | 23 + cypress/e2e/features/cart/add-to-cart.feature | 64 + cypress/e2e/features/cart/add-to-cart.ts | 209 ++ cypress/e2e/features/cart/view-cart.feature | 0 .../e2e/features/checkout/checkout.feature | 0 cypress/e2e/features/checkout/checkout.ts | 0 .../features/product/product-display.feature | 13 + .../e2e/features/product/product-display.ts | 41 + .../features/product/search-product.feature | 0 cypress/e2e/features/user/user-login.feature | 0 cypress/e2e/features/user/user-login.ts | 7 + cypress/e2e/header.cy.ts | 182 ++ cypress/e2e/home.cy.ts | 5 - cypress/e2e/homepage.cy.ts | 41 + cypress/fixtures/example.json | 62 +- cypress/fixtures/product-query.json | 6 + cypress/support/commands.ts | 99 +- cypress/support/e2e.ts | 4 +- cypress/support/step_definitions/common.ts | 7 + cypress/utils/constants.ts | 59 + cypress/utils/price.ts | 19 + cypress/utils/selectors.ts | 0 cypress/utils/url.ts | 16 + docs/tests/homepage.md | 10 + docs/tests/test-design.md | 99 + lib/shopify/index.ts | 25 +- package.json | 20 +- pnpm-lock.yaml | 2638 ++++++++++++++--- tsconfig.json | 17 +- 53 files changed, 3423 insertions(+), 574 deletions(-) create mode 100644 .cypress-cucumber-preprocessorrc.json create mode 100644 Test-Design.md create mode 100644 cypress/e2e/common-step-definitions/common.ts create mode 100644 cypress/e2e/features/cart/add-to-cart.feature create mode 100644 cypress/e2e/features/cart/add-to-cart.ts create mode 100644 cypress/e2e/features/cart/view-cart.feature create mode 100644 cypress/e2e/features/checkout/checkout.feature create mode 100644 cypress/e2e/features/checkout/checkout.ts create mode 100644 cypress/e2e/features/product/product-display.feature create mode 100644 cypress/e2e/features/product/product-display.ts create mode 100644 cypress/e2e/features/product/search-product.feature create mode 100644 cypress/e2e/features/user/user-login.feature create mode 100644 cypress/e2e/features/user/user-login.ts create mode 100644 cypress/e2e/header.cy.ts delete mode 100644 cypress/e2e/home.cy.ts create mode 100644 cypress/e2e/homepage.cy.ts create mode 100644 cypress/fixtures/product-query.json create mode 100644 cypress/support/step_definitions/common.ts create mode 100644 cypress/utils/constants.ts create mode 100644 cypress/utils/price.ts create mode 100644 cypress/utils/selectors.ts create mode 100644 cypress/utils/url.ts create mode 100644 docs/tests/homepage.md create mode 100644 docs/tests/test-design.md diff --git a/.cypress-cucumber-preprocessorrc.json b/.cypress-cucumber-preprocessorrc.json new file mode 100644 index 000000000..2841eb94b --- /dev/null +++ b/.cypress-cucumber-preprocessorrc.json @@ -0,0 +1,7 @@ +{ + "stepDefinitions": [ + "cypress/e2e/**/[filepath].ts", + "cypress/e2e/common-step-definitions/*.ts", + "cypress/support/step_definitions/*.ts" + ] +} diff --git a/.gitignore b/.gitignore index 0298027e4..69ce4a5da 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +#cursor +.cursorrules \ No newline at end of file diff --git a/README.md b/README.md index 732990275..dd2c70b02 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Vercel is happy to partner and work with any commerce provider to help them get Integrations enable upgraded or additional functionality for Next.js Commerce - [Orama](https://github.com/oramasearch/nextjs-commerce) ([Demo](https://vercel-commerce.oramasearch.com/)) + - Upgrades search to include typeahead with dynamic re-rendering, vector-based similarity search, and JS-based configuration. - Search runs entirely in the browser for smaller catalogs or on a CDN for larger. diff --git a/Test-Design.md b/Test-Design.md new file mode 100644 index 000000000..279091584 --- /dev/null +++ b/Test-Design.md @@ -0,0 +1,85 @@ +# Component Hierarchy and Data-Test Attributes + +Voici un schéma Mermaid qui représente les composants et les hiérarchies des attributs data-test pour le composant `ThreeItemGrid`. + +```mermaid +%%{init: {'theme': 'dark'}}%% + +graph TD + +%% Utilisation d'un vert plus foncé (#339966) avec du texte blanc (#fff) pour améliorer le contraste +classDef grid-item-class fill:#339966,stroke:#aaa,stroke-width:2px,color:#fff; + +%% Bleu foncé (#336699) avec texte blanc (#fff) pour les conteneurs +classDef container-class fill:#336699,stroke:#aaa,stroke-width:2px,color:#fff; + +%% Rouge foncé (#cc3333) avec texte blanc (#fff) pour les composants React +classDef react-component-class fill:#cc3333,stroke:#aaa,stroke-width:2px,color:#fff; + +%% Subgraph représentant la structure globale de la grille +subgraph ThreeItemGrid + style ThreeItemGrid fill:#333,stroke:#aaa,stroke-width:2px; + + %% Grid Item avec taille configurable + ThreeItemGridItem[⚛️ Three Item Grids] + class ThreeItemGridItem react-component-class + + GridItem[🗂️ data-test: three-item-grid] + ThreeItemGridItem --> GridItem + class GridItem container-class + + GridItemSize[🔍 data-test: grid-item
⬛ full / ⬜ half] + GridItem --> GridItemSize + class GridItemSize grid-item-class + + %% Grid Product Link pour GridItemSize + GridItemSize --> GridProductLink[🔍 data-test: grid-product-link] + class GridProductLink grid-item-class + + GridProductLink --> GridTileImage[⚛️ GridTileImage] + class GridTileImage react-component-class + + GridTileImage --> GridTileContainer[🗂️ data-test: grid-tile-container] + class GridTileContainer container-class + + GridTileContainer --> GridTileImageItem[🔍 data-test: grid-tile-image] + class GridTileImageItem grid-item-class + + GridTileContainer --> Label[⚛️ Label] + class Label react-component-class + + Label --> LabelContainer[🗂️ data-test: label-container] + class LabelContainer container-class + + LabelContainer --> LabelContentWrapper[🗂️ data-test: label-content-wrapper] + class LabelContentWrapper container-class + + LabelContentWrapper --> LabelTitleText[🔍 data-test: label-title-text] + class LabelTitleText grid-item-class + + LabelContentWrapper --> Price[⚛️ Price] + class Price react-component-class + + Price --> PriceAmount[🔍 data-test: price-amount] + class PriceAmount grid-item-class + + Price --> PriceCurrencyCode[🔍 data-test: price-currency-code] + class PriceCurrencyCode grid-item-class +end + +%% Subgraph pour la légende +subgraph Légende + direction LR + ReactComp[⚛️ Composants React] + class ReactComp react-component-class + + DataTestCont[🗂️ Conteneur data-test] + class DataTestCont container-class + + TestableElem[🔍 Éléments testables] + class TestableElem grid-item-class +end + +``` + +[![](https://mermaid.ink/img/pako:eNqVVs1u20YQfpUFA0ENIKaWlcoWWwRo5aII4ACBraJAKx9W5FBaeLlLLJeJHUGX3nooeilQoCnQs4E8QO96E79A-wid3RUp_oh2woNE7sx837czQ-6svVBG4AVer7dmgumArPt6BQn0A9KPqLrubza93lzMxVLRdEVmZ-a-1yPfa8ZZRjWTgkT9XJA3oDRJeZ6RWIpwe0c-ezIaTSbj8VNC30BIopxouNFAFpyKEK1xHD8lqcwVocn2jjOpQBEOJJRCK5ppmIuQ0yw7g5gsFYt8piHx7RKJGefBDn-QaSWvIXhCKd3d-29ZpFfBcXozCCWXKjBkX-6Uf8Mhr2ocjyeTncYugRwyKwsE5Cqr6DKLlAlQDV0G81N1Xch8CXthYTjC66OEJanMqNAZuQAa6oo8ZZ596yBA6JpIh_-pIi_zhWsEBana3mWIisyEU4LBeahzBWTJ5YJiISMw61g6zrGWWRE5WymAl1jL77Coc0HwyvQt-tcMZSoflmh1GQjUZsNM_C5n1BCbEsVsmSu6MCqMa43H_P90_-f7f__5zRkcgjFlV87fZa0VdTi7LsT9lvj__f3Hz4Ygopr6GjJ8zbSBcy1tmvuqQxrx_RclTlVO6dBowUP8l-wdoIbff60KKF8p8tVCvbj_8J7EOefkc3L_4S-yojy-qoPUlBjEQ2rMevNlbVbotZIRdgo5Z-LadXEbtYZXEO8CTdzh3aTOwefocdWUV4nuUth0K4hnjMPLhC6haJTaYouptHxch-zdq3zToqyHmsfqxw8w-GX1D6ooQdpdUuffO7b2vGvgA-m2AtjDKbCd80C62-TndAG8SLR9qKHblccT69xKvAezyY1HRybr0V1pbHjVaFHeD_jdSx_jNtt46xwPK9gDPSqj4lpqmTHNYYbnSKuYToM2dt8cNG36MrarlF3MrxULy7fGPtTA7crjxXRuJd7XicxFexupsfnUGtssLqhLf4NhmisFIryd4mzUwRPuXHwzP7XpqghtUhBR8zx1xzklfHu3RHP1wDwvlwxJxBSEduw6v3Ar9tSfYvqKRE8bE0FNXundlXfnfIYbnuF-TVHLxp0WM9A-HzXsalBXkxq7OYu_5cV3ZfsLbjoBI1fvjI2jtxLSkUxv4CWgEsoinGXXJnju2Tl27gV4i5pxpuRzby426EpzLS9vRegFOLTAwFM4eq28IKY8w6c8xd3BGaOY_qRcTan4UcqkCIGIaaleueHZztDWxQvW3o0XHB-Nnx0_H05Ono-GJ6fDk4F36wVHm4H3zkIMnx25a3h8OpycfjEab_4HDOwk4w?type=png)](https://mermaid-js.github.io/mermaid-live-editor/edit#pako:eNqVVs1u20YQfpUFA0ENIKaWlcoWWwRo5aII4ACBraJAKx9W5FBaeLlLLJeJHUGX3nooeilQoCnQs4E8QO96E79A-wid3RUp_oh2woNE7sx837czQ-6svVBG4AVer7dmgumArPt6BQn0A9KPqLrubza93lzMxVLRdEVmZ-a-1yPfa8ZZRjWTgkT9XJA3oDRJeZ6RWIpwe0c-ezIaTSbj8VNC30BIopxouNFAFpyKEK1xHD8lqcwVocn2jjOpQBEOJJRCK5ppmIuQ0yw7g5gsFYt8piHx7RKJGefBDn-QaSWvIXhCKd3d-29ZpFfBcXozCCWXKjBkX-6Uf8Mhr2ocjyeTncYugRwyKwsE5Cqr6DKLlAlQDV0G81N1Xch8CXthYTjC66OEJanMqNAZuQAa6oo8ZZ596yBA6JpIh_-pIi_zhWsEBana3mWIisyEU4LBeahzBWTJ5YJiISMw61g6zrGWWRE5WymAl1jL77Coc0HwyvQt-tcMZSoflmh1GQjUZsNM_C5n1BCbEsVsmSu6MCqMa43H_P90_-f7f__5zRkcgjFlV87fZa0VdTi7LsT9lvj__f3Hz4Ygopr6GjJ8zbSBcy1tmvuqQxrx_RclTlVO6dBowUP8l-wdoIbff60KKF8p8tVCvbj_8J7EOefkc3L_4S-yojy-qoPUlBjEQ2rMevNlbVbotZIRdgo5Z-LadXEbtYZXEO8CTdzh3aTOwefocdWUV4nuUth0K4hnjMPLhC6haJTaYouptHxch-zdq3zToqyHmsfqxw8w-GX1D6ooQdpdUuffO7b2vGvgA-m2AtjDKbCd80C62-TndAG8SLR9qKHblccT69xKvAezyY1HRybr0V1pbHjVaFHeD_jdSx_jNtt46xwPK9gDPSqj4lpqmTHNYYbnSKuYToM2dt8cNG36MrarlF3MrxULy7fGPtTA7crjxXRuJd7XicxFexupsfnUGtssLqhLf4NhmisFIryd4mzUwRPuXHwzP7XpqghtUhBR8zx1xzklfHu3RHP1wDwvlwxJxBSEduw6v3Ar9tSfYvqKRE8bE0FNXundlXfnfIYbnuF-TVHLxp0WM9A-HzXsalBXkxq7OYu_5cV3ZfsLbjoBI1fvjI2jtxLSkUxv4CWgEsoinGXXJnju2Tl27gV4i5pxpuRzby426EpzLS9vRegFOLTAwFM4eq28IKY8w6c8xd3BGaOY_qRcTan4UcqkCIGIaaleueHZztDWxQvW3o0XHB-Nnx0_H05Ono-GJ6fDk4F36wVHm4H3zkIMnx25a3h8OpycfjEab_4HDOwk4w) diff --git a/app/product/[handle]/page.tsx b/app/product/[handle]/page.tsx index e2280675d..aff2f4204 100644 --- a/app/product/[handle]/page.tsx +++ b/app/product/[handle]/page.tsx @@ -80,9 +80,12 @@ export default async function ProductPage({ params }: { params: { handle: string __html: JSON.stringify(productJsonLd) }} /> -
-
-
+
+
+
@@ -97,7 +100,7 @@ export default async function ProductPage({ params }: { params: { handle: string
-
+
@@ -116,18 +119,20 @@ async function RelatedProducts({ id }: { id: string }) { if (!relatedProducts.length) return null; return ( -
+

Related Products

    {relatedProducts.map((product) => (
  • +
      {carouselProducts.map((product, i) => (
    • - +
    • diff --git a/components/cart/actions.ts b/components/cart/actions.ts index a2c592557..2d839a435 100644 --- a/components/cart/actions.ts +++ b/components/cart/actions.ts @@ -8,15 +8,20 @@ import { redirect } from 'next/navigation'; export async function addItem(prevState: any, selectedVariantId: string | undefined) { let cartId = cookies().get('cartId')?.value; + console.log('Cart ID before adding item:', cartId); if (!cartId || !selectedVariantId) { + console.error('Cart ID or selected variant ID is missing'); return 'Error adding item to cart'; } try { + console.log('Attempting to add item to Shopify cart'); await addToCart(cartId, [{ merchandiseId: selectedVariantId, quantity: 1 }]); + console.log('Item added to Shopify cart successfully'); revalidateTag(TAGS.cart); } catch (e) { + console.error('Error adding item to cart:', e); return 'Error adding item to cart'; } } diff --git a/components/cart/add-to-cart.tsx b/components/cart/add-to-cart.tsx index 8bcebb06b..5a6483363 100644 --- a/components/cart/add-to-cart.tsx +++ b/components/cart/add-to-cart.tsx @@ -2,11 +2,10 @@ import { PlusIcon } from '@heroicons/react/24/outline'; import clsx from 'clsx'; -import { addItem } from 'components/cart/actions'; import { useProduct } from 'components/product/product-context'; import { Product, ProductVariant } from 'lib/shopify/types'; -import { useFormState } from 'react-dom'; import { useCart } from './cart-context'; +import { addItem } from './actions'; function SubmitButton({ availableForSale, @@ -21,19 +20,20 @@ function SubmitButton({ if (!availableForSale) { return ( - ); } - console.log(selectedVariantId); + // console.log(selectedVariantId); if (!selectedVariantId) { return ( @@ -63,7 +63,11 @@ export default function CartModal() { leaveFrom="opacity-100 backdrop-blur-[.5px]" leaveTo="opacity-0 backdrop-blur-none" > -