From af07890853cd01721bca81dd1e693b62635dda80 Mon Sep 17 00:00:00 2001 From: Richard Park Date: Tue, 2 Aug 2016 00:14:14 -0400 Subject: [PATCH] feat(api): dispatch requests to soundcloud api --- src/core/api/_specs/api-service.spec.js | 107 ++++++++++++++++++++++++ src/core/api/api-service.js | 30 +++++++ src/core/constants.js | 16 ++++ 3 files changed, 153 insertions(+) create mode 100644 src/core/api/_specs/api-service.spec.js create mode 100644 src/core/api/api-service.js create mode 100644 src/core/constants.js diff --git a/src/core/api/_specs/api-service.spec.js b/src/core/api/_specs/api-service.spec.js new file mode 100644 index 0000000..782b4d2 --- /dev/null +++ b/src/core/api/_specs/api-service.spec.js @@ -0,0 +1,107 @@ +import { API_BASE_URL, CLIENT_ID_PARAM, PAGINATION_PARAMS } from 'src/core/constants'; +import { api, dispatch, requestUrl } from '../api-service'; + + +describe('api', () => { + describe('service', () => { + let body; + let server; + let successResponse; + + + beforeEach(() => { + body = {}; + server = sinon.fakeServer.create(); + successResponse = [200, {'Content-type': 'application/json'}, JSON.stringify(body)]; + }); + + + afterEach(() => { + server.restore(); + }); + + + describe('requestUrl()', () => { + it('should add client id param to url', () => { + let url = requestUrl({url: API_BASE_URL}); + expect(url).toMatch(CLIENT_ID_PARAM); + }); + + it('should NOT add duplicate client id param to url', () => { + let regExp = new RegExp(CLIENT_ID_PARAM, 'gi'); + let url = requestUrl({url: `${API_BASE_URL}?${CLIENT_ID_PARAM}`}); + expect(url.match(regExp).length).toBe(1); + }); + + it('should add pagination params to url if options.paginate is true', () => { + let url = requestUrl({paginate: true, url: API_BASE_URL}); + expect(url).toMatch(PAGINATION_PARAMS); + }); + + it('should NOT add pagination params to url by default', () => { + let url = requestUrl({url: API_BASE_URL}); + expect(url).not.toMatch(PAGINATION_PARAMS); + }); + }); + + + describe('dispatch()', () => { + const url = `${API_BASE_URL}?${CLIENT_ID_PARAM}`; + + it('should set request header `Accept: application/json`', () => { + server.respondWith('get', url, ({requestHeaders}) => { + expect(requestHeaders.Accept).toBe('application/json'); + return successResponse; + }); + + dispatch({url: API_BASE_URL}); + server.respond(); + }); + + it('should resolve promise with response body', done => { + server.respondWith('get', url, successResponse); + + dispatch({url: API_BASE_URL}) + .then(responseBody => { + expect(responseBody).toEqual(body); + done(); + }) + .catch(error => { + fail(error); + done(); + }); + + server.respond(); + }); + + it('should reject promise for soundcloud error codes', () => { + [400, 401, 403, 404, 406, 422, 429, 500, 503, 504] + .forEach(code => { + server.respondWith([code, {}, JSON.stringify({})]); + + dispatch({url: API_BASE_URL}) + .catch(error => { + expect(error.status).toBe(code); + }); + + server.respond(); + }); + }); + }); + + + describe('api.fetch()', () => { + it('should perform GET request with correct url', () => { + const url = `${API_BASE_URL}?${CLIENT_ID_PARAM}`; + + server.respondWith('get', url, request => { + expect(request.url).toBe(url); + return successResponse; + }); + + api.fetch(url); + server.respond(); + }); + }); + }); +}); diff --git a/src/core/api/api-service.js b/src/core/api/api-service.js new file mode 100644 index 0000000..97e2a57 --- /dev/null +++ b/src/core/api/api-service.js @@ -0,0 +1,30 @@ +import request from 'superagent'; +import { CLIENT_ID_PARAM, PAGINATION_PARAMS } from 'src/core/constants'; + + +export const api = { + fetch(url) { + return dispatch({url}); + } +}; + + +export function dispatch(options) { + return request[options.method || 'get'](requestUrl(options)) + .set('Accept', 'application/json') + .then(response => response.body); +} + +export function requestUrl({paginate, url}) { + let params = []; + + if (!url.includes(CLIENT_ID_PARAM)) params.push(CLIENT_ID_PARAM); + if (paginate) params.push(PAGINATION_PARAMS); + + if (params.length) { + url += url.indexOf('?') === -1 ? '?' : '&'; + url += params.join('&'); + } + + return url; +} diff --git a/src/core/constants.js b/src/core/constants.js new file mode 100644 index 0000000..eb66444 --- /dev/null +++ b/src/core/constants.js @@ -0,0 +1,16 @@ +//========================================================= +// CONSTANTS +//--------------------------------------------------------- +export const APP_NAME = 'soundcloud-redux'; + + +//===================================== +// API +//------------------------------------- +export const API_BASE_URL = 'https://api.soundcloud.com'; + +export const CLIENT_ID = process.env.SOUNDCLOUD_CLIENT_ID || 'd02c42795f3bcac39f84eee0ae384b00'; +export const CLIENT_ID_PARAM = `client_id=${CLIENT_ID}`; + +export const PAGINATION_LIMIT = 3; +export const PAGINATION_PARAMS = `limit=${PAGINATION_LIMIT}&linked_partitioning=1`;