Added some more client APIs and refactored the client so it doesn't return a function
This commit is contained in:
parent
a4c7e96cb6
commit
559ea98840
8 changed files with 276 additions and 109 deletions
|
|
@ -26,7 +26,7 @@
|
|||
"remote-redux-devtools-on-debugger": "0.6.2"
|
||||
},
|
||||
"scripts": {
|
||||
"check": "eslint --ext \".jsx\" --ignore-pattern node_modules --quiet .",
|
||||
"check": "eslint --ext \".js\" --ignore-pattern node_modules --quiet .",
|
||||
"start": "node node_modules/react-native/local-cli/cli.js start",
|
||||
"test": "mocha --compilers js:babel-register **/*.test.js",
|
||||
"postinstall": "remotedev-debugger --hostname localhost --port 5678 --injectserver"
|
||||
|
|
|
|||
|
|
@ -33,17 +33,17 @@ export function emptyError() {
|
|||
export function bindClientFunc(clientFunc, request, success, failure, ...args) {
|
||||
return (dispatch, getState) => {
|
||||
function onRequest() {
|
||||
dispatch(requestData(request), getState);
|
||||
dispatch(() => requestData(request), getState);
|
||||
}
|
||||
|
||||
function onSuccess(data) {
|
||||
dispatch(requestSuccess(success, data), getState);
|
||||
dispatch(() => requestSuccess(success, data), getState);
|
||||
}
|
||||
|
||||
function onFailure(err) {
|
||||
dispatch(requestFailure(failure, err), getState);
|
||||
dispatch(() => requestFailure(failure, err), getState);
|
||||
}
|
||||
|
||||
return dispatch(clientFunc(onRequest, onSuccess, onFailure, ...args), getState);
|
||||
return dispatch(() => clientFunc(onRequest, onSuccess, onFailure, ...args), getState);
|
||||
};
|
||||
}
|
||||
|
|
@ -6,11 +6,11 @@ import 'isomorphic-fetch';
|
|||
const HEADER_AUTH = 'Authorization';
|
||||
const HEADER_BEARER = 'BEARER';
|
||||
const HEADER_REQUESTED_WITH = 'X-Requested-With';
|
||||
const HEADER_TOKEN = 'token';
|
||||
|
||||
export default class Client {
|
||||
constructor() {
|
||||
this.teamId = '';
|
||||
this.serverVersion = ''; // ??
|
||||
this.logToConsole = false;
|
||||
this.token = '';
|
||||
this.url = '';
|
||||
|
|
@ -26,10 +26,6 @@ export default class Client {
|
|||
this.url = url;
|
||||
}
|
||||
|
||||
setAcceptLanguage(locale) {
|
||||
this.defaultHeaders['Accept-Language'] = locale;
|
||||
}
|
||||
|
||||
setTeamId(id) {
|
||||
this.teamId = id;
|
||||
}
|
||||
|
|
@ -42,10 +38,6 @@ export default class Client {
|
|||
return this.teamId;
|
||||
}
|
||||
|
||||
getServerVersion() {
|
||||
return this.serverVersion;
|
||||
}
|
||||
|
||||
getBaseRoute() {
|
||||
return `${this.url}${this.urlVersion}`;
|
||||
}
|
||||
|
|
@ -114,27 +106,21 @@ export default class Client {
|
|||
return `${this.url}${this.urlVersion}/users/${userId}`;
|
||||
}
|
||||
|
||||
setTranslations(messages) {
|
||||
this.translations = messages;
|
||||
}
|
||||
|
||||
enableLogErrorsToConsole(enabled) {
|
||||
this.logToConsole = enabled;
|
||||
}
|
||||
|
||||
useHeaderToken() {
|
||||
this.useToken = true;
|
||||
if (this.token !== '') {
|
||||
this.defaultHeaders[HEADER_AUTH] = `${HEADER_BEARER} ${this.token}`;
|
||||
}
|
||||
}
|
||||
|
||||
getOptions(options) {
|
||||
const headers = {
|
||||
[HEADER_REQUESTED_WITH]: 'XMLHttpRequest'
|
||||
};
|
||||
|
||||
if (this.token) {
|
||||
headers[HEADER_AUTH] = `${HEADER_BEARER} ${this.token}`;
|
||||
}
|
||||
|
||||
return {
|
||||
headers: {
|
||||
[HEADER_AUTH]: this.token,
|
||||
[HEADER_REQUESTED_WITH]: 'XMLHttpRequest'
|
||||
},
|
||||
headers,
|
||||
...options
|
||||
};
|
||||
}
|
||||
|
|
@ -178,26 +164,37 @@ export default class Client {
|
|||
|
||||
// User routes
|
||||
|
||||
// login(onRequest, onSuccess, onFailure, loginId, password, token) {
|
||||
// const body = {
|
||||
// login_id: loginId,
|
||||
// password,
|
||||
// token
|
||||
// };
|
||||
createUser = (onRequest, onSuccess, onFailure, user) => {
|
||||
return this.doFetch(
|
||||
`${this.getUsersRoute()}/create`,
|
||||
{method: 'post', body: JSON.stringify(user)},
|
||||
onRequest,
|
||||
onSuccess,
|
||||
onFailure
|
||||
);
|
||||
}
|
||||
|
||||
// return this.doFetch(
|
||||
// `${this.getUsersRoute()}/login`,
|
||||
// {method: 'post', body},
|
||||
// onRequest,
|
||||
// (data, response) => {
|
||||
// console.log(response.headers);
|
||||
// // if (response.headers.)
|
||||
login = (onRequest, onSuccess, onFailure, loginId, password, token = null) => {
|
||||
const body = {
|
||||
login_id: loginId,
|
||||
password,
|
||||
token
|
||||
};
|
||||
|
||||
// onSuccess(data, response);
|
||||
// },
|
||||
// onFailure
|
||||
// );
|
||||
// }
|
||||
return this.doFetch(
|
||||
`${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
|
||||
);
|
||||
}
|
||||
|
||||
// getInitialLoad(success, error) {
|
||||
// request.
|
||||
|
|
@ -208,29 +205,41 @@ export default class Client {
|
|||
// end(this.handleResponse.bind(this, 'getInitialLoad', success, error));
|
||||
// }
|
||||
|
||||
// Team routes
|
||||
|
||||
createTeam = (onRequest, onSuccess, onFailure, team) => {
|
||||
return this.doFetch(
|
||||
`${this.getTeamsRoute()}/create`,
|
||||
{method: 'post', body: JSON.stringify(team)},
|
||||
onRequest,
|
||||
onSuccess,
|
||||
onFailure
|
||||
);
|
||||
}
|
||||
|
||||
doFetch = (url, options, onRequest, onSuccess, onFailure) => {
|
||||
return () => {
|
||||
if (onRequest) {
|
||||
onRequest();
|
||||
}
|
||||
|
||||
return fetch(url, this.getOptions(options)).then(
|
||||
(response) => {
|
||||
return response.json().then((data) => ({data, response}));
|
||||
}).then(({data, response}) => {
|
||||
if (!response.ok) {
|
||||
return Promise.reject(data);
|
||||
}
|
||||
|
||||
return onSuccess(data, response);
|
||||
}).catch((err) => {
|
||||
// TODO errors that return non-json data get sent here
|
||||
|
||||
if (this.logToConsole) {
|
||||
console.log(err); // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
onFailure(err);
|
||||
return fetch(url, this.getOptions(options)).then(
|
||||
(response) => {
|
||||
return response.json().then((data) => ({data, response}));
|
||||
}).then(({data, response}) => {
|
||||
if (!response.ok) {
|
||||
return Promise.reject(data);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return onSuccess(data, response);
|
||||
}).catch((err) => {
|
||||
// TODO errors that return non-json data get sent here
|
||||
|
||||
if (this.logToConsole) {
|
||||
console.log(err); // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
onFailure(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
30
test/client.test.js
Normal file
30
test/client.test.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import TestHelper from './test_helper.js';
|
||||
|
||||
describe('Client', () => {
|
||||
it('doFetch', (done) => {
|
||||
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));
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -8,7 +8,8 @@ import TestHelper from './test_helper.js';
|
|||
describe('Client.General', () => {
|
||||
it('General.getClientConfig', (done) => {
|
||||
TestHelper.initBasic(({client}) => {
|
||||
const {onRequest, onSuccess, onFailure} = TestHelper.assertOnRequestHappensFirst(
|
||||
client.getClientConfig(
|
||||
null,
|
||||
(data) => {
|
||||
assert.ok(data.Version);
|
||||
assert.ok(data.BuildNumber);
|
||||
|
|
@ -21,14 +22,13 @@ describe('Client.General', () => {
|
|||
done(new Error(err));
|
||||
}
|
||||
);
|
||||
|
||||
client.getClientConfig(onRequest, onSuccess, onFailure)();
|
||||
});
|
||||
});
|
||||
|
||||
it('General.getPing', (done) => {
|
||||
TestHelper.initBasic(({client}) => {
|
||||
const {onRequest, onSuccess, onFailure} = TestHelper.assertOnRequestHappensFirst(
|
||||
client.getPing(
|
||||
null,
|
||||
() => {
|
||||
done();
|
||||
},
|
||||
|
|
@ -36,14 +36,14 @@ describe('Client.General', () => {
|
|||
done(new Error(err));
|
||||
}
|
||||
);
|
||||
|
||||
client.getPing(onRequest, onSuccess, onFailure)();
|
||||
});
|
||||
});
|
||||
|
||||
it('General.getPing - Invalid URL', (done) => {
|
||||
TestHelper.initBasic(({client}) => {
|
||||
const {onRequest, onSuccess, onFailure} = TestHelper.assertOnRequestHappensFirst(
|
||||
client.setUrl('https://example.com/fake/url');
|
||||
client.getPing(
|
||||
null,
|
||||
() => {
|
||||
done(new Error('ping should\'ve failed'));
|
||||
},
|
||||
|
|
@ -51,24 +51,22 @@ describe('Client.General', () => {
|
|||
done();
|
||||
}
|
||||
);
|
||||
|
||||
client.setUrl('https://example.com/fake/url');
|
||||
client.getPing(onRequest, onSuccess, onFailure)();
|
||||
});
|
||||
});
|
||||
|
||||
// it('General.logClientError', function(done) {
|
||||
// const {onRequest, onSuccess, onFailure} = TestHelper.assertOnRequestHappensFirst(
|
||||
// (data) => {
|
||||
// TestHelper.assertStatusOkay(data);
|
||||
// TestHelper.initBasic(({client}) => {
|
||||
// client.logClientError(
|
||||
// null,
|
||||
// (data) => {
|
||||
// TestHelper.assertStatusOkay(data);
|
||||
|
||||
// done();
|
||||
// },
|
||||
// (err) => {
|
||||
// done(new Error(err));
|
||||
// }
|
||||
// );
|
||||
|
||||
// Client.logClientError(onRequest, onSuccess, onFailure)();
|
||||
// done();
|
||||
// },
|
||||
// (err) => {
|
||||
// done(new Error(err));
|
||||
// }
|
||||
// )();
|
||||
// });
|
||||
// });
|
||||
});
|
||||
|
|
|
|||
27
test/client_team.test.js
Normal file
27
test/client_team.test.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import TestHelper from './test_helper.js';
|
||||
|
||||
describe('Client.Team', () => {
|
||||
it('createTeam', (done) => {
|
||||
const client = TestHelper.createClient();
|
||||
const team = TestHelper.fakeTeam();
|
||||
|
||||
client.createTeam(
|
||||
null,
|
||||
(data) => {
|
||||
assert.equal(data.id.length > 0, true);
|
||||
assert.equal(data.name, team.name);
|
||||
|
||||
done();
|
||||
},
|
||||
(err) => {
|
||||
done(new Error(err));
|
||||
},
|
||||
team
|
||||
);
|
||||
});
|
||||
});
|
||||
58
test/client_user.test.js
Normal file
58
test/client_user.test.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import TestHelper from './test_helper.js';
|
||||
|
||||
describe('Client.User', () => {
|
||||
it('createUser', (done) => {
|
||||
const client = TestHelper.createClient();
|
||||
const user = TestHelper.fakeUser();
|
||||
|
||||
client.createUser(
|
||||
null,
|
||||
(data) => {
|
||||
assert.ok(data.id, 'id is empty');
|
||||
assert.equal(data.email, user.email, 'email addresses aren\'t equal');
|
||||
|
||||
done();
|
||||
},
|
||||
(err) => {
|
||||
done(new Error(err));
|
||||
},
|
||||
user
|
||||
);
|
||||
});
|
||||
|
||||
it('login', (done) => {
|
||||
const client = TestHelper.createClient();
|
||||
const user = TestHelper.fakeUser();
|
||||
|
||||
client.createUser(
|
||||
null,
|
||||
() => {
|
||||
client.login(
|
||||
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');
|
||||
|
||||
done();
|
||||
},
|
||||
(err) => {
|
||||
done(new Error(err));
|
||||
},
|
||||
user.email,
|
||||
user.password
|
||||
);
|
||||
},
|
||||
(err) => {
|
||||
console.log(err);
|
||||
done(new Error(err));
|
||||
},
|
||||
user
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -6,32 +6,36 @@ import assert from 'assert';
|
|||
import Client from 'client/client.js';
|
||||
|
||||
class TestHelper {
|
||||
assertOnRequestHappensFirst(onSuccess, onFailure) {
|
||||
let hasReceivedOnRequest = false;
|
||||
|
||||
return {
|
||||
onRequest: () => {
|
||||
hasReceivedOnRequest = true;
|
||||
},
|
||||
onSuccess: (response, data) => {
|
||||
assert(hasReceivedOnRequest);
|
||||
|
||||
onSuccess(response, data);
|
||||
},
|
||||
onFailure: (err) => {
|
||||
assert(hasReceivedOnRequest);
|
||||
|
||||
onFailure(err);
|
||||
}
|
||||
};
|
||||
constructor() {
|
||||
this.basicClient = null;
|
||||
}
|
||||
|
||||
assertStatusOkay(data) {
|
||||
assertStatusOkay = (data) => {
|
||||
assert(data);
|
||||
assert(data.status === 'OK');
|
||||
}
|
||||
|
||||
createClient() {
|
||||
generateId = () => {
|
||||
// Implementation taken from http://stackoverflow.com/a/2117523
|
||||
let id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
|
||||
|
||||
id = id.replace(/[xy]/g, (c) => {
|
||||
const r = Math.floor(Math.random() * 16);
|
||||
|
||||
let v;
|
||||
if (c === 'x') {
|
||||
v = r;
|
||||
} else {
|
||||
v = (r & 0x3) | 0x8;
|
||||
}
|
||||
|
||||
return v.toString(16);
|
||||
});
|
||||
|
||||
return 'uid' + id;
|
||||
}
|
||||
|
||||
createClient = () => {
|
||||
const client = new Client();
|
||||
|
||||
client.setUrl('http://localhost:8065');
|
||||
|
|
@ -39,7 +43,48 @@ class TestHelper {
|
|||
return client;
|
||||
}
|
||||
|
||||
initBasic(callback) {
|
||||
fakeEmail = () => {
|
||||
return 'success' + this.generateId() + '@simulator.amazonses.com';
|
||||
}
|
||||
|
||||
fakeUser = () => {
|
||||
return {
|
||||
email: this.fakeEmail(),
|
||||
allow_marketing: true,
|
||||
password: 'password1',
|
||||
username: this.generateId()
|
||||
};
|
||||
}
|
||||
|
||||
fakeTeam = () => {
|
||||
const name = this.generateId();
|
||||
|
||||
return {
|
||||
name,
|
||||
display_name: `Unit Test ${name}`,
|
||||
type: 'O',
|
||||
email: this.fakeEmail(),
|
||||
allowed_domains: ''
|
||||
};
|
||||
}
|
||||
|
||||
fakeChannel = () => {
|
||||
const name = this.generateId();
|
||||
|
||||
return {
|
||||
name,
|
||||
display_name: `Unit Test ${name}`,
|
||||
type: 'O'
|
||||
};
|
||||
}
|
||||
|
||||
fakePost = () => {
|
||||
return {
|
||||
message: `Unit Test ${this.generateId()}`
|
||||
};
|
||||
}
|
||||
|
||||
initBasic = (callback) => {
|
||||
const client = this.createClient();
|
||||
|
||||
callback({client});
|
||||
|
|
|
|||
Loading…
Reference in a new issue