@planningcenter/tapestry-migration-cli 3.2.2-rc.8 → 3.2.2

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.
Files changed (44) hide show
  1. package/package.json +3 -3
  2. package/src/components/checkbox/transforms/moveCheckboxImport.test.ts +26 -0
  3. package/src/components/checkbox/transforms/moveCheckboxImport.ts +1 -0
  4. package/src/components/input/transforms/moveInputImport.test.ts +26 -0
  5. package/src/components/input/transforms/moveInputImport.ts +1 -0
  6. package/src/components/input/transforms/numberFieldRenameToInput.test.ts +51 -0
  7. package/src/components/input/transforms/numberFieldRenameToInput.ts +1 -0
  8. package/src/components/radio/transforms/moveRadioImport.test.ts +26 -0
  9. package/src/components/radio/transforms/moveRadioImport.ts +1 -0
  10. package/src/components/select/transforms/moveSelectImport.test.ts +24 -0
  11. package/src/components/select/transforms/moveSelectImport.ts +1 -0
  12. package/src/components/shared/helpers/unsupportedPropsHelpers.ts +24 -0
  13. package/src/components/shared/transformFactories/helpers/manageImports.ts +25 -1
  14. package/src/components/shared/transformFactories/stylePropTransformFactory.test.ts +330 -0
  15. package/src/components/shared/transformFactories/stylePropTransformFactory.ts +156 -15
  16. package/src/components/shared/transformFactories/ternaryConditionalToPropFactory.ts +17 -12
  17. package/src/components/text-area/transforms/moveTextAreaImport.test.ts +26 -0
  18. package/src/components/text-area/transforms/moveTextAreaImport.ts +1 -0
  19. package/src/components/time-field/index.ts +48 -0
  20. package/src/components/time-field/transforms/auditSpreadProps.test.ts +76 -0
  21. package/src/components/time-field/transforms/auditSpreadProps.ts +10 -0
  22. package/src/components/time-field/transforms/convertStyleProps.test.ts +43 -0
  23. package/src/components/time-field/transforms/convertStyleProps.ts +10 -0
  24. package/src/components/time-field/transforms/flagMinMax.test.ts +103 -0
  25. package/src/components/time-field/transforms/flagMinMax.ts +31 -0
  26. package/src/components/time-field/transforms/mergeFieldIntoTimeField.test.ts +106 -0
  27. package/src/components/time-field/transforms/mergeFieldIntoTimeField.ts +5 -0
  28. package/src/components/time-field/transforms/moveTimeFieldImport.test.ts +153 -0
  29. package/src/components/time-field/transforms/moveTimeFieldImport.ts +14 -0
  30. package/src/components/time-field/transforms/sizeMapping.test.ts +173 -0
  31. package/src/components/time-field/transforms/sizeMapping.ts +15 -0
  32. package/src/components/time-field/transforms/stateToInvalid.test.ts +87 -0
  33. package/src/components/time-field/transforms/stateToInvalid.ts +56 -0
  34. package/src/components/time-field/transforms/stateToInvalidTernary.test.ts +100 -0
  35. package/src/components/time-field/transforms/stateToInvalidTernary.ts +11 -0
  36. package/src/components/time-field/transforms/tupleToTime.test.ts +182 -0
  37. package/src/components/time-field/transforms/tupleToTime.ts +107 -0
  38. package/src/components/time-field/transforms/twelveHourClockToHourCycle.test.ts +117 -0
  39. package/src/components/time-field/transforms/twelveHourClockToHourCycle.ts +65 -0
  40. package/src/components/time-field/transforms/unsupportedProps.test.ts +160 -0
  41. package/src/components/time-field/transforms/unsupportedProps.ts +37 -0
  42. package/src/components/toggle-switch/transforms/moveToggleSwitchImport.test.ts +28 -0
  43. package/src/components/toggle-switch/transforms/moveToggleSwitchImport.ts +1 -0
  44. package/src/index.ts +2 -1
@@ -0,0 +1,160 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import transform from "./unsupportedProps"
5
+
6
+ const j = jscodeshift.withParser("tsx")
7
+
8
+ function applyTransform(source: string): string {
9
+ const fileInfo = { path: "test.tsx", source }
10
+ const result = transform(
11
+ fileInfo,
12
+ { j, jscodeshift: j, report: () => {}, stats: () => {} },
13
+ {}
14
+ ) as string | null
15
+ return result || source
16
+ }
17
+
18
+ describe("unsupportedProps transform", () => {
19
+ it("flags ignoredKeys as unsupported", () => {
20
+ const input = `
21
+ import { TimeField } from "@planningcenter/tapestry-react"
22
+
23
+ function Test() {
24
+ return <TimeField ignoredKeys={["ArrowUp"]} value={time} onChange={setTime} />
25
+ }
26
+ `.trim()
27
+
28
+ const result = applyTransform(input)
29
+ expect(result).toContain("TODO: tapestry-migration")
30
+ expect(result).toContain("ignoredKeys")
31
+ })
32
+
33
+ it("flags interval as unsupported", () => {
34
+ const input = `
35
+ import { TimeField } from "@planningcenter/tapestry-react"
36
+
37
+ function Test() {
38
+ return <TimeField interval={15} value={time} onChange={setTime} />
39
+ }
40
+ `.trim()
41
+
42
+ const result = applyTransform(input)
43
+ expect(result).toContain("TODO: tapestry-migration")
44
+ expect(result).toContain("interval")
45
+ })
46
+
47
+ it("flags isIOS as unsupported", () => {
48
+ const input = `
49
+ import { TimeField } from "@planningcenter/tapestry-react"
50
+
51
+ function Test() {
52
+ return <TimeField isIOS value={time} onChange={setTime} />
53
+ }
54
+ `.trim()
55
+
56
+ const result = applyTransform(input)
57
+ expect(result).toContain("TODO: tapestry-migration")
58
+ expect(result).toContain("isIOS")
59
+ })
60
+
61
+ it("flags controlled as unsupported", () => {
62
+ const input = `
63
+ import { TimeField } from "@planningcenter/tapestry-react"
64
+
65
+ function Test() {
66
+ return <TimeField controlled value={time} onChange={setTime} />
67
+ }
68
+ `.trim()
69
+
70
+ const result = applyTransform(input)
71
+ expect(result).toContain("TODO: tapestry-migration")
72
+ expect(result).toContain("controlled")
73
+ })
74
+
75
+ it("flags placeholder as unsupported", () => {
76
+ const input = `
77
+ import { TimeField } from "@planningcenter/tapestry-react"
78
+
79
+ function Test() {
80
+ return <TimeField placeholder="Enter time" value={time} onChange={setTime} />
81
+ }
82
+ `.trim()
83
+
84
+ const result = applyTransform(input)
85
+ expect(result).toContain("TODO: tapestry-migration")
86
+ expect(result).toContain("placeholder")
87
+ })
88
+
89
+ it("does not flag supported props", () => {
90
+ const input = `
91
+ import { TimeField } from "@planningcenter/tapestry-react"
92
+
93
+ function Test() {
94
+ return (
95
+ <TimeField
96
+ value={time}
97
+ onChange={setTime}
98
+ disabled
99
+ required
100
+ size="md"
101
+ label="Start time"
102
+ description="Pick a time"
103
+ invalid
104
+ hourCycle={12}
105
+ hideLabel
106
+ hideTimeZone
107
+ forceLeadingZeros
108
+ readOnly
109
+ name="start"
110
+ className="my-time"
111
+ id="start-time"
112
+ />
113
+ )
114
+ }
115
+ `.trim()
116
+
117
+ const result = applyTransform(input)
118
+ expect(result).not.toContain("TODO: tapestry-migration")
119
+ })
120
+
121
+ it("allows aria-* and data-* attributes", () => {
122
+ const input = `
123
+ import { TimeField } from "@planningcenter/tapestry-react"
124
+
125
+ function Test() {
126
+ return <TimeField aria-describedby="help" data-testid="time" value={time} onChange={setTime} />
127
+ }
128
+ `.trim()
129
+
130
+ const result = applyTransform(input)
131
+ expect(result).not.toContain("TODO: tapestry-migration")
132
+ })
133
+
134
+ it("flags css prop with specific message", () => {
135
+ const input = `
136
+ import { TimeField } from "@planningcenter/tapestry-react"
137
+
138
+ function Test() {
139
+ return <TimeField css={{ color: "red" }} value={time} onChange={setTime} />
140
+ }
141
+ `.trim()
142
+
143
+ const result = applyTransform(input)
144
+ expect(result).toContain("TODO: tapestry-migration")
145
+ expect(result).toContain("CSS prop is not supported")
146
+ })
147
+
148
+ it("does not affect other components", () => {
149
+ const input = `
150
+ import { Button } from "@planningcenter/tapestry-react"
151
+
152
+ function Test() {
153
+ return <Button ignoredKeys={["x"]}>Click</Button>
154
+ }
155
+ `.trim()
156
+
157
+ const result = applyTransform(input)
158
+ expect(result).toBe(input)
159
+ })
160
+ })
@@ -0,0 +1,37 @@
1
+ import { JSXAttribute, Transform } from "jscodeshift"
2
+
3
+ import { addCommentToUnsupportedProps } from "../../shared/actions/addCommentToUnsupportedProps"
4
+ import { TIME_FIELD_SUPPORTED_PROPS } from "../../shared/helpers/unsupportedPropsHelpers"
5
+ import { attributeTransformFactory } from "../../shared/transformFactories/attributeTransformFactory"
6
+
7
+ const transform: Transform = attributeTransformFactory({
8
+ targetComponent: "TimeField",
9
+ targetPackage: "@planningcenter/tapestry-react",
10
+ transform: (element, { j }) => {
11
+ const attrs = element.openingElement.attributes || []
12
+
13
+ const UNSUPPORTED_PROPS = attrs
14
+ .filter(
15
+ (attr) =>
16
+ attr.type === "JSXAttribute" &&
17
+ !TIME_FIELD_SUPPORTED_PROPS.includes(attr.name.name as string) &&
18
+ !(attr.name.name as string).startsWith("aria-") &&
19
+ !(attr.name.name as string).startsWith("data-")
20
+ )
21
+ .map((attr) => (attr as JSXAttribute).name.name as string)
22
+
23
+ return addCommentToUnsupportedProps({
24
+ element,
25
+ j,
26
+ messageSuffix: (prop) => {
27
+ if (prop === "css") {
28
+ return "\n * CSS prop is not supported. Use className or style prop instead.\n"
29
+ }
30
+ return ""
31
+ },
32
+ props: UNSUPPORTED_PROPS,
33
+ })
34
+ },
35
+ })
36
+
37
+ export default transform
@@ -96,6 +96,34 @@ function Test() {
96
96
  })
97
97
  })
98
98
 
99
+ describe("import conflict handling", () => {
100
+ it("should use TToggleSwitch alias when ToggleSwitch is already imported from another package", () => {
101
+ const input = `
102
+ import { ToggleSwitch } from "some-other-library"
103
+ import { ToggleSwitch as ReactToggleSwitch } from "@planningcenter/tapestry-react"
104
+
105
+ function Test() {
106
+ return (
107
+ <div>
108
+ <ToggleSwitch />
109
+ <ReactToggleSwitch />
110
+ </div>
111
+ )
112
+ }
113
+ `.trim()
114
+
115
+ const result = applyTransform(input)
116
+ expect(result).toContain(
117
+ 'import { ToggleSwitch } from "some-other-library"'
118
+ )
119
+ expect(result).toContain(
120
+ 'import { ToggleSwitch as TToggleSwitch } from "@planningcenter/tapestry"'
121
+ )
122
+ expect(result).toContain("<TToggleSwitch")
123
+ expect(result).not.toContain("ReactToggleSwitch")
124
+ })
125
+ })
126
+
99
127
  describe("edge cases", () => {
100
128
  it("should handle already migrated imports", () => {
101
129
  const input = `
@@ -4,6 +4,7 @@ import { componentTransformFactory } from "../../shared/transformFactories/compo
4
4
 
5
5
  const transform: Transform = componentTransformFactory({
6
6
  condition: () => true,
7
+ conflictAlias: "TToggleSwitch",
7
8
  fromComponent: "ToggleSwitch",
8
9
  fromPackage: "@planningcenter/tapestry-react",
9
10
  toComponent: "ToggleSwitch",
package/src/index.ts CHANGED
@@ -19,6 +19,7 @@ const COMPONENTS_SET = new Set([
19
19
  "radio",
20
20
  "select",
21
21
  "text-area",
22
+ "time-field",
22
23
  "toggle-switch",
23
24
  ])
24
25
 
@@ -27,7 +28,7 @@ program
27
28
  .description("Run a migration of a component from Tapestry React to Tapestry")
28
29
  .argument(
29
30
  "<component-name>",
30
- "The name of the component to migrate (button, checkbox, input, link, radio, select, text-area, toggle-switch)"
31
+ "The name of the component to migrate (button, checkbox, input, link, radio, select, text-area, time-field, toggle-switch)"
31
32
  )
32
33
  .requiredOption(
33
34
  "-p, --path <path>",