import MockAdapter from 'axios-mock-adapter'; import { memoize, cloneDeep } from 'lodash'; import { getFixture, getJSONFixture } from 'helpers/fixtures'; import waitForPromises from 'helpers/wait_for_promises'; import axios from '~/lib/utils/axios_utils'; import UsersSelect from '~/users_select'; // fixtures ------------------------------------------------------------------- const getUserSearchHTML = memoize((fixturePath) => { const html = getFixture(fixturePath); const parser = new DOMParser(); const el = parser.parseFromString(html, 'text/html').querySelector('.assignee'); return el.outerHTML; }); const getUsersFixture = memoize(() => getJSONFixture('autocomplete/users.json')); export const getUsersFixtureAt = (idx) => getUsersFixture()[idx]; // test context --------------------------------------------------------------- export const createTestContext = ({ fixturePath }) => { let mock = null; let subject = null; const setup = () => { const rootEl = document.createElement('div'); rootEl.innerHTML = getUserSearchHTML(fixturePath); document.body.appendChild(rootEl); mock = new MockAdapter(axios); mock.onGet('/-/autocomplete/users.json').reply(200, cloneDeep(getUsersFixture())); }; const teardown = () => { mock.restore(); document.body.innerHTML = ''; subject = null; }; const createSubject = () => { if (subject) { throw new Error('test subject is already created'); } subject = new UsersSelect(null); }; return { setup, teardown, createSubject, }; }; // finders ------------------------------------------------------------------- export const findAssigneesInputs = () => document.querySelectorAll('input[name="merge_request[assignee_ids][]'); export const findAssigneesInputsModel = () => Array.from(findAssigneesInputs()).map((input) => ({ value: input.value, dataset: { ...input.dataset }, })); export const findUserSearchButton = () => document.querySelector('.js-user-search'); export const findDropdownItem = ({ id }) => document.querySelector(`li[data-user-id="${id}"] a`); export const findDropdownItemsModel = () => Array.from(document.querySelectorAll('.dropdown-content li')).map((el) => { if (el.classList.contains('divider')) { return { type: 'divider', }; } else if (el.classList.contains('dropdown-header')) { return { type: 'dropdown-header', text: el.textContent, }; } return { type: 'user', userId: el.dataset.userId, }; }); // arrange/act helpers ------------------------------------------------------- export const setAssignees = (...users) => { findAssigneesInputs().forEach((x) => x.remove()); const container = document.querySelector('.js-sidebar-assignee-data'); container.prepend( ...users.map((user) => { const input = document.createElement('input'); input.name = 'merge_request[assignee_ids][]'; input.value = user.id.toString(); input.setAttribute('data-avatar-url', user.avatar_url); input.setAttribute('data-name', user.name); input.setAttribute('data-username', user.username); input.setAttribute('data-can-merge', user.can_merge); return input; }), ); }; export const toggleDropdown = () => findUserSearchButton().click(); export const waitForDropdownItems = async () => { await axios.waitForAll(); await waitForPromises(); }; // assertion helpers --------------------------------------------------------- export const createUnassignedExpectation = () => { return [ { type: 'user', userId: '0' }, { type: 'divider' }, ...getUsersFixture().map((x) => ({ type: 'user', userId: x.id.toString(), })), ]; }; export const createAssignedExpectation = ({ header, assigned }) => { const assignedIds = new Set(assigned.map((x) => x.id)); const unassignedIds = getUsersFixture().filter((x) => !assignedIds.has(x.id)); return [ { type: 'user', userId: '0' }, { type: 'divider' }, { type: 'dropdown-header', text: header }, ...assigned.map((x) => ({ type: 'user', userId: x.id.toString() })), { type: 'divider' }, ...unassignedIds.map((x) => ({ type: 'user', userId: x.id.toString() })), ]; }; export const createInputsModelExpectation = (users) => users.map((user) => ({ value: user.id.toString(), dataset: { approved: user.approved.toString(), avatar_url: user.avatar_url, can_merge: user.can_merge.toString(), can_update_merge_request: user.can_update_merge_request.toString(), id: user.id.toString(), name: user.name, show_status: user.show_status.toString(), state: user.state, username: user.username, web_url: user.web_url, }, }));