Skip to content
Open
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
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error",
"react/jsx-filename-extension": "error",
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
"react-hooks/exhaustive-deps": "warn",
"import/no-unresolved": ["off", { "ignore": [".css$"] }],
"import/prefer-default-export": "off",
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
# Wizeline Academy - 2021 React Bootcamp

Please refere to the following [GIST](https://gist.github.com/erickwize/d7311bfc972080c162c43cbb7dc80587) for further instructions

Code sandbox: https://codesandbox.io/s/core-concepts-and-styling-evtvz

# Mini-Challenge 2: Intro to Testing
## Answer the following questions first

1. Using `create-react-app`, what do we need to set up for testing?
A: `create-react-app` comes with `Jest` and `react-testing-library` by default, but in order for `Jest` to locate them they need to have one of the following conventions:
- Files with `.js` suffix in` __tests__` folders, files with `.test.js` or `.spec.js`.
Jest can also be paired with other testing libraries/utilities like Enzyme but those must me installed using `yarn add` or `npm install`.

2. What components are worth to test in your development?
A: In my opinion it would be components that have some kind of interaction that can be mimicked and function used.

3. Can you apply TDD once you already created components?
A: Yes, the concept of TDD is to test first (create failing test) then make those test pass and finally refactor, so when adding new change to that component one can start using TDD, providing little by little more more of the TDD advantages.
_TDD is a cycle that is best done in chunks._
38,900 changes: 38,900 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

49 changes: 32 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,32 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@babel/preset-env": "^7.13.10",
"@babel/preset-react": "^7.12.13",
"@testing-library/jest-dom": "^5.11.10",
"@testing-library/react": "^10.4.9",
"@testing-library/user-event": "^12.1.3",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"jest": "^26.6.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.3"
"react-scripts": "^4.0.3",
"react-test-renderer": "^17.0.1",
"styled-components": "^5.2.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"test": "jest",
"test:coverage": "jest --coverage --watchAll=false",
"coverage": "react-scripts test --env=jsdom --coverage --watchAll",
"eject": "react-scripts eject",
"lint": "eslint ./src --ext .js,.jsx",
"lint:fix": "eslint ./src --ext .js,.jsx --fix"
},
"devDependencies": {
"@testing-library/react-hooks": "^5.1.1",
"eslint-config-airbnb": "^18.2.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-eslint-comments": "^3.2.0",
Expand All @@ -29,8 +37,6 @@
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.20.6",
"eslint-plugin-react-hooks": "^4.1.0",
"husky": "^4.2.5",
"lint-staged": "^10.2.13",
"prettier": "^2.1.1",
"pretty-quick": "^3.0.0"
},
Expand All @@ -46,16 +52,25 @@
"last 1 safari version"
]
},
"lint-staged": {
"*.{js, jsx, css, json}": [
"yarn run lint:fix",
"pretty-quick --staged",
"git add"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
"jest": {
"collectCoverageFrom": [
"src/**/**.*.{js,jsx,ts,tsx}",
"src/**/*.{js,jsx,ts,tsx}",
"!<rootDir>/node_modules/",
"!<rootDir>/path/to/dir/"
],
"coveragePathIgnorePatterns": [
"/node_modules/",
"/src/serviceWorker.js",
"/src/index.js"
],
"coverageThreshold": {
"global": {
"statements": 70,
"branches": 70,
"lines": 70,
"functions": 70
}
}
}
}
97 changes: 97 additions & 0 deletions src/__tests__/_App.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from 'react';
import { screen, cleanup, render, fireEvent } from '@testing-library/react';
import { renderHook, act } from '@testing-library/react-hooks';
import AppLayout from '../components/App';
import NotFound from '../pages/NotFound';
import { useVideoInfo, useVideList } from '../providers/GlobalContext';
import VideoMock from '../utils/mock/youtube-videos-mock.json';

afterEach(() => {
cleanup();
});

const MockVideoInfo = VideoMock.items[1].snippet;

it('Should render NotFound', () => {
const notFoundPage = render(<NotFound />);
expect(notFoundPage).toMatchSnapshot();
// const notfound = screen.getByTestId('not-found');
// expect(notfound).toBeInTheDocument();
});

it('Should render App', () => {
act(() => {
const app = render(<AppLayout />);
expect(app).toMatchSnapshot();
});
const homePage = screen.getByTestId('yt-videocards');
const headerMenu = screen.getByTestId('yt-header');
expect(homePage).toBeInTheDocument();
expect(headerMenu).toBeInTheDocument();
});

it('Should render App Header', () => {
act(() => {
const app = render(<AppLayout />);
});
const headerMenu = screen.getByTestId('yt-header');
expect(headerMenu).toBeInTheDocument();
const SearchInput = screen.getByPlaceholderText('Search...');
expect(SearchInput).toBeInTheDocument();
SearchInput.focus();
fireEvent.change(SearchInput, { target: { value: 'rise against' } });
expect(SearchInput.value).toBe('rise against');
fireEvent.keyDown(SearchInput, { key: 'Enter', code: 'Enter' });
});

test('Test useVideoInfo Hook', () => {
const { result } = renderHook(() => useVideoInfo());
expect(result.current.video).toEqual({});
expect(typeof result.current.updateVideoInfo).toBe('function');

act(() => {
result.current.updateVideoInfo(MockVideoInfo);
});
expect(result.current.video).toEqual({
channelId: 'UCPGzT4wecuWM0BH9mPiulXg',
channelTitle: 'Wizeline',
description:
'Follow Hector Padilla, Wizeline Director of Engineering, for a lively tour of our office. In 2018, Wizeline opened its stunning new office in Guadalajara, Jalisco, ...',
liveBroadcastContent: 'none',
publishTime: '2019-09-30T23:54:32Z',
publishedAt: '2019-09-30T23:54:32Z',
thumbnails: {
default: {
height: 90,
url: 'https://i.ytimg.com/vi/nmXMgqjQzls/default.jpg',
width: 120,
},
high: {
height: 360,
url: 'https://i.ytimg.com/vi/nmXMgqjQzls/hqdefault.jpg',
width: 480,
},
medium: {
height: 180,
url: 'https://i.ytimg.com/vi/nmXMgqjQzls/mqdefault.jpg',
width: 320,
},
},
title: 'Video Tour | Welcome to Wizeline Guadalajara',
});
});

test('Test useVideList Hook', () => {
const { result } = renderHook(() => useVideList());
expect(result.current.videoList).toEqual([]);
expect(typeof result.current.updateVideoList).toBe('function');
act(() => {
result.current.updateVideoList([
VideoMock.items[0],
VideoMock.items[1],
VideoMock.items[3],
]);
});
const videoList = [VideoMock.items[0], VideoMock.items[1], VideoMock.items[3]];
expect(result.current.videoList).toEqual(videoList);
});
62 changes: 62 additions & 0 deletions src/__tests__/_Header.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from 'react';
import { screen, cleanup, render, fireEvent } from '@testing-library/react';
import { renderHook } from '@testing-library/react-hooks';
import HeaderMenu from '../components/Header';

afterEach(() => {
cleanup();
});

const doSearch = jest.fn();

it('Should render Header', () => {
const header = render(<HeaderMenu />);
const headerComponent = screen.getByTestId('yt-header');
expect(headerComponent).toBeInTheDocument();
expect(headerComponent).toContainHTML('Dark mode');
expect(headerComponent).toContainHTML('input');
expect(header).toMatchSnapshot();
});

it('Toggle Header Dark mode', () => {
render(<HeaderMenu />);

const switchInput = screen.getByLabelText('Dark mode', { type: 'checkbox' });
expect(switchInput).toBeInTheDocument();
fireEvent(
switchInput,
new MouseEvent('click', {
checked: true,
})
);
expect(switchInput.checked).toBe(true);
fireEvent(
switchInput,
new MouseEvent('click', {
checked: false,
})
);
expect(switchInput.checked).toBe(false);
});

it('Search value change', () => {
render(<HeaderMenu doSearch={doSearch} />);

const SearchInput = screen.getByPlaceholderText('Search...');
expect(SearchInput).toBeInTheDocument();
SearchInput.focus();
fireEvent.change(SearchInput, { target: { value: 'wizeline' } });
expect(SearchInput.value).toBe('wizeline');

fireEvent.keyDown(SearchInput, { key: 'Enter', code: 'Enter' });
setTimeout(() => {
expect(doSearch).toHaveBeenCalledWith('wizeline');
}, 10);

fireEvent.blur(SearchInput, { key: 'Enter', code: 'Enter' });
setTimeout(() => {
act(() => {
expect(doSearch).toHaveBeenCalledWith('wizeline');
});
}, 10);
});
37 changes: 37 additions & 0 deletions src/__tests__/_Home.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { screen, cleanup, render, fireEvent } from '@testing-library/react';
import HomePage from '../pages/Home';
import VideoMock from '../utils/mock/youtube-videos-mock.json';

afterEach(() => {
cleanup();
});

const selectCard = jest.fn();
const cleanVideoData = {
channel: 'Wizeline',
channelId: 'UCPGzT4wecuWM0BH9mPiulXg',
description:
'Engineering a better tomorrow. Wizeline is a global software development company that helps its clients solve their biggest challenges with design and ...',
link: 'https://www.youtube.com/embed/7PtYNO6g7eI?autoplay=1&color=white',
thumbnail: 'https://i.ytimg.com/vi/7PtYNO6g7eI/mqdefault.jpg',
title: 'We Are Wizeline',
uploadDate: 'April 12, 2019',
videoId: '7PtYNO6g7eI',
};

it('Map through videoData', () => {
const homePage = render(<HomePage videoList={VideoMock.items} selectCard={selectCard} />);
expect(homePage).toMatchSnapshot();
const videoCards = screen.getAllByTestId('yt-videocard');
expect(videoCards.length).toBe(25);
});

it('Select video card', () => {
render(<HomePage videoList={VideoMock.items} selectCard={selectCard} />);
const videoCards = screen.getAllByTestId('yt-videocard');
expect(videoCards.length).toBe(25);

fireEvent.click(videoCards[4]);
expect(selectCard).toHaveBeenCalledWith(cleanVideoData);
});
50 changes: 50 additions & 0 deletions src/__tests__/_VideoCard.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import { screen, cleanup, render, fireEvent } from '@testing-library/react';
import VideoCard from '../components/VideoCard';
import VideoMock from '../utils/mock/youtube-videos-mock.json';
import { getReadableDate, random } from '../utils/fns';

afterEach(() => {
cleanup();
});

const MockVideoInfo = VideoMock.items[1].snippet;
MockVideoInfo.uploadDate = getReadableDate(VideoMock.items[1].snippet.publishedAt);
MockVideoInfo.thumbnail = VideoMock.items[1].snippet.thumbnails.medium.url;
MockVideoInfo.channel = VideoMock.items[1].snippet.channelTitle;

it('Test Utils: getReadableDate', () => {
expect(MockVideoInfo.uploadDate).toBe('September 30, 2019');
});

it('Test Utils: random', () => {
expect(typeof random(10)).toBe('number');
});

it('Should render VideoCard Info', () => {
const videoCard = render(<VideoCard videoData={MockVideoInfo} />);
expect(videoCard).toMatchSnapshot();
const videoCardComponent = screen.getByTestId('yt-videocard');
expect(videoCardComponent).toBeInTheDocument();
expect(videoCardComponent).toHaveTextContent(
'Follow Hector Padilla, Wizeline Director of Engineering, for a lively tour of our office. In 2018, Wizeline opened its stunning new office in Guadalajara, Jalisco, ...Wizeline | September 30, 2019Video Tour | Welcome to Wizeline G...'
);
});

it('Handle videoCard click event', () => {
const cardClick = jest.fn();
render(<VideoCard videoData={MockVideoInfo} cardClick={cardClick} />);
const videoCardComponent = screen.getByTestId('yt-videocard');
expect(videoCardComponent).toBeInTheDocument();
fireEvent.click(videoCardComponent);
expect(cardClick).toHaveBeenCalledWith(MockVideoInfo);
});

it('Handle videoCard mouse event', () => {
const cardClick = jest.fn();
render(<VideoCard videoData={MockVideoInfo} cardClick={cardClick} />);
const videoCardComponent = screen.getByTestId('yt-videocard');
fireEvent.mouseEnter(videoCardComponent);
const videoCardComponentDes = screen.getByTestId('yt-videocard-description');
expect(videoCardComponentDes).toBeInTheDocument();
});
Loading