import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
import ProtectedBranchEdit from '~/protected_branches/protected_branch_edit';
jest.mock('~/flash');
const TEST_URL = `${TEST_HOST}/url`;
const FORCE_PUSH_TOGGLE_TESTID = 'force-push-toggle';
const CODE_OWNER_TOGGLE_TESTID = 'code-owner-toggle';
const IS_CHECKED_CLASS = 'is-checked';
const IS_DISABLED_CLASS = 'is-disabled';
const IS_LOADING_SELECTOR = '.toggle-loading';
describe('ProtectedBranchEdit', () => {
let mock;
beforeEach(() => {
jest.spyOn(ProtectedBranchEdit.prototype, 'buildDropdowns').mockImplementation();
mock = new MockAdapter(axios);
});
const findForcePushToggle = () =>
document.querySelector(`div[data-testid="${FORCE_PUSH_TOGGLE_TESTID}"] button`);
const findCodeOwnerToggle = () =>
document.querySelector(`div[data-testid="${CODE_OWNER_TOGGLE_TESTID}"] button`);
const create = ({
forcePushToggleChecked = false,
codeOwnerToggleChecked = false,
hasLicense = true,
} = {}) => {
setHTMLFixture(`
`);
return new ProtectedBranchEdit({ $wrap: $('#wrap'), hasLicense });
};
afterEach(() => {
mock.restore();
resetHTMLFixture();
});
describe('when license supports code owner approvals', () => {
beforeEach(() => {
create();
});
it('instantiates the code owner toggle', () => {
expect(findCodeOwnerToggle()).not.toBe(null);
});
});
describe('when license does not support code owner approvals', () => {
beforeEach(() => {
create({ hasLicense: false });
});
it('does not instantiate the code owner toggle', () => {
expect(findCodeOwnerToggle()).toBe(null);
});
});
describe('when toggles are not available in the DOM on page load', () => {
beforeEach(() => {
create({ hasLicense: true });
setHTMLFixture('');
});
afterEach(() => {
resetHTMLFixture();
});
it('does not instantiate the force push toggle', () => {
expect(findForcePushToggle()).toBe(null);
});
it('does not instantiate the code owner toggle', () => {
expect(findCodeOwnerToggle()).toBe(null);
});
});
describe.each`
description | checkedOption | patchParam | finder
${'force push'} | ${'forcePushToggleChecked'} | ${'allow_force_push'} | ${findForcePushToggle}
${'code owner'} | ${'codeOwnerToggleChecked'} | ${'code_owner_approval_required'} | ${findCodeOwnerToggle}
`('when unchecked $description toggle button', ({ checkedOption, patchParam, finder }) => {
let toggle;
beforeEach(() => {
create({ [checkedOption]: false });
toggle = finder();
});
it('is not changed', () => {
expect(toggle).not.toHaveClass(IS_CHECKED_CLASS);
expect(toggle.querySelector(IS_LOADING_SELECTOR)).toBe(null);
expect(toggle).not.toHaveClass(IS_DISABLED_CLASS);
});
describe('when clicked', () => {
beforeEach(async () => {
mock
.onPatch(TEST_URL, { protected_branch: { [patchParam]: true } })
.replyOnce(HTTP_STATUS_OK, {});
});
it('checks and disables button', async () => {
await toggle.click();
expect(toggle).toHaveClass(IS_CHECKED_CLASS);
expect(toggle.querySelector(IS_LOADING_SELECTOR)).not.toBe(null);
expect(toggle).toHaveClass(IS_DISABLED_CLASS);
});
it('sends update to BE', async () => {
await toggle.click();
await axios.waitForAll();
// Args are asserted in the `.onPatch` call
expect(mock.history.patch).toHaveLength(1);
expect(toggle).not.toHaveClass(IS_DISABLED_CLASS);
expect(toggle.querySelector(IS_LOADING_SELECTOR)).toBe(null);
expect(createAlert).not.toHaveBeenCalled();
});
});
describe('when clicked and BE error', () => {
beforeEach(() => {
mock.onPatch(TEST_URL).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR);
toggle.click();
});
it('flashes error', async () => {
await axios.waitForAll();
expect(createAlert).toHaveBeenCalled();
});
});
});
});