Skip to content

Commit 75ec93a

Browse files
committed
test(github): drive the wiring assertions from the alias table itself
1 parent aa9ca47 commit 75ec93a

2 files changed

Lines changed: 61 additions & 18 deletions

File tree

apps/sim/blocks/blocks/github.param-wiring.test.ts

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { describe, expect, it, vi } from 'vitest'
1010
*/
1111
vi.unmock('@/tools/registry')
1212

13-
import { GitHubBlock, GitHubV2Block } from '@/blocks/blocks/github'
13+
import { GITHUB_PARAM_ALIASES, GitHubBlock, GitHubV2Block } from '@/blocks/blocks/github'
1414
import { getTool } from '@/tools/utils'
1515

1616
function map(params: Record<string, unknown>): Record<string, unknown> {
@@ -20,23 +20,66 @@ function map(params: Record<string, unknown>): Record<string, unknown> {
2020
}
2121

2222
/**
23-
* Each pair is (block subBlock id, tool param name, tool id). The serializer
24-
* keys values by subBlock id, so without the mapper the tool param stays
25-
* undefined and the field is inert.
23+
* Derived from the alias table itself rather than mirrored by hand, so a new
24+
* alias cannot be added without these assertions covering it.
2625
*/
27-
const RENAMES = [
28-
['reaction_content', 'content', 'github_create_issue_reaction'],
29-
['reaction_content', 'content', 'github_create_comment_reaction'],
30-
['milestone_title', 'title', 'github_create_milestone'],
31-
['milestone_title', 'title', 'github_update_milestone'],
32-
['milestone_description', 'description', 'github_create_milestone'],
33-
['milestone_description', 'description', 'github_update_milestone'],
34-
['milestone_state', 'state', 'github_list_milestones'],
35-
['milestone_sort', 'sort', 'github_list_milestones'],
36-
['fork_name', 'name', 'github_fork_repo'],
37-
['fork_sort', 'sort', 'github_list_forks'],
38-
['gist_public', 'public', 'github_create_gist'],
39-
] as const
26+
const RENAMES = GITHUB_PARAM_ALIASES.flatMap((alias) =>
27+
alias.operations.map((operation) => [alias.from, alias.to, operation] as const)
28+
)
29+
30+
describe('the alias table is internally coherent', () => {
31+
/**
32+
* A floor, not a mirror: the derived assertions above scale to new aliases on
33+
* their own, but nothing would notice an alias being DELETED — the tests for
34+
* it would simply stop existing. These eight are the defects this suite was
35+
* written for, so their removal has to fail loudly.
36+
*/
37+
it('still covers every field this suite was written to fix', () => {
38+
expect(GITHUB_PARAM_ALIASES.map((a) => a.from).sort()).toEqual([
39+
'fork_name',
40+
'fork_sort',
41+
'gist_public',
42+
'milestone_description',
43+
'milestone_sort',
44+
'milestone_state',
45+
'milestone_title',
46+
'reaction_content',
47+
])
48+
})
49+
50+
it('covers every alias with at least one operation', () => {
51+
expect(GITHUB_PARAM_ALIASES.length).toBeGreaterThan(0)
52+
for (const alias of GITHUB_PARAM_ALIASES) {
53+
expect(alias.operations.length, `${alias.from} is scoped to no operation`).toBeGreaterThan(0)
54+
}
55+
})
56+
57+
/** A typo'd operation id would silently disable the alias — the exact class of bug this PR fixes. */
58+
it.each(GITHUB_PARAM_ALIASES.flatMap((a) => a.operations.map((op) => [a.from, op] as const)))(
59+
'%s is scoped to %s, which the block can actually select',
60+
(_from, operation) => {
61+
expect(GitHubBlock.tools.access).toContain(operation)
62+
}
63+
)
64+
65+
/** An alias pointing at an operation where its field never renders can never fire. */
66+
it.each(GITHUB_PARAM_ALIASES.map((a) => [a.from, a] as const))(
67+
'%s renders on every operation it is scoped to',
68+
(from, alias) => {
69+
const rendered = new Set<string>()
70+
for (const sub of GitHubBlock.subBlocks.filter((s) => s.id === from)) {
71+
const value = (sub.condition as { value?: unknown })?.value
72+
for (const op of Array.isArray(value) ? (value as string[]) : [value as string]) {
73+
rendered.add(op)
74+
}
75+
}
76+
expect(rendered.size, `${from} has no subBlock`).toBeGreaterThan(0)
77+
for (const op of alias.operations) {
78+
expect([...rendered]).toContain(op)
79+
}
80+
}
81+
)
82+
})
4083

4184
describe('every renamed subBlock reaches its tool param', () => {
4285
it.each(RENAMES)('%s -> %s', (subBlockId, paramName, toolId) => {

apps/sim/blocks/blocks/github.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const REVIEWER_FIELD = ['reviewers', 'team_reviewers'] as const
1919
* its option id, so the value arrives as the string 'true'/'false' and the
2020
* generic handler only JSON-parses `json`/`array` inputs.
2121
*/
22-
const GITHUB_PARAM_ALIASES: ReadonlyArray<{
22+
export const GITHUB_PARAM_ALIASES: ReadonlyArray<{
2323
from: string
2424
to: string
2525
operations: readonly string[]

0 commit comments

Comments
 (0)