Skip to content

Commit

Permalink
Merge pull request #24 from aneurysmjs/connect-store-hook
Browse files Browse the repository at this point in the history
Connect store hook
  • Loading branch information
aneurysmjs authored Aug 28, 2019
2 parents 4b20968 + 7497747 commit 093029f
Show file tree
Hide file tree
Showing 51 changed files with 866 additions and 281 deletions.
Binary file modified .DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
"purgecss-webpack-plugin": "1.5.0",
"react-dev-utils": "9.0.3",
"react-test-renderer": "16.9.0",
"redux-mock-store": "1.5.3",
"rimraf": "3.0.0",
"run-sequence": "2.2.1",
"sass-loader": "7.2.0",
Expand Down
4 changes: 2 additions & 2 deletions plopfile.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const components = './src/app/components';

const isFunctional = componentType => componentType === 'functional';
const isFunctional = (componentType) => componentType === 'functional';

module.exports = function(plop) {
module.exports = function plopFn(plop) {
plop.setGenerator('React Component', {
description: 'Create a new React component',
prompts: [
Expand Down
9 changes: 9 additions & 0 deletions src/app/__mocks__/axios.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @link https://medium.com/@kilgarenone/use-jest-to-test-redux-async-action-creator-with-axios-in-a-create-react-app-app-d9c9b52eba5e
*/
const axiosMock = jest.genMockFromModule('axios');

// this is the key to fix the axios.create() undefined error!
axiosMock.create = jest.fn(() => axiosMock);

export default axiosMock;
77 changes: 29 additions & 48 deletions src/app/components/core/Footer/Footer.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,45 @@
// @flow strict
import React, { Component } from 'react';
import React from 'react';
// $FlowIgnore
import { connect } from 'react-redux';
import { useSelector } from 'react-redux';

import { footerData } from '@/store/actions';
import { getFooter } from '@/store/reducers/footer';
import type { FooterType } from '@/store/types/FooterType';

import Icon from '@/components/base/Icon/Icon';

import './Footer.scss';

type PropsType = {
footer: FooterType
};

class Footer extends Component<PropsType> {
render() {
const {
footer: {
social,
},
} = this.props;

return (
<footer className="footer">
<div className="container">
<div className="footer__top">
<div className="row">
<div className="col">
<div data-testid="social">
{social && social.map((s) => (
<Icon
key={s.id}
path={`social/${s.icon}`}
/>
))}
</div>
const Footer = () => {
const { social }: FooterType = useSelector(getFooter);

return (
<footer className="footer">
<div className="container">
<div className="footer__top">
<div className="row">
<div className="col">
<div data-testid="social">
{social && social.map((s) => (
<Icon
key={s.id}
path={`social/${s.icon}`}
/>
))}
</div>
</div>
</div>
</div>
<div className="footer__bottom">
<div className="footer__copyright">
<span data-testid="copyright">Copyright © {new Date().getFullYear()}. All Rights Reserved</span>
</div>
</div>
<div className="footer__bottom">
<div className="footer__copyright">
<span data-testid="copyright">
Copyright © {new Date().getFullYear()}. All Rights Reserved
</span>
</div>
</footer>
);
}
}

const mapStateToProps = (state) => ({
footer: state.footer,
});

const mapDispatchToProps = {
footerData,
</div>
</footer>
);
};

export default connect(
mapStateToProps,
mapDispatchToProps,
)(Footer);
export default Footer;
1 change: 0 additions & 1 deletion src/app/components/core/Footer/Footer.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @flow strict
import React from 'react';
// $FlowFixMe
import { cleanup } from '@testing-library/react';
Expand Down
54 changes: 8 additions & 46 deletions src/app/components/core/Header/Header.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,15 @@
// @flow strict
import React, { useState } from 'react';
import React from 'react';

import Icon from '@/components/base/Icon/Icon';
import Navigation from '@/components/core/Navigation/Navigation';
import { useLazy } from '@/hooks/useLazy';
import { UserMenu } from '@/components/core/UserMenu';

import './Header.scss';

const Header = () => {
const [open, setOpen] = useState(false);

const handleOpen = () => setOpen(!open);

const Sidebar = useLazy(
() => import(/* webpackChunkName: "Sidebar" */'@/components/shared/Sidebar/Sidebar'),
open,
);

return (
<div className="header">
{Sidebar
? (
<Sidebar
title="Cart"
side="right"
isOpen={open}
onClose={handleOpen}
>
<p className="lead">
You have nothing, let&apos;s shop!
</p>
</Sidebar>)
: null}
<Navigation />
<div className="header__user-menu">
<span
tabIndex="-1"
role="button"
onKeyPress={() => {}}
onClick={handleOpen}
>
<Icon
size="20"
path="icons/cart"
/>
</span>
</div>
</div>
);
};

const Header = () => (
<div className="header">
<Navigation />
<UserMenu />
</div>
);
export default Header;
6 changes: 0 additions & 6 deletions src/app/components/core/Header/Header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,4 @@
background: var(--white);
border-bottom: 1px solid #6c6c6c1f;
width: 100%;

@include element(user-menu) {
align-items: center;
display: flex;
padding: 0 px-to-rem(16);
}
}
7 changes: 3 additions & 4 deletions src/app/components/core/Header/Header.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// @flow strict
import React from 'react';
import { act } from 'react-dom/test-utils';
import { BrowserRouter as Router } from 'react-router-dom';
// $FlowFixMe
import { render } from '@testing-library/react';

import renderWithRedux from '@/utils/testing/renderWithRedux';

import Header from './Header';

Expand All @@ -12,7 +11,7 @@ describe('Header', () => {
let testRenderer = {};

await act(async () => {
testRenderer = render(
testRenderer = renderWithRedux(
<Router>
<Header />
</Router>,
Expand Down
59 changes: 59 additions & 0 deletions src/app/components/core/UserMenu/UserMenu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// @flow strict
import React, { useState } from 'react';
// $FlowFixMe
import { useSelector } from 'react-redux';

import Icon from '@/components/base/Icon/Icon';
import { useLazy } from '@/hooks/useLazy';
import { getCart } from '@/store/reducers/cart';

import type { CartType } from '@/store/types/CartType';

import './UserMenu.scss';

const UserMenu = () => {
const [open, setOpen] = useState(false);
const cart: CartType = useSelector(getCart);

const handleOpen = () => setOpen(!open);

const Sidebar = useLazy(
() => import(/* webpackChunkName: "Sidebar" */'@/components/shared/Sidebar/Sidebar'),
open,
);

return (
<div className="user-menu">
{Sidebar
? (
<Sidebar
title="Cart"
side="right"
isOpen={open}
onClose={handleOpen}
>
<p className="lead">
You have nothing, let&apos;s shop!
</p>
</Sidebar>)
: null}
<span
className="user-menu__cart-icon"
tabIndex="-1"
role="button"
onKeyPress={() => {}}
onClick={handleOpen}
>
<Icon
size="20"
path="icons/cart"
/>
<span className="user-menu__cart-quantity">
({ cart.quantity })
</span>
</span>
</div>
);
};

export default UserMenu;
18 changes: 18 additions & 0 deletions src/app/components/core/UserMenu/UserMenu.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@import '~styles/functions/px-to-rem';
@import '~styles/mixins';
@import '~styles/variables';

.user-menu {
align-items: center;
display: flex;
padding: 0 px-to-rem(16);

@include element(cart-icon) {
align-items: center;
display: flex;
}

@include element(cart-quantity) {
margin-left: px-to-rem(5);
}
}
53 changes: 53 additions & 0 deletions src/app/components/core/UserMenu/UserMenu.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
// $FlowFixMe
import { fireEvent } from '@testing-library/react';

import renderWithRedux from '@/utils/testing/renderWithRedux';

import UserMenu from './UserMenu';

describe('UserMenu', () => {
it('should toggle <Sidebar /> when clicking icon', async () => {
let testRenderer = {};

await act(async () => {
testRenderer = renderWithRedux(<UserMenu />);
});

const { queryByRole, queryByTestId } = testRenderer;
const button = queryByRole('button');
const sidebar = queryByTestId('sidebar');

expect(sidebar).toBe(null);

await act(async () => {
fireEvent.click(button);
});

const sidebarOpened = queryByTestId('sidebar');

expect(sidebarOpened).not.toBe(null);

await act(async () => {
fireEvent.click(button);
});

const sidebarClosed = queryByTestId('sidebar');

expect(sidebarClosed).toBe(null);
});

it('should display cart\'s quantity', async () => {
let testRenderer = {};

await act(async () => {
testRenderer = renderWithRedux(<UserMenu />);
});

const { queryByRole } = testRenderer;
const button = queryByRole('button');

expect(button.textContent).toBe('(0)');
});
});
3 changes: 3 additions & 0 deletions src/app/components/core/UserMenu/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// @flow strict
// eslint-disable-next-line import/prefer-default-export
export { default as UserMenu } from './UserMenu';
2 changes: 2 additions & 0 deletions src/app/constants/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// @flow strict

export const ASYNC_ACTION_TYPE = 'ASYNC_ACTION_TYPE';

export const BASE_URL = 'http://localhost:3000/api';

export const COUNTRIES = 'https://restcountries.eu/rest/v2';
Expand Down
2 changes: 0 additions & 2 deletions src/app/hooks/useLazy/useLazy.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ const useLazy = (
return;
}
const module = await getModule();
// eslint-disable-next-line no-console
console.log('module', module);
setAsyncModule(() => module.default);
} catch (err) {
throw new Error(`LazyComponent error: ${err}`);
Expand Down
Loading

0 comments on commit 093029f

Please sign in to comment.