Commit 87aab35c authored by Filipa Lacerda's avatar Filipa Lacerda
Browse files

Merge branch 'ph-ajax-to-axios' into 'master'

Converted $.ajax calls in some JS files to axios

See merge request gitlab-org/gitlab-ce!16717
import $ from 'jquery';
import _ from 'underscore';
import axios from './lib/utils/axios_utils';
const Api = {
groupsPath: '/api/:version/groups.json',
groupPath: '/api/:version/groups/:id.json',
groupPath: '/api/:version/groups/:id',
namespacesPath: '/api/:version/namespaces.json',
groupProjectsPath: '/api/:version/groups/:id/projects.json',
projectsPath: '/api/:version/projects.json',
......@@ -23,42 +23,44 @@ const Api = {
group(groupId, callback) {
const url = Api.buildUrl(Api.groupPath)
.replace(':id', groupId);
return $.ajax({
url,
dataType: 'json',
})
.done(group => callback(group));
return axios.get(url)
.then(({ data }) => {
callback(data);
return data;
});
},
// Return groups list. Filtered by query
groups(query, options, callback) {
const url = Api.buildUrl(Api.groupsPath);
return $.ajax({
url,
data: Object.assign({
return axios.get(url, {
params: Object.assign({
search: query,
per_page: 20,
}, options),
dataType: 'json',
})
.done(groups => callback(groups));
.then(({ data }) => {
callback(data);
return data;
});
},
// Return namespaces list. Filtered by query
namespaces(query, callback) {
const url = Api.buildUrl(Api.namespacesPath);
return $.ajax({
url,
data: {
return axios.get(url, {
params: {
search: query,
per_page: 20,
},
dataType: 'json',
}).done(namespaces => callback(namespaces));
})
.then(({ data }) => callback(data));
},
// Return projects list. Filtered by query
projects(query, options, callback) {
projects(query, options, callback = _.noop) {
const url = Api.buildUrl(Api.projectsPath);
const defaults = {
search: query,
......@@ -70,12 +72,14 @@ const Api = {
defaults.membership = true;
}
return $.ajax({
url,
data: Object.assign(defaults, options),
dataType: 'json',
return axios.get(url, {
params: Object.assign(defaults, options),
})
.done(projects => callback(projects));
.then(({ data }) => {
callback(data);
return data;
});
},
// Return single project
......@@ -97,41 +101,34 @@ const Api = {
url = Api.buildUrl(Api.groupLabelsPath).replace(':namespace_path', namespacePath);
}
return $.ajax({
url,
type: 'POST',
data: { label: data },
dataType: 'json',
return axios.post(url, {
label: data,
})
.done(label => callback(label))
.fail(message => callback(message.responseJSON));
.then(res => callback(res.data))
.catch(e => callback(e.response.data));
},
// Return group projects list. Filtered by query
groupProjects(groupId, query, callback) {
const url = Api.buildUrl(Api.groupProjectsPath)
.replace(':id', groupId);
return $.ajax({
url,
data: {
return axios.get(url, {
params: {
search: query,
per_page: 20,
},
dataType: 'json',
})
.done(projects => callback(projects));
.then(({ data }) => callback(data));
},
commitMultiple(id, data) {
// see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
const url = Api.buildUrl(Api.commitPath)
.replace(':id', encodeURIComponent(id));
return this.wrapAjaxCall({
url,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(data),
dataType: 'json',
return axios.post(url, JSON.stringify(data), {
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
});
},
......@@ -140,40 +137,37 @@ const Api = {
.replace(':id', encodeURIComponent(id))
.replace(':branch', branch);
return this.wrapAjaxCall({
url,
type: 'GET',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
});
return axios.get(url);
},
// Return text for a specific license
licenseText(key, data, callback) {
const url = Api.buildUrl(Api.licensePath)
.replace(':key', key);
return $.ajax({
url,
data,
return axios.get(url, {
params: data,
})
.done(license => callback(license));
.then(res => callback(res.data));
},
gitignoreText(key, callback) {
const url = Api.buildUrl(Api.gitignorePath)
.replace(':key', key);
return $.get(url, gitignore => callback(gitignore));
return axios.get(url)
.then(({ data }) => callback(data));
},
gitlabCiYml(key, callback) {
const url = Api.buildUrl(Api.gitlabCiYmlPath)
.replace(':key', key);
return $.get(url, file => callback(file));
return axios.get(url)
.then(({ data }) => callback(data));
},
dockerfileYml(key, callback) {
const url = Api.buildUrl(Api.dockerfilePath).replace(':key', key);
$.get(url, callback);
return axios.get(url)
.then(({ data }) => callback(data));
},
issueTemplate(namespacePath, projectPath, key, type, callback) {
......@@ -182,23 +176,18 @@ const Api = {
.replace(':type', type)
.replace(':project_path', projectPath)
.replace(':namespace_path', namespacePath);
$.ajax({
url,
dataType: 'json',
})
.done(file => callback(null, file))
.fail(callback);
return axios.get(url)
.then(({ data }) => callback(null, data))
.catch(callback);
},
users(query, options) {
const url = Api.buildUrl(this.usersPath);
return Api.wrapAjaxCall({
url,
data: Object.assign({
return axios.get(url, {
params: Object.assign({
search: query,
per_page: 20,
}, options),
dataType: 'json',
});
},
......@@ -209,21 +198,6 @@ const Api = {
}
return urlRoot + url.replace(':version', gon.api_version);
},
wrapAjaxCall(options) {
return new Promise((resolve, reject) => {
// jQuery 2 is not Promises/A+ compatible (missing catch)
$.ajax(options) // eslint-disable-line promise/catch-or-return
.then(data => resolve(data),
(jqXHR, textStatus, errorThrown) => {
const error = new Error(`${options.url}: ${errorThrown}`);
error.textStatus = textStatus;
if (jqXHR && jqXHR.responseJSON) error.responseJSON = jqXHR.responseJSON;
reject(error);
},
);
});
},
};
export default Api;
import Flash from '../../flash';
import { handleLocationHash } from '../../lib/utils/common_utils';
import axios from '../../lib/utils/axios_utils';
export default class BlobViewer {
constructor() {
......@@ -127,25 +128,18 @@ export default class BlobViewer {
const viewer = viewerParam;
const url = viewer.getAttribute('data-url');
return new Promise((resolve, reject) => {
if (!url || viewer.getAttribute('data-loaded') || viewer.getAttribute('data-loading')) {
resolve(viewer);
return;
}
if (!url || viewer.getAttribute('data-loaded') || viewer.getAttribute('data-loading')) {
return Promise.resolve(viewer);
}
viewer.setAttribute('data-loading', 'true');
viewer.setAttribute('data-loading', 'true');
$.ajax({
url,
dataType: 'JSON',
})
.fail(reject)
.done((data) => {
return axios.get(url)
.then(({ data }) => {
viewer.innerHTML = data.html;
viewer.setAttribute('data-loaded', 'true');
resolve(viewer);
return viewer;
});
});
}
}
......@@ -5,6 +5,7 @@
import { pluralize } from './lib/utils/text_utility';
import { localTimeAgo } from './lib/utils/datetime_utility';
import Pager from './pager';
import axios from './lib/utils/axios_utils';
export default (function () {
const CommitsList = {};
......@@ -43,29 +44,30 @@ export default (function () {
CommitsList.filterResults = function () {
const form = $('.commits-search-form');
const search = CommitsList.searchField.val();
if (search === CommitsList.lastSearch) return;
if (search === CommitsList.lastSearch) return Promise.resolve();
const commitsUrl = form.attr('action') + '?' + form.serialize();
CommitsList.content.fadeTo('fast', 0.5);
return $.ajax({
type: 'GET',
url: form.attr('action'),
data: form.serialize(),
complete: function () {
return CommitsList.content.fadeTo('fast', 1.0);
},
success: function (data) {
const params = form.serializeArray().reduce((acc, obj) => Object.assign(acc, {
[obj.name]: obj.value,
}), {});
return axios.get(form.attr('action'), {
params,
})
.then(({ data }) => {
CommitsList.lastSearch = search;
CommitsList.content.html(data.html);
return history.replaceState({
page: commitsUrl,
CommitsList.content.fadeTo('fast', 1.0);
// Change url so if user reload a page - search results are saved
history.replaceState({
page: commitsUrl,
}, document.title, commitsUrl);
},
error: function () {
})
.catch(() => {
CommitsList.content.fadeTo('fast', 1.0);
CommitsList.lastSearch = null;
},
dataType: 'json',
});
});
};
// Prepare loaded data.
......
......@@ -71,7 +71,7 @@ export const setResizingStatus = ({ commit }, resizing) => {
export const checkCommitStatus = ({ state }) =>
service
.getBranchData(state.currentProjectId, state.currentBranchId)
.then((data) => {
.then(({ data }) => {
const { id } = data.commit;
const selectedBranch =
state.projects[state.currentProjectId].branches[state.currentBranchId];
......@@ -90,7 +90,7 @@ export const commitChanges = (
) =>
service
.commit(state.currentProjectId, payload)
.then((data) => {
.then(({ data }) => {
const { branch } = payload;
if (!data.short_id) {
flash(data.message, 'alert', document, null, false, true);
......@@ -147,8 +147,8 @@ export const commitChanges = (
})
.catch((err) => {
let errMsg = 'Error committing changes. Please try again.';
if (err.responseJSON && err.responseJSON.message) {
errMsg += ` (${stripHtml(err.responseJSON.message)})`;
if (err.response.data && err.response.data.message) {
errMsg += ` (${stripHtml(err.response.data.message)})`;
}
flash(errMsg, 'alert', document, null, false, true);
window.dispatchEvent(new Event('resize'));
......
......@@ -10,7 +10,7 @@ export const getBranchData = (
!state.projects[`${projectId}`].branches[branchId])
|| force) {
service.getBranchData(`${projectId}`, branchId)
.then((data) => {
.then(({ data }) => {
const { id } = data.commit;
commit(types.SET_BRANCH, { projectPath: `${projectId}`, branchName: branchId, branch: data });
commit(types.SET_BRANCH_WORKING_REFERENCE, { projectId, branchId, reference: id });
......
......@@ -8,16 +8,16 @@ class UsersCache extends Cache {
}
return Api.users('', { username })
.then((users) => {
if (!users.length) {
.then(({ data }) => {
if (!data.length) {
throw new Error(`User "${username}" could not be found!`);
}
if (users.length > 1) {
if (data.length > 1) {
throw new Error(`Expected username "${username}" to be unique!`);
}
const user = users[0];
const user = data[0];
this.internalStorage[username] = user;
return user;
});
......
......@@ -122,7 +122,7 @@
select2 group.id, from: '#link_group_id'
fill_in 'expires_at_groups', with: (Time.now + 4.5.days).strftime('%Y-%m-%d')
page.find('body').click
click_on 'share-with-group-tab'
find('.btn-create').click
end
......
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import Api from '~/api';
describe('Api', () => {
......@@ -7,20 +9,17 @@ describe('Api', () => {
api_version: dummyApiVersion,
relative_url_root: dummyUrlRoot,
};
const dummyResponse = 'hello from outer space!';
const sendDummyResponse = () => {
const deferred = $.Deferred();
deferred.resolve(dummyResponse);
return deferred.promise();
};
let originalGon;
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
originalGon = window.gon;
window.gon = Object.assign({}, dummyGon);
});
afterEach(() => {
mock.restore();
window.gon = originalGon;
});
......@@ -38,15 +37,13 @@ describe('Api', () => {
describe('group', () => {
it('fetches a group', (done) => {
const groupId = '123456';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}.json`;
spyOn(jQuery, 'ajax').and.callFake((request) => {
expect(request.url).toEqual(expectedUrl);
expect(request.dataType).toEqual('json');
return sendDummyResponse();
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}`;
mock.onGet(expectedUrl).reply(200, {
name: 'test',
});
Api.group(groupId, (response) => {
expect(response).toBe(dummyResponse);
expect(response.name).toBe('test');
done();
});
});
......@@ -57,19 +54,13 @@ describe('Api', () => {
const query = 'dummy query';
const options = { unused: 'option' };
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups.json`;
const expectedData = Object.assign({
search: query,
per_page: 20,
}, options);
spyOn(jQuery, 'ajax').and.callFake((request) => {
expect(request.url).toEqual(expectedUrl);
expect(request.dataType).toEqual('json');
expect(request.data).toEqual(expectedData);
return sendDummyResponse();
});
mock.onGet(expectedUrl).reply(200, [{
name: 'test',
}]);
Api.groups(query, options, (response) => {
expect(response).toBe(dummyResponse);
expect(response.length).toBe(1);
expect(response[0].name).toBe('test');
done();
});
});
......@@ -79,19 +70,13 @@ describe('Api', () => {
it('fetches namespaces', (done) => {
const query = 'dummy query';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/namespaces.json`;
const expectedData = {
search: query,
per_page: 20,
};
spyOn(jQuery, 'ajax').and.callFake((request) => {
expect(request.url).toEqual(expectedUrl);
expect(request.dataType).toEqual('json');
expect(request.data).toEqual(expectedData);
return sendDummyResponse();
});
mock.onGet(expectedUrl).reply(200, [{
name: 'test',
}]);
Api.namespaces(query, (response) => {
expect(response).toBe(dummyResponse);
expect(response.length).toBe(1);
expect(response[0].name).toBe('test');
done();
});
});
......@@ -103,21 +88,13 @@ describe('Api', () => {
const options = { unused: 'option' };
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json`;
window.gon.current_user_id = 1;
const expectedData = Object.assign({
search: query,
per_page: 20,
membership: true,
simple: true,
}, options);
spyOn(jQuery, 'ajax').and.callFake((request) => {
expect(request.url).toEqual(expectedUrl);
expect(request.dataType).toEqual('json');
expect(request.data).toEqual(expectedData);
return sendDummyResponse();
});
mock.onGet(expectedUrl).reply(200, [{
name: 'test',
}]);
Api.projects(query, options, (response) => {
expect(response).toBe(dummyResponse);
expect(response.length).toBe(1);
expect(response[0].name).toBe('test');
done();
});
});
......@@ -126,20 +103,13 @@ describe('Api', () => {
const query = 'dummy query';
const options = { unused: 'option' };
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json`;
const expectedData = Object.assign({
search: query,
per_page: 20,
simple: true,
}, options);
spyOn(jQuery, 'ajax').and.callFake((request) => {
expect(request.url).toEqual(expectedUrl);
expect(request.dataType).toEqual('json');
expect(request.data).toEqual(expectedData);
return sendDummyResponse();
});
mock.onGet(expectedUrl).reply(200, [{
name: 'test',
}]);
Api.projects(query, options, (response) => {
expect(response).toBe(dummyResponse);
expect(response.length).toBe(1);
expect(response[0].name).toBe('test');
done();
});
});
......@@ -154,16 +124,16 @@ describe('Api', () => {
const expectedData = {
label: labelData,
};
spyOn(jQuery, 'ajax').and.callFake((request) => {
expect(request.url).toEqual(expectedUrl);
expect(request.dataType).toEqual('json');
expect(request.type).toEqual('POST');
expect(request.data).toEqual(expectedData);
return sendDummyResponse();
mock.onPost(expectedUrl).reply((config) => {
expect(config.data).toBe(JSON.stringify(expectedData));
return [200, {
name: 'test',
}];
});
Api.newLabel(namespace, project, labelData, (response) => {
expect(response).toBe(dummyResponse);
expect(response.name).toBe('test');
done();
});
});
......@@ -174,19 +144,13 @@ describe('Api', () => {
const groupId = '123456';
const query = 'dummy query';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/groups/${groupId}/projects.json`;
const expectedData = {
search: query,