diff --git a/.gitignore b/.gitignore index b5514fd00e..43b7af7dde 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,6 @@ coverage out/ build src/frontend/protos -next-env.d.ts \ No newline at end of file +next-env.d.ts +src/frontend/cypress/videos +src/frontend/cypress/screenshots \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b61048b47..3572810850 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,3 +65,5 @@ significant modifications will be credited to OpenTelemetry Authors. ([#273](https://github.com/open-telemetry/opentelemetry-demo/pull/273)) * Reimplemented Frontend app using [Next.js](https://nextjs.org/) Browser client ([#236](https://github.com/open-telemetry/opentelemetry-demo/pull/236)) +* Added Frontend [Cypress](https://www.cypress.io/) E2E tests +([#298](https://github.com/open-telemetry/opentelemetry-demo/pull/298)) diff --git a/docker-compose.yml b/docker-compose.yml index 07cca94df4..333c21f75f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -183,6 +183,50 @@ services: - shippingservice logging: *logging + # Frontend Tests + frontendTests: + image: cypress/included:10.3.1-typescript + depends_on: + - frontend + profiles: + - tests + environment: + - CYPRESS_baseUrl=http://${FRONTEND_ADDR} + - NODE_ENV=production + working_dir: /cypress + volumes: + - ./src/frontend:/cypress + + # Integration Tests + integrationTests: + image: ${IMAGE_NAME}:${IMAGE_VERSION}-integrationTests + container_name: integrationTests + profiles: + - tests + build: + context: ./ + dockerfile: ./test/Dockerfile + environment: + - AD_SERVICE_ADDR + - CART_SERVICE_ADDR + - CHECKOUT_SERVICE_ADDR + - CURRENCY_SERVICE_ADDR + - EMAIL_SERVICE_ADDR + - PAYMENT_SERVICE_ADDR + - PRODUCT_CATALOG_SERVICE_ADDR + - RECOMMENDATION_SERVICE_ADDR + - SHIPPING_SERVICE_ADDR + depends_on: + - adservice + - cartservice + - checkoutservice + - currencyservice + - emailservice + - paymentservice + - productcatalogservice + - recommendationservice + - shippingservice + # PaymentService paymentservice: image: ${IMAGE_NAME}:${IMAGE_VERSION}-paymentservice diff --git a/src/frontend/components/Ad/Ad.tsx b/src/frontend/components/Ad/Ad.tsx index 578aaa1851..4c480296da 100644 --- a/src/frontend/components/Ad/Ad.tsx +++ b/src/frontend/components/Ad/Ad.tsx @@ -1,3 +1,4 @@ +import { CypressFields } from '../../utils/Cypress'; import { useAd } from '../../providers/Ad.provider'; import * as S from './Ad.styled'; @@ -7,7 +8,7 @@ const Ad = () => { } = useAd(); return ( - +

{text}

diff --git a/src/frontend/components/CartDropdown/CartDropdown.tsx b/src/frontend/components/CartDropdown/CartDropdown.tsx index c96a528046..2e05827ae6 100644 --- a/src/frontend/components/CartDropdown/CartDropdown.tsx +++ b/src/frontend/components/CartDropdown/CartDropdown.tsx @@ -1,5 +1,6 @@ import Link from 'next/link'; import { useEffect, useRef } from 'react'; +import { CypressFields } from '../../utils/Cypress'; import { IProductCartItem } from '../../types/Cart'; import ProductPrice from '../ProductPrice'; import * as S from './CartDropdown.styled'; @@ -18,7 +19,7 @@ const CartDropdown = ({ productList, isOpen, onClose }: IProps) => { if (ref.current && !ref.current.contains(event.target as Node)) { onClose(); } - } + }; // Bind the event listener document.addEventListener('mousedown', handleClickOutside); @@ -29,19 +30,17 @@ const CartDropdown = ({ productList, isOpen, onClose }: IProps) => { }, [ref]); return isOpen ? ( - +
Shopping Cart Close - {!productList.length && ( - Your shopping cart is empty - )} + {!productList.length && Your shopping cart is empty} {productList.map( ({ quantity, product: { name, picture, id, priceUsd = { nanos: 0, currencyCode: 'USD', units: 0 } } }) => ( - + {name} @@ -54,7 +53,7 @@ const CartDropdown = ({ productList, isOpen, onClose }: IProps) => {
- Go to Shipping Cart + Go to Shipping Cart
) : null; diff --git a/src/frontend/components/CartIcon/CartIcon.tsx b/src/frontend/components/CartIcon/CartIcon.tsx index c502138cd8..e58b98a2c9 100644 --- a/src/frontend/components/CartIcon/CartIcon.tsx +++ b/src/frontend/components/CartIcon/CartIcon.tsx @@ -1,4 +1,5 @@ import { useState } from 'react'; +import { CypressFields } from '../../utils/Cypress'; import { useCart } from '../../providers/Cart.provider'; import CartDropdown from '../CartDropdown'; import * as S from './CartIcon.styled'; @@ -11,9 +12,9 @@ const CartIcon = () => { return ( <> - setIsOpen(true)}> + setIsOpen(true)}> - {!!items.length && {items.length}} + {!!items.length && {items.length}} setIsOpen(false)} /> diff --git a/src/frontend/components/CheckoutForm/CheckoutForm.tsx b/src/frontend/components/CheckoutForm/CheckoutForm.tsx index 2bcf2dcd25..88f6465c89 100644 --- a/src/frontend/components/CheckoutForm/CheckoutForm.tsx +++ b/src/frontend/components/CheckoutForm/CheckoutForm.tsx @@ -1,5 +1,6 @@ import Link from 'next/link'; import { useCallback, useState } from 'react'; +import { CypressFields } from '../../utils/Cypress'; import Input from '../Input'; import * as S from './CheckoutForm.styled'; @@ -190,7 +191,7 @@ const CheckoutForm = ({ onSubmit }: IProps) => { Continue Shopping - Place Order + Place Order ); diff --git a/src/frontend/components/CheckoutItem/CheckoutItem.tsx b/src/frontend/components/CheckoutItem/CheckoutItem.tsx index 79919c5dee..fba9adf6b8 100644 --- a/src/frontend/components/CheckoutItem/CheckoutItem.tsx +++ b/src/frontend/components/CheckoutItem/CheckoutItem.tsx @@ -1,5 +1,6 @@ import Image from 'next/image'; import { useState } from 'react'; +import { CypressFields } from '../../utils/Cypress'; import { Address } from '../../protos/demo'; import { IProductCheckoutItem } from '../../types/Cart'; import ProductPrice from '../ProductPrice'; @@ -23,7 +24,7 @@ const CheckoutItem = ({ const [isCollapsed, setIsCollapsed] = useState(false); return ( - + diff --git a/src/frontend/components/CurrencySwitcher/CurrencySwitcher.tsx b/src/frontend/components/CurrencySwitcher/CurrencySwitcher.tsx index 979749f98e..e0b6abe7cd 100644 --- a/src/frontend/components/CurrencySwitcher/CurrencySwitcher.tsx +++ b/src/frontend/components/CurrencySwitcher/CurrencySwitcher.tsx @@ -2,6 +2,7 @@ import { useMemo } from 'react'; import getSymbolFromCurrency from 'currency-symbol-map'; import { useCurrency } from '../../providers/Currency.provider'; import * as S from './CurrencySwitcher.styled'; +import { CypressFields } from '../../utils/Cypress'; const CurrencySwitcher = () => { const { currencyCodeList, setSelectedCurrency, selectedCurrency } = useCurrency(); @@ -16,6 +17,7 @@ const CurrencySwitcher = () => { name="currency_code" onChange={event => setSelectedCurrency(event.target.value)} value={selectedCurrency} + data-cy={CypressFields.CurrencySwitcher} > {currencyCodeList.map(currencyCode => (