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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ src/api/apiUtils.ts
*.iml
junit.xml
/reports/
/.awcache
.awcache
/.vscode
13 changes: 12 additions & 1 deletion 00 Base/config/webpack/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CheckerPlugin } = require('awesome-typescript-loader');
const merge = require('webpack-merge');
const helpers = require('./helpers');
var MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = merge(
{},
Expand All @@ -11,7 +12,9 @@ module.exports = merge(
extensions: ['.js', '.ts', '.tsx'],
},
entry: {
app: ['./index.tsx'],
app: ['./index.tsx',
'./content/styles.css',
],
},
module: {
rules: [
Expand All @@ -25,6 +28,10 @@ module.exports = merge(
babelCore: '@babel/core',
},
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
},
],
},
optimization: {
Expand All @@ -45,6 +52,10 @@ module.exports = merge(
template: 'index.html',
}),
new CheckerPlugin(),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
}),
],
}
);
14 changes: 12 additions & 2 deletions 00 Base/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@
"clean": "rimraf dist",
"build": "npm run clean && webpack --config ./config/webpack/prod.js",
"test": "jest -c ./config/test/jest.json --verbose",
"test:watch": "jest -c ./config/test/jest.json --verbose --watchAll -i"
"test:watch": "jest -c ./config/test/jest.json --verbose --watchAll -i",
"test:coverage": "jest -c ./config/test/jest.json --verbose --coverage"
},
"author": "arp82",
"license": "MIT",
"dependencies": {
"@material-ui/core": "^4.1.3",
"axios": "^0.19.0",
"deep-freeze": "0.0.1",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-router-dom": "^5.0.1"
"react-redux": "^7.2.0",
"react-router-dom": "^5.0.1",
"redux": "^4.0.5",
"redux-mock-store": "^1.5.4",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"@babel/cli": "^7.4.4",
Expand All @@ -29,8 +35,12 @@
"@types/react-dom": "^16.8.4",
"@types/react-router-dom": "^4.3.4",
"awesome-typescript-loader": "^5.2.1",
"css-loader": "^3.5.1",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"html-webpack-plugin": "^3.2.0",
"jest": "^24.8.0",
"mini-css-extract-plugin": "^0.9.0",
"rimraf": "^2.6.3",
"ts-jest": "^24.0.2",
"typescript": "^3.5.2",
Expand Down
6 changes: 3 additions & 3 deletions 00 Base/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from 'react';
import { MyComponent } from './myComponent';
import { TodosContainer } from './components';

export const App: React.FunctionComponent = props => (
export const App: React.FunctionComponent = () => (
<div>
<MyComponent nameFromProps="Fruit User" />
<TodosContainer/>
</div>
);
1 change: 1 addition & 0 deletions 00 Base/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { TodosContainer } from './todoList/todosContainer';
50 changes: 50 additions & 0 deletions 00 Base/src/components/todoList/components/todoRow.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as React from 'react';
import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { TodoEntity } from '../../../model/todo';
import { TodoRowComponent } from './todoRow';

Enzyme.configure({ adapter: new Adapter() })

function setup(todo) {
const props = {
key: '1',
todo,
deleteTodo: jest.fn(),
}

const enzymeWrapper = shallow(<TodoRowComponent {...props} />)

return {
props,
enzymeWrapper
}
}

describe('TodoRow', () => {
it('should render self', () => {
const todo: TodoEntity = {
userId: 1,
id: 1,
title: 'Buy',
completed: true,
}

const { enzymeWrapper } = setup(todo)

expect(enzymeWrapper.find('tr')).toHaveLength(1)
expect(enzymeWrapper.find('td')).toHaveLength(4)
expect(enzymeWrapper.find('span')).toHaveLength(3)
expect(enzymeWrapper.find('button').text()).toBe('Delete')
})

it('should call deleteTodo when the button is clicked', () => {
const event = jest.fn()
const { enzymeWrapper, props } = setup([])
const deleteTodoButton = enzymeWrapper.find('button')

deleteTodoButton.simulate('click', event)

expect(props.deleteTodo).toHaveBeenCalledTimes(1)
})
});
42 changes: 42 additions & 0 deletions 00 Base/src/components/todoList/components/todoRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { connect } from 'react-redux';
import { deleteTodo } from '../../../redux/actions/todosActions';

import * as React from 'react';
import {TodoEntity} from '../../../model/todo';

interface Props {
todo: TodoEntity;
deleteTodo: (id: number) => void
}

export const TodoRowComponent = (props: Props) => {
const { deleteTodo } = props
const { id, title, completed } = props.todo
return (
<tr>
<td>
<span>{id}</span>
</td>
<td>
<span>{title}</span>
</td>
<td>
<span>{completed ? 'Completed' : 'Pending'}</span>
</td>
<td>
<button data-testid="deleteTodo-button" onClick={() => deleteTodo(id)}>Delete</button>
</td>
</tr>
);
}

const mapDispatchToProps = dispatch => {
return {
deleteTodo: (id: number) => {return dispatch(deleteTodo(id))},
};
}

export const TodoRow = connect(
null,
mapDispatchToProps
)(TodoRowComponent);
53 changes: 53 additions & 0 deletions 00 Base/src/components/todoList/components/todoTable.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as React from 'react';
import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { TodoTableComponent } from './todoTable';
import { TodoEntity } from '../../../model/todo';

Enzyme.configure({ adapter: new Adapter() })

function setup(todos) {
const props = {
todos,
}

const enzymeWrapper = shallow(<TodoTableComponent {...props} />)

return {
props,
enzymeWrapper
}
}

describe('TodoTable', () => {
it('should render self', () => {
const todos: TodoEntity[] = [
{
userId: 1,
id: 1,
title: 'Buy',
completed: true,
},
{
userId: 1,
id: 2,
title: 'Go to the gym',
completed: false,
}
]

const { enzymeWrapper } = setup(todos)

expect(enzymeWrapper.find('div').hasClass('row')).toBe(true)
expect(enzymeWrapper.find('table').hasClass('table'))
expect(enzymeWrapper.find('table')).toHaveLength(1)
expect(enzymeWrapper.find('thead')).toHaveLength(1)
expect(enzymeWrapper.find('tr')).toHaveLength(1)
expect(enzymeWrapper.find('th')).toHaveLength(4)
expect(enzymeWrapper.find('Id')).toBeDefined()
expect(enzymeWrapper.find('Title')).toBeDefined()
expect(enzymeWrapper.find('Completed')).toBeDefined()
expect(enzymeWrapper.find('Action')).toBeDefined()
expect(enzymeWrapper.find('tbody')).toHaveLength(1)
})
});
40 changes: 40 additions & 0 deletions 00 Base/src/components/todoList/components/todoTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as React from 'react';
import {TodoEntity} from '../../../model/todo';
import { TodoRow } from './todoRow';

interface Props {
todos: TodoEntity[];
}

export const TodoTableComponent = (props: Props) => {
const {todos } = props
return (
<div className="row">
<table className="table">
<thead>
<tr>
<th>
<span>Id</span>
</th>
<th>
<span>Title</span>
</th>
<th>
<span>Completed</span>
</th>
<th>
<span>Action</span>
</th>
</tr>
</thead>
<tbody>
{
todos && todos.map((todo: TodoEntity) =>
<TodoRow key={todo.id} todo={todo} />
)
}
</tbody>
</table>
</div>
);
}
93 changes: 93 additions & 0 deletions 00 Base/src/components/todoList/todosContainer.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import * as React from 'react';
import Enzyme, { shallow } from 'enzyme';
import { TodoEntity } from '../../model/todo';
import { TodoAreaComponent } from './todosContainer';
import Adapter from 'enzyme-adapter-react-16';

import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import ReduxThunk from 'redux-thunk';
const middlewares = [ReduxThunk];
const mockStore = configureStore(middlewares);

Enzyme.configure({ adapter: new Adapter() })

function setup(todos) {
const props = {
todos,
loadTodos: jest.fn(),
addTodo: jest.fn(),
}

const enzymeWrapper = shallow(<TodoAreaComponent {...props} />)

return {
props,
enzymeWrapper
}
}

describe('TodoAreaComponent', () => {
it('should render self', () => {
const todos: TodoEntity[] = [
{
userId: 1,
id: 1,
title: 'Buy',
completed: true,
},
{
userId: 1,
id: 2,
title: 'Go to the gym',
completed: false,
}
]

const { enzymeWrapper } = setup(todos)

expect(enzymeWrapper.find('h1').text()).toBe('Todos')
expect(enzymeWrapper.find('div').hasClass('addTodoContainer')).toBe(true)
expect(enzymeWrapper.find('input').hasClass('todoInput'))
expect(enzymeWrapper.find('span').text()).toBe('New todo:')
expect(enzymeWrapper.find('button').text()).toBe('Add todo')
})

it('should call loadTodos when componentDidMount', () => {
const todos: TodoEntity[] = [
{
userId: 1,
id: 1,
title: 'Buy',
completed: true,
},
{
userId: 1,
id: 2,
title: 'Go to the gym',
completed: false,
}
]

const { props } = setup(todos)
expect(props.loadTodos).toBeCalled()
expect(props.addTodo).not.toBeCalled()
})

it('should call addTodo when the button is clicked', () => {
const event = jest.fn()
const { enzymeWrapper, props } = setup([])
const newTodoButton = enzymeWrapper.find('button')

newTodoButton.simulate('click', event)

expect(props.addTodo).toHaveBeenCalledTimes(1)
})

it('if we dont have todos, should show de text ', () => {
const { enzymeWrapper } = setup([])

expect(enzymeWrapper.find('p').text()).toBe('No todos yet')
})
});
Loading