Skip to content

Commit

Permalink
use destinations for user CM form
Browse files Browse the repository at this point in the history
  • Loading branch information
tony-tvu committed Feb 7, 2024
1 parent 5951311 commit 2be42e2
Show file tree
Hide file tree
Showing 6 changed files with 417 additions and 1 deletion.
1 change: 1 addition & 0 deletions web/src/app/forms/FormField.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ FormField.propTypes = {

multiple: p.bool,

destType: p.string,
options: p.arrayOf(
p.shape({
label: p.string,
Expand Down
2 changes: 1 addition & 1 deletion web/src/app/selection/DestinationInputDirect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export default function DestinationInputDirect(
}

// add live validation icon to the right of the textfield as an endAdornment
if (adorn && props.value === debouncedValue) {
if (adorn && props.value === debouncedValue && !props.disabled) {
iprops = {
endAdornment: <InputAdornment position='end'>{adorn}</InputAdornment>,
...iprops,
Expand Down
56 changes: 56 additions & 0 deletions web/src/app/storybook/defaultDestTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,60 @@ export const destTypes: DestinationTypeInfo[] = [
},
],
},
{
type: 'supports-status',
name: 'Single Field Destination Type',
enabled: true,
disabledMessage: 'Single field destination type must be configured.',
userDisclaimer: '',
isContactMethod: true,
isEPTarget: false,
isSchedOnCallNotify: false,
iconURL: '',
iconAltText: '',
supportsStatusUpdates: true,
statusUpdatesRequired: false,
requiredFields: [
{
fieldID: 'phone-number',
labelSingular: 'Phone Number',
labelPlural: 'Phone Numbers',
hint: 'Include country code e.g. +1 (USA), +91 (India), +44 (UK)',
hintURL: '',
placeholderText: '11235550123',
prefix: '+',
inputType: 'tel',
isSearchSelectable: false,
supportsValidation: true,
},
],
},
{
type: 'required-status',
name: 'Single Field Destination Type',
enabled: true,
disabledMessage: 'Single field destination type must be configured.',
userDisclaimer: '',
isContactMethod: true,
isEPTarget: false,
isSchedOnCallNotify: false,
iconURL: '',
iconAltText: '',
supportsStatusUpdates: false,
statusUpdatesRequired: true,
requiredFields: [
{
fieldID: 'phone-number',
labelSingular: 'Phone Number',
labelPlural: 'Phone Numbers',
hint: 'Include country code e.g. +1 (USA), +91 (India), +44 (UK)',
hintURL: '',
placeholderText: '11235550123',
prefix: '+',
inputType: 'tel',
isSearchSelectable: false,
supportsValidation: true,
},
],
},
]
218 changes: 218 additions & 0 deletions web/src/app/users/UserContactMethodFormDest.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import React from 'react'
import type { Meta, StoryObj } from '@storybook/react'
import UserContactMethodFormDest, { Value } from './UserContactMethodFormDest'
import { expect } from '@storybook/jest'
import { within, screen, userEvent, waitFor } from '@storybook/testing-library'
import { handleDefaultConfig } from '../storybook/graphql'
import { useArgs } from '@storybook/preview-api'
import { HttpResponse, graphql } from 'msw'

const meta = {
title: 'users/UserContactMethodFormDest',
component: UserContactMethodFormDest,
tags: ['autodocs'],
parameters: {
msw: {
handlers: [
handleDefaultConfig,
graphql.query('ValidateDestination', ({ variables: vars }) => {
return HttpResponse.json({
data: {
destinationFieldValidate: vars.input.value === '+15555555555',
},
})
}),
],
},
},
render: function Component(args) {
const [, setArgs] = useArgs()
const onChange = (newValue: Value): void => {
if (args.onChange) args.onChange(newValue)
setArgs({ value: newValue })
}
return <UserContactMethodFormDest {...args} onChange={onChange} />
},
} satisfies Meta<typeof UserContactMethodFormDest>

export default meta
type Story = StoryObj<typeof meta>

export const SupportStatusUpdates: Story = {
args: {
value: {
name: 'supports status',
dest: {
type: 'supports-status',
values: [
{
fieldID: 'phone-number',
value: '+15555555555',
},
],
},
statusUpdates: false,
},
disabled: false,
},
play: async () => {
// ensure status updates checkbox is clickable
const status = await screen.getByLabelText('Send alert status updates')
userEvent.click(status, {
pointerEventsCheck: 1,
})
},
}

export const RequiredStatusUpdates: Story = {
args: {
value: {
name: 'required status',
dest: {
type: 'required-status',
values: [
{
fieldID: 'phone-number',
value: '+15555555555',
},
],
},
statusUpdates: false,
},
disabled: false,
},
play: async () => {
// ensure status updates checkbox is not clickable
const status = await screen.getByLabelText(
'Send alert status updates (cannot be disabled for this type)',
)
userEvent.click(status, {
pointerEventsCheck: 0,
})
},
}

export const ErrorSingleField: Story = {
args: {
value: {
name: '-notvalid',
dest: {
type: 'single-field',
values: [
{
fieldID: 'phone-number',
value: '+',
},
],
},
statusUpdates: false,
},
disabled: false,
errors: [
{
field: 'name',
message: 'must begin with a letter',
name: 'FieldError',
path: [],
details: {},
},
],
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
await userEvent.type(screen.getByLabelText('Phone Number'), '123')

// ensure errors are shown
await expect(canvas.getByText('Must begin with a letter')).toBeVisible()
await expect(await canvas.findByTestId('CloseIcon')).toBeVisible()
},
}

export const ErrorMultiField: Story = {
args: {
value: {
name: '-notvalid',
dest: {
type: 'triple-field',
values: [
{
fieldID: 'first-field',
value: '+',
},
{
fieldID: 'second-field',
value: 'notAnEmail',
},
{
fieldID: 'third-field',
value: '-',
},
],
},
statusUpdates: false,
},
disabled: false,
errors: [
{
field: 'name',
message: 'must begin with a letter',
name: 'FieldError',
path: [],
details: {},
},
],
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
await userEvent.type(screen.getByLabelText('First Item'), '123')

// ensure errors are shown
await expect(canvas.getByText('Must begin with a letter')).toBeVisible()
await waitFor(async () => {
await expect((await canvas.findAllByTestId('CloseIcon')).length).toBe(3)
})
},
}

export const Disabled: Story = {
args: {
value: {
name: 'disabled dest',
dest: {
type: 'triple-field',
values: [],
},
statusUpdates: false,
},
disabled: true,
},
play: async () => {
// ensure all fields are disabled
const destTypeOptions = await screen.getByText(
'Multi Field Destination Type',
)
const firstField = await screen.getByPlaceholderText('11235550123')
const secondField = await screen.getByPlaceholderText('foobar@example.com')
const thirdField = await screen.getByPlaceholderText('slack user ID')

userEvent.click(destTypeOptions, {
pointerEventsCheck: 0,
})
userEvent.click(firstField, {
pointerEventsCheck: 0,
})
userEvent.click(secondField, {
pointerEventsCheck: 0,
})
userEvent.click(thirdField, {
pointerEventsCheck: 0,
})

const status = await screen.getByLabelText(
'Send alert status updates (not supported for this type)',
)
userEvent.click(status, {
pointerEventsCheck: 0,
})
},
}
Loading

0 comments on commit 2be42e2

Please sign in to comment.