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