@planningcenter/tapestry-migration-cli 3.4.1-rc.6 → 3.4.1-rc.8
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/tapestry-migration-cli",
|
|
3
|
-
"version": "3.4.1-rc.
|
|
3
|
+
"version": "3.4.1-rc.8",
|
|
4
4
|
"description": "CLI tool for Tapestry migrations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@emotion/react": "^11.14.0",
|
|
33
|
-
"@planningcenter/tapestry": "^3.4.1-rc.
|
|
33
|
+
"@planningcenter/tapestry": "^3.4.1-rc.8",
|
|
34
34
|
"@planningcenter/tapestry-react": "^4.11.5",
|
|
35
35
|
"@types/jscodeshift": "^17.3.0",
|
|
36
36
|
"@types/node": "^20.0.0",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "1514e1926f05eceaf949c194c3ff366778509e65"
|
|
54
54
|
}
|
|
@@ -15,6 +15,25 @@ function applyTransform(source: string): string | null {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
describe("dropdown orchestrator", () => {
|
|
18
|
+
it("applies linkToLink through the chain", () => {
|
|
19
|
+
const input = `
|
|
20
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
21
|
+
|
|
22
|
+
export default function Test() {
|
|
23
|
+
return (
|
|
24
|
+
<Dropdown title="Actions">
|
|
25
|
+
<Dropdown.Link to="/docs">Docs</Dropdown.Link>
|
|
26
|
+
</Dropdown>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
`.trim()
|
|
30
|
+
|
|
31
|
+
const result = applyTransform(input)
|
|
32
|
+
expect(result).toContain("<DropdownLink")
|
|
33
|
+
expect(result).toContain('href="/docs"')
|
|
34
|
+
expect(result).not.toContain("Dropdown.Link")
|
|
35
|
+
})
|
|
36
|
+
|
|
18
37
|
it("applies itemToAction through the chain", () => {
|
|
19
38
|
const input = `
|
|
20
39
|
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
@@ -38,12 +57,8 @@ export default function Test() {
|
|
|
38
57
|
const input = `
|
|
39
58
|
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
40
59
|
|
|
41
|
-
export default function Test() {
|
|
42
|
-
return
|
|
43
|
-
<Dropdown title="Actions">
|
|
44
|
-
<Dropdown.Link to="/docs">Docs</Dropdown.Link>
|
|
45
|
-
</Dropdown>
|
|
46
|
-
)
|
|
60
|
+
export default function Test({ children }) {
|
|
61
|
+
return <Dropdown title="Actions">{children}</Dropdown>
|
|
47
62
|
}
|
|
48
63
|
`.trim()
|
|
49
64
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { Transform } from "jscodeshift"
|
|
2
2
|
|
|
3
3
|
import itemToAction from "./transforms/itemToAction"
|
|
4
|
+
import linkToLink from "./transforms/linkToLink"
|
|
4
5
|
|
|
5
6
|
// When moveDropdownImport is added, it must remain last in the chain.
|
|
6
7
|
const transform: Transform = (fileInfo, api, options) => {
|
|
7
8
|
let currentSource = fileInfo.source
|
|
8
9
|
let hasAnyChanges = false
|
|
9
10
|
|
|
10
|
-
const transforms: Transform[] = [itemToAction]
|
|
11
|
+
const transforms: Transform[] = [linkToLink, itemToAction]
|
|
11
12
|
|
|
12
13
|
for (const individualTransform of transforms) {
|
|
13
14
|
const result = individualTransform(
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import jscodeshift from "jscodeshift"
|
|
2
|
+
import { describe, expect, it } from "vitest"
|
|
3
|
+
|
|
4
|
+
import transform from "./linkToLink"
|
|
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("linkToLink transform", () => {
|
|
18
|
+
describe("element renaming", () => {
|
|
19
|
+
it("renames Dropdown.Link to DropdownLink", () => {
|
|
20
|
+
const input = `
|
|
21
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
22
|
+
|
|
23
|
+
export default function Test() {
|
|
24
|
+
return (
|
|
25
|
+
<Dropdown title="Nav">
|
|
26
|
+
<Dropdown.Link to="/docs">Docs</Dropdown.Link>
|
|
27
|
+
</Dropdown>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
`.trim()
|
|
31
|
+
|
|
32
|
+
const result = applyTransform(input)
|
|
33
|
+
expect(result).toContain("<DropdownLink")
|
|
34
|
+
expect(result).toContain("</DropdownLink>")
|
|
35
|
+
expect(result).not.toContain("Dropdown.Link")
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it("preserves children through the rename", () => {
|
|
39
|
+
const input = `
|
|
40
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
41
|
+
|
|
42
|
+
export default function Test() {
|
|
43
|
+
return (
|
|
44
|
+
<Dropdown title="Nav">
|
|
45
|
+
<Dropdown.Link to="/docs">Documentation</Dropdown.Link>
|
|
46
|
+
</Dropdown>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
`.trim()
|
|
50
|
+
|
|
51
|
+
const result = applyTransform(input)
|
|
52
|
+
expect(result).toContain("Documentation")
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
describe("prop renaming", () => {
|
|
57
|
+
it("renames to to href", () => {
|
|
58
|
+
const input = `
|
|
59
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
60
|
+
|
|
61
|
+
export default function Test() {
|
|
62
|
+
return (
|
|
63
|
+
<Dropdown title="Nav">
|
|
64
|
+
<Dropdown.Link to="/docs">Docs</Dropdown.Link>
|
|
65
|
+
</Dropdown>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
`.trim()
|
|
69
|
+
|
|
70
|
+
const result = applyTransform(input)
|
|
71
|
+
expect(result).toContain('href="/docs"')
|
|
72
|
+
expect(result).not.toContain("to=")
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it("renames dynamic to expression to href", () => {
|
|
76
|
+
const input = `
|
|
77
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
78
|
+
|
|
79
|
+
export default function Test() {
|
|
80
|
+
return (
|
|
81
|
+
<Dropdown title="Nav">
|
|
82
|
+
<Dropdown.Link to={docsPath()}>Docs</Dropdown.Link>
|
|
83
|
+
</Dropdown>
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
`.trim()
|
|
87
|
+
|
|
88
|
+
const result = applyTransform(input)
|
|
89
|
+
expect(result).toContain("href={docsPath()}")
|
|
90
|
+
expect(result).not.toContain("to=")
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it("preserves external prop", () => {
|
|
94
|
+
const input = `
|
|
95
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
96
|
+
|
|
97
|
+
export default function Test() {
|
|
98
|
+
return (
|
|
99
|
+
<Dropdown title="Nav">
|
|
100
|
+
<Dropdown.Link to="https://example.com" external>External</Dropdown.Link>
|
|
101
|
+
</Dropdown>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
`.trim()
|
|
105
|
+
|
|
106
|
+
const result = applyTransform(input)
|
|
107
|
+
expect(result).toContain("external")
|
|
108
|
+
expect(result).toContain("<DropdownLink")
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
it("preserves unrecognised props", () => {
|
|
112
|
+
const input = `
|
|
113
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
114
|
+
|
|
115
|
+
export default function Test() {
|
|
116
|
+
return (
|
|
117
|
+
<Dropdown title="Nav">
|
|
118
|
+
<Dropdown.Link to="/docs" data-pendo="nav-docs">Docs</Dropdown.Link>
|
|
119
|
+
</Dropdown>
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
`.trim()
|
|
123
|
+
|
|
124
|
+
const result = applyTransform(input)
|
|
125
|
+
expect(result).toContain('data-pendo="nav-docs"')
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
describe("multiple links", () => {
|
|
130
|
+
it("renames all Dropdown.Link elements", () => {
|
|
131
|
+
const input = `
|
|
132
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
133
|
+
|
|
134
|
+
export default function Test() {
|
|
135
|
+
return (
|
|
136
|
+
<Dropdown title="Nav">
|
|
137
|
+
<Dropdown.Link to="/docs">Docs</Dropdown.Link>
|
|
138
|
+
<Dropdown.Link to="/status" external>Status</Dropdown.Link>
|
|
139
|
+
</Dropdown>
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
`.trim()
|
|
143
|
+
|
|
144
|
+
const result = applyTransform(input)
|
|
145
|
+
expect(result).not.toContain("Dropdown.Link")
|
|
146
|
+
const linkCount = (result?.match(/<DropdownLink/g) || []).length
|
|
147
|
+
expect(linkCount).toBe(2)
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
describe("isolation", () => {
|
|
152
|
+
it("does not affect the parent Dropdown element", () => {
|
|
153
|
+
const input = `
|
|
154
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
155
|
+
|
|
156
|
+
export default function Test() {
|
|
157
|
+
return (
|
|
158
|
+
<Dropdown title="Nav">
|
|
159
|
+
<Dropdown.Link to="/docs">Docs</Dropdown.Link>
|
|
160
|
+
</Dropdown>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
`.trim()
|
|
164
|
+
|
|
165
|
+
const result = applyTransform(input)
|
|
166
|
+
expect(result).toContain("<Dropdown ")
|
|
167
|
+
expect(result).toContain("</Dropdown>")
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
it("does not affect Dropdown.Item elements", () => {
|
|
171
|
+
const input = `
|
|
172
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
173
|
+
|
|
174
|
+
export default function Test() {
|
|
175
|
+
return (
|
|
176
|
+
<Dropdown title="Nav">
|
|
177
|
+
<Dropdown.Item onSelect={fn}>Edit</Dropdown.Item>
|
|
178
|
+
<Dropdown.Link to="/docs">Docs</Dropdown.Link>
|
|
179
|
+
</Dropdown>
|
|
180
|
+
)
|
|
181
|
+
}
|
|
182
|
+
`.trim()
|
|
183
|
+
|
|
184
|
+
const result = applyTransform(input)
|
|
185
|
+
expect(result).toContain("Dropdown.Item")
|
|
186
|
+
expect(result).toContain("<DropdownLink")
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
it("does not touch the import statement", () => {
|
|
190
|
+
const input = `
|
|
191
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
192
|
+
|
|
193
|
+
export default function Test() {
|
|
194
|
+
return (
|
|
195
|
+
<Dropdown title="Nav">
|
|
196
|
+
<Dropdown.Link to="/docs">Docs</Dropdown.Link>
|
|
197
|
+
</Dropdown>
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
`.trim()
|
|
201
|
+
|
|
202
|
+
const result = applyTransform(input)
|
|
203
|
+
expect(result).toContain(
|
|
204
|
+
'import { Dropdown } from "@planningcenter/tapestry-react"'
|
|
205
|
+
)
|
|
206
|
+
})
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
describe("no changes scenarios", () => {
|
|
210
|
+
it("returns null when Dropdown is not imported from tapestry-react", () => {
|
|
211
|
+
const input = `
|
|
212
|
+
import { Dropdown } from "some-other-library"
|
|
213
|
+
|
|
214
|
+
export default function Test() {
|
|
215
|
+
return (
|
|
216
|
+
<Dropdown>
|
|
217
|
+
<Dropdown.Link to="/docs">Docs</Dropdown.Link>
|
|
218
|
+
</Dropdown>
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
`.trim()
|
|
222
|
+
|
|
223
|
+
const result = applyTransform(input)
|
|
224
|
+
expect(result).toBe(null)
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
it("returns null when no Dropdown.Link is present", () => {
|
|
228
|
+
const input = `
|
|
229
|
+
import { Dropdown } from "@planningcenter/tapestry-react"
|
|
230
|
+
|
|
231
|
+
export default function Test() {
|
|
232
|
+
return (
|
|
233
|
+
<Dropdown title="Nav">
|
|
234
|
+
<Dropdown.Item onSelect={fn}>Edit</Dropdown.Item>
|
|
235
|
+
</Dropdown>
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
`.trim()
|
|
239
|
+
|
|
240
|
+
const result = applyTransform(input)
|
|
241
|
+
expect(result).toBe(null)
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
it("returns null for empty file", () => {
|
|
245
|
+
expect(applyTransform("")).toBe(null)
|
|
246
|
+
})
|
|
247
|
+
})
|
|
248
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Transform } from "jscodeshift"
|
|
2
|
+
|
|
3
|
+
import { transformAttributeName } from "../../shared/actions/transformAttributeName"
|
|
4
|
+
import { transformElementName } from "../../shared/actions/transformElementName"
|
|
5
|
+
import { attributeTransformFactory } from "../../shared/transformFactories/attributeTransformFactory"
|
|
6
|
+
|
|
7
|
+
const transform: Transform = attributeTransformFactory({
|
|
8
|
+
targetComponent: "Dropdown.Link",
|
|
9
|
+
targetPackage: "@planningcenter/tapestry-react",
|
|
10
|
+
transform: (element, { j, options }) => {
|
|
11
|
+
const toRenamed = transformAttributeName("to", "href", {
|
|
12
|
+
element,
|
|
13
|
+
j,
|
|
14
|
+
options,
|
|
15
|
+
})
|
|
16
|
+
const elementRenamed = transformElementName({
|
|
17
|
+
element,
|
|
18
|
+
name: "DropdownLink",
|
|
19
|
+
})
|
|
20
|
+
return toRenamed || elementRenamed
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
export default transform
|