@planningcenter/tapestry-migration-cli 2.4.0-rc.8 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -6
- package/dist/tapestry-react-shim.cjs +1 -1
- package/package.json +2 -2
- package/src/components/button/index.ts +3 -3
- package/src/components/button/transforms/innerRefToRef.test.ts +170 -0
- package/src/components/button/transforms/innerRefToRef.ts +14 -0
- package/src/components/button/transforms/unsupportedProps.ts +8 -31
- package/src/components/link/index.ts +14 -4
- package/src/components/link/transforms/auditSpreadProps.test.ts +351 -0
- package/src/components/link/transforms/auditSpreadProps.ts +24 -0
- package/src/components/link/transforms/innerRefToRef.test.ts +170 -0
- package/src/components/link/transforms/innerRefToRef.ts +14 -0
- package/src/components/link/transforms/moveLinkImport.test.ts +295 -0
- package/src/components/{button/transforms/linkToButton.ts → link/transforms/moveLinkImport.ts} +4 -5
- package/src/components/link/transforms/{inlineMemberToKind.test.ts → removeInlineMember.test.ts} +13 -28
- package/src/components/link/transforms/removeInlineMember.ts +11 -0
- package/src/components/link/transforms/{inlinePropToKind.test.ts → removeInlineProp.test.ts} +12 -29
- package/src/components/link/transforms/{inlinePropToKind.ts → removeInlineProp.ts} +0 -9
- package/src/components/link/transforms/tooltipToWrapper.test.ts +392 -0
- package/src/components/link/transforms/tooltipToWrapper.ts +35 -0
- package/src/components/link/transforms/unsupportedProps.test.ts +265 -0
- package/src/components/link/transforms/unsupportedProps.ts +58 -0
- package/src/components/shared/helpers/unsupportedPropsHelpers.ts +35 -0
- package/src/components/shared/transformFactories/stylePropTransformFactory.ts +1 -0
- package/src/index.ts +18 -7
- package/src/components/button/transforms/linkToButton.test.ts +0 -426
- package/src/components/link/transforms/inlineMemberToKind.ts +0 -49
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import jscodeshift from "jscodeshift"
|
|
2
|
+
import { describe, expect, it } from "vitest"
|
|
3
|
+
|
|
4
|
+
import transform from "./auditSpreadProps"
|
|
5
|
+
|
|
6
|
+
const j = jscodeshift.withParser("tsx")
|
|
7
|
+
|
|
8
|
+
const AUDIT_COMMENT =
|
|
9
|
+
"TODO: tapestry-migration (spreadAttribute): Spread props can contain unsupported props, please explore usages and migrate as needed."
|
|
10
|
+
|
|
11
|
+
function applyTransform(source: string) {
|
|
12
|
+
const fileInfo = { path: "test.tsx", source }
|
|
13
|
+
return transform(
|
|
14
|
+
fileInfo,
|
|
15
|
+
{ j, jscodeshift: j, report: () => {}, stats: () => {} },
|
|
16
|
+
{}
|
|
17
|
+
) as string | null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe("auditSpreadProps transform", () => {
|
|
21
|
+
describe("basic transformations", () => {
|
|
22
|
+
it("should add comment to Link with single spread prop", () => {
|
|
23
|
+
const input = `
|
|
24
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
25
|
+
|
|
26
|
+
export default function Test() {
|
|
27
|
+
const props = { href: "/test" }
|
|
28
|
+
return <Link {...props}>Go</Link>
|
|
29
|
+
}
|
|
30
|
+
`.trim()
|
|
31
|
+
|
|
32
|
+
const result = applyTransform(input)
|
|
33
|
+
expect(result).toContain(AUDIT_COMMENT)
|
|
34
|
+
expect(result).toContain("{...props}")
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it("should add comment to Link with multiple spread props", () => {
|
|
38
|
+
const input = `
|
|
39
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
40
|
+
|
|
41
|
+
export default function Test() {
|
|
42
|
+
const baseProps = { href: "/test" }
|
|
43
|
+
const styleProps = { className: "link" }
|
|
44
|
+
return <Link {...baseProps} {...styleProps}>Go</Link>
|
|
45
|
+
}
|
|
46
|
+
`.trim()
|
|
47
|
+
|
|
48
|
+
const result = applyTransform(input)
|
|
49
|
+
expect(result).toContain(AUDIT_COMMENT)
|
|
50
|
+
expect(result).toContain("{...baseProps}")
|
|
51
|
+
expect(result).toContain("{...styleProps}")
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it("should handle Link with spread props and regular attributes", () => {
|
|
55
|
+
const input = `
|
|
56
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
57
|
+
|
|
58
|
+
export default function Test() {
|
|
59
|
+
const props = { href: "/test" }
|
|
60
|
+
return <Link label="Go" {...props} external />
|
|
61
|
+
}
|
|
62
|
+
`.trim()
|
|
63
|
+
|
|
64
|
+
const result = applyTransform(input)
|
|
65
|
+
expect(result).toContain(AUDIT_COMMENT)
|
|
66
|
+
expect(result).toContain('label="Go"')
|
|
67
|
+
expect(result).toContain("{...props}")
|
|
68
|
+
expect(result).toContain("external")
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it("should handle multiple Link components with spread props", () => {
|
|
72
|
+
const input = `
|
|
73
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
74
|
+
|
|
75
|
+
export default function Test() {
|
|
76
|
+
const props1 = { href: "/test1" }
|
|
77
|
+
const props2 = { href: "/test2" }
|
|
78
|
+
return (
|
|
79
|
+
<div>
|
|
80
|
+
<Link {...props1}>Go 1</Link>
|
|
81
|
+
<Link {...props2}>Go 2</Link>
|
|
82
|
+
</div>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
`.trim()
|
|
86
|
+
|
|
87
|
+
const result = applyTransform(input)
|
|
88
|
+
expect(result).toContain(AUDIT_COMMENT)
|
|
89
|
+
expect(result).toContain("{...props1}")
|
|
90
|
+
expect(result).toContain("{...props2}")
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
describe("edge cases", () => {
|
|
95
|
+
it("should not transform Link without spread props", () => {
|
|
96
|
+
const input = `
|
|
97
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
98
|
+
|
|
99
|
+
export default function Test() {
|
|
100
|
+
return <Link href="/test">Go</Link>
|
|
101
|
+
}
|
|
102
|
+
`.trim()
|
|
103
|
+
|
|
104
|
+
const result = applyTransform(input)
|
|
105
|
+
expect(result).toBe(null)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it("should not transform if Link is not imported from @planningcenter/tapestry-react", () => {
|
|
109
|
+
const input = `
|
|
110
|
+
import { Link } from "other-library"
|
|
111
|
+
|
|
112
|
+
export default function Test() {
|
|
113
|
+
const props = { href: "/test" }
|
|
114
|
+
return <Link {...props}>Go</Link>
|
|
115
|
+
}
|
|
116
|
+
`.trim()
|
|
117
|
+
|
|
118
|
+
const result = applyTransform(input)
|
|
119
|
+
expect(result).toBe(null)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it("should handle Link with alias import", () => {
|
|
123
|
+
const input = `
|
|
124
|
+
import { Link as TapestryLink } from "@planningcenter/tapestry-react"
|
|
125
|
+
|
|
126
|
+
export default function Test() {
|
|
127
|
+
const props = { href: "/test" }
|
|
128
|
+
return <TapestryLink {...props}>Go</TapestryLink>
|
|
129
|
+
}
|
|
130
|
+
`.trim()
|
|
131
|
+
|
|
132
|
+
const result = applyTransform(input)
|
|
133
|
+
expect(result).toContain(AUDIT_COMMENT)
|
|
134
|
+
expect(result).toContain("{...props}")
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it("should handle mixed Link components (with and without spread props)", () => {
|
|
138
|
+
const input = `
|
|
139
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
140
|
+
|
|
141
|
+
export default function Test() {
|
|
142
|
+
const props = { href: "/test" }
|
|
143
|
+
return (
|
|
144
|
+
<div>
|
|
145
|
+
<Link {...props}>Go</Link>
|
|
146
|
+
<Link href="/static">Static</Link>
|
|
147
|
+
<Link href="/dynamic" external>External</Link>
|
|
148
|
+
</div>
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
`.trim()
|
|
152
|
+
|
|
153
|
+
const result = applyTransform(input)
|
|
154
|
+
expect(result).toContain(AUDIT_COMMENT)
|
|
155
|
+
expect(result).toContain("{...props}")
|
|
156
|
+
expect(result).toContain('<Link href="/static">Static</Link>')
|
|
157
|
+
expect(result).toContain('href="/dynamic"')
|
|
158
|
+
expect(result).toContain("external")
|
|
159
|
+
})
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
describe("complex spread prop scenarios", () => {
|
|
163
|
+
it("should handle Link with complex spread expression", () => {
|
|
164
|
+
const input = `
|
|
165
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
166
|
+
|
|
167
|
+
export default function Test() {
|
|
168
|
+
const baseProps = { className: "link" }
|
|
169
|
+
const additionalProps = isExternal ? { external: true } : {}
|
|
170
|
+
return <Link {...baseProps} {...additionalProps} href="/test">Go</Link>
|
|
171
|
+
}
|
|
172
|
+
`.trim()
|
|
173
|
+
|
|
174
|
+
const result = applyTransform(input)
|
|
175
|
+
expect(result).toContain(AUDIT_COMMENT)
|
|
176
|
+
expect(result).toContain("{...baseProps}")
|
|
177
|
+
expect(result).toContain("{...additionalProps}")
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
it("should handle Link with spread props in different positions", () => {
|
|
181
|
+
const input = `
|
|
182
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
183
|
+
|
|
184
|
+
export default function Test() {
|
|
185
|
+
const props = { className: "link" }
|
|
186
|
+
return (
|
|
187
|
+
<Link
|
|
188
|
+
label="Go"
|
|
189
|
+
{...props}
|
|
190
|
+
href="/test"
|
|
191
|
+
external={false}
|
|
192
|
+
/>
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
`.trim()
|
|
196
|
+
|
|
197
|
+
const result = applyTransform(input)
|
|
198
|
+
expect(result).toContain(AUDIT_COMMENT)
|
|
199
|
+
expect(result).toContain('label="Go"')
|
|
200
|
+
expect(result).toContain("{...props}")
|
|
201
|
+
expect(result).toContain('href="/test"')
|
|
202
|
+
expect(result).toContain("external={false}")
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
it("should handle spread props with object expressions", () => {
|
|
206
|
+
const input = `
|
|
207
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
208
|
+
|
|
209
|
+
export default function Test() {
|
|
210
|
+
return <Link {...{ href: "/test", className: "link" }}>Go</Link>
|
|
211
|
+
}
|
|
212
|
+
`.trim()
|
|
213
|
+
|
|
214
|
+
const result = applyTransform(input)
|
|
215
|
+
expect(result).toContain(AUDIT_COMMENT)
|
|
216
|
+
expect(result).toContain('{...{ href: "/test", className: "link" }}')
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
it("should handle spread props with function calls", () => {
|
|
220
|
+
const input = `
|
|
221
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
222
|
+
|
|
223
|
+
export default function Test() {
|
|
224
|
+
return <Link {...getLinkProps()} {...getStyleProps()}>Go</Link>
|
|
225
|
+
}
|
|
226
|
+
`.trim()
|
|
227
|
+
|
|
228
|
+
const result = applyTransform(input)
|
|
229
|
+
expect(result).toContain(AUDIT_COMMENT)
|
|
230
|
+
expect(result).toContain("{...getLinkProps()}")
|
|
231
|
+
expect(result).toContain("{...getStyleProps()}")
|
|
232
|
+
})
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
describe("self-closing Link components", () => {
|
|
236
|
+
it("should handle self-closing Link with spread props", () => {
|
|
237
|
+
const input = `
|
|
238
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
239
|
+
|
|
240
|
+
export default function Test() {
|
|
241
|
+
const props = { label: "Go", href: "/test" }
|
|
242
|
+
return <Link {...props} />
|
|
243
|
+
}
|
|
244
|
+
`.trim()
|
|
245
|
+
|
|
246
|
+
const result = applyTransform(input)
|
|
247
|
+
expect(result).toContain(AUDIT_COMMENT)
|
|
248
|
+
expect(result).toContain("{...props}")
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it("should handle self-closing Link with multiple spread props and attributes", () => {
|
|
252
|
+
const input = `
|
|
253
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
254
|
+
|
|
255
|
+
export default function Test() {
|
|
256
|
+
const baseProps = { href: "/test" }
|
|
257
|
+
const styleProps = { className: "link" }
|
|
258
|
+
return <Link label="Go" {...baseProps} {...styleProps} external />
|
|
259
|
+
}
|
|
260
|
+
`.trim()
|
|
261
|
+
|
|
262
|
+
const result = applyTransform(input)
|
|
263
|
+
expect(result).toContain(AUDIT_COMMENT)
|
|
264
|
+
expect(result).toContain('label="Go"')
|
|
265
|
+
expect(result).toContain("{...baseProps}")
|
|
266
|
+
expect(result).toContain("{...styleProps}")
|
|
267
|
+
expect(result).toContain("external")
|
|
268
|
+
})
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
describe("no changes scenarios", () => {
|
|
272
|
+
it("should return null when no Link components have spread props", () => {
|
|
273
|
+
const input = `
|
|
274
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
275
|
+
|
|
276
|
+
export default function Test() {
|
|
277
|
+
return (
|
|
278
|
+
<div>
|
|
279
|
+
<Link href="/test">Go</Link>
|
|
280
|
+
<Link label="Static" href="/static" />
|
|
281
|
+
<Link href="/dynamic" external>External</Link>
|
|
282
|
+
</div>
|
|
283
|
+
)
|
|
284
|
+
}
|
|
285
|
+
`.trim()
|
|
286
|
+
|
|
287
|
+
const result = applyTransform(input)
|
|
288
|
+
expect(result).toBe(null)
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
it("should return null when no Link imports exist", () => {
|
|
292
|
+
const input = `
|
|
293
|
+
import { Button } from "@planningcenter/tapestry-react"
|
|
294
|
+
|
|
295
|
+
export default function Test() {
|
|
296
|
+
const props = { onClick: handleClick }
|
|
297
|
+
return <Button {...props}>Save</Button>
|
|
298
|
+
}
|
|
299
|
+
`.trim()
|
|
300
|
+
|
|
301
|
+
const result = applyTransform(input)
|
|
302
|
+
expect(result).toBe(null)
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
it("should return null for empty file", () => {
|
|
306
|
+
const result = applyTransform("")
|
|
307
|
+
expect(result).toBe(null)
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
it("should return null when file has no JSX", () => {
|
|
311
|
+
const input = `
|
|
312
|
+
export function handleClick() {
|
|
313
|
+
console.log("clicked")
|
|
314
|
+
}
|
|
315
|
+
`.trim()
|
|
316
|
+
|
|
317
|
+
const result = applyTransform(input)
|
|
318
|
+
expect(result).toBe(null)
|
|
319
|
+
})
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
describe("different import scenarios", () => {
|
|
323
|
+
it("should handle default import with spread props", () => {
|
|
324
|
+
const input = `
|
|
325
|
+
import Link from "@planningcenter/tapestry-react"
|
|
326
|
+
|
|
327
|
+
export default function Test() {
|
|
328
|
+
const props = { href: "/test" }
|
|
329
|
+
return <Link {...props}>Go</Link>
|
|
330
|
+
}
|
|
331
|
+
`.trim()
|
|
332
|
+
|
|
333
|
+
const result = applyTransform(input)
|
|
334
|
+
expect(result).toBe(null)
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
it("should handle namespace import", () => {
|
|
338
|
+
const input = `
|
|
339
|
+
import * as Tapestry from "@planningcenter/tapestry-react"
|
|
340
|
+
|
|
341
|
+
export default function Test() {
|
|
342
|
+
const props = { href: "/test" }
|
|
343
|
+
return <Tapestry.Link {...props}>Go</Tapestry.Link>
|
|
344
|
+
}
|
|
345
|
+
`.trim()
|
|
346
|
+
|
|
347
|
+
const result = applyTransform(input)
|
|
348
|
+
expect(result).toBe(null)
|
|
349
|
+
})
|
|
350
|
+
})
|
|
351
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Transform } from "jscodeshift"
|
|
2
|
+
|
|
3
|
+
import { addCommentToAttribute } from "../../shared/actions/addCommentToAttribute"
|
|
4
|
+
import { getSpreadProps } from "../../shared/actions/getSpreadProps"
|
|
5
|
+
import { hasSpreadProps } from "../../shared/actions/hasSpreadProps"
|
|
6
|
+
import { attributeTransformFactory } from "../../shared/transformFactories/attributeTransformFactory"
|
|
7
|
+
|
|
8
|
+
const COMMENT =
|
|
9
|
+
"Spread props can contain unsupported props, please explore usages and migrate as needed."
|
|
10
|
+
|
|
11
|
+
const transform: Transform = attributeTransformFactory({
|
|
12
|
+
condition: hasSpreadProps,
|
|
13
|
+
targetComponent: "Link",
|
|
14
|
+
targetPackage: "@planningcenter/tapestry-react",
|
|
15
|
+
transform: (element, { j }) => {
|
|
16
|
+
const spreadProps = getSpreadProps(element)
|
|
17
|
+
spreadProps.forEach((prop) =>
|
|
18
|
+
addCommentToAttribute({ attribute: prop, j, text: COMMENT })
|
|
19
|
+
)
|
|
20
|
+
return spreadProps.length > 0
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
export default transform
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import jscodeshift from "jscodeshift"
|
|
2
|
+
import { describe, expect, it } from "vitest"
|
|
3
|
+
|
|
4
|
+
import transform from "./innerRefToRef"
|
|
5
|
+
|
|
6
|
+
const j = jscodeshift.withParser("tsx")
|
|
7
|
+
|
|
8
|
+
function applyTransform(source: string): string | null {
|
|
9
|
+
const fileInfo = { path: "test.tsx", source }
|
|
10
|
+
return transform(
|
|
11
|
+
fileInfo,
|
|
12
|
+
{ j, jscodeshift: j, report: () => {}, stats: () => {} },
|
|
13
|
+
{}
|
|
14
|
+
) as string | null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe("innerRefToRef transform", () => {
|
|
18
|
+
describe("basic transformations", () => {
|
|
19
|
+
it("should transform Link 'innerRef' prop to 'ref' prop", () => {
|
|
20
|
+
const input = `
|
|
21
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
22
|
+
|
|
23
|
+
export default function Test() {
|
|
24
|
+
return <Link innerRef={linkRef}>Go somewhere</Link>
|
|
25
|
+
}
|
|
26
|
+
`.trim()
|
|
27
|
+
|
|
28
|
+
const expected = `
|
|
29
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
30
|
+
|
|
31
|
+
export default function Test() {
|
|
32
|
+
return <Link ref={linkRef}>Go somewhere</Link>;
|
|
33
|
+
}
|
|
34
|
+
`.trim()
|
|
35
|
+
|
|
36
|
+
const result = applyTransform(input)
|
|
37
|
+
expect(result).toBe(expected)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it("should transform Link 'innerRef' prop to 'ref' prop with function", () => {
|
|
41
|
+
const input = `
|
|
42
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
43
|
+
|
|
44
|
+
export default function Test() {
|
|
45
|
+
return <Link innerRef={(el) => setLinkRef(el)}>Go somewhere</Link>
|
|
46
|
+
}
|
|
47
|
+
`.trim()
|
|
48
|
+
|
|
49
|
+
const expected = `
|
|
50
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
51
|
+
|
|
52
|
+
export default function Test() {
|
|
53
|
+
return <Link ref={(el) => setLinkRef(el)}>Go somewhere</Link>;
|
|
54
|
+
}
|
|
55
|
+
`.trim()
|
|
56
|
+
|
|
57
|
+
const result = applyTransform(input)
|
|
58
|
+
expect(result).toBe(expected)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it("should transform Link 'innerRef' prop to 'ref' prop with useRef", () => {
|
|
62
|
+
const input = `
|
|
63
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
64
|
+
import { useRef } from "react"
|
|
65
|
+
|
|
66
|
+
export default function Test() {
|
|
67
|
+
const linkRef = useRef(null)
|
|
68
|
+
return <Link innerRef={linkRef}>Go somewhere</Link>
|
|
69
|
+
}
|
|
70
|
+
`.trim()
|
|
71
|
+
|
|
72
|
+
const expected = `
|
|
73
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
74
|
+
import { useRef } from "react"
|
|
75
|
+
|
|
76
|
+
export default function Test() {
|
|
77
|
+
const linkRef = useRef(null)
|
|
78
|
+
return <Link ref={linkRef}>Go somewhere</Link>;
|
|
79
|
+
}
|
|
80
|
+
`.trim()
|
|
81
|
+
|
|
82
|
+
const result = applyTransform(input)
|
|
83
|
+
expect(result).toBe(expected)
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
describe("multiple components", () => {
|
|
88
|
+
it("should transform multiple Link components with innerRef", () => {
|
|
89
|
+
const input = `
|
|
90
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
91
|
+
|
|
92
|
+
export default function Test() {
|
|
93
|
+
return (
|
|
94
|
+
<div>
|
|
95
|
+
<Link innerRef={linkRef1}>First</Link>
|
|
96
|
+
<Link innerRef={linkRef2}>Second</Link>
|
|
97
|
+
</div>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
`.trim()
|
|
101
|
+
|
|
102
|
+
const expected = `
|
|
103
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
104
|
+
|
|
105
|
+
export default function Test() {
|
|
106
|
+
return (
|
|
107
|
+
<div>
|
|
108
|
+
<Link ref={linkRef1}>First</Link>
|
|
109
|
+
<Link ref={linkRef2}>Second</Link>
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
`.trim()
|
|
114
|
+
|
|
115
|
+
const result = applyTransform(input)
|
|
116
|
+
expect(result).toBe(expected)
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
describe("edge cases", () => {
|
|
121
|
+
it("should not transform Link without innerRef", () => {
|
|
122
|
+
const input = `
|
|
123
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
124
|
+
|
|
125
|
+
export default function Test() {
|
|
126
|
+
return <Link href="/dashboard">Go to dashboard</Link>
|
|
127
|
+
}
|
|
128
|
+
`.trim()
|
|
129
|
+
|
|
130
|
+
const result = applyTransform(input)
|
|
131
|
+
expect(result).toBe(null)
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
it("should not transform other components with innerRef", () => {
|
|
135
|
+
const input = `
|
|
136
|
+
import { Button } from "@planningcenter/tapestry-react"
|
|
137
|
+
|
|
138
|
+
export default function Test() {
|
|
139
|
+
return <Button innerRef={buttonRef}>Click me</Button>
|
|
140
|
+
}
|
|
141
|
+
`.trim()
|
|
142
|
+
|
|
143
|
+
const result = applyTransform(input)
|
|
144
|
+
expect(result).toBe(null)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it("should preserve other props when transforming innerRef", () => {
|
|
148
|
+
const input = `
|
|
149
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
150
|
+
|
|
151
|
+
export default function Test() {
|
|
152
|
+
const linkRef = null
|
|
153
|
+
return <Link innerRef={linkRef} href="/dashboard" onClick={() => {}}>Go to dashboard</Link>
|
|
154
|
+
}
|
|
155
|
+
`.trim()
|
|
156
|
+
|
|
157
|
+
const expected = `
|
|
158
|
+
import { Link } from "@planningcenter/tapestry-react"
|
|
159
|
+
|
|
160
|
+
export default function Test() {
|
|
161
|
+
const linkRef = null
|
|
162
|
+
return <Link ref={linkRef} href="/dashboard" onClick={() => {}}>Go to dashboard</Link>;
|
|
163
|
+
}
|
|
164
|
+
`.trim()
|
|
165
|
+
|
|
166
|
+
const result = applyTransform(input)
|
|
167
|
+
expect(result).toBe(expected)
|
|
168
|
+
})
|
|
169
|
+
})
|
|
170
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { transformAttributeName } from "../../shared/actions/transformAttributeName"
|
|
2
|
+
import { hasAttribute } from "../../shared/conditions/hasAttribute"
|
|
3
|
+
import { attributeTransformFactory } from "../../shared/transformFactories/attributeTransformFactory"
|
|
4
|
+
|
|
5
|
+
const transform = attributeTransformFactory({
|
|
6
|
+
condition: hasAttribute("innerRef"),
|
|
7
|
+
targetComponent: "Link",
|
|
8
|
+
targetPackage: "@planningcenter/tapestry-react",
|
|
9
|
+
transform: (element) => {
|
|
10
|
+
return transformAttributeName("innerRef", "ref", { element })
|
|
11
|
+
},
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
export default transform
|