Commit d51d6a27 authored by Mark Florian's avatar Mark Florian

Merge branch '334743-fix-sticky-errors-for-oncall-schedule' into 'master'

Reset oncall schedule form on cancel or close

See merge request gitlab-org/gitlab!68076
parents 100a2dd9 6a27ee3c
...@@ -201,20 +201,7 @@ export default { ...@@ -201,20 +201,7 @@ export default {
this.error = null; this.error = null;
}, },
resetForm() { resetForm() {
if (this.isEditMode) { this.form = this.getInitialState();
const { name, description, rules } = this.escalationPolicy;
this.form = {
name,
description,
rules,
};
} else {
this.form = {
name: '',
description: '',
rules: [],
};
}
this.validationState = { this.validationState = {
name: null, name: null,
......
...@@ -45,11 +45,7 @@ export default { ...@@ -45,11 +45,7 @@ export default {
data() { data() {
return { return {
loading: false, loading: false,
form: { form: this.getInitialFormState(),
name: this.schedule?.name,
description: this.schedule?.description,
timezone: this.timezones.find(({ identifier }) => this.schedule?.timezone === identifier),
},
error: '', error: '',
validationState: { validationState: {
name: true, name: true,
...@@ -139,7 +135,7 @@ export default { ...@@ -139,7 +135,7 @@ export default {
this.$refs.addUpdateScheduleModal.hide(); this.$refs.addUpdateScheduleModal.hide();
this.$emit('scheduleCreated'); this.$emit('scheduleCreated');
this.clearScheduleForm(); this.resetForm();
}, },
) )
.catch((error) => { .catch((error) => {
...@@ -154,9 +150,13 @@ export default { ...@@ -154,9 +150,13 @@ export default {
const { const {
projectPath, projectPath,
form: { timezone }, form: {
timezone: { identifier },
},
} = this; } = this;
const isTimezoneUpdated = identifier !== this.schedule.timezone;
this.$apollo this.$apollo
.mutate({ .mutate({
mutation: updateOncallScheduleMutation, mutation: updateOncallScheduleMutation,
...@@ -179,6 +179,10 @@ export default { ...@@ -179,6 +179,10 @@ export default {
throw error; throw error;
} }
this.$refs.addUpdateScheduleModal.hide(); this.$refs.addUpdateScheduleModal.hide();
if (isTimezoneUpdated) {
window.location.reload();
}
}, },
) )
.catch((error) => { .catch((error) => {
...@@ -186,9 +190,6 @@ export default { ...@@ -186,9 +190,6 @@ export default {
}) })
.finally(() => { .finally(() => {
this.loading = false; this.loading = false;
if (timezone !== this.schedule.timezone) {
window.location.reload();
}
}); });
}, },
hideErrorAlert() { hideErrorAlert() {
...@@ -205,10 +206,19 @@ export default { ...@@ -205,10 +206,19 @@ export default {
this.validationState.timezone = !isEmpty(this.form.timezone); this.validationState.timezone = !isEmpty(this.form.timezone);
} }
}, },
clearScheduleForm() { getInitialFormState() {
this.form.name = ''; return {
this.form.description = ''; name: this.schedule?.name,
this.form.timezone = {}; description: this.schedule?.description,
timezone: this.timezones.find(({ identifier }) => this.schedule?.timezone === identifier),
};
},
resetForm() {
this.validationState = {
name: true,
timezone: true,
};
this.form = this.getInitialFormState();
}, },
}, },
}; };
...@@ -223,6 +233,8 @@ export default { ...@@ -223,6 +233,8 @@ export default {
:action-primary="actionsProps.primary" :action-primary="actionsProps.primary"
:action-cancel="actionsProps.cancel" :action-cancel="actionsProps.cancel"
@primary.prevent="isEditMode ? editSchedule() : createSchedule()" @primary.prevent="isEditMode ? editSchedule() : createSchedule()"
@canceled="resetForm"
@close="resetForm"
> >
<gl-alert v-if="error" variant="danger" class="gl-mt-n3 gl-mb-3" @dismiss="hideErrorAlert"> <gl-alert v-if="error" variant="danger" class="gl-mt-n3 gl-mb-3" @dismiss="hideErrorAlert">
{{ errorMsg }} {{ errorMsg }}
......
...@@ -35,7 +35,6 @@ describe('AddScheduleModal', () => { ...@@ -35,7 +35,6 @@ describe('AddScheduleModal', () => {
wrapper = shallowMount(AddEditScheduleModal, { wrapper = shallowMount(AddEditScheduleModal, {
data() { data() {
return { return {
form: mockSchedule,
...data, ...data,
}; };
}, },
...@@ -95,11 +94,6 @@ describe('AddScheduleModal', () => { ...@@ -95,11 +94,6 @@ describe('AddScheduleModal', () => {
wrapper = shallowMount(AddEditScheduleModal, { wrapper = shallowMount(AddEditScheduleModal, {
localVue, localVue,
apolloProvider: fakeApollo, apolloProvider: fakeApollo,
data() {
return {
form: mockSchedule,
};
},
propsData: { propsData: {
modalId: editScheduleModalId, modalId: editScheduleModalId,
isEditMode: true, isEditMode: true,
...@@ -122,6 +116,28 @@ describe('AddScheduleModal', () => { ...@@ -122,6 +116,28 @@ describe('AddScheduleModal', () => {
const submitForm = () => findModal().vm.$emit('primary', { preventDefault: jest.fn() }); const submitForm = () => findModal().vm.$emit('primary', { preventDefault: jest.fn() });
const updatedName = 'Updated schedule name';
const updatedTimezone = mockTimezones[0];
const updatedDescription = 'Updated schedule description';
const updateForm = () => {
const emitUpdate = (args) => findModalForm().vm.$emit('update-schedule-form', args);
emitUpdate({
type: 'name',
value: updatedName,
});
emitUpdate({
type: 'description',
value: updatedDescription,
});
emitUpdate({
type: 'timezone',
value: updatedTimezone,
});
};
describe('Schedule create', () => { describe('Schedule create', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ modalId: addScheduleModalId }); createComponent({ modalId: addScheduleModalId });
...@@ -149,6 +165,8 @@ describe('AddScheduleModal', () => { ...@@ -149,6 +165,8 @@ describe('AddScheduleModal', () => {
it("doesn't hide a modal and shows error alert on fail", async () => { it("doesn't hide a modal and shows error alert on fail", async () => {
const error = 'some error'; const error = 'some error';
mutate.mockImplementation(() => Promise.reject(error)); mutate.mockImplementation(() => Promise.reject(error));
updateForm();
await nextTick();
submitForm(); submitForm();
await waitForPromises(); await waitForPromises();
...@@ -162,6 +180,8 @@ describe('AddScheduleModal', () => { ...@@ -162,6 +180,8 @@ describe('AddScheduleModal', () => {
mutate.mockImplementation(() => mutate.mockImplementation(() =>
Promise.resolve({ data: { oncallScheduleCreate: { errors: [] } } }), Promise.resolve({ data: { oncallScheduleCreate: { errors: [] } } }),
); );
updateForm();
await nextTick();
submitForm(); submitForm();
expect(mutate).toHaveBeenCalledWith({ expect(mutate).toHaveBeenCalledWith({
mutation: expect.any(Object), mutation: expect.any(Object),
...@@ -169,8 +189,9 @@ describe('AddScheduleModal', () => { ...@@ -169,8 +189,9 @@ describe('AddScheduleModal', () => {
variables: { variables: {
oncallScheduleCreateInput: { oncallScheduleCreateInput: {
projectPath, projectPath,
...mockSchedule, name: updatedName,
timezone: mockSchedule.timezone.identifier, description: updatedDescription,
timezone: updatedTimezone.identifier,
}, },
}, },
}); });
...@@ -184,9 +205,27 @@ describe('AddScheduleModal', () => { ...@@ -184,9 +205,27 @@ describe('AddScheduleModal', () => {
); );
submitForm(); submitForm();
expect(findModalForm().props('form')).toMatchObject({ expect(findModalForm().props('form')).toMatchObject({
name: '', name: undefined,
description: '', description: undefined,
timezone: {}, timezone: undefined,
});
});
it('should reset the form on modal cancel', async () => {
updateForm();
await nextTick();
expect(findModalForm().props('form')).toMatchObject({
name: updatedName,
description: updatedDescription,
timezone: updatedTimezone,
});
findModal().vm.$emit('canceled', { preventDefault: jest.fn() });
await nextTick();
expect(findModalForm().props('form')).toMatchObject({
name: undefined,
description: undefined,
timezone: undefined,
}); });
}); });
}); });
...@@ -220,13 +259,13 @@ describe('AddScheduleModal', () => { ...@@ -220,13 +259,13 @@ describe('AddScheduleModal', () => {
expect(mutate).toHaveBeenCalledWith({ expect(mutate).toHaveBeenCalledWith({
mutation: expect.any(Object), mutation: expect.any(Object),
update: expect.anything(), update: expect.any(Function),
variables: { variables: {
iid: mockSchedule.iid, iid: mockSchedule.iid,
projectPath, projectPath,
name: mockSchedule.name, name: mockSchedule.name,
description: mockSchedule.description, description: mockSchedule.description,
timezone: mockSchedule.timezone.identifier, timezone: mockSchedule.timezone,
}, },
}); });
await waitForPromises(); await waitForPromises();
...@@ -260,20 +299,16 @@ describe('AddScheduleModal', () => { ...@@ -260,20 +299,16 @@ describe('AddScheduleModal', () => {
useMockLocationHelper(); useMockLocationHelper();
it('it should not reload the page if the timezone has not changed', async () => { it('it should not reload the page if the timezone has not changed', async () => {
mutate.mockResolvedValueOnce({}); mutate.mockResolvedValueOnce({ data: { oncallScheduleUpdate: { errors: [] } } });
submitForm(); submitForm();
await waitForPromises(); await waitForPromises();
expect(window.location.reload).not.toHaveBeenCalled(); expect(window.location.reload).not.toHaveBeenCalled();
}); });
it('it should reload the page if the timezone has changed', async () => { it('it should reload the page if the timezone has changed', async () => {
createComponent({ mutate.mockResolvedValueOnce({ data: { oncallScheduleUpdate: { errors: [] } } });
data: { form: { ...mockSchedule, timezone: mockTimezones[1] } }, updateForm();
schedule: mockSchedule, await nextTick();
isEditMode: true,
modalId: editScheduleModalId,
});
mutate.mockResolvedValueOnce({});
submitForm(); submitForm();
expect(mutate).toHaveBeenCalledWith({ expect(mutate).toHaveBeenCalledWith({
mutation: updateOncallScheduleMutation, mutation: updateOncallScheduleMutation,
...@@ -281,14 +316,32 @@ describe('AddScheduleModal', () => { ...@@ -281,14 +316,32 @@ describe('AddScheduleModal', () => {
variables: { variables: {
iid: mockSchedule.iid, iid: mockSchedule.iid,
projectPath, projectPath,
name: mockSchedule.name, name: updatedName,
description: mockSchedule.description, description: updatedDescription,
timezone: mockTimezones[1].identifier, timezone: updatedTimezone.identifier,
}, },
}); });
await waitForPromises(); await waitForPromises();
expect(window.location.reload).toHaveBeenCalled(); expect(window.location.reload).toHaveBeenCalled();
}); });
}); });
it('should reset the form on modal cancel', async () => {
updateForm();
await nextTick();
expect(findModalForm().props('form')).toMatchObject({
name: updatedName,
description: updatedDescription,
timezone: updatedTimezone,
});
findModal().vm.$emit('canceled', { preventDefault: jest.fn() });
await nextTick();
expect(findModalForm().props('form')).toMatchObject({
name: mockSchedule.name,
description: mockSchedule.description,
timezone: { identifier: mockSchedule.timezone },
});
});
}); });
}); });
...@@ -38,7 +38,7 @@ export const getOncallSchedulesQueryResponse = { ...@@ -38,7 +38,7 @@ export const getOncallSchedulesQueryResponse = {
iid: '37', iid: '37',
name: 'Test schedule from query', name: 'Test schedule from query',
description: 'Description 1 lives here', description: 'Description 1 lives here',
timezone: 'Pacific/Honolulu', timezone: 'America/Los_Angeles',
rotations: { nodes: mockRotations }, rotations: { nodes: mockRotations },
}, },
], ],
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
"formatted_offset": "-11:00" "formatted_offset": "-11:00"
}, },
{ {
"identifier": "Pacific/US/Canada", "identifier": "America/Los_Angeles",
"name": "Pacific Time (US & Canada)", "name": "Pacific Time (US & Canada)",
"abbr": "PT", "abbr": "PT",
"formatted_offset": "-7:00" "formatted_offset": "-7:00"
......
...@@ -391,7 +391,7 @@ describe('AddEditRotationModal', () => { ...@@ -391,7 +391,7 @@ describe('AddEditRotationModal', () => {
expect(findForm().props('form')).toMatchObject({ expect(findForm().props('form')).toMatchObject({
startsAt: { startsAt: {
date: new Date('2021-01-13T00:00:00.000Z'), date: new Date('2021-01-13T00:00:00.000Z'),
time: 1, time: 3,
}, },
}); });
}); });
...@@ -400,7 +400,7 @@ describe('AddEditRotationModal', () => { ...@@ -400,7 +400,7 @@ describe('AddEditRotationModal', () => {
expect(findForm().props('form')).toMatchObject({ expect(findForm().props('form')).toMatchObject({
endsAt: { endsAt: {
date: new Date('2021-03-13T00:00:00.000Z'), date: new Date('2021-03-13T00:00:00.000Z'),
time: 5, time: 7,
}, },
}); });
}); });
......
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