Skip to content

Commit 465972b

Browse files
authored
PLU-512: auto check step formsg (#1253)
## Changes - Additional property for AppAuth `autoCheckStep` - now set to `true` for FormSG - When `autoCheckStep` is set to true for the app, the `executeTestStep` will be called automatically when "Save & Continue" is clicked <img width="310" height="220" alt="image" src="https://github.com/user-attachments/assets/e64f018c-d037-405e-b694-c2c84e50279b" /> - Test results now auto expands when executeTestStep is completed ## Refactors - `executeTestStep` now accepts `stepId` as a param which defaults to `currentStepId`. This is to allow executeTestStep to be called when creating a new pipe and currentStepId is not set yet. - Expanded TestResult should not render anything for If-Then steps ## How to test - Add a form sg step --> Test results should appear and expand - Modify a form sg connection --> Test results should also appear and expand automatically ## Updated E2E tests opengovsg/plumber-e2e#34
1 parent 9a48ca1 commit 465972b

File tree

8 files changed

+63
-24
lines changed

8 files changed

+63
-24
lines changed

packages/backend/src/apps/formsg/auth/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import verifyCredentials from './verify-credentials'
1111

1212
const auth: IUserAddedConnectionAuth = {
1313
connectionType: 'user-added' as const,
14-
14+
autoCheckStep: true,
1515
fields: [
1616
{
1717
key: 'formId',

packages/backend/src/graphql/schema.graphql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,11 +278,11 @@ type ConnectionModalLabel {
278278
type AppAuth {
279279
connectionType: String!
280280
connectionRegistrationType: String
281-
282281
fields: [Field] # Only for user-added connections
283282
authenticationSteps: [AuthenticationStep]
284283
reconnectionSteps: [ReconnectionStep]
285284
connectionModalLabel: ConnectionModalLabel
285+
autoCheckStep: Boolean
286286
}
287287

288288
enum ArgumentEnumType {

packages/frontend/src/components/FlowStepConfigurationModal/ChooseAndAddConnection/index.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,14 @@ export default function ChooseAndAddConnection(
6464
props: ChooseAndAddConnectionProps,
6565
) {
6666
const { onClose } = props
67-
const { flowId, onCreateStep, onDrawerOpen, onUpdateStep, setCurrentStepId } =
68-
useContext(EditorContext)
67+
const {
68+
flowId,
69+
onCreateStep,
70+
onDrawerOpen,
71+
onUpdateStep,
72+
setCurrentStepId,
73+
executeTestStep,
74+
} = useContext(EditorContext)
6975
const { modalState, patchModalState, step, prevStepId } = useContext(
7076
FlowStepConfigurationContext,
7177
)
@@ -136,6 +142,11 @@ export default function ChooseAndAddConnection(
136142
onClose()
137143
onDrawerOpen()
138144
setCurrentStepId(newStepId)
145+
if (selectedApp?.auth?.autoCheckStep && newStepId) {
146+
// need to deliberately set the step id because
147+
// closure of executeTestStep may still hold reference to old step id
148+
executeTestStep({ stepId: newStepId })
149+
}
139150
} catch (error) {
140151
console.error('Error selecting app and event', error)
141152
} finally {
@@ -149,10 +160,11 @@ export default function ChooseAndAddConnection(
149160
prevStepId,
150161
step,
151162
onClose,
152-
onCreateStep,
153-
onUpdateStep,
154163
onDrawerOpen,
155164
setCurrentStepId,
165+
onCreateStep,
166+
onUpdateStep,
167+
executeTestStep,
156168
],
157169
)
158170

packages/frontend/src/components/FlowStepTestController/TestResult.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { EditorContext } from '@/contexts/Editor'
99
import { TOOLBOX_ACTIONS } from '@/helpers/toolbox'
1010
import type { Variable } from '@/helpers/variables'
1111

12-
import { getForEachDataMessage, getIfThenOutput } from './utils'
12+
import { getForEachDataMessage } from './utils'
1313

1414
function getNoOutputMessage(
1515
selectedActionOrTrigger: TestResultsProps['selectedActionOrTrigger'],
@@ -79,13 +79,7 @@ export default function TestResult(props: TestResultsProps): JSX.Element {
7979
}
8080

8181
if (isIfThenStep) {
82-
const isConditionMet = variables?.[0]?.value as boolean
83-
const [variant, message] = getIfThenOutput(isConditionMet, step.id)
84-
return (
85-
<Infobox variant={variant} width="full">
86-
<Box>{message}</Box>
87-
</Infobox>
88-
)
82+
return null
8983
}
9084

9185
return (
@@ -107,6 +101,14 @@ export default function TestResult(props: TestResultsProps): JSX.Element {
107101
return (
108102
<Collapse
109103
in={isOpen}
104+
transition={{
105+
enter: {
106+
type: false,
107+
},
108+
exit: {
109+
type: false,
110+
},
111+
}}
110112
style={{
111113
width: '100%',
112114
marginTop: 0,

packages/frontend/src/components/FlowSubstep/index.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { IAction, IStep, ISubstep, ITrigger } from '@plumber/types'
22

33
import { useCallback, useContext, useEffect, useMemo, useState } from 'react'
44
import { useFormContext } from 'react-hook-form'
5-
import { Box, Stack, useDisclosure } from '@chakra-ui/react'
5+
import { Box, Stack, useDisclosure, usePrevious } from '@chakra-ui/react'
66
import { useToast } from '@opengovsg/design-system-react'
77

88
import FlowStepTestController from '@/components/FlowStepTestController'
@@ -11,7 +11,6 @@ import { getInputFlag } from '@/config/flags'
1111
import { EditorContext } from '@/contexts/Editor'
1212
import { LaunchDarklyContext } from '@/contexts/LaunchDarkly'
1313
import { hasDirtyFields, validateSubstep } from '@/helpers/editor'
14-
import { isIfThenStep } from '@/helpers/toolbox'
1514
import { validateStepParams } from '@/helpers/validateStepParams'
1615

1716
type FlowSubstepProps = {
@@ -31,6 +30,7 @@ function FlowSubstep(props: FlowSubstepProps): JSX.Element {
3130
onUpdateStep,
3231
setShouldWarnOnLeave,
3332
testExecutionSteps,
33+
isTestExecuting,
3434
} = useContext(EditorContext)
3535
const {
3636
isOpen: isTestResultOpen,
@@ -45,6 +45,7 @@ function FlowSubstep(props: FlowSubstepProps): JSX.Element {
4545
validateSubstep(substep, formContext.getValues() as IStep),
4646
)
4747
const [hasDeletedVars, setHasDeletedVars] = useState(false)
48+
const previousIsTestExecuting = usePrevious(isTestExecuting)
4849

4950
/*
5051
* NOTE: we use dirtyFields instead of isDirty because dirtyFields only tracks
@@ -73,6 +74,16 @@ function FlowSubstep(props: FlowSubstepProps): JSX.Element {
7374
[args, step.createdAt, selectedActionOrTrigger, getFlagValue],
7475
)
7576

77+
/**
78+
* We show the test result right after a chek step is run
79+
* i.e. isTestExecuting = true --> isTestExecuting = false
80+
*/
81+
useEffect(() => {
82+
if (isTestExecuting === false && previousIsTestExecuting === true) {
83+
onTestResultOpen()
84+
}
85+
}, [isTestExecuting, onTestResultOpen, step, previousIsTestExecuting])
86+
7687
useEffect(() => {
7788
function validate(step: unknown) {
7889
const typedStep = step as IStep
@@ -123,15 +134,12 @@ function FlowSubstep(props: FlowSubstepProps): JSX.Element {
123134
async (testRunMetadata?: Record<string, unknown>) => {
124135
try {
125136
await saveStep()
126-
await executeTestStep(testRunMetadata)
127-
if (!isIfThenStep(step)) {
128-
onTestResultOpen()
129-
}
137+
await executeTestStep({ testRunMetadata })
130138
} catch (error) {
131139
console.error('Error saving and test step')
132140
}
133141
},
134-
[saveStep, executeTestStep, step, onTestResultOpen],
142+
[saveStep, executeTestStep],
135143
)
136144

137145
return (

packages/frontend/src/contexts/Editor.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ interface IEditorContextValue {
5050
shouldWarnOnLeave: boolean
5151
stepsWithVars: StepWithVariables[]
5252
varInfoMap: VariableInfoMap
53-
executeTestStep: (testRunMetadata?: Record<string, unknown>) => Promise<void>
53+
executeTestStep: ({
54+
testRunMetadata,
55+
stepId,
56+
}: {
57+
testRunMetadata?: Record<string, unknown>
58+
stepId?: string | null
59+
}) => Promise<void>
5460
onDrawerOpen: () => void
5561
onDrawerClose: () => void
5662
setCurrentStepId: (stepId: string | null) => void
@@ -344,12 +350,21 @@ export const EditorProvider = ({
344350
)
345351

346352
const executeTestStep = useCallback(
347-
async (testRunMetadata?: Record<string, unknown>) => {
353+
async ({
354+
testRunMetadata,
355+
stepId = currentStepId,
356+
}: {
357+
testRunMetadata?: Record<string, unknown>
358+
stepId?: string | null
359+
}) => {
360+
if (!stepId) {
361+
throw new Error('Step ID is required')
362+
}
348363
try {
349364
await executeStep({
350365
variables: {
351366
input: {
352-
stepId: currentStepId,
367+
stepId,
353368
testRunMetadata,
354369
},
355370
},

packages/frontend/src/graphql/queries/get-apps.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export const GET_APPS = gql`
3232
auth {
3333
connectionType
3434
connectionRegistrationType
35+
autoCheckStep
3536
fields {
3637
key
3738
label

packages/types/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,7 @@ interface IBaseAuth {
648648
$: IGlobalVariable,
649649
): Promise<IVerifyConnectionRegistrationOutput>
650650
connectionModalLabel?: IConnectionModalLabel
651+
autoCheckStep?: boolean
651652
}
652653

653654
interface IUserAddedConnectionAuth extends IBaseAuth {

0 commit comments

Comments
 (0)