Skip to content

Conversation

@cylcrow
Copy link

@cylcrow cylcrow commented Mar 8, 2021

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.development under the name of REACT_APP_YOUTUBE_KEY

Notes:

  • There are uncovered components for testing, sorry... I wanted to make my PR sooner, I'll cover them in a later revision.
  • I added a prototype for theming, is not finished, do not expect too much.

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:
image
image

Theming prototype:
image

Coverage:
image

cylcrow and others added 19 commits February 19, 2021 16:16
- Removed unnecessary files
- Added first tests
- Added first components
- Added dependencies for testing
- 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
Copy link

@jparciga jparciga left a 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).

Screen Shot 2021-03-17 at 13 51 26

Screen Shot 2021-03-17 at 13 51 40

Improvements

  1. Whenever you have time, it'll be great to apply media queries to have a responsive design

Screen Shot 2021-03-17 at 13 38 15

  1. For some reason the video player size is looking weird

Screen Shot 2021-03-17 at 13 37 35

  1. Sometimes when I click on a related video the following error appears:

Screen Shot 2021-03-17 at 13 39 01

Comment on lines +11 to +14
const contextValue = { search: jest.fn(), videos: youtubeMockedData.items };
const Wrap = contextWrapper(SearchContext, contextValue, Component);
const { container } = renderWithTheme(Wrap, theme);
return { container };

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 👌🏻

Comment on lines +14 to +27
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);
});

Choose a reason for hiding this comment

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

Nice test case!

Comment on lines +27 to +37
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();
});

Choose a reason for hiding this comment

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

Excellent 👏🏻

Comment on lines +7 to +17
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">

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

Suggested change
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">

Comment on lines +13 to +21
useEffect(() => {
/* global YT */
/* eslint no-undef: "error" */
window.player = new YT.Player('player', {
height: '50%',
width: '60%',
videoId,
});
});

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.

Suggested change
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]);

Comment on lines +1 to +11
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;

Choose a reason for hiding this comment

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

Nice util 👍🏻

Comment on lines +1 to +30
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;

Choose a reason for hiding this comment

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

Excellent!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants