Skip to content

Commit 227ab97

Browse files
authored
Merge pull request #3746 from liam-hq/devin/1760084909-fix-index-deletion-display
fix: correct display messages for index, constraint, enum, and extension operations
2 parents 163b522 + 20118ea commit 227ab97

File tree

2 files changed

+382
-3
lines changed

2 files changed

+382
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { formatArguments } from './formatArguments'
3+
4+
describe('formatArguments', () => {
5+
describe('formatRemoveOperation - index deletion bug fix', () => {
6+
it('should display "Removing index" for index deletion, not "Removing table"', () => {
7+
const args = {
8+
operations: [
9+
{
10+
op: 'remove',
11+
path: '/tables/users/indexes/idx_email',
12+
},
13+
],
14+
}
15+
16+
const result = formatArguments(args)
17+
18+
expect(result).toEqual([" Removing index 'idx_email'"])
19+
})
20+
21+
it('should display "Removing index" for index with complex name', () => {
22+
const args = {
23+
operations: [
24+
{
25+
op: 'remove',
26+
path: '/tables/document_embeddings/indexes/idx_document_embeddings',
27+
},
28+
],
29+
}
30+
31+
const result = formatArguments(args)
32+
33+
expect(result).toEqual([" Removing index 'idx_document_embeddings'"])
34+
})
35+
36+
it('should display "Removing constraint" for constraint deletion', () => {
37+
const args = {
38+
operations: [
39+
{
40+
op: 'remove',
41+
path: '/tables/users/constraints/fk_user_role',
42+
},
43+
],
44+
}
45+
46+
const result = formatArguments(args)
47+
48+
expect(result).toEqual([" Removing constraint 'fk_user_role'"])
49+
})
50+
51+
it('should display "Removing column" for column deletion', () => {
52+
const args = {
53+
operations: [
54+
{
55+
op: 'remove',
56+
path: '/tables/users/columns/email',
57+
},
58+
],
59+
}
60+
61+
const result = formatArguments(args)
62+
63+
expect(result).toEqual([" Removing column 'email'"])
64+
})
65+
66+
it('should display "Removing table" for table deletion', () => {
67+
const args = {
68+
operations: [
69+
{
70+
op: 'remove',
71+
path: '/tables/users',
72+
},
73+
],
74+
}
75+
76+
const result = formatArguments(args)
77+
78+
expect(result).toEqual(["Removing table 'users'"])
79+
})
80+
81+
it('should NOT match table when path contains nested resources', () => {
82+
const args = {
83+
operations: [
84+
{
85+
op: 'remove',
86+
path: '/tables/products/indexes/idx_product_name',
87+
},
88+
],
89+
}
90+
91+
const result = formatArguments(args)
92+
93+
expect(result).not.toContain("Removing table 'products'")
94+
expect(result).toEqual([" Removing index 'idx_product_name'"])
95+
})
96+
97+
it('should display "Removing enum" for enum deletion', () => {
98+
const args = {
99+
operations: [
100+
{
101+
op: 'remove',
102+
path: '/enums/user_status',
103+
},
104+
],
105+
}
106+
107+
const result = formatArguments(args)
108+
109+
expect(result).toEqual(["Removing enum 'user_status'"])
110+
})
111+
112+
it('should display "Removing extension" for extension deletion', () => {
113+
const args = {
114+
operations: [
115+
{
116+
op: 'remove',
117+
path: '/extensions/uuid-ossp',
118+
},
119+
],
120+
}
121+
122+
const result = formatArguments(args)
123+
124+
expect(result).toEqual(["Removing extension 'uuid-ossp'"])
125+
})
126+
127+
it('should handle unknown path gracefully', () => {
128+
const args = {
129+
operations: [
130+
{
131+
op: 'remove',
132+
path: '/unknown/path',
133+
},
134+
],
135+
}
136+
137+
const result = formatArguments(args)
138+
139+
expect(result).toEqual(['Removing /unknown/path'])
140+
})
141+
142+
it('should handle missing path', () => {
143+
const args = {
144+
operations: [
145+
{
146+
op: 'remove',
147+
},
148+
],
149+
}
150+
151+
const result = formatArguments(args)
152+
153+
expect(result).toEqual(['Removing unknown'])
154+
})
155+
})
156+
157+
describe('formatReplaceOperation - update operations', () => {
158+
it('should display "Updating index" for index update', () => {
159+
const args = {
160+
operations: [
161+
{
162+
op: 'replace',
163+
path: '/tables/users/indexes/idx_email',
164+
},
165+
],
166+
}
167+
168+
const result = formatArguments(args)
169+
170+
expect(result).toEqual([" Updating index 'idx_email'"])
171+
})
172+
173+
it('should display "Updating constraint" for constraint update', () => {
174+
const args = {
175+
operations: [
176+
{
177+
op: 'replace',
178+
path: '/tables/users/constraints/fk_user_role',
179+
},
180+
],
181+
}
182+
183+
const result = formatArguments(args)
184+
185+
expect(result).toEqual([" Updating constraint 'fk_user_role'"])
186+
})
187+
188+
it('should display "Updating column" for column update', () => {
189+
const args = {
190+
operations: [
191+
{
192+
op: 'replace',
193+
path: '/tables/users/columns/email',
194+
},
195+
],
196+
}
197+
198+
const result = formatArguments(args)
199+
200+
expect(result).toEqual([" Updating column 'email'"])
201+
})
202+
203+
it('should handle unknown path gracefully', () => {
204+
const args = {
205+
operations: [
206+
{
207+
op: 'replace',
208+
path: '/unknown/path',
209+
},
210+
],
211+
}
212+
213+
const result = formatArguments(args)
214+
215+
expect(result).toEqual(['Updating /unknown/path'])
216+
})
217+
218+
it('should handle missing path', () => {
219+
const args = {
220+
operations: [
221+
{
222+
op: 'replace',
223+
},
224+
],
225+
}
226+
227+
const result = formatArguments(args)
228+
229+
expect(result).toEqual(['Updating unknown'])
230+
})
231+
})
232+
233+
describe('multiple operations', () => {
234+
it('should format multiple remove operations correctly', () => {
235+
const args = {
236+
operations: [
237+
{
238+
op: 'remove',
239+
path: '/tables/users/indexes/idx_email',
240+
},
241+
{
242+
op: 'remove',
243+
path: '/tables/users/constraints/fk_user_role',
244+
},
245+
{
246+
op: 'remove',
247+
path: '/tables/users/columns/deprecated_field',
248+
},
249+
],
250+
}
251+
252+
const result = formatArguments(args)
253+
254+
expect(result).toEqual([
255+
" Removing index 'idx_email'",
256+
" Removing constraint 'fk_user_role'",
257+
" Removing column 'deprecated_field'",
258+
])
259+
})
260+
261+
it('should format mixed operations correctly', () => {
262+
const args = {
263+
operations: [
264+
{
265+
op: 'remove',
266+
path: '/tables/users/indexes/idx_old',
267+
},
268+
{
269+
op: 'replace',
270+
path: '/tables/users/indexes/idx_email',
271+
},
272+
{
273+
op: 'remove',
274+
path: '/tables/old_table',
275+
},
276+
],
277+
}
278+
279+
const result = formatArguments(args)
280+
281+
expect(result).toEqual([
282+
" Removing index 'idx_old'",
283+
" Updating index 'idx_email'",
284+
"Removing table 'old_table'",
285+
])
286+
})
287+
})
288+
289+
describe('edge cases', () => {
290+
it('should handle index name extraction from complex paths', () => {
291+
const args = {
292+
operations: [
293+
{
294+
op: 'remove',
295+
path: '/tables/very_long_table_name/indexes/idx_very_long_index_name',
296+
},
297+
],
298+
}
299+
300+
const result = formatArguments(args)
301+
302+
expect(result).toEqual([" Removing index 'idx_very_long_index_name'"])
303+
})
304+
305+
it('should handle paths with special characters in names', () => {
306+
const args = {
307+
operations: [
308+
{
309+
op: 'remove',
310+
path: '/tables/users/indexes/idx_user_email_v2',
311+
},
312+
],
313+
}
314+
315+
const result = formatArguments(args)
316+
317+
expect(result).toEqual([" Removing index 'idx_user_email_v2'"])
318+
})
319+
320+
it('should use fallback name when regex does not match', () => {
321+
const args = {
322+
operations: [
323+
{
324+
op: 'remove',
325+
path: '/tables//indexes/',
326+
},
327+
],
328+
}
329+
330+
const result = formatArguments(args)
331+
332+
expect(result).toEqual([" Removing index 'index'"])
333+
})
334+
})
335+
336+
describe('operation type variations', () => {
337+
it('should handle "type" field instead of "op" field', () => {
338+
const args = {
339+
operations: [
340+
{
341+
type: 'remove',
342+
path: '/tables/users/indexes/idx_email',
343+
},
344+
],
345+
}
346+
347+
const result = formatArguments(args)
348+
349+
expect(result).toEqual([" Removing index 'idx_email'"])
350+
})
351+
})
352+
})

0 commit comments

Comments
 (0)