Skip to content

Commit

Permalink
Merge 35c548f into 31b3a22
Browse files Browse the repository at this point in the history
  • Loading branch information
richardscarrott committed Oct 22, 2016
2 parents 31b3a22 + 35c548f commit bed7096
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ node_js:
cache:
directories:
- node_modules
sudo: false
branches:
only:
- master
sudo: false
script:
- npm test
- npm run build
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 60fram.es React Boilerplate [![Build Status](https://travis-ci.org/60frames/react-boilerplate.svg?branch=master)](https://travis-ci.org/60frames/react-boilerplate)
# 60fram.es React Boilerplate [![Build Status](https://travis-ci.org/60frames/react-boilerplate.svg?branch=master)](https://travis-ci.org/60frames/react-boilerplate) [![Coverage Status](https://coveralls.io/repos/github/60frames/react-boilerplate/badge.svg?branch=master)](https://coveralls.io/github/60frames/react-boilerplate?branch=master)

Production-ready boilerplate for building *universal* web apps with [React](https://github.com/facebook/react) and [Redux](https://github.com/reactjs/redux)

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"compression": "^1.6.1",
"css-reset": "60frames/css-reset.git#1.0.0",
"debug": "^2.2.0",
"es6-error": "^4.0.0",
"express": "^4.13.4",
"isomorphic-fetch": "^2.2.1",
"ms": "^0.7.1",
Expand Down
2 changes: 1 addition & 1 deletion src/actions/quote/quote.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import fetch from 'utils/fetch';
import fetch from 'utils/fetch/fetch';

export const FETCH_QUOTE_REQUEST = 'FETCH_QUOTE_REQUEST';
export const FETCH_QUOTE_SUCCESS = 'FETCH_QUOTE_SUCCESS';
Expand Down
4 changes: 2 additions & 2 deletions src/actions/quote/quote.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/* global jest */
/* eslint-env jasmine */

jest.mock('utils/fetch');
jest.mock('utils/fetch/fetch');

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import fetch from 'utils/fetch';
import fetch from 'utils/fetch/fetch';
import {
FETCH_QUOTE_REQUEST,
FETCH_QUOTE_SUCCESS,
Expand Down
2 changes: 1 addition & 1 deletion src/components/notfound/NotFound.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import styles from './NotFound.css';
import styles from 'components/notfound/NotFound.css';

function NotFound() {
return (
Expand Down
11 changes: 0 additions & 11 deletions src/utils/ExtendableError.js

This file was deleted.

12 changes: 6 additions & 6 deletions src/utils/fetch.js → src/utils/fetch/fetch.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fetch from 'isomorphic-fetch';
import NetworkError from 'utils/NetworkError';
import isomorphicFetch from 'isomorphic-fetch';
import NetworkError from 'utils/networkerror/NetworkError';

function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
Expand Down Expand Up @@ -35,7 +35,7 @@ function parseError(response) {
* Wrapper around `window.fetch` to handle json parsing and offer a
* consistent error interface.
*
* xhr('/Users')
* fetch('/Users')
* .then(json => {
* console.log('success', json);
* }, networkError => {
Expand All @@ -48,17 +48,17 @@ function parseError(response) {
* @param {Object} options https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch
* @return {Promise}
*/
function xhr(url, options = {}) {
function fetch(url, options = {}) {
options = Object.assign({
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}, options);

return fetch(url, options)
return isomorphicFetch(url, options)
.then(checkStatus)
.then(parseSuccess, parseError);
}

export default xhr;
export default fetch;
106 changes: 106 additions & 0 deletions src/utils/fetch/fetch.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
jest.mock('isomorphic-fetch');

import isomorphicFetch from 'isomorphic-fetch';
import fetch from 'utils/fetch/fetch';

describe('utils/fetch/fetch', () => {

let throwFn;

beforeEach(() => {
const response = new Response('{}', { status: 200 , statusText: 'OKs' });
isomorphicFetch.mockClear();
isomorphicFetch.mockReturnValue(Promise.resolve(response));
throwFn = jest.fn(() => { throw new Error('expected `throwFn` not to be called') });
});

it('returns a promise', () => {
expect(fetch('http://foo.com/bar')).toBeInstanceOf(Promise);
});

it('uses json headers by default', () => {
fetch('http://foo.com/bar');
expect(isomorphicFetch).toBeCalledWith('http://foo.com/bar', {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
});

describe('successful responses', () => {

it('handles valid json responses', () => {
const response = new Response('{ "foo": "bar" }', { status: 200, statusText: 'OKs' });
isomorphicFetch.mockReturnValue(Promise.resolve(response));
return fetch('http://foo.com/bar')
.then(data => {
expect(data).toEqual({ foo: 'bar' });
});
});

it('handles invalid json responses', () => {
const response = new Response('{ invalid json', { status: 200, statusText: 'OKs' });
isomorphicFetch.mockReturnValue(Promise.resolve(response));
return fetch('http://foo.com/bar')
.then(throwFn, error => {
expect(error.message).toBe('Invalid JSON Response');
});
});

[{
status: 201,
statusText: 'Created'
}, {
status: 204,
statusText: 'No Content'
}].forEach(({ status, statusText }) => {
it(`handles ${status} responses`, () => {
const response = new Response(void 0, { status, statusText });
isomorphicFetch.mockReturnValue(Promise.resolve(response));
return fetch('http://foo.com/bar')
.then(data => {
expect(data).toEqual({});
});
});
});

});

describe('unsuccessful responses', () => {

it('handles valid json responses', () => {
const response = new Response('{ "foo": "bar" }', { status: 400, statusText: 'Bad Request' });
isomorphicFetch.mockReturnValue(Promise.resolve(response));
return fetch('http://foo.com/bar')
.then(throwFn, error => {
expect(error.status).toBe(400);
expect(error.message).toBe('Bad Request');
expect(error.response).toEqual({ foo: 'bar' });
});
});

it('handles invalid json responses', () => {
const response = new Response('{ invalid json', { status: 400, statusText: 'Bad Request' });
isomorphicFetch.mockReturnValue(Promise.resolve(response));
return fetch('http://foo.com/bar')
.then(throwFn, error => {
expect(error.status).toBe(400);
expect(error.message).toBe('Bad Request');
expect(error.response).toEqual({});
});
});

it('handles offline / cors errors', () => {
isomorphicFetch.mockReturnValue(Promise.resolve({ message: 'Failed to fetch' }));
return fetch('http://foo.com/bar')
.then(throwFn, error => {
expect(error.status).toBe(void 0);
expect(error.message).toBe('Failed to fetch');
expect(error.response).toEqual({});
});
});

});

});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ExtendableError from 'utils/ExtendableError';
import ExtendableError from 'es6-error';

class NetworkError extends ExtendableError {
constructor(message, status, json = {}) {
Expand Down
29 changes: 29 additions & 0 deletions src/utils/networkerror/NetworkError.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import NetworkError from 'utils/networkerror/NetworkError';

describe('utils/networkerror/NetworkError', () => {

it('extends `Error`', () => {
expect(new NetworkError()).toBeInstanceOf(Error);
});

it('defines `message`', () => {
expect(new NetworkError('Foo bar').message).toBe('Foo bar');
});

it('defines `status`', () => {
expect(new NetworkError(void 0, 404).status).toBe(404);
});

it('defines `response`', () => {
expect(new NetworkError(void 0, 404, {
foo: 'bar'
}).response).toEqual({
foo: 'bar'
});
});

it('`response` defaults to an object', () => {
expect(new NetworkError().response).toEqual({});
});

});

0 comments on commit bed7096

Please sign in to comment.