Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

e2e: Happy path #927

Merged
merged 1 commit into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 22 additions & 12 deletions __tests__/example.spec.ts
Original file line number Diff line number Diff line change
@@ -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);
});
10 changes: 3 additions & 7 deletions src/app/(main)/categories/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<Metadata> => {
const { category } = await execute(ProductListByCategoryDocument, {
Expand All @@ -20,7 +20,7 @@ export default async function Page({ params }: { params: { slug: string } }) {
variables: { slug: params.slug },
});

if (!category) {
if (!category || !category.products) {
notFound();
}

Expand All @@ -35,11 +35,7 @@ export default async function Page({ params }: { params: { slug: string } }) {
</div>
<section className="sm:py-18 mx-auto max-w-2xl px-8 py-12 sm:px-6 lg:max-w-7xl">
<h2 className="sr-only">Products in category {category.name}</h2>
<div className="mt-4 grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-4">
{products?.edges.map(({ node: product }, index) => (
<ProductElement key={product.id} product={product} loading={index < 4 ? "eager" : "lazy"} />
))}
</div>
<ProductsList products={products.edges.map((e) => e.node)} />
</section>
</div>
);
Expand Down
9 changes: 2 additions & 7 deletions src/app/(main)/page.tsx
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -17,14 +17,9 @@ export default async function Page() {
return (
<div>
<h1 className="sr-only">Saleor Storefront example</h1>
{/* <CollectionList /> */}
<section className="mx-auto max-w-7xl p-8">
<h2 className="sr-only">Product list</h2>
<div className="mt-4 grid gap-8 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
{products.map((product, index) => (
<ProductElement key={product.id} product={product} loading={index < 4 ? "eager" : "lazy"} />
))}
</div>
<ProductsList products={products} />
</section>
</div>
);
Expand Down
6 changes: 3 additions & 3 deletions src/app/(main)/products/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -18,7 +18,7 @@ export async function generateMetadata({
params: { slug: string };
searchParams: { variant?: string };
}): Promise<Metadata> {
const { product } = await execute(ProductElementDocument, {
const { product } = await execute(ProductDetailsDocument, {
variables: {
slug: decodeURIComponent(params.slug),
},
Expand Down Expand Up @@ -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),
},
Expand Down
8 changes: 2 additions & 6 deletions src/app/(main)/products/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -38,11 +38,7 @@ export default async function Page({ searchParams }: Props) {
</div>
<section className="sm:py-18 mx-auto max-w-2xl px-8 py-12 sm:px-6 lg:max-w-7xl">
<h2 className="sr-only">Product list</h2>
<div className="my-8 grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-4">
{products?.edges.map(({ node: product }, index) => (
<ProductElement key={product.id} product={product} loading={index < 4 ? "eager" : "lazy"} />
))}
</div>
<ProductsList products={products.edges.map((e) => e.node)} />
<Pagination pageInfo={products.pageInfo} />
</section>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -18,9 +26,5 @@ query ProductElement($slug: String!) {
}
}
}
thumbnail(size: 1024, format: WEBP) {
url
alt
}
}
}
2 changes: 1 addition & 1 deletion src/graphql/ProductList.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ query ProductList {
products(first: 12, channel: "default-channel") {
edges {
node {
...Product
...ProductListItem
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/graphql/ProductListByCategory.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ query ProductListByCategory($slug: String!) {
products(first: 100, channel: "default-channel") {
edges {
node {
...Product
...ProductListItem
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -26,4 +18,12 @@ fragment Product on Product {
}
}
}
category {
id
name
}
thumbnail(size: 1024, format: WEBP) {
url
alt
}
}
2 changes: 1 addition & 1 deletion src/graphql/ProductListPaginated.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ query ProductListPaginated($first: Int!, $after: String) {
totalCount
edges {
node {
...Product
...ProductListItem
}
cursor
}
Expand Down
4 changes: 2 additions & 2 deletions src/ui/atoms/Loader.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export function Loader() {
return (
<div className="text-center">
<div role="status">
<div className="text-center" aria-busy="true" role="status">
<div>
<svg
aria-hidden="true"
className="mr-2 inline h-12 w-12 animate-spin fill-gray-600 text-gray-200 dark:text-gray-600"
Expand Down
8 changes: 6 additions & 2 deletions src/ui/components/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ export async function Nav() {
<div className="">
<Link href="/cart" className="group -m-2 flex items-center p-2">
<ShoppingBagIcon className="h-6 w-6 flex-shrink-0 " aria-hidden="true" />
<span className="ml-2 text-sm font-medium ">{lineCount || ""}</span>
<span className="sr-only">items in cart, view bag</span>
{lineCount && (
<>
<span className="ml-2 text-sm font-medium ">{lineCount}</span>
<span className="sr-only">items in cart, view bag</span>
</>
)}
</Link>
</div>
</div>
Expand Down
52 changes: 27 additions & 25 deletions src/ui/components/ProductElement.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Link href={`/products/${product.slug}`} key={product.id}>
<div>
{product?.thumbnail?.url && (
<ProductImageWrapper
loading={loading}
src={product.thumbnail.url}
alt={product.thumbnail.alt ?? ""}
width={512}
height={512}
/>
)}
<div className="mt-2 flex justify-between">
<div>
<h3 className="text-sm font-semibold text-gray-700">{product.name}</h3>
<p className="text-sm text-gray-500">{product?.category?.name}</p>
<li data-testid="ProductElement">
<Link href={`/products/${product.slug}`} key={product.id}>
<div>
{product?.thumbnail?.url && (
<ProductImageWrapper
loading={loading}
src={product.thumbnail.url}
alt={product.thumbnail.alt ?? ""}
width={512}
height={512}
/>
)}
<div className="mt-2 flex justify-between">
<div>
<h3 className="text-sm font-semibold text-gray-700">{product.name}</h3>
<p className="text-sm text-gray-500">{product?.category?.name}</p>
</div>
<p className="text-sm font-medium text-gray-900">
{formatMoneyRange({
start: product?.pricing?.priceRange?.start?.gross,
stop: product?.pricing?.priceRange?.stop?.gross,
})}
</p>
</div>
<p className="text-sm font-medium text-gray-900">
{formatMoneyRange({
start: product?.pricing?.priceRange?.start?.gross,
stop: product?.pricing?.priceRange?.stop?.gross,
})}
</p>
</div>
</div>
</Link>
</Link>
</li>
);
}
16 changes: 16 additions & 0 deletions src/ui/components/ProductsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ProductElement } from "./ProductElement";
import { type ProductListItemFragment } from "@/gql/graphql";

export const ProductsList = ({ products }: { products: readonly ProductListItemFragment[] }) => {
return (
<ul
role="list"
data-testid="ProductsList"
className="my-8 grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-4"
>
{products.map((product, index) => (
<ProductElement key={product.id} product={product} loading={index < 4 ? "eager" : "lazy"} />
))}
</ul>
);
};