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

Styling/userview #44

Merged
merged 22 commits into from
Jan 7, 2024
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
130 changes: 126 additions & 4 deletions cypress/e2e/spec.cy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,127 @@
describe('template spec', () => {
it('passes', () => {
cy.visit('https://example.cypress.io')
//Need to login before testing
describe('API Tests', () => {
beforeEach(() => {
cy.visit('http://localhost:3000/');
})
})
it('Fetches and displays Wikipedia page contents', () => {
cy.intercept('GET', 'https://en.wikipedia.org/w/api.php?', {
statusCode: 200,
fixture: 'wikipediaApiResponse',
}).as('fetchContents');
cy.wait('@fetchContents').then(({ response }) => {
expect(response.statusCode).to.equal(200);
});
cy.contains('Loading...').should('not.exist');
cy.contains('An error occurred').should('not.exist');
});

it('Handles error when API fails', () => {
cy.intercept('GET', 'https://en.wikipedia.org/w/api.php?', {
statusCode: 500,
body: 'Server Error',
delayMs: 200,
}).as('fetchError');
cy.wait('@fetchError').then(({ response }) => {
expect(response.statusCode).to.equal(500);
cy.contains('An error occurred').should('exist');
});
});
});

describe('App Component', () => {
beforeEach(() => {
cy.visit('http://localhost:3000/');
})

it('Loads the app properly', () => {
cy.get('.header-text').should('be.visible');
cy.get('.login-button').should('be.visible');
cy.get('.random-headline').should('be.visible');
});

it('Displays random controversies', () => {
cy.get('.result-name').should('contain', '');
cy.get('.random-headline').should('contain', 'Random Controversy');
cy.get('.card').should('be.visible');
cy.get('.card')
.children()
.first()
.within(() => {
cy.contains('h2', '');
cy.contains('p', '');
cy.contains('button', '😡Save Controversy😡');
cy.contains('button', '🤬Save as favorite controversy🤬');
});
});
});

describe('Can search for a Controversy', () => {
beforeEach(() => {
cy.visit('http://localhost:3000/');
//placeholder for login flow
});

it('Searches for a term, then clears input', () => {
cy.get('input[type="text"]').should('be.visible');
cy.get('input[type="text"]').type('SearchTerm{enter}');
cy.get('input[type="text"]').should('have.text', '');
});

it('Displays controversies for a search result', () => {
cy.get('.card').should('be.visible');
cy.get('.result-name').should('contain', '');
cy.get('.results-list')
.children()
.first()
.within(() => {
cy.contains('h2', '');
cy.contains('p', '');
cy.contains('button', '😡Save Controversy😡');
cy.contains('button', '🤬Save as favorite controversy🤬');
});
cy.get('.results-list')
.children()
.last()
.within(() => {
cy.contains('h2', '');
cy.contains('p', '');
cy.contains('button', '😡Save Controversy😡');
cy.contains('button', '🤬Save as favorite controversy🤬');
});
});
});

describe('Card Component', () => {
beforeEach(() => {
cy.visit('http://localhost:3000/');
})

it('Renders snippet properly', () => {
cy.get('.card-content').should('be.visible');
cy.get('h2').should('contain', '');
cy.get('p').should('contain', '');
});

it('Handles show more/show less functionality', () => {

});
});

describe('UserView Component', () => {
beforeEach(() => {
cy.visit('http://localhost:3000/');
//login flow placeholder
})

it('Loads page content properly', () => {
cy.get('#profile').should('be.visible');
cy.get('#profile').click();
cy.visit('http://localhost:3000/Profile');
cy.get('.filter-buttons').should('have.descendants', 'button');
// cy.get('.article').should('be.visible');
});

it('Saves controversy properly', () => {

});
});
5 changes: 0 additions & 5 deletions cypress/fixtures/example.json

This file was deleted.

3 changes: 3 additions & 0 deletions cypress/fixtures/sampleRandomCards.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"need": "one sample result with multiple wiki cards"
}
18 changes: 18 additions & 0 deletions cypress/fixtures/wikipediaApiResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"query": {
"search": [
{
"title": "Example Title 1",
"snippet": "This is an example snippet for the first result."
},
{
"title": "Example Title 2",
"snippet": "Another example snippet for the second result."
},
{
"title": "Example Title 3",
"snippet": "Another example snippet for the third result."
}
]
}
}
55 changes: 29 additions & 26 deletions src/App/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import './App.css';
import Card from '../Card/Card.js';
import useSearchResults from '../hooks/useSearchResults.js';
import Profile from '../UserView/UserView.js';
import ErrorBoundary from '../Errors/ErrorBoundary.js';

function App() {
const { isLoading, isAuthenticated } = useAuth0();
Expand Down Expand Up @@ -44,38 +45,40 @@ function App() {
}

return (
<div className="App">
<header className="App-header">
<Link to="/" className="logo-link">
<h1 className='header-text'>H8rAid!</h1>
</Link>
{isAuthenticated && <button onClick={() => navigate("/profile")}>Profile</button>}
<NavBarButtons />
</header>
<Routes>
<Route path='/' element={<WikipediaSearch savedControversies={savedControversies} saveControversy={saveControversy} />} />
<Route path='/main' element={<Navigate to='/' />} />
<Route path='/profile' element={<Profile savedControversies={savedControversies} />} />
<Route path="article/:id" element={<WikipediaSearch />} />
</Routes>
{showRandomControversy && (
<ErrorBoundary>
<div className="App">
<header className="App-header">
<Link to="/" className="logo-link">
<h1 className='header-text'>H8rAid!</h1>
</Link>
{isAuthenticated && <button id='profile' onClick={() => navigate("/profile")}>Profile</button>}
<NavBarButtons />
</header>
<Routes>
<Route path='/' element={<WikipediaSearch savedControversies={savedControversies} saveControversy={saveControversy} />} />
<Route path='/main' element={<Navigate to='/' />} />
<Route path='/profile' element={<Profile savedControversies={savedControversies} />} />
<Route path="article/:id" element={<WikipediaSearch />} />
</Routes>
{showRandomControversy && (
<section className='random-view'>
<h2 className='random-headline'>Random Controversy</h2>
{controversies[0] && <h2 className='result-name'>{initialResults.title}</h2>}
<section className='results-list'>
{controversies.map((item, i) => (
<Card
key={i}
title={item.parse.title}
snippet={item.parse.text["*"]}
onSave={() => saveControversy(item.parse.text["*"])}
onSaveAsFavorite={() => saveControversy(item.parse.text["*"], true)}
/>
))}
{controversies.map((item, i) => (
<Card
key={i}
title={item.parse.title}
snippet={item.parse.text["*"]}
onSave={() => saveControversy(item.parse.text["*"])}
onSaveAsFavorite={() => saveControversy(item.parse.text["*"], true)}
/>
))}
</section>
</section>
)}
</div>
)}
</div>
</ErrorBoundary>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

);
};

Expand Down
7 changes: 6 additions & 1 deletion src/Card/Card.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState } from 'react';
import DOMPurify from 'dompurify';
import './Card.css';
import modifyRelativeUrls from '../hooks/modifyRelativeUrls';
import PropTypes from "prop-types";

const Card = ({ snippet, onSave, onSaveAsFavorite }) => {
const [showFullContent, setShowFullContent] = useState(false);
Expand All @@ -23,4 +24,8 @@ const Card = ({ snippet, onSave, onSaveAsFavorite }) => {
);
};

export default Card;
export default Card;

Card.propTypes = {
snippet: PropTypes.string.isRequired,
};
32 changes: 32 additions & 0 deletions src/Errors/ErrorBoundary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import ErrorPage from '../Errors/Errors.js';
import React, { Component } from 'react';

class ErrorBoundary extends Component {
constructor(error) {
super(error);
this.state = {
hasError: false,
errorMessage: '',
};
}

static getDerivedStateFromError(error) {
if (error.message === 'Network response was not ok') {
return { hasError: true, errorMessage: 'Error in SpecificComponent' };
}
if(error.message === 'Error fetching Wikipedia page:') {
return{ hasError: true, errorMessage: 'Cannot fetch Wikipedia page'}
}
return { hasError: true, errorMessage: error.toString() };
}

componentsDidCatch(error, errorInfo) {
console.error('ErrorBoundary caught an error:', error, errorInfo);
}

render() {
return this.state.hasError ? <ErrorPage errorMessage={"An Error has Occurred"} /> : this.props.children;
}
}

export default ErrorBoundary;
12 changes: 12 additions & 0 deletions src/Errors/Errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';

const errorMessage = ({ errorMessage }) => {
return (
<div className="error-page">
<h2>Error Encountered</h2>
<p>{errorMessage}</p>
</div>
);
};

export default errorMessage;
Empty file removed src/Main/Main.css
Empty file.
17 changes: 17 additions & 0 deletions src/UserView/UserView.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.profile {
flex-direction: column;
}

.filter-buttons, .profile {
display: flex;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

She cute

}

.filter-buttons {
justify-content: center;
}

@media screen and (max-width: 500px) {
.results-list {
flex-direction: column;
}
}
8 changes: 7 additions & 1 deletion src/UserView/UserView.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, { useState } from 'react';
import Card from '../Card/Card';
import PropTypes from "prop-types";
import './UserView.css';

const Profile = ({ savedControversies }) => {
const [showFavorites, setShowFavorites] = useState(false);
Expand Down Expand Up @@ -39,4 +41,8 @@ const Profile = ({ savedControversies }) => {
);
};

export default Profile;
export default Profile;

Profile.propTypes = {
savedControversies: PropTypes.array.isRequired,
}