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

Heatmap #8

Merged
merged 63 commits into from
Oct 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
444acc7
header task: first commit
bahobab Sep 25, 2020
d7e6cf6
header task: fixed missing default 'javascript'
bahobab Sep 25, 2020
34c1fd3
header task: fixed default link: '/search/javascript'
bahobab Sep 25, 2020
c6faa67
header after first review
bahobab Sep 27, 2020
f46dc2d
header fixing test
bahobab Sep 27, 2020
ae0229e
implemented unit test
bahobab Sep 27, 2020
84feae2
header: before rebase after app-skeleton-review
bahobab Sep 27, 2020
e74b390
resolved conflicts. Fixed unit tests
bahobab Sep 28, 2020
60db4f7
footer: initial commit
bahobab Sep 28, 2020
a462336
implemented Footer.js and Footer.style.js
bahobab Sep 28, 2020
b7c4094
footer: completed unit tests
bahobab Sep 28, 2020
0b12d62
hero-section: initial commit with with fixes from previous PR
bahobab Sep 28, 2020
0817a00
Merge branch 'master' into hero-section
bahobab Sep 28, 2020
e99e5dc
hero-section: completed unit tests
bahobab Sep 29, 2020
2c55849
Merge branch 'hero-section' of https://github.com/ooloo-io/reddit-tim…
bahobab Sep 29, 2020
88238ac
hero-section: fixed linting issues in unit tests
bahobab Sep 29, 2020
0e72262
hero-section: fixed Apps to have all unit tests pass
bahobab Sep 29, 2020
035041f
hero-section: added missing test descriptions in footer.js
bahobab Sep 29, 2020
880d020
hero-section: refactor components and file structure after review
bahobab Sep 29, 2020
2c629e2
info-section: initial commit
bahobab Sep 29, 2020
97ed18d
Merge branch 'master' into info-section
bahobab Sep 30, 2020
3c568ed
info-section: implemented About and How it works sections
bahobab Sep 30, 2020
c4f0d4d
Merge branch 'info-section' of https://github.com/ooloo-io/reddit-tim…
bahobab Sep 30, 2020
bb4486d
info-section: fix link to https://ooloo.io/employers
bahobab Sep 30, 2020
13bdf67
info-section: implemented react-router-hash-link
bahobab Sep 30, 2020
b4a1e4e
info-section: fixed ooloo.io link
bahobab Sep 30, 2020
ee27a75
info-section: implemented unit tests
bahobab Sep 30, 2020
bf59a70
info-section: fixed linting errors
bahobab Sep 30, 2020
d71c19d
info-section: fixed linting errors
bahobab Sep 30, 2020
3ec116c
info-section: fix unit test using this: https://github.com/testing-li…
bahobab Sep 30, 2020
242aefa
info-section: commit after review
bahobab Oct 1, 2020
2780c04
subreddit-form: initial commit. Setup folder structure
bahobab Oct 1, 2020
5b11f42
Merge branch 'master' into subreddit-form
bahobab Oct 1, 2020
f2c2e2d
subreddit-form: implement tests
bahobab Oct 1, 2020
4bb12dc
Merge branch 'subreddit-form' of https://github.com/ooloo-io/reddit-t…
bahobab Oct 1, 2020
c112f47
subreddit-form: fix lint error in Header.js
bahobab Oct 1, 2020
04cf9d2
subreddit-form: completed unit and e2e tests
bahobab Oct 2, 2020
0de4627
subreddit-form: fixes and cleanup after review
bahobab Oct 2, 2020
56554d7
load-the-data: initial commit: added LoadTheData.js
bahobab Oct 2, 2020
56d31c6
load-the-data: fetching data implemented. But unit test and e2e test …
bahobab Oct 3, 2020
7326c4f
Merge branch 'master' into load-the-data
bahobab Oct 3, 2020
1af6086
load-the-data: troubleshooting tests
bahobab Oct 3, 2020
5a60619
Merge branch 'load-the-data' of https://github.com/ooloo-io/reddit-ti…
bahobab Oct 3, 2020
7f50064
load-the-data: continue troubleshooting tests
bahobab Oct 3, 2020
9179df7
load-the-data: fix linting error
bahobab Oct 3, 2020
02223cf
load-the-data: fix the code to fetch top 500 posts
bahobab Oct 3, 2020
1bd7a8e
load-the-data: troubleshooting unit test - 'invalid json response bod…
bahobab Oct 4, 2020
4361e96
load-the-data: integration test passing
bahobab Oct 4, 2020
e061c4a
load-the-data: refactor code after review. still 1 test to fix in Sea…
bahobab Oct 4, 2020
baaccb4
laod-the-data: all tests pass
bahobab Oct 5, 2020
49ccf49
heatmap: first commit: setup heatmap table
bahobab Oct 6, 2020
dd0d221
Merge branch 'master' into heatmap
bahobab Oct 6, 2020
623001e
heatmap: implemented heatmap architecture
bahobab Oct 6, 2020
b552fcb
Merge branch 'heatmap' of https://github.com/ooloo-io/reddit-timer-ba…
bahobab Oct 6, 2020
cf83cc2
heatmap: implemented user timezone
bahobab Oct 6, 2020
2ccfbe7
heatmap: implemented hover, highlit and timezone
bahobab Oct 7, 2020
1b15f5f
heatmap: completed implementation - start testing
bahobab Oct 7, 2020
8040245
heatmap: refactor component structure - set test skeleton
bahobab Oct 7, 2020
6f72e72
heatmap: complete integration tests
bahobab Oct 8, 2020
33c282b
heatmap: complete. fix user timezone in tests
bahobab Oct 8, 2020
62c79e4
heatmap: refactor code after review
bahobab Oct 9, 2020
ae2d7de
heatmap: fix all test errors. ready to merge pr
bahobab Oct 10, 2020
278ff8e
heatmap: fix last test errors. ready to merge pr
bahobab Oct 10, 2020
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
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
"@testing-library/react": "^10.4.5",
"@testing-library/react-hooks": "^3.4.2",
"@testing-library/user-event": "^12.0.11",
"eslint-plugin-styled-components-a11y": "^0.0.16",
"eslint-plugin-styled-components-a11y": "^0.0.17",
"history": "^5.0.0",
"jest-axe": "^4.0.0",
"jest-fetch-mock": "^3.0.3",
"jest-styled-components": "^7.0.3",
"msw": "^0.21.2",
"prop-types": "^15.7.2",
"react": "^16.13.0",
Expand All @@ -23,7 +25,7 @@
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jest-environment-jsdom-sixteen",
"test": "TZ=Europe/Berlin react-scripts test --env=jest-environment-jsdom-sixteen",
"eject": "react-scripts eject",
"lint": "eslint .",
"format": "eslint --fix .",
Expand Down
55 changes: 47 additions & 8 deletions src/__tests__/SearchPage.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import React from 'react';
import { MemoryRouter, Route } from 'react-router-dom';
import { render, screen, within } from '@testing-library/react';
import {
render, screen, within, waitFor,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom/extend-expect';
import { axe } from 'jest-axe';
import 'jest-styled-components';

import App from '../app';
import { defaultSubReddit } from '../config';

const setup = (initialPath = '/') => {
let history;

render(
const view = render(
<MemoryRouter initialEntries={[initialPath]}>
<App />
<Route
Expand All @@ -22,19 +26,46 @@ const setup = (initialPath = '/') => {
/>
</MemoryRouter>,
);
return { history };
return { ...view, history };
};

describe('search page', () => {
describe('heatmap', () => {
it('loads top post for subreddit in URL', async () => {
setup('/search/reactjs');

screen.getByText('loading-spinner.svg');

// this is just a placeholder assertion that tests if the result
// was rendered correctly
expect(await screen.findByText('500')).toBeInTheDocument();
expect(screen.queryByText('loading-spinner.svg')).not.toBeInTheDocument();
// expect(await screen.findByText('500')).toBeInTheDocument();

expect(await screen.findByTestId('heatmap')).toBeInTheDocument();
await waitFor(() => expect(screen.queryByText('loading-spinner.svg')).not.toBeInTheDocument());

const heatmap = screen.getByTestId('heatmap');
const cells = await within(heatmap).findAllByRole('button');
expect(cells.length).toEqual(7 * 24);

const numberOfPostsPerCell = cells.map((cell) => cell.innerHTML);
expect(numberOfPostsPerCell).toMatchSnapshot();

const timezone = screen.getByText('All times are shown in your timezone:');
expect(within(timezone).getByText('Europe/Berlin')).toBeInTheDocument();
});

it('highlights cell on click', async () => {
setup('/search/reactjs');

const heatmap = await screen.findByTestId('heatmap');
const cells = await within(heatmap).findAllByRole('button');

const cellToClick = cells[1];
// expect(cellToClick).toHaveStyle('border: none');
expect(cellToClick).toHaveStyleRule('border: none');

userEvent.click(cellToClick);
// expect(cellToClick).toHaveStyle('border: 1px solid #1e2537');
expect(cellToClick).toHaveStyleRule('border: 1px solid #1e2537');
});

test('renders error message', async () => {
Expand All @@ -45,7 +76,7 @@ describe('search page', () => {
});

describe('subreddit form', () => {
it('updates the URL when submitting the form', () => {
it('updates the URL when submitting the form', async () => {
const { history } = setup('/search/python');
const searchInput = screen.getByLabelText('r /');

Expand All @@ -62,7 +93,7 @@ describe('subreddit form', () => {
expect(history.location.pathname).toEqual('/search/Gatsbyjs');
});

it('input value changes to default subredit when seach link in header is clicked', () => {
it('input value changes to default subredit when seach link in header is clicked', async () => {
setup('/search/reactjs');
const searchInput = screen.getByRole('textbox');
const header = screen.getByRole('banner');
Expand All @@ -71,5 +102,13 @@ describe('subreddit form', () => {
userEvent.click(searchLink);

expect(searchInput.value).toBe(defaultSubReddit);
await waitFor(() => expect(screen.queryByText('loading-spinner.svg')).not.toBeInTheDocument());
});

it('no accessibility violation', async () => {
const { container } = setup('/search/reactjs');

expect(await screen.findByTestId('heatmap')).toBeInTheDocument();
expect(await axe(container)).toHaveNoViolations();
});
});
115 changes: 115 additions & 0 deletions src/__tests__/_Heatmap.js_
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import React from 'react';
import { MemoryRouter, Route } from 'react-router-dom';
import {
render, screen, waitForElementToBeRemoved, within,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom/extend-expect';
import 'jest-styled-components';

import {
cellBackgroundColorMap, mapWeekday, postsTimeSlots, getUserTimeZone,
} from '../config';

import App from '../app';

const weekdays = Object.values(mapWeekday);
const cellBackgroundColor = Object.values(cellBackgroundColorMap);

const setup = (initialPath = '/') => {
let history;

render(
<MemoryRouter initialEntries={[initialPath]}>
<App />
<Route
path="*"
render={(props) => {
history = props.history;
return null;
}}
/>
</MemoryRouter>,
);
return { history };
};

describe('heatmap', () => {
it.each(weekdays)(
'weekdays are shown from Sunday to Saturday', async (weekday) => {
setup('/search/less-than-500-posts');
// find weekday container element tr.weekday
// assert that it contains Sunday, Monday, Tuesday, Wednesday
// Thursday, Friday, Saturday
const spinner = screen.getByText('loading-spinner.svg');

await waitForElementToBeRemoved(spinner);

screen.getByRole('table');
// weekday
screen.getByRole('cell', { name: weekday });
},
);

it.each(postsTimeSlots)(
'hours are shown from 12:00am to 10:00pm', async (postsTimeSlot) => {
setup('/search/reactjs');
// find hours container element th.timeline
// assert that it contains 12:00am, 2:00am..
const spinner = screen.getByText('loading-spinner.svg');

await waitForElementToBeRemoved(spinner);

screen.getByRole('table');

const timeSlots = screen.getAllByRole('columnheader');
// screen.debug(timeSlot);
within(timeSlots[1]).getByText(postsTimeSlot);
},
);

it('each combination of weekday and hour is represented by a square box', async () => {
setup('/search/less-than-500-posts');

const spinner = screen.getByText('loading-spinner.svg');
await waitForElementToBeRemoved(spinner);
screen.getByRole('table');

const cells = await document.querySelector('td.cell');
// select cells td.cell
const el = within(cells).getByText(cells.textContent);
const numPosts = Number(el.textContent);

expect(el).toHaveStyle({ border: 'unset', backgroundColor: '#a0ce93' });
// assert that background-color correspond to numeric innerText value
expect(el).toHaveStyle({ backgroundColor: `${cellBackgroundColor[numPosts]}` });

// assert that each has width === height
expect(el).toHaveStyleRule('width', '40px');
expect(el).toHaveStyleRule('height', '40px');

// assert that innerText.value is a number
// expect(el).toHaveValue(numPosts);

// assert that element is highlighted when hovered
userEvent.hover(el);
expect(el).toHaveStyle({ border: '1px solid red' });
userEvent.unhover(el);
expect(el).toHaveStyle({ border: 'unset' });

// assert that element is highlighted when clicked
userEvent.click(el);
expect(el).toHaveStyle({ border: '1px solid red' });
});

it("the user' timezone is shown below the heatmap", async () => {
setup('/search/less-than-500-posts');
// select div.timezone
// assert that the element contains "America/Chicago - Central Saving Time"
const spinner = screen.getByText('loading-spinner.svg');

await waitForElementToBeRemoved(spinner);
screen.getByRole('table');
screen.getByText(getUserTimeZone());
});
});
Loading