Skip to content

Commit de38e52

Browse files
EbonsignoriCopilot
andauthored
Fix webhook "Properties of" dropdowns rendering empty (#61008)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent 6776269 commit de38e52

2 files changed

Lines changed: 71 additions & 7 deletions

File tree

src/webhooks/lib/index.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,22 @@ export async function getInitialPageWebhooks(version: string): Promise<InitialWe
7777
data: defaultAction ? webhook[defaultAction] : {},
7878
}
7979

80-
// remove all nested params for the initial webhooks page, we'll load
81-
// them by request
80+
// Remove all nested params for the initial webhooks page — we'll load
81+
// them on demand via the /api/webhooks/v1 endpoint. Shallow-clone the
82+
// data object and each body parameter first so we don't mutate the
83+
// objects cached by getWebhooks(), which would cause the lazy-loaded
84+
// fetch to return empty childParamsGroups.
8285
if (initialWebhook.data.bodyParameters) {
83-
for (const bodyParam of initialWebhook.data.bodyParameters) {
84-
if (bodyParam.childParamsGroups) {
85-
bodyParam.childParamsGroups = []
86-
}
86+
initialWebhook.data = {
87+
...initialWebhook.data,
88+
bodyParameters: initialWebhook.data.bodyParameters.map((bodyParam) => ({
89+
...bodyParam,
90+
...(bodyParam.childParamsGroups ? { childParamsGroups: [] } : {}),
91+
})),
8792
}
8893
}
8994

90-
initialWebhooks.push({ ...initialWebhook })
95+
initialWebhooks.push(initialWebhook)
9196
}
9297
initialWebhooksCache.set(version, initialWebhooks)
9398
return initialWebhooks

src/webhooks/lib/tests/index.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { describe, expect, it } from 'vitest'
2+
3+
import { getInitialPageWebhooks, getWebhook } from '../index'
4+
5+
// Use a version that's guaranteed to exist in the data directory.
6+
const VERSION = 'free-pro-team@latest'
7+
8+
// Pick a webhook category whose data file has body parameters with
9+
// non-empty childParamsGroups so we can verify they survive the
10+
// initial-page stripping.
11+
const CATEGORY = 'projects_v2_item'
12+
13+
describe('getInitialPageWebhooks does not corrupt the getWebhook cache', () => {
14+
it('strips childParamsGroups from the initial-page data', async () => {
15+
const initial = await getInitialPageWebhooks(VERSION)
16+
const initialWebhook = initial.find((w) => w.name === CATEGORY)
17+
expect(initialWebhook).toBeDefined()
18+
19+
for (const bp of initialWebhook!.data.bodyParameters ?? []) {
20+
if (bp.childParamsGroups) {
21+
expect(bp.childParamsGroups, `initial ${bp.name} should be stripped`).toHaveLength(0)
22+
}
23+
}
24+
})
25+
26+
it('preserves childParamsGroups in the getWebhook cache after getInitialPageWebhooks runs', async () => {
27+
// Seed the cache and record original childParamsGroups lengths.
28+
const before = await getWebhook(VERSION, CATEGORY)
29+
expect(before).toBeDefined()
30+
31+
const originalLengths: Record<string, number> = {}
32+
for (const [action, actionData] of Object.entries(before!)) {
33+
for (const bp of actionData.bodyParameters ?? []) {
34+
if (bp.childParamsGroups && bp.childParamsGroups.length > 0) {
35+
originalLengths[`${action}.${bp.name}`] = bp.childParamsGroups.length
36+
}
37+
}
38+
}
39+
expect(Object.keys(originalLengths).length).toBeGreaterThan(0)
40+
41+
// This intentionally empties childParamsGroups for the initial page render.
42+
await getInitialPageWebhooks(VERSION)
43+
44+
// getWebhook returns cached data — it must NOT have been mutated.
45+
const after = await getWebhook(VERSION, CATEGORY)
46+
expect(after).toBeDefined()
47+
48+
for (const [key, expectedLen] of Object.entries(originalLengths)) {
49+
const [action, paramName] = key.split('.')
50+
const bp = after![action]?.bodyParameters?.find(
51+
(p: { name?: string }) => p.name === paramName,
52+
)
53+
expect(
54+
bp?.childParamsGroups?.length,
55+
`${key}.childParamsGroups should still have ${expectedLen} entries`,
56+
).toBe(expectedLen)
57+
}
58+
})
59+
})

0 commit comments

Comments
 (0)