Commit 9d0f8bac authored by Paul Slaughter's avatar Paul Slaughter

Merge branch 'mg-refactor-select2-ajax' into 'master'

Replace ajax methods in select2 instances

See merge request gitlab-org/gitlab!55996
parents c0075c3c 549fb72e
......@@ -2,30 +2,8 @@ import $ from 'jquery';
import { escape } from 'lodash';
import { __ } from '~/locale';
import Api from './api';
import axios from './lib/utils/axios_utils';
import { normalizeHeaders } from './lib/utils/common_utils';
import { loadCSSFile } from './lib/utils/css_utils';
const fetchGroups = (params) => {
axios[params.type.toLowerCase()](params.url, {
params: params.data,
})
.then((res) => {
const results = res.data || [];
const headers = normalizeHeaders(res.headers);
const currentPage = parseInt(headers['X-PAGE'], 10) || 0;
const totalPages = parseInt(headers['X-TOTAL-PAGES'], 10) || 0;
const more = currentPage < totalPages;
params.success({
results,
pagination: {
more,
},
});
})
.catch(params.error);
};
import { select2AxiosTransport } from './lib/utils/select2_utils';
const groupsSelect = () => {
loadCSSFile(gon.select2_css_path)
......@@ -51,9 +29,7 @@ const groupsSelect = () => {
url: Api.buildUrl(groupsPath),
dataType: 'json',
quietMillis: 250,
transport(params) {
fetchGroups(params);
},
transport: select2AxiosTransport,
data(search, page) {
return {
search,
......@@ -63,8 +39,6 @@ const groupsSelect = () => {
};
},
results(data, page) {
if (data.length) return { results: [] };
const groups = data.length ? data : data.results || [];
const more = data.pagination ? data.pagination.more : false;
const results = groups.filter((group) => skipGroups.indexOf(group.id) === -1);
......
......@@ -5,6 +5,7 @@ import Autosave from './autosave';
import AutoWidthDropdownSelect from './issuable/auto_width_dropdown_select';
import { loadCSSFile } from './lib/utils/css_utils';
import { parsePikadayDate, pikadayToString } from './lib/utils/datetime_utility';
import { select2AxiosTransport } from './lib/utils/select2_utils';
import { queryToObject, objectToQuery } from './lib/utils/url_utility';
import UsersSelect from './users_select';
import ZenMode from './zen_mode';
......@@ -199,15 +200,16 @@ export default class IssuableForm {
search,
};
},
results(data) {
results({ results }) {
return {
// `data` keys are translated so we can't just access them with a string based key
results: data[Object.keys(data)[0]].map((name) => ({
results: results[Object.keys(results)[0]].map((name) => ({
id: name,
text: name,
})),
};
},
transport: select2AxiosTransport,
},
initSelection(el, callback) {
const val = el.val();
......
import axios from './axios_utils';
import { normalizeHeaders, parseIntPagination } from './common_utils';
// This is used in the select2 config to replace jQuery.ajax with axios
export const select2AxiosTransport = (params) => {
axios({
method: params.type?.toLowerCase() || 'get',
url: params.url,
params: params.data,
})
.then((res) => {
const results = res.data || [];
const headers = normalizeHeaders(res.headers);
const pagination = parseIntPagination(headers);
const more = pagination.nextPage > pagination.page;
params.success({
results,
pagination: {
more,
},
});
})
.catch(params.error);
};
......@@ -3,6 +3,7 @@ import $ from 'jquery';
import Api from '~/api';
import groupsSelect from '~/groups_select';
import { loadCSSFile } from '~/lib/utils/css_utils';
import { select2AxiosTransport } from '~/lib/utils/select2_utils';
import { s__ } from '~/locale';
const onLimitCheckboxChange = (checked, $limitByNamespaces, $limitByProjects) => {
......@@ -29,12 +30,13 @@ const getDropdownConfig = (placeholder, apiPath, textProp) => ({
},
results(data) {
return {
results: data.map((entity) => ({
results: data.results.map((entity) => ({
id: entity.id,
text: entity[textProp],
})),
};
},
transport: select2AxiosTransport,
},
});
......
import $ from 'jquery';
import { loadCSSFile } from '~/lib/utils/css_utils';
import { select2AxiosTransport } from '~/lib/utils/select2_utils';
import { s__ } from '~/locale';
import PersistentUserCallout from '~/persistent_user_callout';
......@@ -27,12 +28,13 @@ const getDropdownConfig = (placeholder, url) => ({
},
results(data) {
return {
results: data.map((entity) => ({
results: data.results.map((entity) => ({
id: entity.source_id,
text: entity.path,
})),
};
},
transport: select2AxiosTransport,
},
});
......
import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import { setHTMLFixture } from 'helpers/fixtures';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import { select2AxiosTransport } from '~/lib/utils/select2_utils';
import 'select2/select2';
const TEST_URL = '/test/api/url';
const TEST_SEARCH_DATA = { extraSearch: 'test' };
const TEST_DATA = [{ id: 1 }];
const TEST_SEARCH = 'FOO';
describe('lib/utils/select2_utils', () => {
let mock;
let resultsSpy;
beforeEach(() => {
setHTMLFixture('<div><input id="root" /></div>');
mock = new MockAdapter(axios);
resultsSpy = jest.fn().mockReturnValue({ results: [] });
});
afterEach(() => {
mock.restore();
});
const setupSelect2 = (input) => {
input.select2({
ajax: {
url: TEST_URL,
quietMillis: 250,
transport: select2AxiosTransport,
data(search, page) {
return {
search,
page,
...TEST_SEARCH_DATA,
};
},
results: resultsSpy,
},
});
};
const setupSelect2AndSearch = async () => {
const $input = $('#root');
setupSelect2($input);
$input.select2('search', TEST_SEARCH);
jest.runOnlyPendingTimers();
await waitForPromises();
};
describe('select2AxiosTransport', () => {
it('uses axios to make request', async () => {
// setup mock response
const replySpy = jest.fn();
mock.onGet(TEST_URL).reply((...args) => replySpy(...args));
await setupSelect2AndSearch();
expect(replySpy).toHaveBeenCalledWith(
expect.objectContaining({
url: TEST_URL,
method: 'get',
params: {
page: 1,
search: TEST_SEARCH,
...TEST_SEARCH_DATA,
},
}),
);
});
it.each`
headers | pagination
${{}} | ${{ more: false }}
${{ 'X-PAGE': '1', 'x-next-page': 2 }} | ${{ more: true }}
`(
'passes results and pagination to results callback, with headers=$headers',
async ({ headers, pagination }) => {
mock.onGet(TEST_URL).reply(200, TEST_DATA, headers);
await setupSelect2AndSearch();
expect(resultsSpy).toHaveBeenCalledWith(
{ results: TEST_DATA, pagination },
1,
expect.anything(),
);
},
);
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment