-
Notifications
You must be signed in to change notification settings - Fork 52
Mini ch 3 #52
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
base: master
Are you sure you want to change the base?
Mini ch 3 #52
Conversation
- Removed unnecessary files - Added first tests - Added first components - Added dependencies for testing
…not yet created components
- First iteration for base components - Modified Header structure: created StyledSection component to a better arrangement of components
- Added card component - Added HomeVideos component - Added tests for new added components - Added/refactored styles for HomeVideo and Card component - Refactored tests for Card component
…ests refactor to comply just with react-testing-library
- Added roles to elements to improve accesibility - Refactored tests to find elements by role instead of their id
- ✨ Added theming prototype - ✅ Added first specs to test integration with theming
- Changed directory name 'Base' to 'ui', indicating that files contained here will be for general UI integration - Updated tests in Card component
- Refactored code - Moved mocked files to a new folder - Mocked API calls - Created tests for custom hooks
- Added test for YT playback frame - Added component for youtube playback
- Added SmallVideoCard component - Added RelatedVideoList component - Added styles for each new component - Added tests for each new component
- Removed unnecesary code from VideoPlayerContainer - Added tests to assert small captions video change - Improved code format
jparciga
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mini-Challenge 3 Feedback:
Acceptance Criteria
✅ Videos in the Home View are fetched from the YouTube API and displayed correctly.
✅ Users can search for YouTube videos using the search field on the header.
✅ A video can be played from the Video Details View after clicking on it.
✅ The video information and related videos list are displayed correctly on the Video Details View: Please add the title and description for the selected video on the Video Details View.
✅ When a user clicks on a related video the video player, information, and related videos list are updated.
Bonus Points
✅ Custom Hooks for API calls are implemented and tested correctly.
✅ Testing coverage is above 60%. (Please include a screenshot of the code coverage report in your PR description).
Improvements
- Whenever you have time, it'll be great to apply media queries to have a responsive design
- For some reason the video player size is looking weird
- Sometimes when I click on a related video the following error appears:
| const contextValue = { search: jest.fn(), videos: youtubeMockedData.items }; | ||
| const Wrap = contextWrapper(SearchContext, contextValue, Component); | ||
| const { container } = renderWithTheme(Wrap, theme); | ||
| return { container }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a nice way to mock the context value 👌🏻
| it('shows content complying with ARIA attributes', () => { | ||
| const video = youtubeMockedData.items[0]; | ||
| const { container } = build(<VideoCard video={video} />); | ||
|
|
||
| const img = getByRole(container, 'img'); | ||
| const figcaption = container.querySelector('figcaption'); | ||
|
|
||
| expect(img).toHaveAttribute('alt', video.snippet.title); | ||
| expect(img).toHaveAttribute('src', video.snippet.thumbnails.high.url); | ||
| expect(figcaption).toHaveTextContent(video.snippet.description); | ||
|
|
||
| expect(getByTitle(container, 'video-title')).toHaveTextContent(video.snippet.title); | ||
| expect(container).toHaveTextContent(video.snippet.description); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice test case!
| it('fires user search until presses enter', () => { | ||
| const EXPECTED_TEXT = 'Hello, '; | ||
| const TRIGGER_TYPING = 'there'; | ||
| const { searchInput, contextValue } = build(); | ||
| fireEvent.change(searchInput(), { target: { value: TRIGGER_TYPING } }); | ||
| fireEvent.change(searchInput(), { target: { value: EXPECTED_TEXT } }); | ||
| expect(searchInput().value).toBe(EXPECTED_TEXT); | ||
| expect(contextValue.search).not.toHaveBeenCalled(); | ||
| fireEvent.keyPress(searchInput(), { key: 'Enter', code: 13, charCode: 13 }); | ||
| expect(contextValue.search).toHaveBeenCalled(); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent 👏🏻
| const StyledLayoutWrapper = styled.div` | ||
| background: ${({ theme }) => theme.color.background}; | ||
| width: 100%; | ||
| height: 100%; | ||
| `; | ||
|
|
||
| const LayoutWrapper = ({ children }) => { | ||
| const { theme } = useContext(ThemeContext); | ||
|
|
||
| return ( | ||
| <StyledLayoutWrapper data-testid="layout-wrapper" theme={theme} role="application"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not necessary to get the current theme from the context so your styled-components can use it. Since you're wrapping your App using the ThemeProvider all your styled-components will automatically receive the current theme in their props. https://styled-components.com/docs/advanced
| const StyledLayoutWrapper = styled.div` | |
| background: ${({ theme }) => theme.color.background}; | |
| width: 100%; | |
| height: 100%; | |
| `; | |
| const LayoutWrapper = ({ children }) => { | |
| const { theme } = useContext(ThemeContext); | |
| return ( | |
| <StyledLayoutWrapper data-testid="layout-wrapper" theme={theme} role="application"> | |
| const StyledLayoutWrapper = styled.div` | |
| background: ${({ theme }) => theme.color.background}; | |
| width: 100%; | |
| height: 100%; | |
| `; | |
| const LayoutWrapper = ({ children }) => { | |
| return ( | |
| <StyledLayoutWrapper data-testid="layout-wrapper" role="application"> |
| useEffect(() => { | ||
| /* global YT */ | ||
| /* eslint no-undef: "error" */ | ||
| window.player = new YT.Player('player', { | ||
| height: '50%', | ||
| width: '60%', | ||
| videoId, | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be a good idea to add the videoId as a dependency for this useEffect so this code its executed only when the videoId changes.
| useEffect(() => { | |
| /* global YT */ | |
| /* eslint no-undef: "error" */ | |
| window.player = new YT.Player('player', { | |
| height: '50%', | |
| width: '60%', | |
| videoId, | |
| }); | |
| }); | |
| useEffect(() => { | |
| /* global YT */ | |
| /* eslint no-undef: "error" */ | |
| window.player = new YT.Player('player', { | |
| height: '50%', | |
| width: '60%', | |
| videoId, | |
| }); | |
| }, [videoId]); |
| import React from 'react'; | ||
| import { render } from '@testing-library/react'; | ||
| import { ThemeProvider } from 'styled-components'; | ||
| import { lightTheme } from '../../../providers/themes'; | ||
|
|
||
| const renderWithTheme = (Component, theme = lightTheme) => { | ||
| const contextValue = { theme, switchTheme: jest.fn() }; | ||
| return render(<ThemeProvider theme={contextValue}>{Component}</ThemeProvider>); | ||
| }; | ||
|
|
||
| export default renderWithTheme; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice util 👍🏻
| import youtubeMockedData from './youtubeMockedData'; | ||
|
|
||
| const errorObject = { | ||
| error: { | ||
| code: 403, | ||
| message: '', | ||
| errors: [ | ||
| { | ||
| message: '', | ||
| domain: '', | ||
| reason: '', | ||
| }, | ||
| ], | ||
| }, | ||
| }; | ||
| const mockedGoogleAPIObject = (shouldResolveToSuccess = true) => ({ | ||
| load: jest.fn(), | ||
| client: { | ||
| request: jest.fn().mockReturnValue( | ||
| new Promise((res, rej) => { | ||
| if (shouldResolveToSuccess) { | ||
| res({ result: youtubeMockedData }); | ||
| } | ||
| rej(errorObject); | ||
| }) | ||
| ), | ||
| }, | ||
| }); | ||
|
|
||
| export default mockedGoogleAPIObject; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent!





What this PR do?
Performs tasks specified for Mini challenge 3
Any background context you want to provide?
Add your google API Key in a file called
.env.developmentunder the name ofREACT_APP_YOUTUBE_KEYNotes:
Where should the reviewer start?
Well... I'm not sure, it was a really big refactor and new features.
How should this be manually tested?
running tests
Screenshots
UI:


Theming prototype:

Coverage:
