From 5c95551e8f1b4566dd98d78fdfdf7d98c3e6603c Mon Sep 17 00:00:00 2001 From: ayusharma Date: Fri, 29 Jun 2018 01:15:54 +0200 Subject: [PATCH] refactor: unit tests and api service refactor: fixes login api success call refactor: fixes login respose for success case --- src/webui/src/components/Header/index.js | 10 ++--- .../src/components/PackageSidebar/index.jsx | 4 +- src/webui/src/modules/detail/index.jsx | 2 +- src/webui/src/modules/home/index.js | 4 +- src/webui/utils/api.js | 42 +++++++++++++++---- test/unit/webui/components/__mocks__/api.js | 6 +-- test/unit/webui/components/header.spec.js | 28 +++++++++---- test/unit/webui/components/store/login.js | 16 +++---- test/unit/webui/components/store/logo.js | 6 ++- 9 files changed, 72 insertions(+), 46 deletions(-) diff --git a/src/webui/src/components/Header/index.js b/src/webui/src/components/Header/index.js index 3426805c1..19d0d95ad 100644 --- a/src/webui/src/components/Header/index.js +++ b/src/webui/src/components/Header/index.js @@ -44,7 +44,7 @@ export default class Header extends React.Component { componentWillMount() { API.request('logo') - .then((response) => response.text().then((logo) => this.setState({logo}))) + .then((logo) => this.setState({logo})) .catch((error) => { throw new Error(error); }); @@ -66,13 +66,13 @@ export default class Header extends React.Component { username: this.state.username, password: this.state.password }; - let resp = await API.request(`login`, 'POST', { + const resp = await API.request(`login`, 'POST', { body: JSON.stringify(credentials), headers: { Accept: HEADERS.JSON, 'Content-Type': HEADERS.JSON } - }).then((response) => response.json()); + }); storage.setItem('token', resp.token); storage.setItem('username', resp.username); @@ -80,9 +80,9 @@ export default class Header extends React.Component { } catch (e) { const errorObj = { title: 'Unable to login', - type: 'error' + type: 'error', + description: e.error }; - errorObj.description = e.message; this.setState({loginError: errorObj}); } } diff --git a/src/webui/src/components/PackageSidebar/index.jsx b/src/webui/src/components/PackageSidebar/index.jsx index 82f535dcb..deed61706 100644 --- a/src/webui/src/components/PackageSidebar/index.jsx +++ b/src/webui/src/components/PackageSidebar/index.jsx @@ -33,9 +33,7 @@ export default class PackageSidebar extends React.Component { let packageMeta; try { - packageMeta = await API.request(`sidebar/${packageName}`, 'GET').then(function(response) { - return response.json(); - }); + packageMeta = await API.request(`sidebar/${packageName}`, 'GET'); } catch (err) { this.setState({ failed: true diff --git a/src/webui/src/modules/detail/index.jsx b/src/webui/src/modules/detail/index.jsx index acd93be16..0c305426c 100644 --- a/src/webui/src/modules/detail/index.jsx +++ b/src/webui/src/modules/detail/index.jsx @@ -47,7 +47,7 @@ export default class Detail extends React.Component { }); try { - const resp = await API.request(`package/readme/${packageName}`, 'GET').then((response) => response.text()); + const resp = await API.request(`package/readme/${packageName}`, 'GET'); this.setState({ readMe: resp }); diff --git a/src/webui/src/modules/home/index.js b/src/webui/src/modules/home/index.js index 8160d79f8..72a19879f 100644 --- a/src/webui/src/modules/home/index.js +++ b/src/webui/src/modules/home/index.js @@ -51,7 +51,7 @@ export default class Home extends React.Component { async loadPackages() { try { - this.req = await API.request('packages', 'GET').then((response) => response.json()); + this.req = await API.request('packages', 'GET'); if (this.state.query === '') { this.setState({ @@ -70,7 +70,7 @@ export default class Home extends React.Component { async searchPackage(query) { try { - this.req = await API.request(`/search/${query}`, 'GET').then((response) => response.json()); + this.req = await API.request(`/search/${query}`, 'GET'); // Implement cancel feature later if (this.state.query === query) { diff --git a/src/webui/utils/api.js b/src/webui/utils/api.js index c76ffe3e2..fa0436ca4 100644 --- a/src/webui/utils/api.js +++ b/src/webui/utils/api.js @@ -17,18 +17,42 @@ class API { url = window.VERDACCIO_API_URL + url; } - function handleErrors(response) { - if (!response.ok) { - throw Error(response.statusText); + /** + * Handles response according to content type + * @param {object} response + * @returns {promise} + */ + function handleResponseType(response) { + if (response.headers) { + const contentType = response.headers.get('Content-Type'); + if (contentType.includes('application/pdf')) { + return Promise.all([response.ok, response.blob()]); + } + if (contentType.includes('application/json')) { + return Promise.all([response.ok, response.json()]); + } + // it includes all text types + if (contentType.includes('text/')) { + return Promise.all([response.ok, response.text()]); + } } - return response; } - return fetch(url, { - method, - credentials: 'same-origin', - ...options - }).then(handleErrors); + return new Promise((resolve, reject) => { + fetch(url, { + method, + credentials: 'same-origin', + ...options + }) + .then(handleResponseType) + .then(([responseOk, body]) => { + if (responseOk) { + resolve(body); + } else { + reject(body); + } + }); + }); } } diff --git a/test/unit/webui/components/__mocks__/api.js b/test/unit/webui/components/__mocks__/api.js index 2c8e2cf3e..afd8eeb44 100644 --- a/test/unit/webui/components/__mocks__/api.js +++ b/test/unit/webui/components/__mocks__/api.js @@ -22,11 +22,7 @@ const register = (url, method = 'get', options = {}) => { if (url === 'sidebar/verdaccio' && method.toLocaleLowerCase() === 'get') { return new Promise(function(resolve) { - resolve({ - json: function() { - return packageMeta; - } - }); + resolve(packageMeta); }); } diff --git a/test/unit/webui/components/header.spec.js b/test/unit/webui/components/header.spec.js index 2bb42f3ae..a0718d5be 100644 --- a/test/unit/webui/components/header.spec.js +++ b/test/unit/webui/components/header.spec.js @@ -55,7 +55,7 @@ describe('
component shallow', () => { it('handleSubmit - should give error for blank username and password', () => { const HeaderWrapper = wrapper.find(Header).dive(); - const handleSubmit = HeaderWrapper.instance().handleSubmit; + const {handleSubmit} = HeaderWrapper.instance(); const error = { description: "Username or password can't be empty!", title: 'Unable to login', @@ -67,11 +67,14 @@ describe('
component shallow', () => { it('handleSubmit - should login successfully', () => { const HeaderWrapper = wrapper.find(Header).dive(); - const handleSubmit = HeaderWrapper.instance().handleSubmit; - + const {handleSubmit} = HeaderWrapper.instance(); + const event = {preventDefault: () => {}} + const spy = jest.spyOn(event, 'preventDefault'); + HeaderWrapper.setState({ username: 'sam', password: '1234' }); - handleSubmit().then(() => { + handleSubmit(event).then(() => { + expect(spy).toHaveBeenCalled(); expect(storage.getItem('token')).toEqual('TEST_TOKEN'); expect(storage.getItem('username')).toEqual('sam'); }); @@ -79,30 +82,37 @@ describe('
component shallow', () => { it('handleSubmit - login should failed with 401', () => { const HeaderWrapper = wrapper.find(Header).dive(); - const handleSubmit = HeaderWrapper.instance().handleSubmit; + const {handleSubmit} = HeaderWrapper.instance(); const errorObject = { title: 'Unable to login', type: 'error', - description: 'Unauthorized' + description: 'bad username/password, access denied' }; + const event = { preventDefault: () => { } } + const spy = jest.spyOn(event, 'preventDefault'); HeaderWrapper.setState({ username: 'sam', password: '12345' }); - handleSubmit().catch((error) => { + handleSubmit(event).then(() => { + expect(spy).toHaveBeenCalled(); expect(HeaderWrapper.state('loginError')).toEqual(errorObject); }); }); it('handleSubmit - login should failed with when no data is sent', () => { const HeaderWrapper = wrapper.find(Header).dive(); - const handleSubmit = HeaderWrapper.instance().handleSubmit; + const {handleSubmit} = HeaderWrapper.instance(); const error = { title: 'Unable to login', type: 'error', description: "Username or password can't be empty!" }; + const event = { preventDefault: () => { } } + const spy = jest.spyOn(event, 'preventDefault'); + HeaderWrapper.setState({}); - handleSubmit().then(() => { + handleSubmit(event).then(() => { + expect(spy).toHaveBeenCalled(); expect(HeaderWrapper.state('loginError')).toEqual(error); }); }); diff --git a/test/unit/webui/components/store/login.js b/test/unit/webui/components/store/login.js index 35f6897fc..bbe89e9e1 100644 --- a/test/unit/webui/components/store/login.js +++ b/test/unit/webui/components/store/login.js @@ -4,21 +4,17 @@ * @returns {promise} */ export default function(config) { - return new Promise(function(resolve, reject) { + return new Promise((resolve, reject) => { const body = JSON.parse(config.body); if (body.username === 'sam' && body.password === '1234') { - return new Promise(function(resolve) { resolve({ - json: function() { - return { - username: 'sam', - token: 'TEST_TOKEN' - } - } + username: 'sam', + token: 'TEST_TOKEN' }); - }); } else { - throw Error('Unauthorized'); + reject({ + error: 'bad username/password, access denied' + }); } }); } diff --git a/test/unit/webui/components/store/logo.js b/test/unit/webui/components/store/logo.js index 74162df22..11c4e9a3b 100644 --- a/test/unit/webui/components/store/logo.js +++ b/test/unit/webui/components/store/logo.js @@ -1,10 +1,12 @@ /** - * Mock response for login api + * Mock response for logo api * @returns {promise} */ export default function() { const response = { - url: 'http://xyz.com/image.jpg' + text(){ + return 'http://xyz.com/image.jpg'; + } }; return Promise.resolve(response); }