diff --git a/__tests__/example.spec.ts b/__tests__/example.spec.ts index 1b57c1054..13baf1e18 100644 --- a/__tests__/example.spec.ts +++ b/__tests__/example.spec.ts @@ -1,18 +1,28 @@ -import { test, expect } from "@playwright/test"; +import { expect, test } from "@playwright/test"; -test("has title", async ({ page }) => { - await page.goto("https://playwright.dev/"); +test("test", async ({ page }) => { + await page.goto("/"); + await page.getByTestId("ProductElement").first().click(); + await page.getByRole("button", { name: "Add to cart" }).click(); - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Playwright/); -}); + await page.getByRole("link", { name: "1 items in cart, view bag" }).click(); + await page.getByRole("link", { name: "Checkout" }).click(); -test("get started link", async ({ page }) => { - await page.goto("https://playwright.dev/"); + await page.getByLabel("First name*").fill("Jan"); + await page.getByLabel("Last name*").fill("Kowalski"); + await page.getByLabel("Street address*").fill("3111 Broadway"); + await page.getByLabel("City*").fill("New York"); + await page.getByLabel("Zip code*").fill("10027"); + await page.getByLabel("Phone number").fill("+48123456789"); - // Click the get started link. - await page.getByRole("link", { name: "Get started" }).click(); + await page + .frameLocator('iframe[title="Iframe for card number"]') + .getByLabel("Card number") + .fill("4111 1111 4555 1142"); + await page.frameLocator('iframe[title="Iframe for expiry date"]').getByLabel("Expiry date").fill("03/30"); + await page.frameLocator('iframe[title="Iframe for security code"]').getByLabel("Security code").fill("333"); + await page.getByLabel("Name on card").fill("Jan Kowalski"); + await page.getByRole("button", { name: "Pay" }).click(); - // Expects page to have a heading with the name of Installation. - await expect(page.getByRole("heading", { name: "Installation" })).toBeVisible(); + expect(true).toBe(true); }); diff --git a/src/app/(main)/categories/[slug]/page.tsx b/src/app/(main)/categories/[slug]/page.tsx index be41a8f67..976423dd8 100644 --- a/src/app/(main)/categories/[slug]/page.tsx +++ b/src/app/(main)/categories/[slug]/page.tsx @@ -2,7 +2,7 @@ import { notFound } from "next/navigation"; import { type Metadata } from "next"; import { ProductListByCategoryDocument } from "@/gql/graphql"; import { execute } from "@/lib/graphql"; -import { ProductElement } from "@/ui/components/ProductElement"; +import { ProductsList } from "@/ui/components/ProductsList"; export const generateMetadata = async ({ params }: { params: { slug: string } }): Promise => { const { category } = await execute(ProductListByCategoryDocument, { @@ -20,7 +20,7 @@ export default async function Page({ params }: { params: { slug: string } }) { variables: { slug: params.slug }, }); - if (!category) { + if (!category || !category.products) { notFound(); } @@ -35,11 +35,7 @@ export default async function Page({ params }: { params: { slug: string } }) {

Products in category {category.name}

-
- {products?.edges.map(({ node: product }, index) => ( - - ))} -
+ e.node)} />
); diff --git a/src/app/(main)/page.tsx b/src/app/(main)/page.tsx index 9840b5815..1a9c2f792 100644 --- a/src/app/(main)/page.tsx +++ b/src/app/(main)/page.tsx @@ -1,6 +1,6 @@ import { ProductListDocument } from "@/gql/graphql"; import { execute } from "@/lib/graphql"; -import { ProductElement } from "@/ui/components/ProductElement"; +import { ProductsList } from "@/ui/components/ProductsList"; export const metadata = { title: "Saleor Storefront example", @@ -17,14 +17,9 @@ export default async function Page() { return (

Saleor Storefront example

- {/* */}

Product list

-
- {products.map((product, index) => ( - - ))} -
+
); diff --git a/src/app/(main)/products/[slug]/page.tsx b/src/app/(main)/products/[slug]/page.tsx index f16941a41..39dba2a1e 100644 --- a/src/app/(main)/products/[slug]/page.tsx +++ b/src/app/(main)/products/[slug]/page.tsx @@ -8,7 +8,7 @@ import { AddButton } from "./AddButton"; import { VariantSelector } from "@/ui/components/VariantSelector"; import { ProductImageWrapper } from "@/ui/atoms/ProductImageWrapper"; import { execute, formatMoney } from "@/lib/graphql"; -import { CheckoutAddLineDocument, ProductElementDocument, ProductListDocument } from "@/gql/graphql"; +import { CheckoutAddLineDocument, ProductDetailsDocument, ProductListDocument } from "@/gql/graphql"; import * as Checkout from "@/lib/checkout"; export async function generateMetadata({ @@ -18,7 +18,7 @@ export async function generateMetadata({ params: { slug: string }; searchParams: { variant?: string }; }): Promise { - const { product } = await execute(ProductElementDocument, { + const { product } = await execute(ProductDetailsDocument, { variables: { slug: decodeURIComponent(params.slug), }, @@ -56,7 +56,7 @@ const parser = edjsHTML(); export default async function Page(props: { params: { slug: string }; searchParams: { variant?: string } }) { const { params, searchParams } = props; - const { product } = await execute(ProductElementDocument, { + const { product } = await execute(ProductDetailsDocument, { variables: { slug: decodeURIComponent(params.slug), }, diff --git a/src/app/(main)/products/page.tsx b/src/app/(main)/products/page.tsx index c3113bd59..07bc7c139 100644 --- a/src/app/(main)/products/page.tsx +++ b/src/app/(main)/products/page.tsx @@ -2,7 +2,7 @@ import { notFound } from "next/navigation"; import { ProductListPaginatedDocument } from "@/gql/graphql"; import { ProductsPerPage, execute } from "@/lib/graphql"; import { Pagination } from "@/ui/components/Pagination"; -import { ProductElement } from "@/ui/components/ProductElement"; +import { ProductsList } from "@/ui/components/ProductsList"; export const metadata = { title: "Product List ยท Saleor Storefront example", @@ -38,11 +38,7 @@ export default async function Page({ searchParams }: Props) {

Product list

-
- {products?.edges.map(({ node: product }, index) => ( - - ))} -
+ e.node)} />
diff --git a/src/graphql/ProductElement.graphql b/src/graphql/ProductDetails.graphql similarity index 80% rename from src/graphql/ProductElement.graphql rename to src/graphql/ProductDetails.graphql index 6514b8f17..f71bcfc7c 100644 --- a/src/graphql/ProductElement.graphql +++ b/src/graphql/ProductDetails.graphql @@ -1,11 +1,19 @@ -query ProductElement($slug: String!) { +query ProductDetails($slug: String!) { product(slug: $slug, channel: "default-channel") { id name - description slug + description seoTitle seoDescription + thumbnail(size: 1024, format: WEBP) { + url + alt + } + category { + id + name + } variants { id name @@ -18,9 +26,5 @@ query ProductElement($slug: String!) { } } } - thumbnail(size: 1024, format: WEBP) { - url - alt - } } } diff --git a/src/graphql/ProductList.graphql b/src/graphql/ProductList.graphql index 2447e4c42..9dace4bb3 100644 --- a/src/graphql/ProductList.graphql +++ b/src/graphql/ProductList.graphql @@ -2,7 +2,7 @@ query ProductList { products(first: 12, channel: "default-channel") { edges { node { - ...Product + ...ProductListItem } } } diff --git a/src/graphql/ProductListByCategory.graphql b/src/graphql/ProductListByCategory.graphql index 02d2457e3..3c9a7beb8 100644 --- a/src/graphql/ProductListByCategory.graphql +++ b/src/graphql/ProductListByCategory.graphql @@ -7,7 +7,7 @@ query ProductListByCategory($slug: String!) { products(first: 100, channel: "default-channel") { edges { node { - ...Product + ...ProductListItem } } } diff --git a/src/graphql/Product.graphql b/src/graphql/ProductListItem.graphql similarity index 86% rename from src/graphql/Product.graphql rename to src/graphql/ProductListItem.graphql index 77d31ac7a..85754687a 100644 --- a/src/graphql/Product.graphql +++ b/src/graphql/ProductListItem.graphql @@ -1,15 +1,7 @@ -fragment Product on Product { +fragment ProductListItem on Product { id name slug - thumbnail(size: 1024, format: WEBP) { - url - alt - } - category { - id - name - } pricing { priceRange { start { @@ -26,4 +18,12 @@ fragment Product on Product { } } } + category { + id + name + } + thumbnail(size: 1024, format: WEBP) { + url + alt + } } diff --git a/src/graphql/ProductListPaginated.graphql b/src/graphql/ProductListPaginated.graphql index 2c4fe7642..1c5d70667 100644 --- a/src/graphql/ProductListPaginated.graphql +++ b/src/graphql/ProductListPaginated.graphql @@ -3,7 +3,7 @@ query ProductListPaginated($first: Int!, $after: String) { totalCount edges { node { - ...Product + ...ProductListItem } cursor } diff --git a/src/ui/atoms/Loader.tsx b/src/ui/atoms/Loader.tsx index 77281e1f9..151a1939f 100644 --- a/src/ui/atoms/Loader.tsx +++ b/src/ui/atoms/Loader.tsx @@ -1,7 +1,7 @@ export function Loader() { return ( -
-
+
+
{lineCount || ""} - items in cart, view bag + {lineCount && ( + <> + {lineCount} + items in cart, view bag + + )}
diff --git a/src/ui/components/ProductElement.tsx b/src/ui/components/ProductElement.tsx index e5cbe9baa..8eae38bda 100644 --- a/src/ui/components/ProductElement.tsx +++ b/src/ui/components/ProductElement.tsx @@ -1,37 +1,39 @@ import Link from "next/link"; import { ProductImageWrapper } from "@/ui/atoms/ProductImageWrapper"; -import type { ProductFragment } from "@/gql/graphql"; +import type { ProductListItemFragment } from "@/gql/graphql"; import { formatMoneyRange } from "@/lib/graphql"; -export function ProductElement(props: { product: ProductFragment } & { loading: "eager" | "lazy" }) { +export function ProductElement(props: { product: ProductListItemFragment } & { loading: "eager" | "lazy" }) { const { product, loading } = props; return ( - -
- {product?.thumbnail?.url && ( - - )} -
-
-

{product.name}

-

{product?.category?.name}

+
  • + +
    + {product?.thumbnail?.url && ( + + )} +
    +
    +

    {product.name}

    +

    {product?.category?.name}

    +
    +

    + {formatMoneyRange({ + start: product?.pricing?.priceRange?.start?.gross, + stop: product?.pricing?.priceRange?.stop?.gross, + })} +

    -

    - {formatMoneyRange({ - start: product?.pricing?.priceRange?.start?.gross, - stop: product?.pricing?.priceRange?.stop?.gross, - })} -

    -
  • - + + ); } diff --git a/src/ui/components/ProductsList.tsx b/src/ui/components/ProductsList.tsx new file mode 100644 index 000000000..5ce0d6fe1 --- /dev/null +++ b/src/ui/components/ProductsList.tsx @@ -0,0 +1,16 @@ +import { ProductElement } from "./ProductElement"; +import { type ProductListItemFragment } from "@/gql/graphql"; + +export const ProductsList = ({ products }: { products: readonly ProductListItemFragment[] }) => { + return ( +
      + {products.map((product, index) => ( + + ))} +
    + ); +};