Skip to content

Commit ba481e3

Browse files
committed
feat: add tests
1 parent eef3974 commit ba481e3

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import { beforeEach, describe, expect, it, vi } from 'vitest'
2+
3+
import generateAiSteps from '@/graphql/mutations/ai/generate-ai-steps'
4+
import { Action } from '@/graphql/mutations/ai/schemas/actions.zod'
5+
import { Trigger } from '@/graphql/mutations/ai/schemas/triggers.zod'
6+
7+
const mocks = vi.hoisted(() => ({
8+
generateObject: vi.fn(),
9+
langfusePromptGet: vi.fn(),
10+
}))
11+
12+
vi.mock('ai', () => ({
13+
generateObject: mocks.generateObject,
14+
}))
15+
16+
vi.mock('@/helpers/langfuse', () => ({
17+
langfuseClient: {
18+
prompt: {
19+
get: mocks.langfusePromptGet,
20+
},
21+
},
22+
}))
23+
24+
vi.mock('@/helpers/launch-darkly', () => ({
25+
getLdFlagValue: vi.fn().mockResolvedValue('aids-v0'),
26+
}))
27+
28+
const DEFAULT_MOCKED_TRIGGER = {
29+
appKey: 'formsg',
30+
key: 'newSubmission',
31+
description:
32+
'This is a formsg trigger, which starts the workflow when a new submission is received',
33+
position: 1,
34+
type: 'trigger',
35+
config: {
36+
stepName: 'New FormSG submission',
37+
templateConfig: {},
38+
},
39+
}
40+
41+
const DEFAULT_MOCKED_ACTIONS = [
42+
{
43+
appKey: 'postman',
44+
key: 'sendTransactionalEmail',
45+
description: 'This is a postman action, which sends a transactional email',
46+
type: 'action',
47+
config: {
48+
stepName: 'Send a welcome email to the new user',
49+
templateConfig: {},
50+
},
51+
position: 2,
52+
},
53+
{
54+
appKey: 'postman-sms',
55+
key: 'sendSms',
56+
description: 'This is a postman action, which sends a SMS',
57+
type: 'action',
58+
config: {
59+
stepName: 'Send a welcome SMS to the new user',
60+
templateConfig: {},
61+
},
62+
position: 3,
63+
},
64+
]
65+
66+
const DEFAULT_MOCKED_OUTPUT = {
67+
object: {
68+
trigger: DEFAULT_MOCKED_TRIGGER,
69+
actions: DEFAULT_MOCKED_ACTIONS,
70+
},
71+
}
72+
73+
const DEFAULT_INPUT = {
74+
trigger: 'New FormSG submission',
75+
actions:
76+
'Send a welcome email to the new user\nSend a welcome SMS to the new user',
77+
}
78+
79+
describe('generateAiSteps mutation', () => {
80+
let context: any
81+
82+
beforeEach(async () => {
83+
vi.resetAllMocks()
84+
85+
mocks.langfusePromptGet.mockResolvedValue({ prompt: 'system prompt' })
86+
87+
context = {
88+
currentUser: {
89+
90+
},
91+
}
92+
})
93+
94+
it('should generate steps with valid input', async () => {
95+
mocks.generateObject.mockResolvedValueOnce(DEFAULT_MOCKED_OUTPUT)
96+
97+
const result = await generateAiSteps(
98+
null,
99+
{ input: DEFAULT_INPUT },
100+
context,
101+
)
102+
103+
expect(result.trigger).toStrictEqual(DEFAULT_MOCKED_TRIGGER)
104+
expect(result.actions).toStrictEqual(DEFAULT_MOCKED_ACTIONS)
105+
})
106+
107+
it('should throw an error if the input is invalid', async () => {
108+
await expect(
109+
generateAiSteps(
110+
null,
111+
{
112+
input: {
113+
trigger: 'gibberish',
114+
actions: 'gibberish',
115+
},
116+
},
117+
context,
118+
),
119+
).rejects.toThrow('Trigger description must be at least 15 characters')
120+
})
121+
122+
it('should throw an error if the input is invalid', async () => {
123+
await expect(
124+
generateAiSteps(
125+
null,
126+
{
127+
input: {
128+
trigger: 'New user submit a new form response',
129+
actions: 'gibberish',
130+
},
131+
},
132+
context,
133+
),
134+
).rejects.toThrow('Actions description must be at least 30 characters')
135+
})
136+
137+
it('should map step positions correctly', async () => {
138+
mocks.generateObject.mockResolvedValueOnce(DEFAULT_MOCKED_OUTPUT)
139+
140+
const result = await generateAiSteps(
141+
null,
142+
{ input: DEFAULT_INPUT },
143+
context,
144+
)
145+
146+
expect((result.trigger as Trigger).position).toBe(1)
147+
expect((result.actions as Action[])[0].position).toBe(2)
148+
expect((result.actions as Action[])[1].position).toBe(3)
149+
})
150+
})

0 commit comments

Comments
 (0)