Commit 5a0b7fee authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '262849-edit-schedule-dor-backend' into 'master'

Allow schedule update

See merge request gitlab-org/gitlab!49295
parents 1b962786 80b9d7c4
......@@ -66,7 +66,9 @@ export default {
editScheduleVariables() {
return {
projectPath: this.projectPath,
...this.form,
iid: this.schedule.iid,
name: this.form.name,
description: this.form.description,
timezone: this.form.timezone.identifier,
};
},
......@@ -79,14 +81,12 @@ export default {
this.$apollo
.mutate({
mutation: updateOncallScheduleMutation,
variables: {
oncallScheduleEditInput: this.editScheduleVariables,
},
variables: this.editScheduleVariables,
update(store, { data }) {
updateStoreAfterScheduleEdit(store, getOncallSchedulesQuery, data, { projectPath });
},
})
.then(({ data: { oncallScheduleEdit: { errors: [error] } } }) => {
.then(({ data: { oncallScheduleUpdate: { errors: [error] } } }) => {
if (error) {
throw error;
}
......@@ -114,6 +114,7 @@ export default {
ref="updateScheduleModal"
modal-id="updateScheduleModal"
size="sm"
:data-testid="`update-schedule-modal-${schedule.iid}`"
:title="$options.i18n.editSchedule"
:action-primary="actionsProps.primary"
:action-cancel="actionsProps.cancel"
......
mutation oncallScheduleUpdate($oncallScheduleUpdateInput: oncallScheduleUpdateInput!) {
oncallScheduleUpdate(input: $oncallScheduleUpdateInput) {
mutation oncallScheduleUpdate(
$iid: String!
$projectPath: ID!
$name: String
$description: String
$timezone: String
) {
oncallScheduleUpdate(
input: {
iid: $iid
projectPath: $projectPath
name: $name
description: $description
timezone: $timezone
}
) {
errors
oncallSchedule {
iid
......
......@@ -4,6 +4,7 @@ exports[`UpdateScheduleModal renders update schedule modal layout 1`] = `
<gl-modal-stub
actioncancel="[object Object]"
actionprimary="[object Object]"
data-testid="update-schedule-modal-37"
modalclass=""
modalid="updateScheduleModal"
size="sm"
......
/* eslint-disable no-unused-vars */
import { shallowMount, createLocalVue } from '@vue/test-utils';
import createMockApollo from 'jest/helpers/mock_apollo_helper';
import { GlModal } from '@gitlab/ui';
import { GlModal, GlAlert } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import waitForPromises from 'helpers/wait_for_promises';
import getOncallSchedulesQuery from 'ee/oncall_schedules/graphql/queries/get_oncall_schedules.query.graphql';
import updateOncallScheduleMutation from 'ee/oncall_schedules/graphql/mutations/update_oncall_schedule.mutation.graphql';
import UpdateScheduleModal, { i18n } from 'ee/oncall_schedules/components/edit_schedule_modal.vue';
import { UPDATE_SCHEDULE_ERROR } from 'ee/oncall_schedules/utils/error_messages';
import { getOncallSchedulesQueryResponse, updateScheduleResponse } from './mocks/apollo_mock';
import {
getOncallSchedulesQueryResponse,
updateScheduleResponse,
updateScheduleResponseWithErrors,
} from './mocks/apollo_mock';
import mockTimezones from './mocks/mockTimezones.json';
const localVue = createLocalVue();
const projectPath = 'group/project';
const mutate = jest.fn();
const mockHideModal = jest.fn();
const schedule =
getOncallSchedulesQueryResponse.data.project.incidentManagementOncallSchedules.nodes[0];
localVue.use(VueApollo);
......@@ -23,6 +28,7 @@ describe('UpdateScheduleModal', () => {
let updateScheduleHandler;
const findModal = () => wrapper.find(GlModal);
const findAlert = () => wrapper.find(GlAlert);
async function awaitApolloDomMock() {
await wrapper.vm.$nextTick(); // kick off the DOM update
......@@ -30,11 +36,11 @@ describe('UpdateScheduleModal', () => {
await wrapper.vm.$nextTick(); // kick off the DOM update for flash
}
async function destroySchedule(localWrapper) {
async function updateSchedule(localWrapper) {
await jest.runOnlyPendingTimers();
await localWrapper.vm.$nextTick();
localWrapper.vm.$emit('primary');
localWrapper.find(GlModal).vm.$emit('primary', { preventDefault: jest.fn() });
}
const createComponent = ({ data = {}, props = {} } = {}) => {
......@@ -42,13 +48,11 @@ describe('UpdateScheduleModal', () => {
data() {
return {
...data,
form:
getOncallSchedulesQueryResponse.data.project.incidentManagementOncallSchedules.nodes[0],
form: schedule,
};
},
propsData: {
schedule:
getOncallSchedulesQueryResponse.data.project.incidentManagementOncallSchedules.nodes[0],
schedule,
...props,
},
provide: {
......@@ -70,13 +74,32 @@ describe('UpdateScheduleModal', () => {
localVue.use(VueApollo);
updateScheduleHandler = updateHandler;
const requestHandlers = [[updateOncallScheduleMutation, updateScheduleHandler]];
const requestHandlers = [
[getOncallSchedulesQuery, jest.fn().mockResolvedValue(getOncallSchedulesQueryResponse)],
[updateOncallScheduleMutation, updateScheduleHandler],
];
fakeApollo = createMockApollo(requestHandlers);
fakeApollo.clients.defaultClient.cache.writeQuery({
query: getOncallSchedulesQuery,
variables: {
projectPath: 'group/project',
},
data: getOncallSchedulesQueryResponse.data,
});
wrapper = shallowMount(UpdateScheduleModal, {
localVue,
apolloProvider: fakeApollo,
data() {
return {
form: schedule,
};
},
propsData: {
schedule,
},
provide: {
projectPath,
timezones: mockTimezones,
......@@ -114,8 +137,13 @@ describe('UpdateScheduleModal', () => {
expect(mutate).toHaveBeenCalledWith({
mutation: expect.any(Object),
update: expect.anything(),
// TODO: Once the BE is complete for the mutation update this spec to use the correct params
variables: expect.anything(),
variables: {
iid: schedule.iid,
projectPath,
name: schedule.name,
description: schedule.description,
timezone: schedule.timezone.identifier,
},
});
});
......@@ -123,8 +151,7 @@ describe('UpdateScheduleModal', () => {
mutate.mockResolvedValueOnce({ data: { oncallScheduleUpdate: { errors: [] } } });
findModal().vm.$emit('primary', { preventDefault: jest.fn() });
await waitForPromises();
// TODO: Once the BE is complete for the mutation update this spec to use the call
expect(mockHideModal).not.toHaveBeenCalled();
expect(mockHideModal).toHaveBeenCalled();
});
it("doesn't hide the modal on fail", async () => {
......@@ -137,6 +164,34 @@ describe('UpdateScheduleModal', () => {
});
describe('with mocked Apollo client', () => {
// TODO: Once the BE is complete for the mutation add specs here for that via a destroyHandler
it('has the name of the schedule to update based on getOncallSchedulesQuery', async () => {
createComponentWithApollo();
await jest.runOnlyPendingTimers();
await wrapper.vm.$nextTick();
expect(findModal().attributes('data-testid')).toBe(`update-schedule-modal-${schedule.iid}`);
});
it('calls a mutation with correct parameters and updates a schedule', async () => {
createComponentWithApollo();
await updateSchedule(wrapper);
expect(updateScheduleHandler).toHaveBeenCalled();
});
it('displays alert if mutation had a recoverable error', async () => {
createComponentWithApollo({
updateHandler: jest.fn().mockResolvedValue(updateScheduleResponseWithErrors),
});
await updateSchedule(wrapper);
await awaitApolloDomMock();
const alert = findAlert();
expect(alert.exists()).toBe(true);
expect(alert.text()).toContain('Houston, we have a problem');
});
});
});
......@@ -68,7 +68,7 @@ export const destroyScheduleResponseWithErrors = {
export const updateScheduleResponse = {
data: {
oncallScheduleDestroy: {
oncallScheduleUpdate: {
errors: [],
oncallSchedule: {
__typename: 'IncidentManagementOncallSchedule',
......@@ -81,6 +81,21 @@ export const updateScheduleResponse = {
},
};
export const updateScheduleResponseWithErrors = {
data: {
oncallScheduleUpdate: {
errors: ['Houston, we have a problem'],
oncallSchedule: {
__typename: 'IncidentManagementOncallSchedule',
iid: '37',
name: 'Test schedule 2',
description: 'Description 2 lives here',
timezone: 'Pacific/Honolulu',
},
},
},
};
export const preExistingSchedule = {
description: 'description',
iid: '1',
......
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