Skip to content

Commit

Permalink
Merge 72f8980 into f1104ae
Browse files Browse the repository at this point in the history
  • Loading branch information
segunolalive committed Dec 20, 2017
2 parents f1104ae + 72f8980 commit 3c7c6d9
Show file tree
Hide file tree
Showing 144 changed files with 4,114 additions and 1,461 deletions.
2 changes: 1 addition & 1 deletion .coveralls.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
repo_token: COVERALLS_REPO_TOKEN
repo_token: RF9Gn0DcrIITCfsdfz4hrfRUC2kUGq0qF
2 changes: 0 additions & 2 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
/server/docs
/server/test
/dist
/client/__tests__
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
language: node_js
node_js:
- "6"
- "8"
env:
global:
- export NODE_ENV=test
before_script:
- npm install -g codeclimate-test-reporter
script:
- npm test
after_success:
- codeclimate-test-reporter < coverage/lcov.info
- npm run coverage
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

[![License](http://img.shields.io/badge/license-MIT-blue.svg)](http://opensource.org/licenses/MIT)
[![Build Status](https://travis-ci.org/segunolalive/helloBooks.svg?branch=development)](https://travis-ci.org/segunolalive/helloBooks)
[![Coverage Status](https://coveralls.io/repos/github/segunolalive/helloBooks/badge.svg?branch=development)](https://coveralls.io/github/segunolalive/helloBooks?branch=development)
[![Test Coverage](https://codeclimate.com/github/segunolalive/helloBooks/badges/coverage.svg)](https://codeclimate.com/github/segunolalive/helloBooks/coverage)
[![Coverage Status](https://coveralls.io/repos/github/segunolalive/helloBooks/badge.svg?branch=development)](https://coveralls.io/github/segunolalive/helloBooks)
[![Code Climate](https://codeclimate.com/github/segunolalive/helloBooks/badges/gpa.svg)](https://codeclimate.com/github/segunolalive/helloBooks?branch=development)

## A Library app
Expand Down Expand Up @@ -63,7 +64,7 @@ npm run start

#### API Documentation

* <https://www.segunolalive-hellobooks.com.herokuapp/api-docs>
* <https://www.segunolalive-hellobooks.herokuapp.com/api-docs>

#### Testing

Expand All @@ -79,7 +80,7 @@ Then start the client by running `npm run start:client`.

In another terminal window, run `npm run start:server:e2e` to start the application server in test-mode.

In a third terminal window run `npm run e2e:server` to start the selenium server.
In a third terminal window run `npm run e2e-server` to start the selenium server.

In a fourth terminal window run `npm run test:e2e`

Expand Down
6 changes: 6 additions & 0 deletions client/__tests__/__mocks__/Notify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Notify from '../../actions/Notify';

Notify.success = jest.spyOn(Notify, 'success');
Notify.error = jest.spyOn(Notify, 'error');

export default Notify;
12 changes: 6 additions & 6 deletions client/__tests__/__mocks__/mockLocalStorage.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
const localStorage = {
const mockLocalStorage = {
store: {},
setItem(key, value) {
return ({ ...localStorage.store, [key]: value });
return ({ ...mockLocalStorage.store, [key]: value });
},
getItem(key) {
return localStorage.store[key];
return mockLocalStorage.store[key];
},
removeItem(key) {
delete localStorage.store[key];
delete mockLocalStorage.store[key];
},
clear() {
localStorage.store = {};
mockLocalStorage.store = {};
}
};

export default localStorage;
export default mockLocalStorage;
7 changes: 0 additions & 7 deletions client/__tests__/__mocks__/notify.js

This file was deleted.

45 changes: 45 additions & 0 deletions client/__tests__/__mocks__/superagent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
let mockDelay;
let mockError;
let mockResponse = {
status() {
return 200;
},
ok: true,
get: jest.genMockFunction(),
toError: jest.genMockFunction(),
data: { message: 'success' }
};

const request = {
post: jest.genMockFunction().mockReturnThis(),
get: jest.genMockFunction().mockReturnThis(),
send: jest.genMockFunction().mockReturnThis(),
query: jest.genMockFunction().mockReturnThis(),
field: jest.genMockFunction().mockReturnThis(),
set: jest.genMockFunction().mockReturnThis(),
accept: jest.genMockFunction().mockReturnThis(),
timeout: jest.genMockFunction().mockReturnThis(),
end: jest.genMockFunction().mockImplementation(function cb(callback) {
if (mockDelay) {
this.delayTimer = setTimeout(callback, 0, mockError, mockResponse);
return;
}

callback(mockError, mockResponse);
}),

__setMockDelay(boolValue) {
mockDelay = boolValue;
},
__setMockResponse(mockRes) {
mockResponse = mockRes;
},
__setMockError(mockErr) {
mockError = mockErr;
},
__setMockResponseBody(body) {
mockResponse.body = body;
}
};

export default request;
137 changes: 85 additions & 52 deletions client/__tests__/actions/adminActions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ import { addBook,
} from '../../actions/adminActions/books';
import { fetchNotifications } from '../../actions/adminActions/notifications';
import actionTypes from '../../actions/actionTypes';
import uploadFile from '../../actions/uploadFile';
import Notify from '../__mocks__/Notify';

import notify from '../__mocks__/notify';

window.CLOUDINARY_API_BASE = 'CLOUDINARY_API_BASE';
window.CLOUDINARY_UPLOAD_PRESET = 'CLOUDINARY_UPLOAD_PRESET';

const middleware = [thunk];
const mockStore = configureMockStore(middleware);
Expand All @@ -22,16 +25,23 @@ describe('ADMIN ACTIONS', () => {
afterEach(() => moxios.uninstall());

describe('addBook', () => {
it('returns a success toast on success', () => {
it('creates CREATE_BOOK action type and a toast on success', () => {
const book = { title: 4, authors: 'Funke' };
moxios.stubRequest('/api/v1/books', {
status: 200,
response: { message: 'success' }
});
const expectedActions = [];
response: {
message: 'success',
book
},
});
const expectedActions = [{
book,
type: 'CREATE_BOOK'
}];
const store = mockStore({});
return store.dispatch(addBook(1)).then(() => {
return store.dispatch(addBook(book)).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(notify.success).toHaveBeenCalled();
expect(Notify.success).toHaveBeenCalled();
});
});

Expand All @@ -44,35 +54,44 @@ describe('ADMIN ACTIONS', () => {
const store = mockStore({});
return store.dispatch(addBook(1)).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(notify.error).toHaveBeenCalled();
expect(Notify.error).toHaveBeenCalled();
expect(Notify.error.mock.calls[0]).toEqual(['failure']);
});
});
});

describe('editBook', () => {
it('returns a success toast on success', () => {
it('creates EDIT_BOOK_INFO action type and a toast on success', () => {
const book = { title: 4, authors: 'Funke' };
moxios.stubRequest('/api/v1/books/1', {
status: 200,
response: { message: 'success' }
});
const expectedActions = [];
response: {
message: 'success',
book
},
});
const expectedActions = [{
book,
type: 'EDIT_BOOK_INFO'
}];
const store = mockStore({});
return store.dispatch(editBook(1, {})).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(notify.success).toHaveBeenCalled();
expect(Notify.success).toHaveBeenCalled();
expect(Notify.success.mock.calls[0]).toEqual(['success']);
});
});

it('returns a success toast on failure', () => {
it('returns a failure toast on failure', () => {
moxios.stubRequest('/api/v1/books/1', {
status: 500,
response: { message: 'success' }
response: { message: 'failure' }
});
const expectedActions = [];
const store = mockStore({});
return store.dispatch(editBook(1, {})).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(notify.success).toHaveBeenCalled();
expect(Notify.error).toHaveBeenCalled();
});
});
});
Expand All @@ -87,20 +106,20 @@ describe('ADMIN ACTIONS', () => {
const store = mockStore({});
return store.dispatch(deleteBook(1)).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(notify.success).toHaveBeenCalled();
expect(Notify.success).toHaveBeenCalled();
});
});

it('toasts a message and creates no action on failure', () => {
moxios.stubRequest('/api/v1/books/1', {
status: 500,
response: { message: 'success' }
response: { message: 'failure' }
});
const expectedActions = [];
const store = mockStore({});
return store.dispatch(deleteBook(1)).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(notify.error).toHaveBeenCalled();
expect(Notify.error).toHaveBeenCalled();
});
});
});
Expand All @@ -109,13 +128,15 @@ describe('ADMIN ACTIONS', () => {
it('returns a success toast on success', () => {
moxios.stubRequest('/api/v1/books/category', {
status: 200,
response: { message: 'success' }
response: { message: 'success', category: 'new category' }
});
const expectedActions = [];
const expectedActions = [
{ type: 'ADD_BOOK_CATEGORY', category: 'new category' }
];
const store = mockStore({});
return store.dispatch(addBookCategory('category')).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(notify.success).toHaveBeenCalled();
expect(Notify.success).toHaveBeenCalled();
});
});

Expand All @@ -124,18 +145,20 @@ describe('ADMIN ACTIONS', () => {
status: 500,
response: { message: 'failure' }
});
const expectedActions = [];
const expectedActions = [{
message: 'failure',
type: 'ADD_BOOK_CATEGORY_FAILURE',
}];
const store = mockStore({});
return store.dispatch(addBookCategory('category')).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(notify.error).toHaveBeenCalled();
expect(Notify.error).toHaveBeenCalled();
});
});
});

describe('fetchNotifications', () => {
it('it creates IS_FETCHING_NOTIFICATIONS, GET_ADMIN_NOTIFICATIONS ' +
'and SET_NOTICATIONS_PAGINATION when successful', () => {
it('it creates IS_FETCHING_NOTIFICATIONS, GET_ADMIN_NOTIFICATIONS and SET_NOTICATIONS_PAGINATION when successful', () => {
const { notifications } = mockStoreData.notificationReducer;
const { pagination } = mockStoreData.notificationReducer;
moxios.stubRequest('/api/v1/admin-notifications', {
Expand All @@ -151,34 +174,32 @@ describe('ADMIN ACTIONS', () => {
const store = mockStore({});
return store.dispatch(fetchNotifications()).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(notify.success).toHaveBeenCalled();
});
});

it('it creates IS_FETCHING_NOTIFICATIONS, GET_MORE_ADMIN_NOTIFICATIONS ' +
'and SET_NOTICATIONS_PAGINATION when successfully called with offset > 0',
() => {
const { notifications } = mockStoreData.notificationReducer;
const { pagination } = mockStoreData.notificationReducer;
moxios.stubRequest('/api/v1/admin-notifications?offset=20&', {
status: 200,
response: { message: 'success', notifications, metadata: pagination }
});
const expectedActions = [
{ type: actionTypes.IS_FETCHING_NOTIFICATIONS, status: true },
{ type: actionTypes.SET_NOTICATIONS_PAGINATION, pagination },
{ type: actionTypes.GET_MORE_ADMIN_NOTIFICATIONS, notifications },
{ type: actionTypes.IS_FETCHING_NOTIFICATIONS, status: false }
];
const store = mockStore({});
return store.dispatch(fetchNotifications({ offset: 20 })).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(notify.success).toHaveBeenCalled();
expect(Notify.success).toHaveBeenCalled();
});
});

it('it creates IS_FETCHING_NOTIFICATIONS actions and sends an error ' +
'notification with on failure', () => {
it('it creates IS_FETCHING_NOTIFICATIONS, GET_MORE_ADMIN_NOTIFICATIONS and SET_NOTICATIONS_PAGINATION when successfully called with offset > 0',
() => {
const { notifications } = mockStoreData.notificationReducer;
const { pagination } = mockStoreData.notificationReducer;
moxios.stubRequest('/api/v1/admin-notifications?offset=20&', {
status: 200,
response: { message: 'success', notifications, metadata: pagination }
});
const expectedActions = [
{ type: actionTypes.IS_FETCHING_NOTIFICATIONS, status: true },
{ type: actionTypes.SET_NOTICATIONS_PAGINATION, pagination },
{ type: actionTypes.GET_MORE_ADMIN_NOTIFICATIONS, notifications },
{ type: actionTypes.IS_FETCHING_NOTIFICATIONS, status: false }
];
const store = mockStore({});
return store.dispatch(fetchNotifications({ offset: 20 })).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(Notify.success).toHaveBeenCalled();
});
});

it('it creates IS_FETCHING_NOTIFICATIONS actions and sends an error notification with on failure', () => {
const { notifications } = mockStoreData.notificationReducer;
const { pagination } = mockStoreData.notificationReducer;
moxios.stubRequest('/api/v1/admin-notifications', {
Expand All @@ -192,7 +213,19 @@ describe('ADMIN ACTIONS', () => {
const store = mockStore({});
return store.dispatch(fetchNotifications()).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(notify.success).toHaveBeenCalled();
expect(Notify.success).toHaveBeenCalled();
});
});
});

describe('uploadFile', () => {
it('handles file upload success', (done) => {
const store = mockStore({});
return store.dispatch(uploadFile('file')).then((response) => {
expect(response.ok).toBe(true);
expect(response.status()).toBe(200);
expect(response.data.message).toBe('success');
done();
});
});
});
Expand Down
Loading

0 comments on commit 3c7c6d9

Please sign in to comment.