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
21 changes: 11 additions & 10 deletions 00 Base/config/webpack/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ module.exports = merge(
{
context: helpers.resolveFromRootPath('src'),
resolve: {
extensions: ['.js', '.ts', '.tsx'],
modules: [
'node_modules'
]
extensions: ['.js', '.ts', '.tsx', '.css', '.scss', '.less'],
},
entry: {
app: ['./index.tsx'],
Expand All @@ -28,14 +25,18 @@ module.exports = merge(
babelCore: '@babel/core',
}
},
{
test: /\.css$/,
loaders: ['style-loader', 'css-loader'],
},
{
test: /\.s[ac]ss$/i,
loaders: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.less$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'less-loader' }
]
}
use: ['style-loader', 'css-loader', 'less-loader'],
},
],
},
optimization: {
Expand Down
17 changes: 13 additions & 4 deletions 00 Base/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,23 @@
"author": "arp82",
"license": "MIT",
"dependencies": {
"@material-ui/core": "^4.9.9",
"@material-ui/icons": "^4.9.1",
"axios": "^0.19.2",
"babel-polyfill": "^6.26.0",
"@babel/preset-react": "^7.9.4",
"@babel/preset-stage-0": "^7.8.3",
"@material-ui/core": "^4.9.9",
"axios": "^0.19.0",
"babel-core": "^7.0.0-bridge.0",
"identity-obj-proxy": "^3.0.0",
"jest-transform-css": "^2.0.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-redux": "^7.2.0",
"react-router-dom": "^5.0.1",
"react-test-renderer": "^16.13.1",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"sass-loader": "^8.0.2",
"react-test-renderer": "^16.13.1",
"sinon": "^9.0.1",
"style-loader": "^1.1.3",
"ts-jest": "^25.3.1"
Expand All @@ -48,11 +51,17 @@
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"html-webpack-plugin": "^3.2.0",
"jest": "^24.9.0",
"jest": "^24.8.0",
"less": "^3.11.1",
"less-loader": "^5.0.0",
"node-sass": "^4.13.1",
"react-addons-test-utils": "^15.6.2",
"redux-devtools-extension": "^2.13.8",
"redux-mock-store": "^1.5.4",
"rimraf": "^2.6.3",
"sass-loader": "^7.2.0",
"style-loader": "^1.1.3",
"ts-jest": "^24.0.2",
"typescript": "^3.5.2",
"webpack": "^4.32.2",
"webpack-cli": "^3.3.2",
Expand Down
7 changes: 4 additions & 3 deletions 00 Base/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as React from 'react';
import { MessagesSection } from './components';
import { MyComponent } from './components/myComponent';
import './styles.less';

export const App: React.FunctionComponent = props => (
export const App: React.FunctionComponent = (props) => (
<div>
<MessagesSection />
<MyComponent nameFromProps="Fruit User" />
</div>
);
1 change: 1 addition & 0 deletions 00 Base/src/components/myComponent/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { MyComponent, Posts } from './myComponent';
59 changes: 59 additions & 0 deletions 00 Base/src/components/myComponent/myComponent.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as React from 'react';
// import { render, cleanup } from '@testing-library/react';
import {
render,
fireEvent,
waitForElement,
act,
RenderResult,
} from '@testing-library/react';
//import * as myApi from '../myApi';

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Please delete all comented code

@dailymp dailymp Apr 14, 2020

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Try to increase the coverage here
image

import { MyComponent, Props } from './myComponent';
import { Provider } from 'react-redux';
import * as redux from 'react-redux';
import { createStore } from 'redux';
import Enzyme, { mount } from 'enzyme';
import EnzymeAdapter from 'enzyme-adapter-react-16';
import { fetchPosts } from '../../redux/actions/index';

import reducer from '../../redux/reducers/index';
jest.mock('./MyComponent.tsx', () => ({
MyComponent: () => <div />,
}));

const baseProps: Props = {
nameFromProps: null,
};
Enzyme.configure({ adapter: new EnzymeAdapter() });

//afterEach(cleanup);
describe('My component', () => {
let props: Props;
beforeEach(() => {
props = { ...baseProps };
});

const name = 'Title';
const getWrapper = (
mockStore = createStore(reducer, { posts: { posts: [] } })
) =>
mount(
<Provider store={mockStore}>
<MyComponent nameFromProps={name} />
</Provider>
);

it('should display the title provided', () => {
const wrapper = getWrapper();
expect(wrapper.find('h1').text()).toEqual(`Hello ${name}!`);
});

it('should dispatch the get post action', () => {
const mockStore = createStore(reducer, { posts: { posts: [] } });
mockStore.dispatch = jest.fn();

const wrapper = getWrapper(mockStore);
wrapper.find('button').simulate('click');
expect(mockStore.dispatch).toHaveBeenCalledTimes(1);
});
});
64 changes: 64 additions & 0 deletions 00 Base/src/components/myComponent/myComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as React from 'react';

import { useSelector, useDispatch } from 'react-redux';
import { fetchPosts, deletePost, addPost } from './../../redux/actions/index';
import './styles.less';

import Button from '@material-ui/core/Button';
import Chip from '@material-ui/core/Chip';

import { MyInputComponent } from '../myInputComponent/myInputComponent';
export interface Props {
nameFromProps: string;
}
export interface Posts {
id: Number;
userId: Number;
title: string;
body: string;
}

export const MyComponent: React.FunctionComponent<Props> = (props) => {
const { nameFromProps } = props;
const dispatch = useDispatch();
const posts = useSelector((state) => state.posts.posts);

return (
<>
<div className="container">
<h1>Hello {nameFromProps}!</h1>
<Button
variant="contained"
color="primary"
onClick={() => dispatch(fetchPosts())}
>
Get post from API
</Button>
<div className="chip-container">
{!!posts
? posts.map((el: Posts) => (
<Chip
color="primary"
label={el.title}
key={el.id.toString()}
onDelete={() => dispatch(deletePost(el.id))}
/>
))
: null}
</div>
<MyInputComponent
addPost={(newPost) =>
dispatch(
addPost({
id: Math.floor(Math.random() * 1000),
userId: 1,
title: newPost,
body: newPost,
})
)
}
/>
</div>
</>
);
};
12 changes: 12 additions & 0 deletions 00 Base/src/components/myComponent/styles.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.container {
text-align: center;
.chip-container {
display: block;
position: relative;
margin-top: 25px;
.MuiChip-root {
margin-left: 5px;
margin-top: 5px;
}
}
}
1 change: 1 addition & 0 deletions 00 Base/src/components/myInputComponent/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { MyInputComponent } from './myInputComponent';
31 changes: 31 additions & 0 deletions 00 Base/src/components/myInputComponent/myInputComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as React from 'react';
import TextField from '@material-ui/core/TextField';
import { Add } from '@material-ui/icons';
import './styles.less';

export interface Props {
addPost: Function;
}

export const MyInputComponent: React.FunctionComponent<Props> = (props) => {
const { addPost } = props;
const [name, setName] = React.useState('');

return (
<div className="input-component">
<TextField
label="Add post"
value={name}
onChange={(e) => setName(e.target.value)}
/>
{!!name ? (
<Add
onClick={() => {
addPost(name);
setName('');
}}
/>
) : null}
</div>
);
};
9 changes: 9 additions & 0 deletions 00 Base/src/components/myInputComponent/styles.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.input-component {
.MuiFormControl-root {
margin-top: 10px;
}
.MuiSvgIcon-root {
margin-top: 35px;
color: #00ff00;
}
}
18 changes: 8 additions & 10 deletions 00 Base/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { App } from './app';
import { Provider } from 'react-redux'
import { createStore, compose, applyMiddleware } from 'redux'
import {MessagesReducer} from './redux/reducers/MessagesReducer'
import thunk from 'redux-thunk'
import { Provider } from 'react-redux';
import store from './redux/store';

const MessagesStore = createStore(MessagesReducer,compose(applyMiddleware(thunk)));
import { App } from './app';
import 'babel-polyfill'

ReactDOM.render(
<Provider store={MessagesStore}>
<Provider store={store}>
<App />
</Provider>,

document.getElementById('root'));
</Provider>,
document.getElementById('root')
);
1 change: 1 addition & 0 deletions 00 Base/src/myApi/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { getListOfFruit, getPosts } from './myApi';
19 changes: 19 additions & 0 deletions 00 Base/src/myApi/myApi.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { getListOfFruit, getPosts } from './myApi';

describe('myApi tests', () => {
it('getListOfFruit should return an array of string', () => {
expect(getListOfFruit()).resolves.toEqual([
'grape',
'pineapple',
'watermelon',
'orange',
'lemon',
'strawberry',
'cherry',
'peach',
]);
});
it('should fecth some post from the api', () => {
expect(getPosts()).rejects.toThrowError('Error fetching');

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This test is not semantic, please fix it

});
});
30 changes: 30 additions & 0 deletions 00 Base/src/myApi/myApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as BEApi from './myBackEndApiEndpoint';
import axios from 'axios';
import { Posts } from '../components/myComponent/index';

export const getListOfFruit = (): Promise<string[]> => {
return BEApi.getFruits('http://fruityfruit.com')
.then(resolveFruits)
.catch(handleError);
};

const resolveFruits = (fruits: string[]) => {
return fruits;
};

const handleError = () => {
throw new Error('Where is my fruit???');
};
export const getPosts = (): Promise<Posts[]> => {
return axios
.get('https://jsonplaceholder.typicode.com/posts')
.then(resolvePosts)
.catch(handlePostError);
};
const resolvePosts = (posts: any) => {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This posts is not typed

console.log('resolvePosts -> posts', posts);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Delete this comment

return posts.data;
};
const handlePostError = () => {
throw new Error('Error fetching');
};
12 changes: 12 additions & 0 deletions 00 Base/src/myApi/myBackEndApiEndpoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const getFruits = (_url: string) => {
return Promise.resolve([
'grape',
'pineapple',
'watermelon',
'orange',
'lemon',
'strawberry',
'cherry',
'peach',
]);
}
Loading