Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Meta, StoryFn } from '@storybook/react'
import { http, HttpResponse } from 'msw'

import { FormResponseMode, FormSettings } from 'formsg-shared/types/form'

Expand Down Expand Up @@ -75,6 +76,22 @@ Loading.parameters = {
msw: { handlers: { default: buildMswRoutes({ delay: 'infinite' }) } },
}

export const Error = Template.bind({})
Error.parameters = {
msw: {
handlers: {
default: [
http.get('/api/v3/admin/forms/:formId/settings', () =>
HttpResponse.json(
{ message: 'Internal Server Error' },
{ status: 500 },
),
),
],
},
},
}

export const Mobile = Template.bind({})
Mobile.parameters = {
...StorageModeRetryEnabled.parameters,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { composeStories } from '@storybook/react'
import { act, render, screen } from '@testing-library/react'

import * as stories from './SettingsWebhooksPage.stories'

const { Error: ErrorStory, UnsupportedEmailMode } = composeStories(stories)

const UNSUPPORTED_MSG = /webhooks are only available in storage mode/i
const ERROR_MSG = /couldn't load webhook settings/i

describe('SettingsWebhooksPage', () => {
it('shows an error state, not the unsupported-mode message, when the settings fetch fails', async () => {
await act(async () => {
render(<ErrorStory />)
})

await screen.findByText(ERROR_MSG)
// The error is announced to assistive tech (it appears after an async failure).
expect(screen.getByRole('alert')).toBeInTheDocument()
expect(
screen.getByRole('button', { name: /try again/i }),
).toBeInTheDocument()
expect(screen.queryByText(UNSUPPORTED_MSG)).not.toBeInTheDocument()
})

it('still shows the unsupported-mode message for a form whose mode genuinely lacks webhook support', async () => {
await act(async () => {
render(<UnsupportedEmailMode />)
})

await screen.findByText(UNSUPPORTED_MSG)
expect(screen.queryByText(ERROR_MSG)).not.toBeInTheDocument()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@ import { useUser } from '~features/user/queries'

import { CategoryHeader } from './components/CategoryHeader'
import { WebhooksSection } from './components/WebhooksSection'
import { WebhooksErrorMsg } from './components/WebhooksSection/WebhooksErrorMsg'
import { WebhooksUnsupportedMsg } from './components/WebhooksSection/WebhooksUnsupportedMsg'
import { useAdminFormSettings } from './queries'

export const SettingsWebhooksPage = (): JSX.Element => {
const { t } = useTranslation()
const gb = useGrowthBook()
const { data: settings, isLoading } = useAdminFormSettings()
const {
data: settings,
isLoading,
isError,
isRefetching,
refetch,
} = useAdminFormSettings()
const userRes = useUser()

useEffect(() => {
Expand All @@ -27,9 +34,13 @@ export const SettingsWebhooksPage = (): JSX.Element => {

const enableMrfWebhooks = useFeatureIsOn(featureFlags.enableMrfWebhooks)

if (isError) {
return <WebhooksErrorMsg onRetry={refetch} isRetrying={isRefetching} />
}

const enableWebhooks =
!isLoading &&
(settings?.responseMode == FormResponseMode.Encrypt ||
(settings?.responseMode === FormResponseMode.Encrypt ||
Comment thread
LoneRifle marked this conversation as resolved.
(settings?.responseMode === FormResponseMode.Multirespondent &&
enableMrfWebhooks))

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useTranslation } from 'react-i18next'
import { Flex, Text } from '@chakra-ui/react'

import Button from '~components/Button'

export interface WebhooksErrorMsgProps {
onRetry: () => void
isRetrying?: boolean
}

export const WebhooksErrorMsg = ({
onRetry,
isRetrying = false,
}: WebhooksErrorMsgProps): JSX.Element => {
const { t } = useTranslation()
const { title, body, button } = t(
'features.adminForm.settings.webhooks.error',
{
returnObjects: true,
},
)
return (
<Flex justify="center" flexDir="column" textAlign="center" role="alert">
<Text textStyle="h2" as="h2" color="primary.500" mb="1rem">
{title}
</Text>
<Text textStyle="body-1" color="secondary.500" mb="2.5rem">
{body}
</Text>
<Flex justify="center">
<Button
isLoading={isRetrying}
loadingText={button.loadingText}
onClick={() => void onRetry()}
>
Comment thread
LoneRifle marked this conversation as resolved.
{button.label}
</Button>
</Flex>
</Flex>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,12 @@ export const enSG = {
label: 'Enable retries',
description: `Your system must meet certain requirements before retries can be safely enabled. [Learn more]({url})`,
},
error: {
title: "Couldn't load webhook settings",
body: "Something went wrong while loading this form's settings. This does not affect your form or its responses. Please try again.",
button: {
label: 'Try again',
loadingText: 'Trying again…',
},
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,12 @@ export interface Webhooks extends HasTitle {
label: string
description: string
}
error: {
title: string
body: string
button: {
label: string
loadingText: string
}
}
}
Loading