Skip to content

Commit

Permalink
Merge pull request #40 from 2308-Bread/feat/Cypress_refactor
Browse files Browse the repository at this point in the history
Feat/cypress refactor
  • Loading branch information
dsstevens committed Feb 10, 2024
2 parents 4425bc2 + 9969bee commit a63045c
Show file tree
Hide file tree
Showing 15 changed files with 155 additions and 69 deletions.
13 changes: 6 additions & 7 deletions cypress/e2e/detail_page_spec.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,14 @@ describe("BreadDetail Page", () => {
});

it("should display the bread recipe", () => {
cy.get('.recipeDetail').contains('Ingredients:');
cy.get('.recipeDetail').contains('Ingredients');
cy.get('.recipeDetail').contains('500g tapioca flour');
cy.get('.recipeDetail').contains('bake at 375°F (190°C) for 15-20 minutes.');
});

it("should navigate back to the bread list page using browser back action", () => {
cy.visit('/breads/Brazil');
cy.url().should('include', '/breads/Brazil');
cy.get('h2').contains('Breads from Brazil').should('be.visible');
});

it("should display the bread image", () => {
cy.get('.breadImage').should('be.visible').and('have.attr', 'src');
});


});
14 changes: 14 additions & 0 deletions cypress/e2e/error_page.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
describe('Error Handling for Bad Paths', () => {
it('redirects to an error page or shows an error message for a non-existent route', () => {
cy.visit('/some/nonexistent/route');
cy.get('.error-message').should('exist');
cy.get('.error-message').should('contain', 'Sorry, this page doesn\'t exist.');
});

it("should return to the main page when the Home button is clicked", () => {
cy.visit('/some/nonexistent/route');
cy.contains('Home').click();
cy.location("pathname").should("eq", "/");
});

});
16 changes: 14 additions & 2 deletions cypress/e2e/list_page_spec.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,21 @@ describe("BreadList Page", () => {
cy.visit('/breads/Brazil');
});

it("should display the country name and description", () => {
it("should return to the main page when the Home button is clicked", () => {
cy.contains('Home').click();
cy.location("pathname").should("eq", "/");
});

it("should display the country name", () => {
cy.get('h2').contains('Breads from Brazil');
cy.get('p').contains('Pão de queijo is a famous Brazilian cheese bread');
});

it("should display the country history", () => {
cy.get('p').contains('Brazil, the largest country in South America,');
});

it("should display the country culinary history", () => {
cy.get('p').contains('Brazil\'s culinary history is a vibrant tapestry of flavors,');
});

it("should list the breads for that country", () => {
Expand Down
6 changes: 6 additions & 0 deletions src/apiCalls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ export const fetchBreadsForCountry = (countryName: string): Promise<ApiResponse>
return fetch(`https://rails-bread-face5cd9a02c.herokuapp.com/api/v1/countries/${countryName}`)
.then(response => {
if (!response.ok) {
if (response.status >= 400 && response.status < 500) {
throw new Error('Network response was not ok');
} else if (response.status >= 500) {
throw new Error("Something went wrong, please try again later.");
} else {
throw new Error(`Unexpected error. Status: ${response.status}`);
}
}
return response.json();
})
Expand Down
3 changes: 2 additions & 1 deletion src/apiTypes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export interface BreadAttributes {

export interface CountryAttributes {
name: string;
description: string;
overview: string;
culinary: string;
}

export interface BreadData {
Expand Down
4 changes: 2 additions & 2 deletions src/components/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ function App() {
<Route path="/" element={<Main />} />
<Route path="/breads/:id" element={<BreadList />} />
<Route path="/breads/:id/:breadId" element={<BreadDetail />} />
<Route path="/*" element={<Error />} />
<Route path="*" element={<Error />} />
</Routes>
</div>
</BrowserRouter>
);
}

export default App;
export default App;
87 changes: 65 additions & 22 deletions src/components/BreadDetail/BreadDetail.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
font-size: 1rem;
}


.BreadDetail p {
margin-bottom: 3rem;
font-size: .5rem;
Expand All @@ -43,46 +42,48 @@
font-family: 'Abel', sans-serif;
width: 80%;
height: 80%;
padding: 1.5rem;
padding: 1.7rem;
border-radius: 65px;
overflow-y: auto;
display: flex;
flex-direction: column;
align-items: center;
margin: 0 auto;
font-size: large;
padding-top: 2rem;
font-size: 1rem;
padding-top: .5rem;
}

.recipeDetail > p {
padding-top: 4rem;
.recipeDetail > h4 {
padding-top: .5rem;
color: black
}

.breadImage {
max-width: 75%;
height: auto;
width: 300px;
height: 100%;
}

/* SMALL - MEDIUM BREAKPOINT */
@media screen and (min-width: 470px) and (max-width: 700) and (orientation: portrait){
/* iPhone 12 Pro BREAKPOINT */
@media screen and (min-width: 390px) and (max-width: 469px) and (orientation: portrait){
.BreadDetail {
margin-top: 1rem;
text-align: center;
font-family: 'Abel', sans-serif;
margin-bottom: 1rem;
}

.recipeSection {
height: calc(100vh - 337px);
.recipeDetail {
font-size: 1.1rem;
}

.recipeDetail {
font-size: 2rem;
.BreadDetail h3 {
margin-right: 1.2rem;
margin-left: 1.2rem;
}
}

/* RESPONSIVE MEDIUM BREAKPOINT */
@media screen and (min-width: 700px) and (max-width: 750px ) and (orientation: portrait) {
/* SMALL - MEDIUM BREAKPOINT */
@media screen and (min-width: 470px) and (max-width: 700) and (orientation: portrait){
.BreadDetail {
margin-top: 1rem;
text-align: center;
Expand All @@ -91,30 +92,45 @@
}

.recipeSection {
height: calc(100vh - 305px);
height: calc(100vh - 337px);
}

.recipeDetail {
font-size: 2rem;
}

.BreadDetail h3 {
margin-right: 1.2rem;
margin-left: 1.2rem;
}
}

/* iPhone 12 Pro BREAKPOINT */
@media screen and (min-width: 390px) and (max-width: 469px) and (orientation: portrait){
/* RESPONSIVE MEDIUM BREAKPOINT */
@media screen and (min-width: 700px) and (max-width: 750px ) and (orientation: portrait) {
.BreadDetail {
margin-top: 1rem;
text-align: center;
font-family: 'Abel', sans-serif;
margin-bottom: 1rem;
}

.recipeSection {
height: calc(100vh - 305px);
}

.recipeDetail {
font-size: 1.1rem;
font-size: 2rem;
}

.BreadDetail h3 {
margin-right: 1.2rem;
margin-left: 1.2rem;
}
}


/* IPAD BREAKPOINT */
@media screen and (min-width: 750px) and (max-width: 1400px ) and (orientation: portrait) {
@media screen and (min-width: 750px) and (max-width: 1400px) and (orientation: portrait) {
.BreadDetail {
margin-top: 3rem;
text-align: center;
Expand All @@ -128,15 +144,42 @@

.recipeDetail {
font-size: 2rem;
padding-right: 2rem;
padding-left: 4rem;
}

.BreadDetail h3 {
margin-right: 1.5rem;
margin-left: 1.5rem;
font-size: 2rem;
}
}

/* LARGE BREAKPOINT */
@media screen and (min-width: 1025px) {
@media screen and (min-width: 1000px) and (orientation: landscape){
.BreadDetail {
margin-top: 4rem;
text-align: center;
font-family: 'Abel', sans-serif;
margin-bottom: 1rem;
}

.BreadDetail >h2 {
font-size: 4rem;
}

.BreadDetail > h3 {
margin-left: 5rem;
margin-right: 5rem;
font-size: 1.8rem;
}

.recipeDetail {
font-size: 1.5rem;
}

.breadImage {
width: 400px;
height: 100%;
}
}
17 changes: 6 additions & 11 deletions src/components/BreadDetail/BreadDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,30 @@
// BreadDetail.tsx
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { useParams, useNavigate } from "react-router-dom";
import { fetchBreadsForCountry } from "../../apiCalls";
import "./BreadDetail.css";
import { BreadAttributes } from "../../apiTypes";

const BreadDetail = () => {
const { id: countryName, breadId } = useParams<{
id: string;
breadId: string;
}>();
const { id: countryName, breadId } = useParams<{ id: string; breadId: string; }>();
const [breadDetail, setBreadDetail] = useState<BreadAttributes | null>(null);
const navigate = useNavigate();

useEffect(() => {
if (countryName) {
console.log(`Fetching bread detail for ${breadId} from ${countryName}...`);
fetchBreadsForCountry(countryName)
.then((data) => {
console.log("Bread detail data:", data);
const bread = data.breads.data.find(bread => bread.attributes.name === breadId);
if (bread) {
setBreadDetail(bread.attributes);
} else {
console.error(`Bread with ID ${breadId} not found.`);
navigate('/error'); // Redirect to error page
}
})
.catch((error) => {
console.error("Fetching error:", error);
navigate('/error'); // Redirect to error page
});
}
}, [countryName, breadId]);
}, [countryName, breadId, navigate]);

if (!breadDetail) return <div>Loading...</div>;

Expand Down
27 changes: 20 additions & 7 deletions src/components/BreadList/BreadList.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* SMALL BREAKPOINTS */
.BreadListWrapper {
margin-top: 5rem;
margin-top: 2rem;
text-align: center;
margin-bottom: 1rem;
}
Expand Down Expand Up @@ -70,22 +71,34 @@
}

/* MEDIUM BREAKPOINT */
@media screen and (min-width: 750px) and (max-width: 1024px) and (orientation: landscape) {
@media screen and (min-width: 750px) and (max-width: 1024px) and (orientation: portrait) {
.BreadListWrapper {
margin-top: 4rem;
font-size: xx-large;
margin-top: 2rem;
}

.BreadListWrapper > h2 {
margin-bottom: 1rem;
}

.listDetail {
font-size: 2rem;
}
}

/* LARGE BREAKPOINT */
@media screen and (min-width: 1025px) and (orientation: landscape){
@media screen and (min-width: 1025px){
.BreadListWrapper h2 {
margin-top: 5rem;
margin-top: 2rem;
font-size: xx-large;
margin-bottom: 1rem;
}

.BreadListWrapper p {
font-size: 1.3rem
}

.listDetail {
font-size: xx-large;
font-size: 2rem
}

}
11 changes: 5 additions & 6 deletions src/components/BreadList/BreadList.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
// BreadList.tsx
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate, Link } from 'react-router-dom';
import { useParams, Link, useNavigate } from 'react-router-dom';
import { fetchBreadsForCountry } from '../../apiCalls';
import './BreadList.css';
import { BreadData, CountryData, ApiResponse } from '../../apiTypes';

const BreadList = () => {
const navigate = useNavigate();
const { id: countryName } = useParams();
const [breads, setBreads] = useState<BreadData[]>([]);
const [country, setCountry] = useState<CountryData | null>(null);
const navigate = useNavigate();

useEffect(() => {
if (countryName) {
Expand All @@ -19,8 +18,7 @@ const BreadList = () => {
setBreads(data.breads.data);
})
.catch(error => {
console.error("Fetching error:", error);
navigate('/');
navigate('/error'); // Redirect to error page
});
}
}, [countryName, navigate]);
Expand All @@ -30,7 +28,8 @@ const BreadList = () => {
return (
<div className="BreadListWrapper">
<h2>Breads from {country.attributes.name}</h2>
<p>{country.attributes.description}</p>
<p>{country.attributes.overview}</p>
<p>{country.attributes.culinary}</p>
<section className='listSection'>
<div className='listDetail'>
<ul>
Expand Down
Loading

0 comments on commit a63045c

Please sign in to comment.