diff --git a/src/actions/helpers.js b/src/actions/helpers.js index 1b9605c71..d6a1938db 100644 --- a/src/actions/helpers.js +++ b/src/actions/helpers.js @@ -31,19 +31,15 @@ export function emptyError() { } export function bindClientFunc(clientFunc, request, success, failure, ...args) { - return (dispatch, getState) => { - function onRequest() { - return dispatch(requestData(request), getState); - } + return async (dispatch, getState) => { + dispatch(requestData(request), getState); - function onSuccess(data) { - return dispatch(requestSuccess(success, data), getState); - } + try { + const data = await clientFunc(...args); - function onFailure(err) { - return dispatch(requestFailure(failure, err), getState); + dispatch(requestSuccess(success, data), getState); + } catch (err) { + dispatch(requestFailure(failure, err)); } - - return dispatch(() => clientFunc(...args, onRequest, onSuccess, onFailure), getState); }; } diff --git a/src/client/client.js b/src/client/client.js index 8a7ebc2ee..a60fdc652 100644 --- a/src/client/client.js +++ b/src/client/client.js @@ -3,9 +3,12 @@ const HEADER_AUTH = 'Authorization'; const HEADER_BEARER = 'BEARER'; +const HEADER_CONTENT_TYPE = 'Content-Type'; const HEADER_REQUESTED_WITH = 'X-Requested-With'; const HEADER_TOKEN = 'token'; +const CONTENT_TYPE_JSON = 'application/json'; + export default class Client { constructor() { this.teamId = ''; @@ -125,126 +128,96 @@ export default class Client { // General routes - getClientConfig = (onRequest, onSuccess, onFailure) => { + getClientConfig = async () => { return this.doFetch( `${this.getGeneralRoute()}/client_props`, - {method: 'get'}, - onRequest, - onSuccess, - onFailure + {method: 'get'} ); } - getPing = (onRequest, onSuccess, onFailure) => { + getPing = async () => { return this.doFetch( `${this.getGeneralRoute()}/ping`, - {method: 'get'}, - onRequest, - onSuccess, - onFailure + {method: 'get'} ); } - logClientError = (message, level, onRequest, onSuccess, onFailure) => { + logClientError = async (message, level = 'ERROR') => { const body = { message, - level: level || 'ERROR' + level }; return this.doFetch( `${this.getGeneralRoute()}/log_client`, - {method: 'post', body}, - onRequest, - onSuccess, - onFailure + {method: 'post', body} ); } // User routes - createUser = (user, onRequest, onSuccess, onFailure) => { + createUser = async (user) => { return this.doFetch( `${this.getUsersRoute()}/create`, - {method: 'post', body: JSON.stringify(user)}, - onRequest, - onSuccess, - onFailure + {method: 'post', body: JSON.stringify(user)} ); } - login = (loginId, password, token, onRequest, onSuccess, onFailure) => { + login = async (loginId, password, token = '') => { const body = { login_id: loginId, password, token }; - return this.doFetch( + const {response, data} = await this.doFetchWithResponse( `${this.getUsersRoute()}/login`, - {method: 'post', body: JSON.stringify(body)}, - onRequest, - (data, response) => { - if (response.headers.has(HEADER_TOKEN)) { - this.token = response.headers.get(HEADER_TOKEN); - } - - onSuccess(data, response); - }, - onFailure + {method: 'post', body: JSON.stringify(body)} ); + + if (response.headers.has(HEADER_TOKEN)) { + this.token = response.headers.get(HEADER_TOKEN); + } + + return data; } - getInitialLoad = (onRequest, onSuccess, onFailure) => { + getInitialLoad = async () => { return this.doFetch( `${this.getUsersRoute()}/initial_load`, - {method: 'get'}, - onRequest, - onSuccess, - onFailure + {method: 'get'} ); } // Team routes - createTeam = (team, onRequest, onSuccess, onFailure) => { + createTeam = async (team) => { return this.doFetch( `${this.getTeamsRoute()}/create`, - {method: 'post', body: JSON.stringify(team)}, - onRequest, - onSuccess, - onFailure + {method: 'post', body: JSON.stringify(team)} ); } - fetchTeams = (onRequest, onSuccess, onFailure) => { + fetchTeams = async () => { return this.doFetch( `${this.getTeamsRoute()}/all_team_listings`, - {method: 'get'}, - onRequest, - onSuccess, - onFailure + {method: 'get'} ); } // Channel routes - createChannel = (channel, onRequest, onSuccess, onFailure) => { + createChannel = async (channel) => { return this.doFetch( `${this.getChannelsRoute()}/create`, - {method: 'post', body: JSON.stringify(channel)}, - onRequest, - onSuccess, - onFailure + {method: 'post', body: JSON.stringify(channel)} ); } - fetchChannels = (onRequest, onSuccess, onFailure) => { + fetchChannels = async () => { return this.doFetch( `${this.getChannelsRoute()}/`, - {method: 'get'}, - onRequest, - onSuccess, - onFailure + {method: 'get'} ); } @@ -259,45 +232,50 @@ export default class Client { ); } - createPost = (post, onRequest, onSuccess, onFailure) => { + createPost = async (post) => { return this.doFetch( `${this.getPostsRoute(post.channel_id)}/create`, - {method: 'post', body: JSON.stringify(post)}, - onRequest, - onSuccess, - onFailure + {method: 'post', body: JSON.stringify(post)} ); } - doFetch = async (url, options, onRequest, onSuccess, onFailure) => { - if (onRequest) { - onRequest(); - } - try { - const resp = await fetch(url, this.getOptions(options)); - let data; + doFetch = async (url, options) => { + const {data} = await this.doFetchWithResponse(url, options); - const contentType = resp.headers.get('Content-Type') || 'unknown'; - if (contentType.match(/application\/json/)) { - data = await resp.json(); - } else { - data = await resp.text(); - } - if (resp.ok) { - return onSuccess(data, resp); - } - let msg; - if (contentType === 'application/json') { - msg = data.message; - } else { - msg = data; - } - throw new Error(msg); - } catch (err) { - if (this.logToConsole) { - console.log(err); // eslint-disable-line no-console - } - return onFailure(err); + return data; + } + + doFetchWithResponse = async (url, options) => { + const response = await fetch(url, this.getOptions(options)); + + const contentType = response.headers.get(HEADER_CONTENT_TYPE); + const isJson = contentType && contentType.indexOf(CONTENT_TYPE_JSON) !== -1; + + let data; + if (isJson) { + data = await response.json(); + } else { + data = await response.text(); } + + if (response.ok) { + return { + response, + data + }; + } + + let msg; + if (isJson) { + msg = data.message || ''; + } else { + msg = data; + } + + if (this.logToConsole) { + console.error(msg); // eslint-disable-line no-console + } + + throw new Error(msg); } } diff --git a/test/actions/general.test.js b/test/actions/general.test.js index 10ae793d6..a220ff51f 100644 --- a/test/actions/general.test.js +++ b/test/actions/general.test.js @@ -10,7 +10,7 @@ import TestHelper from 'test_helper.js'; describe('Actions.General', () => { it('getClientConfig', (done) => { - TestHelper.initClient(Client, () => { + TestHelper.initBasic(Client).then(() => { const store = configureStore(); store.subscribe(() => { @@ -36,7 +36,7 @@ describe('Actions.General', () => { }); it('getPing', (done) => { - TestHelper.initClient(Client, () => { + TestHelper.initBasic(Client).then(() => { const store = configureStore(); store.subscribe(() => { @@ -54,7 +54,7 @@ describe('Actions.General', () => { }); it('getPing - Invalid URL', (done) => { - TestHelper.initClient(Client, () => { + TestHelper.initBasic(Client).then(() => { const store = configureStore(); store.subscribe(() => { diff --git a/test/client/client.test.js b/test/client/client.test.js index 13c4a8b35..ba6312bcc 100644 --- a/test/client/client.test.js +++ b/test/client/client.test.js @@ -1,7 +1,6 @@ // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import assert from 'assert'; import fetchMock from 'fetch_mock'; import TestHelper from 'test_helper.js'; @@ -35,25 +34,9 @@ fetchMock.post(/\/log_client/, { }); describe('Client', () => { - it('doFetch', (done) => { + it('doFetch', async () => { const client = TestHelper.createClient(); - let onRequestCalled = false; - - client.doFetch( - `${client.getGeneralRoute()}/ping`, - {}, - () => { - onRequestCalled = true; - }, - () => { - assert.ok(onRequestCalled, 'onSuccess called before onRequest'); - - done(); - }, - (err) => { - done(new Error(err)); - } - ); + return client.doFetch(`${client.getGeneralRoute()}/ping`, {}); }); }); diff --git a/test/client/client_channel.test.js b/test/client/client_channel.test.js index e444af061..9429cbe67 100644 --- a/test/client/client_channel.test.js +++ b/test/client/client_channel.test.js @@ -6,24 +6,14 @@ import assert from 'assert'; import TestHelper from 'test_helper.js'; describe('Client.Channel', () => { - it('createChannel', (done) => { - TestHelper.initBasic(({client, team}) => { - const channel = TestHelper.fakeChannel(team.id); + it('createChannel', async () => { + const {client, team} = await TestHelper.initBasic(); + const channel = TestHelper.fakeChannel(team.id); - client.createChannel( - channel, - null, - (data) => { - assert.ok(data.id, 'id is empty'); - assert.equal(data.name, channel.name, 'name doesn\'t match'); - assert.equal(data.team_id, channel.team_id, 'team id doesn\'t match'); + const rchannel = await client.createChannel(channel); - done(); - }, - (err) => { - done(new Error(err)); - } - ); - }); + assert.ok(rchannel.id, 'id is empty'); + assert.equal(rchannel.name, channel.name, 'name doesn\'t match'); + assert.equal(rchannel.team_id, channel.team_id, 'team id doesn\'t match'); }); }); diff --git a/test/client/client_general.test.js b/test/client/client_general.test.js index 5f78e70be..6a6491aa7 100644 --- a/test/client/client_general.test.js +++ b/test/client/client_general.test.js @@ -5,71 +5,43 @@ import assert from 'assert'; import TestHelper from 'test_helper.js'; -describe('Client.General', () => { - it('getClientConfig', (done) => { - TestHelper.initBasic(({client}) => { - client.getClientConfig( - null, - (data) => { - assert.ok(data.Version); - assert.ok(data.BuildNumber); - assert.ok(data.BuildDate); - assert.ok(data.BuildHash); +describe('Client.General', function() { + it('getClientConfig', async () => { + const {client} = await TestHelper.initBasic(); - done(); - }, - (err) => { - done(new Error(err)); - } - ); - }); + const clientConfig = await client.getClientConfig('foo'); + + assert.ok(clientConfig.Version); + assert.ok(clientConfig.BuildNumber); + assert.ok(clientConfig.BuildDate); + assert.ok(clientConfig.BuildHash); }); - it('getPing', (done) => { - TestHelper.initBasic(({client}) => { - client.getPing( - null, - () => { - done(); - }, - (err) => { - done(new Error(err)); - } - ); - }); + it('getPing', async () => { + const {client} = await TestHelper.initBasic(); + + await client.getPing(); }); - it('getPing - Invalid URL', (done) => { - TestHelper.initBasic(({client}) => { - client.setUrl('https://example.com/fake/url'); + it('getPing - Invalid URL', async () => { + const {client} = await TestHelper.initBasic(); + client.setUrl('https://example.com/fake/url'); - client.getPing( - null, - () => { - done(new Error('ping should\'ve failed')); - }, - () => { - done(); - } - ); - }); + let errored; + try { + await client.getPing(); + + errored = false; + } catch (err) { + errored = true; + } + + assert.ok(errored, 'should have errored'); }); - it('logClientError', function(done) { - TestHelper.initBasic(({client}) => { - client.logClientError( - 'this is a test', - 'ERROR', - null, - (data) => { - TestHelper.assertStatusOkay(data); + it('logClientError', async () => { + const {client} = await TestHelper.initBasic(); - done(); - }, - (err) => { - done(new Error(err)); - } - ); - }); + await client.logClientError('this is a test'); }); }); diff --git a/test/client/client_post.test.js b/test/client/client_post.test.js index d054a1985..cb2ff521a 100644 --- a/test/client/client_post.test.js +++ b/test/client/client_post.test.js @@ -6,22 +6,12 @@ import assert from 'assert'; import TestHelper from 'test_helper.js'; describe('Client.Post', () => { - it('createPost', (done) => { - TestHelper.initBasic(({client, channel}) => { - const post = TestHelper.fakePost(channel.id); + it('createPost', async () => { + const {client, channel} = await TestHelper.initBasic(); + const post = TestHelper.fakePost(channel.id); - client.createPost( - post, - null, - (data) => { - assert.ok(data.id, 'id is empty'); + const rpost = await client.createPost(post); - done(); - }, - (err) => { - done(new Error(err)); - } - ); - }); + assert.ok(rpost.id, 'id is empty'); }); }); diff --git a/test/client/client_team.test.js b/test/client/client_team.test.js index 7f9b6b3bc..aeab356f5 100644 --- a/test/client/client_team.test.js +++ b/test/client/client_team.test.js @@ -6,22 +6,13 @@ import assert from 'assert'; import TestHelper from 'test_helper.js'; describe('Client.Team', () => { - it('createTeam', (done) => { + it('createTeam', async () => { const client = TestHelper.createClient(); const team = TestHelper.fakeTeam(); - client.createTeam( - team, - null, - (data) => { - assert.equal(data.id.length > 0, true); - assert.equal(data.name, team.name); + const rteam = await client.createTeam(team); - done(); - }, - (err) => { - done(new Error(err)); - } - ); + assert.equal(rteam.id.length > 0, true); + assert.equal(rteam.name, team.name); }); }); diff --git a/test/client/client_user.test.js b/test/client/client_user.test.js index db477cb39..b933ea67f 100644 --- a/test/client/client_user.test.js +++ b/test/client/client_user.test.js @@ -6,70 +6,37 @@ import assert from 'assert'; import TestHelper from 'test_helper.js'; describe('Client.User', () => { - it('createUser', (done) => { + it('createUser', async () => { const client = TestHelper.createClient(); const user = TestHelper.fakeUser(); - client.createUser( - user, - null, - (data) => { - assert.ok(data.id, 'id is empty'); - assert.equal(data.email, user.email, 'email addresses aren\'t equal'); + const ruser = await client.createUser(user); - done(); - }, - (err) => { - done(new Error(err)); - } - ); + assert.ok(ruser.id, 'id is empty'); + assert.equal(ruser.email, user.email, 'email addresses aren\'t equal'); }); - it('login', (done) => { + it('login', async () => { const client = TestHelper.createClient(); const user = TestHelper.fakeUser(); - client.createUser( - user, - null, - () => { - client.login( - user.email, - user.password, - '', - null, - (data) => { - assert.ok(data.id, 'id is empty'); - assert.equal(data.email, user.email, 'email addresses aren\'t equal'); - assert.ok(client.token, 'token is empty'); + user.password = 'password'; + await client.createUser(user); - done(); - }, - (err) => { - done(new Error(err)); - } - ); - }, - (err) => { - done(new Error(err)); - } - ); + const ruser = await client.login(user.email, user.password); + + assert.ok(ruser.id, 'id is empty'); + assert.equal(ruser.email, user.email, 'email addresses aren\'t equal'); + assert.ok(!ruser.password, 'returned password should be empty'); + assert.ok(client.token, 'token is empty'); }); - it('getInitialLoad', (done) => { - TestHelper.initBasic(({client, user}) => { - client.getInitialLoad( - null, - (data) => { - assert.ok(data.user.id.length, 'id is empty'); - assert.equal(data.user.id, user.id, 'user ids don\'t match'); + it('getInitialLoad', async () => { + const {client, user} = await TestHelper.initBasic(); - done(); - }, - (err) => { - done(new Error(err)); - } - ); - }); + const data = await client.getInitialLoad(); + + assert.ok(data.user.id.length, 'id is empty'); + assert.equal(data.user.id, user.id, 'user ids don\'t match'); }); }); diff --git a/test/sanity.test.js b/test/sanity.test.js index 64130158e..56b8c4d8c 100644 --- a/test/sanity.test.js +++ b/test/sanity.test.js @@ -14,15 +14,20 @@ describe('Sanity test', () => { Promise.resolve(true).then(() => { done(); }).catch((err) => { - done.fail(err); + done(err); }); }); + it('async/await', async () => { + await Promise.resolve(true); + }); + it('fetch', (done) => { fetch('http://example.com').then(() => { done(); - }).catch((err) => { - done.fail(err); + }).catch(() => { + // No internet connection, but fetch still returned at least + done(); }); }); }); diff --git a/test/test_helper.js b/test/test_helper.js index b9809fb70..e42fa7cd6 100644 --- a/test/test_helper.js +++ b/test/test_helper.js @@ -130,7 +130,6 @@ fetchMock.post(/\/users\/login$/, (url, opts) => { token: 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' }, body: {...fakeUserRespBody, - ...reqBody, email: reqBody.login_id } }; @@ -244,83 +243,26 @@ class TestHelper { }; } - initClient = (client, callback) => { + initBasic = async (client = this.createClient()) => { client.setUrl(Config.DefaultServerUrl); + this.basicClient = client; - client.createUser( - this.fakeUser(), - null, - (user) => { - this.basicUser = user; + this.basicUser = await client.createUser(this.fakeUser()); + await client.login(this.basicUser.email, PASSWORD); - client.login( - user.email, - PASSWORD, - '', - null, - () => { - client.createTeam( - this.fakeTeam(), - null, - (team) => { - this.basicTeam = team; + this.basicTeam = await client.createTeam(this.fakeTeam()); + client.setTeamId(this.basicTeam.id); - client.setTeamId(team.id); + this.basicChannel = await client.createChannel(this.fakeChannel(this.basicTeam.id)); + this.basicPost = await client.createPost(this.fakePost(this.basicChannel.id)); - client.createChannel( - this.fakeChannel(this.basicTeam.id), - null, - (channel) => { - this.basicChannel = channel; - - client.createPost( - this.fakePost(this.basicChannel.id), - null, - (post) => { - this.basicPost = post; - - callback({ - client, - user: this.basicUser, - team: this.basicTeam, - channel: this.basicChannel, - post: this.basicPost - }); - }, - (err) => { - console.error(err); - throw err; - } - ); - }, - (err) => { - console.error(err); - throw err; - } - ); - }, - (err) => { - console.error(err); - throw err; - } - ); - }, - (err) => { - console.error(err); - throw err; - } - ); - }, - (err) => { - throw err; - } - ); - } - - initBasic = (callback) => { - this.basicClient = this.createClient(); - - this.initClient(this.basicClient, callback); + return { + client: this.basicClient, + user: this.basicUser, + team: this.basicTeam, + channel: this.basicChannel, + post: this.basicPost + }; } }