summaryrefslogtreecommitdiff
path: root/spec/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/blame/blame_redirect_spec.js1
-rw-r--r--spec/frontend/blob_edit/blob_bundle_spec.js7
-rw-r--r--spec/frontend/feature_flags/components/feature_flags_spec.js58
-rw-r--r--spec/frontend/ide/components/ide_spec.js7
-rw-r--r--spec/frontend/notes/components/mr_discussion_filter_spec.js8
-rw-r--r--spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js82
-rw-r--r--spec/frontend/work_items/components/work_item_detail_modal_spec.js133
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_children_wrapper_spec.js5
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js16
-rw-r--r--spec/frontend/work_items/components/work_item_links/work_item_links_spec.js6
-rw-r--r--spec/frontend/work_items/mock_data.js18
11 files changed, 156 insertions, 185 deletions
diff --git a/spec/frontend/blame/blame_redirect_spec.js b/spec/frontend/blame/blame_redirect_spec.js
index 326f60a5b13..5cd91ec5f1f 100644
--- a/spec/frontend/blame/blame_redirect_spec.js
+++ b/spec/frontend/blame/blame_redirect_spec.js
@@ -6,7 +6,6 @@ jest.mock('~/alert');
describe('Blame page redirect', () => {
beforeEach(() => {
- global.window = Object.create(window);
const url = 'https://gitlab.com/flightjs/Flight/-/blame/master/file.json';
Object.defineProperty(window, 'location', {
writable: true,
diff --git a/spec/frontend/blob_edit/blob_bundle_spec.js b/spec/frontend/blob_edit/blob_bundle_spec.js
index 89d507b4ec5..6a7ca3288cb 100644
--- a/spec/frontend/blob_edit/blob_bundle_spec.js
+++ b/spec/frontend/blob_edit/blob_bundle_spec.js
@@ -11,6 +11,13 @@ jest.mock('~/blob_edit/edit_blob');
jest.mock('~/alert');
describe('BlobBundle', () => {
+ beforeAll(() => {
+ // HACK: Workaround readonly property in Jest
+ Object.defineProperty(window, 'onbeforeunload', {
+ writable: true,
+ });
+ });
+
it('does not load SourceEditor by default', () => {
blobBundle();
expect(SourceEditor).not.toHaveBeenCalled();
diff --git a/spec/frontend/feature_flags/components/feature_flags_spec.js b/spec/frontend/feature_flags/components/feature_flags_spec.js
index 8492fe7bdde..c0cfec384f0 100644
--- a/spec/frontend/feature_flags/components/feature_flags_spec.js
+++ b/spec/frontend/feature_flags/components/feature_flags_spec.js
@@ -1,9 +1,9 @@
import { GlAlert, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import Vue, { nextTick } from 'vue';
+import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import { TEST_HOST } from 'spec/test_constants';
import ConfigureFeatureFlagsModal from '~/feature_flags/components/configure_feature_flags_modal.vue';
import EmptyState from '~/feature_flags/components/empty_state.vue';
@@ -11,7 +11,7 @@ import FeatureFlagsComponent from '~/feature_flags/components/feature_flags.vue'
import FeatureFlagsTable from '~/feature_flags/components/feature_flags_table.vue';
import createStore from '~/feature_flags/store/index';
import axios from '~/lib/utils/axios_utils';
-import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
+import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
import { getRequestData } from '../mock_data';
@@ -43,7 +43,7 @@ describe('Feature flags', () => {
let mock;
let store;
- const factory = (provide = mockData, fn = mount) => {
+ const factory = (provide = mockData, fn = mountExtended) => {
store = createStore(mockState);
wrapper = fn(FeatureFlagsComponent, {
store,
@@ -54,10 +54,13 @@ describe('Feature flags', () => {
});
};
- const configureButton = () => wrapper.find('[data-testid="ff-configure-button"]');
- const newButton = () => wrapper.find('[data-testid="ff-new-button"]');
- const userListButton = () => wrapper.find('[data-testid="ff-user-list-button"]');
+ const configureButton = () => wrapper.findByTestId('ff-configure-button');
+ const newButton = () => wrapper.findByTestId('ff-new-button');
+ const userListButton = () => wrapper.findByTestId('ff-user-list-button');
const limitAlert = () => wrapper.findComponent(GlAlert);
+ const findTablePagination = () => wrapper.findComponent(TablePagination);
+ const findFeatureFlagsTable = () => wrapper.findComponent(FeatureFlagsTable);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
beforeEach(() => {
mock = new MockAdapter(axios);
@@ -81,7 +84,7 @@ describe('Feature flags', () => {
it('makes the new feature flag button do nothing if clicked', () => {
expect(newButton().exists()).toBe(true);
expect(newButton().props('disabled')).toBe(false);
- expect(newButton().props('href')).toBe(undefined);
+ expect(newButton().props('href')).toBeUndefined();
});
it('shows a feature flags limit reached alert', () => {
@@ -171,9 +174,8 @@ describe('Feature flags', () => {
factory();
await waitForPromises();
- await nextTick();
- emptyState = wrapper.findComponent(GlEmptyState);
+ emptyState = findEmptyState();
});
it('should render the empty state', () => {
@@ -219,7 +221,7 @@ describe('Feature flags', () => {
});
it('should render a table with feature flags', () => {
- const table = wrapper.findComponent(FeatureFlagsTable);
+ const table = findFeatureFlagsTable();
expect(table.exists()).toBe(true);
expect(table.props('featureFlags')).toEqual(
expect.arrayContaining([
@@ -232,7 +234,7 @@ describe('Feature flags', () => {
});
it('should toggle a flag when receiving the toggle-flag event', () => {
- const table = wrapper.findComponent(FeatureFlagsTable);
+ const table = findFeatureFlagsTable();
const [flag] = table.props('featureFlags');
table.vm.$emit('toggle-flag', flag);
@@ -255,15 +257,15 @@ describe('Feature flags', () => {
describe('pagination', () => {
it('should render pagination', () => {
- expect(wrapper.findComponent(TablePagination).exists()).toBe(true);
+ expect(findTablePagination().exists()).toBe(true);
});
it('should make an API request when page is clicked', () => {
- jest.spyOn(wrapper.vm, 'updateFeatureFlagOptions');
- wrapper.findComponent(TablePagination).vm.change(4);
+ const axiosGet = jest.spyOn(axios, 'get');
+ findTablePagination().vm.change(4);
- expect(wrapper.vm.updateFeatureFlagOptions).toHaveBeenCalledWith({
- page: '4',
+ expect(axiosGet).toHaveBeenCalledWith('http://test.host/endpoint.json', {
+ params: { page: '4' },
});
});
});
@@ -272,16 +274,12 @@ describe('Feature flags', () => {
describe('unsuccessful request', () => {
beforeEach(() => {
- mock
- .onGet(mockState.endpoint, { params: { page: '1' } })
- .replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR, {});
-
factory();
return waitForPromises();
});
it('should render error state', () => {
- const emptyState = wrapper.findComponent(GlEmptyState);
+ const emptyState = findEmptyState();
expect(emptyState.props('title')).toEqual('There was an error fetching the feature flags.');
expect(emptyState.props('description')).toEqual(
'Try again in a few moments or contact your support team.',
@@ -303,20 +301,12 @@ describe('Feature flags', () => {
});
describe('rotate instance id', () => {
- beforeEach(() => {
- mock
- .onGet(`${TEST_HOST}/endpoint.json`, { params: { page: '1' } })
- .reply(HTTP_STATUS_OK, getRequestData, {});
- factory();
- return waitForPromises();
- });
-
it('should fire the rotate action when a `token` event is received', () => {
- const actionSpy = jest.spyOn(wrapper.vm, 'rotateInstanceId');
- const modal = wrapper.findComponent(ConfigureFeatureFlagsModal);
- modal.vm.$emit('token');
+ factory();
+ const axiosPost = jest.spyOn(axios, 'post');
+ wrapper.findComponent(ConfigureFeatureFlagsModal).vm.$emit('token');
- expect(actionSpy).toHaveBeenCalled();
+ expect(axiosPost).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/ide/components/ide_spec.js b/spec/frontend/ide/components/ide_spec.js
index f2a684ab65e..eb8f2a5e4ac 100644
--- a/spec/frontend/ide/components/ide_spec.js
+++ b/spec/frontend/ide/components/ide_spec.js
@@ -45,6 +45,13 @@ describe('WebIDE', () => {
const callOnBeforeUnload = (e = {}) => window.onbeforeunload(e);
+ beforeAll(() => {
+ // HACK: Workaround readonly property in Jest
+ Object.defineProperty(window, 'onbeforeunload', {
+ writable: true,
+ });
+ });
+
beforeEach(() => {
stubPerformanceWebAPI();
diff --git a/spec/frontend/notes/components/mr_discussion_filter_spec.js b/spec/frontend/notes/components/mr_discussion_filter_spec.js
index 405043ff2a0..beb25c30af6 100644
--- a/spec/frontend/notes/components/mr_discussion_filter_spec.js
+++ b/spec/frontend/notes/components/mr_discussion_filter_spec.js
@@ -80,15 +80,15 @@ describe('Merge request discussion filter component', () => {
wrapper.findComponent(GlCollapsibleListbox).vm.$emit('hidden');
expect(updateMergeRequestFilters).toHaveBeenCalledWith(expect.anything(), [
- 'commit_branches',
- 'status',
'assignees_reviewers',
+ 'comments',
+ 'commit_branches',
'edits',
'labels',
+ 'lock_status',
'mentions',
+ 'status',
'tracking',
- 'comments',
- 'lock_status',
]);
});
diff --git a/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js
index e78e1be7882..a07a60438fb 100644
--- a/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/approvals/approvals_spec.js
@@ -2,6 +2,7 @@ import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { GlButton, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import { createMockSubscription as createMockApolloSubscription } from 'mock-apollo-client';
import approvedByCurrentUser from 'test_fixtures/graphql/merge_requests/approvals/approvals.query.graphql.json';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -16,6 +17,7 @@ import {
} from '~/vue_merge_request_widget/components/approvals/messages';
import eventHub from '~/vue_merge_request_widget/event_hub';
import approvedByQuery from 'ee_else_ce/vue_merge_request_widget/components/approvals/queries/approvals.query.graphql';
+import approvedBySubscription from 'ee_else_ce/vue_merge_request_widget/components/approvals/queries/approvals.subscription.graphql';
import { createCanApproveResponse } from 'jest/approvals/mock_data';
Vue.use(VueApollo);
@@ -42,21 +44,36 @@ const testApprovals = () => ({
});
describe('MRWidget approvals', () => {
+ let mockedSubscription;
let wrapper;
let service;
let mr;
- const createComponent = (props = {}, response = approvedByCurrentUser) => {
- const requestHandlers = [[approvedByQuery, jest.fn().mockResolvedValue(response)]];
+ const createComponent = (options = {}, responses = { query: approvedByCurrentUser }) => {
+ mockedSubscription = createMockApolloSubscription();
+
+ const requestHandlers = [[approvedByQuery, jest.fn().mockResolvedValue(responses.query)]];
+ const subscriptionHandlers = [[approvedBySubscription, () => mockedSubscription]];
const apolloProvider = createMockApollo(requestHandlers);
+ const provide = {
+ ...options.provide,
+ glFeatures: {
+ realtimeApprovals: options.provide?.glFeatures?.realtimeApprovals || false,
+ },
+ };
+
+ subscriptionHandlers.forEach(([document, stream]) => {
+ apolloProvider.defaultClient.setRequestHandler(document, stream);
+ });
wrapper = shallowMount(Approvals, {
apolloProvider,
propsData: {
mr,
service,
- ...props,
+ ...options.props,
},
+ provide,
stubs: {
GlSprintf,
},
@@ -97,6 +114,7 @@ describe('MRWidget approvals', () => {
isOpen: true,
state: 'open',
targetProjectFullPath: 'gitlab-org/gitlab',
+ id: 1,
iid: '1',
};
@@ -114,7 +132,7 @@ describe('MRWidget approvals', () => {
mr.isOpen = false;
- createComponent({}, response);
+ createComponent({}, { query: response });
await waitForPromises();
});
@@ -128,7 +146,7 @@ describe('MRWidget approvals', () => {
const response = JSON.parse(JSON.stringify(approvedByCurrentUser));
response.data.project.mergeRequest.approvedBy.nodes = [];
- createComponent({}, response);
+ createComponent({}, { query: response });
await waitForPromises();
});
@@ -146,7 +164,7 @@ describe('MRWidget approvals', () => {
describe('and MR is unapproved', () => {
beforeEach(async () => {
- createComponent({}, canApproveResponse);
+ createComponent({}, { query: canApproveResponse });
await waitForPromises();
});
@@ -167,7 +185,7 @@ describe('MRWidget approvals', () => {
describe('with no approvers', () => {
beforeEach(async () => {
canApproveResponse.data.project.mergeRequest.approvedBy.nodes = [];
- createComponent({}, canApproveResponse);
+ createComponent({}, { query: canApproveResponse });
await nextTick();
});
@@ -186,7 +204,7 @@ describe('MRWidget approvals', () => {
canApproveResponse.data.project.mergeRequest.approvedBy.nodes[0].id = 2;
- createComponent({}, canApproveResponse);
+ createComponent({}, { query: canApproveResponse });
await waitForPromises();
});
@@ -202,7 +220,7 @@ describe('MRWidget approvals', () => {
describe('when approve action is clicked', () => {
beforeEach(async () => {
- createComponent({}, canApproveResponse);
+ createComponent({}, { query: canApproveResponse });
await waitForPromises();
});
@@ -259,7 +277,7 @@ describe('MRWidget approvals', () => {
beforeEach(async () => {
const response = JSON.parse(JSON.stringify(approvedByCurrentUser));
- createComponent({}, response);
+ createComponent({}, { query: response });
await waitForPromises();
});
@@ -320,7 +338,7 @@ describe('MRWidget approvals', () => {
beforeEach(async () => {
optionalApprovalsResponse.data.project.mergeRequest.userPermissions.canApprove = true;
- createComponent({}, optionalApprovalsResponse);
+ createComponent({}, { query: optionalApprovalsResponse });
await waitForPromises();
});
@@ -335,7 +353,7 @@ describe('MRWidget approvals', () => {
describe('and cannot approve', () => {
beforeEach(async () => {
- createComponent({}, optionalApprovalsResponse);
+ createComponent({}, { query: optionalApprovalsResponse });
await nextTick();
});
@@ -366,4 +384,44 @@ describe('MRWidget approvals', () => {
});
});
});
+
+ describe('realtime approvals update', () => {
+ describe('realtime_approvals feature disabled', () => {
+ beforeEach(() => {
+ jest.spyOn(console, 'warn').mockImplementation();
+ createComponent();
+ });
+
+ it('does not subscribe to the approvals update socket', () => {
+ expect(mr.setApprovals).not.toHaveBeenCalled();
+ mockedSubscription.next({});
+ // eslint-disable-next-line no-console
+ expect(console.warn).toHaveBeenCalledWith(
+ expect.stringMatching('Mock subscription has no observer, this will have no effect'),
+ );
+ expect(mr.setApprovals).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('realtime_approvals feature enabled', () => {
+ const subscriptionApproval = { approved: true };
+ const subscriptionResponse = {
+ data: { mergeRequestApprovalStateUpdated: subscriptionApproval },
+ };
+
+ beforeEach(() => {
+ createComponent({
+ provide: { glFeatures: { realtimeApprovals: true } },
+ });
+ });
+
+ it('updates approvals when the subscription data is streamed to the Apollo client', () => {
+ expect(mr.setApprovals).not.toHaveBeenCalled();
+
+ mockedSubscription.next(subscriptionResponse);
+
+ expect(mr.setApprovals).toHaveBeenCalledWith(subscriptionApproval);
+ });
+ });
+ });
});
diff --git a/spec/frontend/work_items/components/work_item_detail_modal_spec.js b/spec/frontend/work_items/components/work_item_detail_modal_spec.js
index 1bdf5d1c840..e305cc310bd 100644
--- a/spec/frontend/work_items/components/work_item_detail_modal_spec.js
+++ b/spec/frontend/work_items/components/work_item_detail_modal_spec.js
@@ -6,21 +6,16 @@ import waitForPromises from 'helpers/wait_for_promises';
import createMockApollo from 'helpers/mock_apollo_helper';
import { stubComponent } from 'helpers/stub_component';
import WorkItemDetailModal from '~/work_items/components/work_item_detail_modal.vue';
-import deleteWorkItemFromTaskMutation from '~/work_items/graphql/delete_task_from_work_item.mutation.graphql';
import deleteWorkItemMutation from '~/work_items/graphql/delete_work_item.mutation.graphql';
import WorkItemDetail from '~/work_items/components/work_item_detail.vue';
-import {
- deleteWorkItemFromTaskMutationErrorResponse,
- deleteWorkItemFromTaskMutationResponse,
- deleteWorkItemMutationErrorResponse,
- deleteWorkItemResponse,
-} from '../mock_data';
+import { deleteWorkItemMutationErrorResponse, deleteWorkItemResponse } from '../mock_data';
describe('WorkItemDetailModal component', () => {
let wrapper;
Vue.use(VueApollo);
+ const workItemId = 'gid://gitlab/WorkItem/1';
const hideModal = jest.fn();
const GlModal = {
template: `
@@ -33,37 +28,23 @@ describe('WorkItemDetailModal component', () => {
},
};
- const defaultPropsData = {
- issueGid: 'gid://gitlab/WorkItem/1',
- workItemId: 'gid://gitlab/WorkItem/2',
- };
-
const findModal = () => wrapper.findComponent(GlModal);
const findAlert = () => wrapper.findComponent(GlAlert);
const findWorkItemDetail = () => wrapper.findComponent(WorkItemDetail);
const createComponent = ({
- lockVersion,
- lineNumberStart,
- lineNumberEnd,
error = false,
- deleteWorkItemFromTaskMutationHandler = jest
- .fn()
- .mockResolvedValue(deleteWorkItemFromTaskMutationResponse),
deleteWorkItemMutationHandler = jest.fn().mockResolvedValue(deleteWorkItemResponse),
} = {}) => {
const apolloProvider = createMockApollo([
- [deleteWorkItemFromTaskMutation, deleteWorkItemFromTaskMutationHandler],
[deleteWorkItemMutation, deleteWorkItemMutationHandler],
]);
wrapper = shallowMount(WorkItemDetailModal, {
apolloProvider,
propsData: {
- ...defaultPropsData,
- lockVersion,
- lineNumberStart,
- lineNumberEnd,
+ workItemId,
+ workItemIid: '1',
},
data() {
return {
@@ -87,9 +68,9 @@ describe('WorkItemDetailModal component', () => {
expect(findWorkItemDetail().props()).toEqual({
isModal: true,
- workItemId: defaultPropsData.workItemId,
- workItemParentId: defaultPropsData.issueGid,
- workItemIid: null,
+ workItemId,
+ workItemIid: '1',
+ workItemParentId: null,
});
});
@@ -143,85 +124,31 @@ describe('WorkItemDetailModal component', () => {
});
describe('delete work item', () => {
- describe('when there is task data', () => {
- it('emits workItemDeleted and closes modal', async () => {
- const mutationMock = jest.fn().mockResolvedValue(deleteWorkItemFromTaskMutationResponse);
- createComponent({
- lockVersion: 1,
- lineNumberStart: '3',
- lineNumberEnd: '3',
- deleteWorkItemFromTaskMutationHandler: mutationMock,
- });
- const newDesc = 'updated work item desc';
-
- findWorkItemDetail().vm.$emit('deleteWorkItem');
- await waitForPromises();
-
- expect(wrapper.emitted('workItemDeleted')).toEqual([[newDesc]]);
- expect(hideModal).toHaveBeenCalled();
- expect(mutationMock).toHaveBeenCalledWith({
- input: {
- id: defaultPropsData.issueGid,
- lockVersion: 1,
- taskData: { id: defaultPropsData.workItemId, lineNumberEnd: 3, lineNumberStart: 3 },
- },
- });
- });
-
- it.each`
- errorType | mutationMock | errorMessage
- ${'an error in the mutation response'} | ${jest.fn().mockResolvedValue(deleteWorkItemFromTaskMutationErrorResponse)} | ${'Error'}
- ${'a network error'} | ${jest.fn().mockRejectedValue(new Error('GraphQL networkError'))} | ${'GraphQL networkError'}
- `(
- 'shows an error message when there is $errorType',
- async ({ mutationMock, errorMessage }) => {
- createComponent({
- lockVersion: 1,
- lineNumberStart: '3',
- lineNumberEnd: '3',
- deleteWorkItemFromTaskMutationHandler: mutationMock,
- });
-
- findWorkItemDetail().vm.$emit('deleteWorkItem');
- await waitForPromises();
-
- expect(wrapper.emitted('workItemDeleted')).toBeUndefined();
- expect(hideModal).not.toHaveBeenCalled();
- expect(findAlert().text()).toBe(errorMessage);
- },
- );
+ it('emits workItemDeleted and closes modal', async () => {
+ const mutationMock = jest.fn().mockResolvedValue(deleteWorkItemResponse);
+ createComponent({ deleteWorkItemMutationHandler: mutationMock });
+
+ findWorkItemDetail().vm.$emit('deleteWorkItem');
+ await waitForPromises();
+
+ expect(wrapper.emitted('workItemDeleted')).toEqual([[workItemId]]);
+ expect(hideModal).toHaveBeenCalled();
+ expect(mutationMock).toHaveBeenCalledWith({ input: { id: workItemId } });
});
- describe('when there is no task data', () => {
- it('emits workItemDeleted and closes modal', async () => {
- const mutationMock = jest.fn().mockResolvedValue(deleteWorkItemResponse);
- createComponent({ deleteWorkItemMutationHandler: mutationMock });
-
- findWorkItemDetail().vm.$emit('deleteWorkItem');
- await waitForPromises();
-
- expect(wrapper.emitted('workItemDeleted')).toEqual([[defaultPropsData.workItemId]]);
- expect(hideModal).toHaveBeenCalled();
- expect(mutationMock).toHaveBeenCalledWith({ input: { id: defaultPropsData.workItemId } });
- });
-
- it.each`
- errorType | mutationMock | errorMessage
- ${'an error in the mutation response'} | ${jest.fn().mockResolvedValue(deleteWorkItemMutationErrorResponse)} | ${'Error'}
- ${'a network error'} | ${jest.fn().mockRejectedValue(new Error('GraphQL networkError'))} | ${'GraphQL networkError'}
- `(
- 'shows an error message when there is $errorType',
- async ({ mutationMock, errorMessage }) => {
- createComponent({ deleteWorkItemMutationHandler: mutationMock });
-
- findWorkItemDetail().vm.$emit('deleteWorkItem');
- await waitForPromises();
-
- expect(wrapper.emitted('workItemDeleted')).toBeUndefined();
- expect(hideModal).not.toHaveBeenCalled();
- expect(findAlert().text()).toBe(errorMessage);
- },
- );
+ it.each`
+ errorType | mutationMock | errorMessage
+ ${'an error in the mutation response'} | ${jest.fn().mockResolvedValue(deleteWorkItemMutationErrorResponse)} | ${'Error'}
+ ${'a network error'} | ${jest.fn().mockRejectedValue(new Error('GraphQL networkError'))} | ${'GraphQL networkError'}
+ `('shows an error message when there is $errorType', async ({ mutationMock, errorMessage }) => {
+ createComponent({ deleteWorkItemMutationHandler: mutationMock });
+
+ findWorkItemDetail().vm.$emit('deleteWorkItem');
+ await waitForPromises();
+
+ expect(wrapper.emitted('workItemDeleted')).toBeUndefined();
+ expect(hideModal).not.toHaveBeenCalled();
+ expect(findAlert().text()).toBe(errorMessage);
});
});
});
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_children_wrapper_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_children_wrapper_spec.js
index 08b9408c656..b06be6c8083 100644
--- a/spec/frontend/work_items/components/work_item_links/work_item_children_wrapper_spec.js
+++ b/spec/frontend/work_items/components/work_item_links/work_item_children_wrapper_spec.js
@@ -53,11 +53,12 @@ describe('WorkItemChildrenWrapper', () => {
it('remove event on child triggers `removeChild` event', () => {
createComponent();
+ const workItem = { id: 'gid://gitlab/WorkItem/2' };
const firstChild = findWorkItemLinkChildItems().at(0);
- firstChild.vm.$emit('removeChild', 'gid://gitlab/WorkItem/2');
+ firstChild.vm.$emit('removeChild', workItem);
- expect(wrapper.emitted('removeChild')).toEqual([['gid://gitlab/WorkItem/2']]);
+ expect(wrapper.emitted('removeChild')).toEqual([[workItem]]);
});
it('emits `show-modal` on `click` event', () => {
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js
index bc429bfb037..71d1a0e253f 100644
--- a/spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js
+++ b/spec/frontend/work_items/components/work_item_links/work_item_link_child_spec.js
@@ -236,7 +236,7 @@ describe('WorkItemLinkChild', () => {
it('removeChild event on menu triggers `click-remove-child` event', () => {
itemMenuEl.vm.$emit('removeChild');
- expect(wrapper.emitted('removeChild')).toEqual([[workItemTask.id]]);
+ expect(wrapper.emitted('removeChild')).toEqual([[workItemTask]]);
});
});
@@ -249,7 +249,7 @@ describe('WorkItemLinkChild', () => {
(widget) => widget.type === WIDGET_TYPE_HIERARCHY,
);
const getChildrenNodes = () => getWidgetHierarchy().children.nodes;
- const findFirstItemId = () => getChildrenNodes()[0].id;
+ const findFirstItem = () => getChildrenNodes()[0];
beforeEach(() => {
getWorkItemTreeQueryHandler.mockClear();
@@ -328,7 +328,7 @@ describe('WorkItemLinkChild', () => {
findExpandButton().vm.$emit('click');
await waitForPromises();
- findTreeChildren().vm.$emit('removeChild', findFirstItemId());
+ findTreeChildren().vm.$emit('removeChild', findFirstItem());
await waitForPromises();
expect($toast.show).toHaveBeenCalledWith('Child removed', {
@@ -343,23 +343,23 @@ describe('WorkItemLinkChild', () => {
const childrenNodes = getChildrenNodes();
expect(findTreeChildren().props('children')).toEqual(childrenNodes);
- findTreeChildren().vm.$emit('removeChild', findFirstItemId());
+ findTreeChildren().vm.$emit('removeChild', findFirstItem());
await waitForPromises();
expect(findTreeChildren().props('children')).toEqual([]);
});
it('calls correct mutation with correct variables', async () => {
- const firstItemId = findFirstItemId();
+ const firstItem = findFirstItem();
findExpandButton().vm.$emit('click');
await waitForPromises();
- findTreeChildren().vm.$emit('removeChild', firstItemId);
+ findTreeChildren().vm.$emit('removeChild', firstItem);
expect(mutationChangeParentHandler).toHaveBeenCalledWith({
input: {
- id: firstItemId,
+ id: firstItem.id,
hierarchyWidget: {
parentId: null,
},
@@ -383,7 +383,7 @@ describe('WorkItemLinkChild', () => {
findExpandButton().vm.$emit('click');
await waitForPromises();
- findTreeChildren().vm.$emit('removeChild', findFirstItemId());
+ findTreeChildren().vm.$emit('removeChild', findFirstItem());
await waitForPromises();
expect(createAlert).toHaveBeenCalledWith({
diff --git a/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js b/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js
index cc3d2394231..786f8604039 100644
--- a/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js
+++ b/spec/frontend/work_items/components/work_item_links/work_item_links_spec.js
@@ -240,7 +240,7 @@ describe('WorkItemLinks', () => {
});
it('calls correct mutation with correct variables', async () => {
- findWorkItemLinkChildrenWrapper().vm.$emit('removeChild', firstChild.id);
+ findWorkItemLinkChildrenWrapper().vm.$emit('removeChild', firstChild);
await waitForPromises();
@@ -255,7 +255,7 @@ describe('WorkItemLinks', () => {
});
it('shows toast when mutation succeeds', async () => {
- findWorkItemLinkChildrenWrapper().vm.$emit('removeChild', firstChild.id);
+ findWorkItemLinkChildrenWrapper().vm.$emit('removeChild', firstChild);
await waitForPromises();
@@ -267,7 +267,7 @@ describe('WorkItemLinks', () => {
it('renders correct number of children after removal', async () => {
expect(findWorkItemLinkChildrenWrapper().props().children).toHaveLength(4);
- findWorkItemLinkChildrenWrapper().vm.$emit('removeChild', firstChild.id);
+ findWorkItemLinkChildrenWrapper().vm.$emit('removeChild', firstChild);
await waitForPromises();
expect(findWorkItemLinkChildrenWrapper().props().children).toHaveLength(3);
diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js
index 0a0835bcb36..0d5f92d0f4a 100644
--- a/spec/frontend/work_items/mock_data.js
+++ b/spec/frontend/work_items/mock_data.js
@@ -714,24 +714,6 @@ export const deleteWorkItemMutationErrorResponse = {
},
};
-export const deleteWorkItemFromTaskMutationResponse = {
- data: {
- workItemDeleteTask: {
- workItem: { id: 123, descriptionHtml: 'updated work item desc' },
- errors: [],
- },
- },
-};
-
-export const deleteWorkItemFromTaskMutationErrorResponse = {
- data: {
- workItemDeleteTask: {
- workItem: { id: 123, descriptionHtml: 'updated work item desc' },
- errors: ['Error'],
- },
- },
-};
-
export const workItemDatesSubscriptionResponse = {
data: {
issuableDatesUpdated: {