Skip to content

Commit

Permalink
fix: geo 863 add publish announcement confirmation (#645)
Browse files Browse the repository at this point in the history
  • Loading branch information
goemen authored Aug 8, 2024
1 parent bf45826 commit e3e8310
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ vi.mock('../../services/notificationService', () => ({
}));

const mockRouterPush = vi.fn();
const mockRouterBack = vi.fn();
vi.mock('vue-router', () => ({
useRouter: () => ({
push: (...args) => mockRouterPush(...args),
back: () => mockRouterBack(),
}),
}));

Expand Down Expand Up @@ -88,6 +90,13 @@ describe('AddAnnouncementPage', () => {
await fireEvent.update(linkUrl, 'https://example.com');
await fireEvent.update(displayLinkAs, 'Example.pdf');
await fireEvent.click(publishButton);
await waitFor(() => {
expect(
screen.getByText('Are you sure you want to publish this announcement?'),
).toBeInTheDocument();
});
const continueButton = screen.getByRole('button', { name: 'Confirm' });
await fireEvent.click(continueButton);
await waitFor(() => {
expect(mockAddAnnouncement).toHaveBeenCalledWith(
expect.objectContaining({
Expand All @@ -103,6 +112,33 @@ describe('AddAnnouncementPage', () => {
expect(mockRouterPush).toHaveBeenCalledWith('/announcements');
});
});
it('should not publish when confirmation cancel is clicked', async () => {
const { getByRole, getByLabelText, getByText } = await wrappedRender();
const publishButton = getByRole('button', { name: 'Publish' });
const title = getByLabelText('Title');
const description = getByLabelText('Description');
const linkUrl = getByLabelText('Link URL');
const displayLinkAs = getByLabelText('Display Link As');
await fireEvent.update(title, 'Test Title');
await fireEvent.update(description, 'Test Description');
const publishOn = getByLabelText('Publish On');
const expiresOn = getByLabelText('Expires On');
await setDate(publishOn, () => getByText('15'));
await setDate(expiresOn, () => getByText('20'));
await fireEvent.update(linkUrl, 'https://example.com');
await fireEvent.update(displayLinkAs, 'Example.pdf');
await fireEvent.click(publishButton);
await waitFor(() => {
expect(
screen.getByText('Are you sure you want to publish this announcement?'),
).toBeInTheDocument();
});
const cancelButton = screen.getByRole('button', { name: 'Close' });
await fireEvent.click(cancelButton);
await waitFor(() => {
expect(mockAddAnnouncement).not.toHaveBeenCalled();
});
});
it('should show error message when title is empty', async () => {
const { getByRole, getByText } = await wrappedRender();
const publishButton = getByRole('button', { name: 'Publish' });
Expand Down Expand Up @@ -177,7 +213,7 @@ describe('AddAnnouncementPage', () => {
await fireEvent.update(linkUrl, 'https://example.com');
await fireEvent.update(displayLinkAs, 'Example.pdf');
await fireEvent.click(publishButton);
expect(mockAddAnnouncement).not.toHaveBeenCalled();
expect(mockAddAnnouncement).not.toHaveBeenCalled();
});
});
it('should show error message when link url is invalid', async () => {
Expand Down Expand Up @@ -307,9 +343,52 @@ describe('AddAnnouncementPage', () => {
await fireEvent.update(linkUrl, 'https://example.com');
await fireEvent.update(displayLinkAs, 'Example.pdf');
await fireEvent.click(publishButton);
await waitFor(() => {
expect(
screen.getByText(
'Are you sure you want to publish this announcement?',
),
).toBeInTheDocument();
});
const continueButton = screen.getByRole('button', { name: 'Confirm' });
await fireEvent.click(continueButton);
await waitFor(() => {
expect(mockError).toHaveBeenCalled();
});
});
});

describe('when cancel button is clicked', () => {
it('should navigate to announcements page', async () => {
const { getByRole } = await wrappedRender();
const cancelButton = getByRole('button', { name: 'Cancel' });
await fireEvent.click(cancelButton);
await waitFor(() => {
expect(mockRouterBack).toHaveBeenCalled();
});
});

describe('when form is dirty', () => {
it('should show confirmation dialog', async () => {
const { getByRole } = await wrappedRender();
const title = screen.getByLabelText('Title');
await fireEvent.update(title, 'Test Title');
const cancelButton = getByRole('button', { name: 'Cancel' });
await fireEvent.click(cancelButton);
await waitFor(() => {
expect(
screen.getByText(
'Are you sure want to cancel this changes. This process cannot be undone.',
),
).toBeInTheDocument();
});

const continueButton = screen.getByRole('button', { name: 'Continue' });
await fireEvent.click(continueButton);
await waitFor(() => {
expect(mockRouterBack).toHaveBeenCalled();
});
});
});
});
});
61 changes: 55 additions & 6 deletions admin-frontend/src/components/announcements/AnnouncementForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
<div class="toolbar">
<h1>{{ title }}</h1>
<span class="fill-remaining-space"></span>
<v-btn variant="text" color="primary" class="mr-2" @click="$router.back()"
<v-btn variant="text" color="primary" class="mr-2" @click="handleCancel"
>Cancel</v-btn
>

<v-btn
variant="outlined"
color="primary"
Expand Down Expand Up @@ -114,7 +115,7 @@
<span class="attachment-label">Display Link As</span>
<v-text-field
single-line
variant="outlined"
variant="filled"
placeholder="eg., DocumentName.pdf"
label="Display Link As"
v-model="linkDisplayName"
Expand All @@ -125,27 +126,43 @@
</v-col>
</v-row>
</div>
<ConfirmationDialog ref="confirmDialog">
<template v-slot:message>
<p>
Are you sure want to cancel this changes. This process cannot be undone.
</p>
</template>
</ConfirmationDialog>
<ConfirmationDialog ref="publishConfirmationDialog">
<template v-slot:message>
<p>Are you sure you want to publish this announcement?</p>
</template>
</ConfirmationDialog>
</template>

<script lang="ts" setup>
import VueDatePicker from '@vuepic/vue-datepicker';
import { defineProps, defineEmits, watch } from 'vue';
import { defineProps, defineEmits, watch, ref } from 'vue';
import { AnnouncementFormValue } from '../../types/announcements';
import { useField, useForm } from 'vee-validate';
import * as zod from 'zod';
import { isEmpty } from 'lodash';
import { LocalDate, nativeJs } from '@js-joda/core';
const emits = defineEmits(['save']);
import ConfirmationDialog from '../util/ConfirmationDialog.vue';
import { useRouter } from 'vue-router';
type Props = {
announcement: AnnouncementFormValue | null;
title: string;
};
const router = useRouter();
const emits = defineEmits(['save']);
const confirmDialog = ref<typeof ConfirmationDialog>();
const publishConfirmationDialog = ref<typeof ConfirmationDialog>();
const { announcement } = defineProps<Props>();
const { handleSubmit, setErrors, errors } = useForm({
const { handleSubmit, setErrors, errors, meta } = useForm({
initialValues: {
title: announcement?.title || '',
description: announcement?.description || '',
Expand Down Expand Up @@ -203,6 +220,22 @@ watch(noExpiry, () => {
}
});
const handleCancel = async () => {
if (!meta.value.dirty) {
router.back();
return;
}
const result = await confirmDialog.value?.open('Confirm Cancel', undefined, {
titleBold: true,
resolveText: 'Continue',
});
if (result) {
router.back();
}
};
const handleSave = (status: 'DRAFT' | 'PUBLISHED') =>
handleSubmit(async (values) => {
if (!values.published_on && status === 'PUBLISHED') {
Expand Down Expand Up @@ -231,6 +264,22 @@ const handleSave = (status: 'DRAFT' | 'PUBLISHED') =>
return;
}
if (status === 'PUBLISHED') {
const confirmation = await publishConfirmationDialog.value?.open(
'Confirm Publish',
undefined,
{
titleBold: true,
resolveText: 'Confirm',
rejectText: 'Close',
},
);
if (!confirmation) {
return;
}
}
await emits('save', {
...values,
linkDisplayName: isEmpty(values.linkDisplayName)
Expand Down

0 comments on commit e3e8310

Please sign in to comment.