238 lines
7.4 KiB
JavaScript
238 lines
7.4 KiB
JavaScript
import { GlAlert, GlFormInput, GlForm, GlLink } from '@gitlab/ui';
|
|
import Vue, { nextTick } from 'vue';
|
|
import VueApollo from 'vue-apollo';
|
|
import createMockApollo from 'helpers/mock_apollo_helper';
|
|
import waitForPromises from 'helpers/wait_for_promises';
|
|
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
|
import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
|
|
import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
|
|
import issueSetTitleMutation from '~/boards/graphql/issue_set_title.mutation.graphql';
|
|
import * as cacheUpdates from '~/boards/graphql/cache_updates';
|
|
import updateEpicTitleMutation from '~/sidebar/queries/update_epic_title.mutation.graphql';
|
|
import { updateIssueTitleResponse, updateEpicTitleResponse } from '../../mock_data';
|
|
|
|
Vue.use(VueApollo);
|
|
|
|
const TEST_TITLE = 'New item title';
|
|
const TEST_ISSUE_A = {
|
|
id: 'gid://gitlab/Issue/1',
|
|
iid: 8,
|
|
title: 'Issue 1',
|
|
referencePath: 'h/b#1',
|
|
webUrl: 'webUrl',
|
|
};
|
|
const TEST_ISSUE_B = {
|
|
id: 'gid://gitlab/Issue/2',
|
|
iid: 9,
|
|
title: 'Issue 2',
|
|
referencePath: 'h/b#2',
|
|
webUrl: 'webUrl',
|
|
};
|
|
|
|
describe('BoardSidebarTitle', () => {
|
|
let wrapper;
|
|
let mockApollo;
|
|
|
|
const issueSetTitleMutationHandlerSuccess = jest.fn().mockResolvedValue(updateIssueTitleResponse);
|
|
const issueSetTitleMutationHandlerFailure = jest.fn().mockRejectedValue(new Error('error'));
|
|
const updateEpicTitleMutationHandlerSuccess = jest
|
|
.fn()
|
|
.mockResolvedValue(updateEpicTitleResponse);
|
|
|
|
beforeEach(() => {
|
|
cacheUpdates.setError = jest.fn();
|
|
});
|
|
|
|
afterEach(() => {
|
|
localStorage.clear();
|
|
});
|
|
|
|
const createWrapper = ({
|
|
item = TEST_ISSUE_A,
|
|
provide = {},
|
|
issueSetTitleMutationHandler = issueSetTitleMutationHandlerSuccess,
|
|
} = {}) => {
|
|
mockApollo = createMockApollo([
|
|
[issueSetTitleMutation, issueSetTitleMutationHandler],
|
|
[updateEpicTitleMutation, updateEpicTitleMutationHandlerSuccess],
|
|
]);
|
|
|
|
wrapper = shallowMountExtended(BoardSidebarTitle, {
|
|
apolloProvider: mockApollo,
|
|
provide: {
|
|
canUpdate: true,
|
|
fullPath: 'gitlab-org',
|
|
issuableType: 'issue',
|
|
isEpicBoard: false,
|
|
...provide,
|
|
},
|
|
propsData: {
|
|
activeItem: item,
|
|
},
|
|
stubs: {
|
|
'board-editable-item': BoardEditableItem,
|
|
},
|
|
});
|
|
};
|
|
|
|
const findForm = () => wrapper.findComponent(GlForm);
|
|
const findAlert = () => wrapper.findComponent(GlAlert);
|
|
const findFormInput = () => wrapper.findComponent(GlFormInput);
|
|
const findGlLink = () => wrapper.findComponent(GlLink);
|
|
const findEditableItem = () => wrapper.findComponent(BoardEditableItem);
|
|
const findCancelButton = () => wrapper.findByTestId('cancel-button');
|
|
const findTitle = () => wrapper.findByTestId('item-title');
|
|
const findCollapsed = () => wrapper.findByTestId('collapsed-content');
|
|
|
|
it('renders title and reference', () => {
|
|
createWrapper();
|
|
|
|
expect(findTitle().text()).toContain(TEST_ISSUE_A.title);
|
|
expect(findCollapsed().text()).toContain(TEST_ISSUE_A.referencePath);
|
|
});
|
|
|
|
it('does not render alert', () => {
|
|
createWrapper();
|
|
|
|
expect(findAlert().exists()).toBe(false);
|
|
});
|
|
|
|
it('links title to the corresponding issue', () => {
|
|
createWrapper();
|
|
|
|
expect(findGlLink().attributes('href')).toBe('webUrl');
|
|
});
|
|
|
|
describe('when new title is submitted', () => {
|
|
beforeEach(async () => {
|
|
createWrapper();
|
|
|
|
findFormInput().vm.$emit('input', TEST_TITLE);
|
|
findForm().vm.$emit('submit', { preventDefault: () => {} });
|
|
await nextTick();
|
|
});
|
|
|
|
it('collapses sidebar and renders new title', async () => {
|
|
await waitForPromises();
|
|
expect(findCollapsed().isVisible()).toBe(true);
|
|
});
|
|
|
|
it('renders correct title', async () => {
|
|
createWrapper({ item: { ...TEST_ISSUE_A, title: TEST_TITLE } });
|
|
await waitForPromises();
|
|
|
|
expect(findTitle().text()).toContain(TEST_TITLE);
|
|
});
|
|
});
|
|
|
|
it.each`
|
|
issuableType | isEpicBoard | queryHandler | notCalledHandler
|
|
${'issue'} | ${false} | ${issueSetTitleMutationHandlerSuccess} | ${updateEpicTitleMutationHandlerSuccess}
|
|
${'epic'} | ${true} | ${updateEpicTitleMutationHandlerSuccess} | ${issueSetTitleMutationHandlerSuccess}
|
|
`(
|
|
'updates $issuableType title',
|
|
async ({ issuableType, isEpicBoard, queryHandler, notCalledHandler }) => {
|
|
createWrapper({
|
|
provide: {
|
|
issuableType,
|
|
isEpicBoard,
|
|
},
|
|
});
|
|
|
|
await nextTick();
|
|
|
|
findFormInput().vm.$emit('input', TEST_TITLE);
|
|
findForm().vm.$emit('submit', { preventDefault: () => {} });
|
|
await nextTick();
|
|
|
|
expect(queryHandler).toHaveBeenCalled();
|
|
expect(notCalledHandler).not.toHaveBeenCalled();
|
|
},
|
|
);
|
|
|
|
describe('when submitting and invalid title', () => {
|
|
beforeEach(async () => {
|
|
createWrapper();
|
|
|
|
findFormInput().vm.$emit('input', '');
|
|
findForm().vm.$emit('submit', { preventDefault: () => {} });
|
|
await nextTick();
|
|
});
|
|
|
|
it('does not update title', () => {
|
|
expect(issueSetTitleMutationHandlerSuccess).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('when abandoning the form without saving', () => {
|
|
beforeEach(async () => {
|
|
createWrapper();
|
|
|
|
wrapper.vm.$refs.sidebarItem.expand();
|
|
findFormInput().vm.$emit('input', TEST_TITLE);
|
|
findEditableItem().vm.$emit('off-click');
|
|
await nextTick();
|
|
});
|
|
|
|
it('does not collapses sidebar and shows alert', () => {
|
|
expect(findCollapsed().isVisible()).toBe(false);
|
|
expect(findAlert().exists()).toBe(true);
|
|
expect(localStorage.getItem(`${TEST_ISSUE_A.id}/item-title-pending-changes`)).toBe(
|
|
TEST_TITLE,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('when accessing the form with pending changes', () => {
|
|
beforeAll(() => {
|
|
localStorage.setItem(`${TEST_ISSUE_A.id}/item-title-pending-changes`, TEST_TITLE);
|
|
|
|
createWrapper();
|
|
});
|
|
|
|
it('sets title, expands item and shows alert', () => {
|
|
expect(findFormInput().attributes('value')).toBe(TEST_TITLE);
|
|
expect(findCollapsed().isVisible()).toBe(false);
|
|
expect(findAlert().exists()).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('when cancel button is clicked', () => {
|
|
beforeEach(async () => {
|
|
createWrapper({ item: TEST_ISSUE_B });
|
|
|
|
findFormInput().vm.$emit('input', TEST_TITLE);
|
|
findCancelButton().vm.$emit('click');
|
|
await nextTick();
|
|
});
|
|
|
|
it('collapses sidebar and render former title', () => {
|
|
expect(issueSetTitleMutationHandlerSuccess).not.toHaveBeenCalled();
|
|
expect(findCollapsed().isVisible()).toBe(true);
|
|
expect(findTitle().text()).toBe(TEST_ISSUE_B.title);
|
|
});
|
|
});
|
|
|
|
describe('when the mutation fails', () => {
|
|
beforeEach(async () => {
|
|
createWrapper({
|
|
item: TEST_ISSUE_B,
|
|
issueSetTitleMutationHandler: issueSetTitleMutationHandlerFailure,
|
|
});
|
|
|
|
findFormInput().vm.$emit('input', 'Invalid title');
|
|
findForm().vm.$emit('submit', { preventDefault: () => {} });
|
|
await nextTick();
|
|
});
|
|
|
|
it('collapses sidebar and renders former item title', async () => {
|
|
expect(findCollapsed().isVisible()).toBe(true);
|
|
expect(findTitle().text()).toContain(TEST_ISSUE_B.title);
|
|
await waitForPromises();
|
|
expect(cacheUpdates.setError).toHaveBeenCalledWith(
|
|
expect.objectContaining({ message: 'An error occurred when updating the title' }),
|
|
);
|
|
});
|
|
});
|
|
});
|