hotfix: merge with develop

This commit is contained in:
George Lima 2018-11-28 22:54:08 -03:00
commit 8e9816b031
29 changed files with 1833 additions and 13461 deletions

View File

@ -4,9 +4,10 @@
"env": {
"browser": true,
"node": true,
"mocha": true
"mocha": true,
"jest/globals": true
},
"plugins": ["flowtype"],
"plugins": ["flowtype", "jest"],
"settings": {
"flowtype": {
"onlyFilesWithFlowAnnotation": true
@ -34,10 +35,12 @@
"error",
{
"code": 120,
"tabWidth": 2,
"ignoreUrls": true,
"ignoreComments": true,
"ignoreStrings": true,
"ignorePattern": "<p[^>]*>.*?</p>"
"ignorePattern": "<p[^>]*>.*?</p>",
"ignoreTrailingComments": true
}
]
}

4
.gitignore vendored
View File

@ -4,4 +4,6 @@ dist
.DS_Store
flow-coverage
build
.docz
.docz
coverage
flow-typed

View File

@ -24,9 +24,9 @@ yarn install
To run the application on port 8080
```bash
yarn dev
yarn start
```
## License
© Zcash Foundation 2018
© Zcash Foundation 2018

View File

@ -0,0 +1,26 @@
import configureStore from 'redux-mock-store';
import { ADD_TODO, addTodo } from '../../app/redux/modules/todo';
const store = configureStore()();
describe('Todo Actions', () => {
beforeEach(() => store.clearActions());
test('should create an action to add a new todo', () => {
const text = 'Hello World!';
store.dispatch(addTodo(text));
expect(store.getActions()[0]).toEqual(
expect.objectContaining({
type: ADD_TODO,
payload: {
text,
id: expect.any(String),
editing: false,
createdAt: expect.any(Number),
},
}),
);
});
});

View File

@ -0,0 +1,20 @@
import React from 'react';
import { render } from 'react-testing-library';
import { MemoryRouter } from 'react-router-dom';
import 'jest-dom/extend-expect';
import { SidebarComponent } from '../../app/components/Sidebar';
describe('<Sidebar />', () => {
describe('render()', () => {
test('should render correctly', () => {
const { asFragment } = render(
<MemoryRouter>
<SidebarComponent />
</MemoryRouter>,
);
expect(asFragment()).toMatchSnapshot();
});
});
});

View File

@ -0,0 +1,30 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Sidebar /> render() should render correctly 1`] = `
<DocumentFragment>
<div
class="sc-bdVaJa fnXMXv"
>
<a
href="/"
>
Dashboard
</a>
<a
href="/send"
>
Send
</a>
<a
href="/receive"
>
Receive
</a>
<a
href="/settings"
>
Settings
</a>
</div>
</DocumentFragment>
`;

View File

@ -0,0 +1,16 @@
import { getApp } from '../setup/utils';
describe('ZCash', () => {
const app = getApp();
beforeEach(() => app.start());
afterEach(() => {
app.stop();
});
test('should open the window', () => {
app.client.getWindowCount().then((count) => {
expect(count).equal(1);
});
});
});

View File

@ -0,0 +1,25 @@
import todoReducer, { ADD_TODO } from '../../app/redux/modules/todo';
describe('Todo Reducer', () => {
test('should return the valid initial state', () => {
const action = { type: 'UNKNOWN_ACTION' };
const initialState = [];
expect(todoReducer(undefined, action)).toEqual(initialState);
});
test('should add a new todo', () => {
const action = {
type: ADD_TODO,
payload: {
id: 'abc123',
text: 'Hello World!',
editing: false,
createdAt: new Date().getTime(),
},
};
const expectedState = [action.payload];
expect(todoReducer(undefined, action)).toEqual(expectedState);
});
});

2
__tests__/setup/jest.js Normal file
View File

@ -0,0 +1,2 @@
jest.DEFAULT_TIMEOUT_INTERVAL = 20000;
jest.setTimeout(20000);

11
__tests__/setup/utils.js Normal file
View File

@ -0,0 +1,11 @@
import electron from 'electron';
import { Application } from 'spectron';
export const TIMEOUT = 10000;
export const getApp = () => new Application({
path: electron,
args: ['.'],
startTimeout: TIMEOUT,
waitTimeout: TIMEOUT,
});

View File

@ -1,15 +0,0 @@
// @flow
import uuidv4 from 'uuid/v4';
import { ADD_TODO } from '../constants/actions';
import { getTimestamp } from '../utils/timestamp';
export const addTodo = (text: string) => ({
type: ADD_TODO,
payload: {
text,
id: uuidv4(),
editing: false,
createdAt: getTimestamp(),
},
});

View File

@ -1,8 +0,0 @@
// @flow
import { CANCEL_UPDATE_TODO } from '../constants/actions';
export const cancelUpdateTodo = (id: string) => ({
type: CANCEL_UPDATE_TODO,
payload: { id },
});

View File

@ -1,8 +0,0 @@
// @flow
import { DELETE_TODO } from '../constants/actions';
export const deleteTodo = (id: string) => ({
type: DELETE_TODO,
payload: { id },
});

View File

@ -1,8 +0,0 @@
// @flow
import { TOGGLE_EDIT_TODO } from '../constants/actions';
export const toggleEdit = (id: string) => ({
type: TOGGLE_EDIT_TODO,
payload: { id },
});

View File

@ -1,11 +0,0 @@
// @flow
import { UPDATE_TODO } from '../constants/actions';
export const updateTodo = (id: string, text: string) => ({
type: UPDATE_TODO,
payload: {
text,
id,
},
});

View File

@ -5,18 +5,18 @@ import { Provider } from 'react-redux';
import { ConnectedRouter } from 'connected-react-router';
import { ThemeProvider } from 'styled-components';
import { configureStore, history } from './store/configure';
import { configureStore, history } from './redux/create';
import { Router } from './router/container';
import theme from './theme';
const store = configureStore({});
export default () => (
<Provider store={store}>
<ConnectedRouter history={history}>
<ThemeProvider theme={theme}>
<ThemeProvider theme={theme}>
<Provider store={store}>
<ConnectedRouter history={history}>
<Router />
</ThemeProvider>
</ConnectedRouter>
</Provider>
</ConnectedRouter>
</Provider>
</ThemeProvider>
);

View File

@ -13,7 +13,7 @@ const Wrapper = styled.div`
left: 0;
top: 0;
height: 100vh;
background: #ccc;
background-color: ${props => props.theme.colors.secondary};
`;
const StyledLink = styled(Link)`

View File

@ -3,7 +3,8 @@ name: Sidebar
---
import { Playground, PropsTable } from 'docz'
import { SidebarComponent } from './index.js'
import { SidebarComponent } from './Sidebar.js'
import { DoczWrapper } from '../theme.js'
# Sidebar
@ -12,5 +13,7 @@ import { SidebarComponent } from './index.js'
## Basic usage
<Playground>
<SidebarComponent />
<DoczWrapper>
{() => <SidebarComponent />}
</DoczWrapper>
</Playground>

View File

@ -1,7 +0,0 @@
// @flow
export const ADD_TODO = 'ADD_TODO';
export const DELETE_TODO = 'DELETE_TODO';
export const UPDATE_TODO = 'UPDATE_TODO';
export const TOGGLE_EDIT_TODO = 'TOGGLE_EDIT_TODO';
export const CANCEL_UPDATE_TODO = 'CANCEL_UPDATE_TODO';

View File

@ -2,11 +2,10 @@
import { connect } from 'react-redux';
import TodoView from '../views/todo';
import { addTodo } from '../actions/add-todo';
import { deleteTodo } from '../actions/delete-todo';
import { toggleEdit } from '../actions/toggle-edit-todo';
import { updateTodo } from '../actions/update-todo';
import { cancelUpdateTodo } from '../actions/cancel-update-todo';
import {
addTodo, deleteTodo, toggleEdit, updateTodo, cancelUpdateTodo,
} from '../redux/modules/todo';
import type { AppState } from '../types/app-state';
import type { Dispatch } from '../types/redux';

View File

@ -1,53 +0,0 @@
// @flow
import {
ADD_TODO,
DELETE_TODO,
UPDATE_TODO,
CANCEL_UPDATE_TODO,
TOGGLE_EDIT_TODO,
} from '../constants/actions';
import type { TodoType } from '../types/todo';
import type { Action } from '../types/redux';
const initialState = [];
export default (state: Array<TodoType> = initialState, action: Action) => {
switch (action.type) {
case ADD_TODO:
return [
...state,
action.payload,
];
case DELETE_TODO:
// $FlowFixMe
return state.filter((todo: Object) => todo.id !== action.payload.id);
case TOGGLE_EDIT_TODO: {
const { id } = action.payload;
const todos = [...state];
const index = todos.map(todo => todo.id).indexOf(id);
todos[index].editing = true;
return todos;
}
case UPDATE_TODO: {
const { id, text } = action.payload;
const todos = [...state];
const index = todos.map(todo => todo.id).indexOf(id);
todos[index].text = text;
todos[index].editing = false;
return todos;
}
case CANCEL_UPDATE_TODO: {
const { id } = action.payload;
const todos = [...state];
const index = todos.map(todo => todo.id).indexOf(id);
todos[index].editing = false;
return todos;
}
default:
return state;
}
};

22
app/redux/create.js Normal file
View File

@ -0,0 +1,22 @@
// @flow
import { createStore, applyMiddleware, compose } from 'redux';
import { routerMiddleware } from 'connected-react-router';
import { createBrowserHistory } from 'history';
import thunk from 'redux-thunk';
import { createRootReducer } from './modules/reducer';
export const history = createBrowserHistory();
const shouldEnableDevTools = (process.env.NODE_ENV !== 'production' || process.env.NODE_ENV !== 'staging') && window.devToolsExtension;
export const configureStore = (initialState: Object) => {
const middleware = applyMiddleware(thunk, routerMiddleware(history));
const enhancer = compose(
middleware,
shouldEnableDevTools ? window.devToolsExtension() : f => f,
);
return createStore(createRootReducer(history), initialState, enhancer);
};

View File

@ -2,9 +2,11 @@
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';
import type { History } from 'react-router-dom';
import todoReducer from './todo';
export const createRootReducer = (history: Object) => combineReducers({
export const createRootReducer = (history: History) => combineReducers({
todos: todoReducer,
router: connectRouter(history),
});

78
app/redux/modules/todo.js Normal file
View File

@ -0,0 +1,78 @@
// @flow
import UUID from 'uuid/v4';
import { getTimestamp } from '../../utils/timestamp';
import type { Action } from '../../types/redux';
import type { TodoType } from '../../types/todo';
// Actions
export const ADD_TODO = 'ADD_TODO';
export const DELETE_TODO = 'DELETE_TODO';
export const UPDATE_TODO = 'UPDATE_TODO';
export const TOGGLE_EDIT_TODO = 'TOGGLE_EDIT_TODO';
export const CANCEL_UPDATE_TODO = 'CANCEL_UPDATE_TODO';
// Actions Creators
export const addTodo = (text: string) => ({
type: ADD_TODO,
payload: {
text,
id: UUID(),
editing: false,
createdAt: getTimestamp(),
},
});
export const cancelUpdateTodo = (id: string) => ({
type: CANCEL_UPDATE_TODO,
payload: { id },
});
export const deleteTodo = (id: string) => ({
type: DELETE_TODO,
payload: { id },
});
export const toggleEdit = (id: string) => ({
type: TOGGLE_EDIT_TODO,
payload: { id },
});
export const updateTodo = (id: string, text: string) => ({
type: UPDATE_TODO,
payload: {
text,
id,
},
});
// Initial State
const initialState = [];
// Reducers
export default (state: Array<TodoType> = initialState, action: Action): Array<TodoType> => {
switch (action.type) {
case ADD_TODO:
return [...state, action.payload];
case DELETE_TODO:
return state.filter((todo: TodoType) => todo.id !== action.payload.id);
case TOGGLE_EDIT_TODO: {
const { id } = action.payload;
return state.map(todo => (todo.id === id ? { ...todo, editing: true } : todo));
}
case UPDATE_TODO: {
const { id, text } = action.payload;
return state.map(todo => (todo.id === id ? { ...todo, editing: false, text } : todo));
}
case CANCEL_UPDATE_TODO: {
const { id } = action.payload;
return state.map(todo => (todo.id === id ? { ...todo, editing: false } : todo));
}
default:
return state;
}
};
// SideEffects

View File

@ -1,35 +0,0 @@
// @flow
import { createStore, applyMiddleware, compose } from 'redux';
import { routerMiddleware } from 'connected-react-router';
import { createBrowserHistory } from 'history';
import thunk from 'redux-thunk';
import { createRootReducer } from '../reducers';
export const history = createBrowserHistory();
export const configureStore = (initialState: Object) => {
let enhancer;
const middleware = applyMiddleware(
thunk,
routerMiddleware(history),
);
if (
process.env.NODE_ENV !== 'production'
|| process.env.NODE_ENV !== 'staging'
) {
enhancer = compose(
middleware,
window.devToolsExtension ? window.devToolsExtension() : f => f,
);
} else {
enhancer = compose(middleware);
}
return createStore(
createRootReducer(history),
initialState,
enhancer,
);
};

View File

@ -1,9 +1,11 @@
// @flow
import React from 'react';
import { ThemeProvider } from 'styled-components';
import theme from 'styled-theming';
import { DARK } from './constants/themes';
export default {
const appTheme = {
mode: DARK,
fontFamily: 'Open Sans',
colors: {
@ -21,3 +23,9 @@ export default {
paragraph: 12,
},
};
export default appTheme;
/* eslint-disable react/prop-types */
// $FlowFixMe
export const DoczWrapper = ({ children }) => <ThemeProvider theme={appTheme}>{children()}</ThemeProvider>;

13253
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,9 @@
"preelectron:prepare": "yarn build",
"icon:build": "./node_modules/.bin/electron-icon-maker --input=build-assets/icon.png --output=./build",
"docz:dev": "docz dev",
"docz:build": "docz build"
"docz:build": "docz build",
"test": "jest",
"test:watch": "jest --watch"
},
"author": {
"name": "André Neves",
@ -53,17 +55,23 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-flowtype": "^3.2.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jest": "^22.1.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.7.0",
"file-loader": "^2.0.0",
"flow-bin": "^0.87.0",
"glow": "^1.2.2",
"html-webpack-plugin": "^3.1.0",
"jest": "^23.6.0",
"jest-dom": "^2.1.1",
"node-sass": "^4.8.3",
"postcss-loader": "^3.0.0",
"pre-commit": "^1.2.2",
"react-testing-library": "^5.3.1",
"redux-logger": "^3.0.6",
"redux-mock-store": "^1.5.3",
"sass-loader": "^7.1.0",
"spectron": "^5.0.0",
"style-loader": "^0.23.1",
"uglifyjs-webpack-plugin": "^2.0.1",
"wait-on": "^3.2.0",
@ -106,7 +114,10 @@
"./node_modules/**/*"
],
"linux": {
"icon": "./build/icons/png"
"icon": "./build/icons/png",
"target": [
"deb"
]
},
"mac": {
"category": "public.app-category.productivity",
@ -116,5 +127,14 @@
"dmg"
]
}
},
"jest": {
"setupTestFrameworkScriptFile": "<rootDir>/__tests__/setup/jest.js",
"testPathIgnorePatterns": [
"<rootDir>/__tests__/setup/"
]
},
"resolutions": {
"babel-core": "7.0.0-bridge.0"
}
}

1579
yarn.lock

File diff suppressed because it is too large Load Diff