@planningcenter/tapestry-migration-cli 3.5.0 → 3.6.1-qa-1035.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.
Files changed (52) hide show
  1. package/README.md +37 -0
  2. package/dist/tapestry-react-shim.cjs +195 -11
  3. package/package.json +3 -3
  4. package/src/availableComponents.ts +1 -0
  5. package/src/components/button/transforms/tooltipToWrapper.test.ts +50 -3
  6. package/src/components/button/transforms/tooltipToWrapper.ts +18 -0
  7. package/src/components/flex/index.test.ts +291 -0
  8. package/src/components/flex/index.ts +54 -0
  9. package/src/components/flex/transforms/alignmentToAlign.test.ts +185 -0
  10. package/src/components/flex/transforms/alignmentToAlign.ts +73 -0
  11. package/src/components/flex/transforms/auditSpreadProps.test.ts +93 -0
  12. package/src/components/flex/transforms/auditSpreadProps.ts +6 -0
  13. package/src/components/flex/transforms/axisToDirection.test.ts +155 -0
  14. package/src/components/flex/transforms/axisToDirection.ts +77 -0
  15. package/src/components/flex/transforms/convertStyleProps.test.ts +147 -0
  16. package/src/components/flex/transforms/convertStyleProps.ts +23 -0
  17. package/src/components/flex/transforms/cssFlexAliasesToProps.test.ts +202 -0
  18. package/src/components/flex/transforms/cssFlexAliasesToProps.ts +110 -0
  19. package/src/components/flex/transforms/distributionToJustify.test.ts +214 -0
  20. package/src/components/flex/transforms/distributionToJustify.ts +76 -0
  21. package/src/components/flex/transforms/flexPropToExpand.test.ts +156 -0
  22. package/src/components/flex/transforms/flexPropToExpand.ts +100 -0
  23. package/src/components/flex/transforms/innerRefToRef.test.ts +100 -0
  24. package/src/components/flex/transforms/innerRefToRef.ts +14 -0
  25. package/src/components/flex/transforms/mediaQueriesToResponsive.test.ts +714 -0
  26. package/src/components/flex/transforms/mediaQueriesToResponsive.ts +523 -0
  27. package/src/components/flex/transforms/moveFlexImport.test.ts +202 -0
  28. package/src/components/flex/transforms/moveFlexImport.ts +14 -0
  29. package/src/components/flex/transforms/paddingPropsToFlex.test.ts +252 -0
  30. package/src/components/flex/transforms/paddingPropsToFlex.ts +150 -0
  31. package/src/components/flex/transforms/setDefaultAxis.test.ts +126 -0
  32. package/src/components/flex/transforms/setDefaultAxis.ts +30 -0
  33. package/src/components/flex/transforms/spacingToGap.test.ts +176 -0
  34. package/src/components/flex/transforms/spacingToGap.ts +49 -0
  35. package/src/components/flex/transforms/unsupportedProps.test.ts +141 -0
  36. package/src/components/flex/transforms/unsupportedProps.ts +17 -0
  37. package/src/components/select/index.ts +2 -0
  38. package/src/components/select/transforms/onChangeSignature.test.ts +224 -0
  39. package/src/components/select/transforms/onChangeSignature.ts +172 -0
  40. package/src/components/shared/actions/resolveConstantAttributeValue.test.ts +122 -0
  41. package/src/components/shared/actions/resolveConstantAttributeValue.ts +31 -0
  42. package/src/components/shared/helpers/unsupportedPropsHelpers.ts +41 -0
  43. package/src/components/shared/transformFactories/stylePropTransformFactory.test.ts +47 -0
  44. package/src/components/shared/transformFactories/stylePropTransformFactory.ts +16 -0
  45. package/src/components/toggle-switch/index.ts +2 -0
  46. package/src/components/toggle-switch/transforms/onClickToOnChange.test.ts +210 -0
  47. package/src/components/toggle-switch/transforms/onClickToOnChange.ts +71 -0
  48. package/src/index.test.ts +79 -0
  49. package/src/index.ts +29 -0
  50. package/src/migrationList.ts +22 -0
  51. package/src/utils/componentLabel.test.ts +61 -0
  52. package/src/utils/componentLabel.ts +15 -0
@@ -0,0 +1,155 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import transform from "./axisToDirection"
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("axisToDirection transform", () => {
18
+ it('maps axis="horizontal" to direction="row"', () => {
19
+ const input = `
20
+ import { StackView } from "@planningcenter/tapestry-react"
21
+
22
+ export default function Test() {
23
+ return <StackView axis="horizontal">Test</StackView>
24
+ }
25
+ `.trim()
26
+
27
+ const result = applyTransform(input)
28
+ expect(result).toContain('direction="row"')
29
+ expect(result).not.toContain("axis")
30
+ })
31
+
32
+ it('maps axis="vertical" to direction="column"', () => {
33
+ const input = `
34
+ import { StackView } from "@planningcenter/tapestry-react"
35
+
36
+ export default function Test() {
37
+ return <StackView axis="vertical">Test</StackView>
38
+ }
39
+ `.trim()
40
+
41
+ const result = applyTransform(input)
42
+ expect(result).toContain('direction="column"')
43
+ expect(result).not.toContain("axis")
44
+ })
45
+
46
+ it("maps an expression-wrapped string literal", () => {
47
+ const input = `
48
+ import { StackView } from "@planningcenter/tapestry-react"
49
+
50
+ export default function Test() {
51
+ return <StackView axis={"horizontal"}>Test</StackView>
52
+ }
53
+ `.trim()
54
+
55
+ const result = applyTransform(input)
56
+ expect(result).toContain('direction="row"')
57
+ expect(result).not.toContain("axis")
58
+ })
59
+
60
+ it("maps the StackView.HORIZONTAL constant", () => {
61
+ const input = `
62
+ import { StackView } from "@planningcenter/tapestry-react"
63
+
64
+ export default function Test() {
65
+ return <StackView axis={StackView.HORIZONTAL}>Test</StackView>
66
+ }
67
+ `.trim()
68
+
69
+ const result = applyTransform(input)
70
+ expect(result).toContain('direction="row"')
71
+ expect(result).not.toContain("axis")
72
+ expect(result).not.toContain("StackView.HORIZONTAL")
73
+ })
74
+
75
+ it("maps the StackView.VERTICAL constant", () => {
76
+ const input = `
77
+ import { StackView } from "@planningcenter/tapestry-react"
78
+
79
+ export default function Test() {
80
+ return <StackView axis={StackView.VERTICAL}>Test</StackView>
81
+ }
82
+ `.trim()
83
+
84
+ const result = applyTransform(input)
85
+ expect(result).toContain('direction="column"')
86
+ expect(result).not.toContain("StackView.VERTICAL")
87
+ })
88
+
89
+ it("flags a dynamic axis value and leaves it in place", () => {
90
+ const input = `
91
+ import { StackView } from "@planningcenter/tapestry-react"
92
+
93
+ export default function Test({ orientation }) {
94
+ return <StackView axis={orientation}>Test</StackView>
95
+ }
96
+ `.trim()
97
+
98
+ const result = applyTransform(input)
99
+ expect(result).toContain("axis={orientation}")
100
+ expect(result).toContain("TODO: tapestry-migration (axis)")
101
+ expect(result).not.toContain('direction="')
102
+ })
103
+
104
+ it("migrates a ternary axis value to a ternary direction value", () => {
105
+ const input = `
106
+ import { StackView } from "@planningcenter/tapestry-react"
107
+
108
+ export default function Test() {
109
+ return <StackView axis={isNarrow ? "vertical" : "horizontal"}>Test</StackView>
110
+ }
111
+ `.trim()
112
+
113
+ const result = applyTransform(input)
114
+ expect(result).toContain('direction={isNarrow ? "column" : "row"}')
115
+ expect(result).not.toContain("axis")
116
+ expect(result).not.toContain("TODO")
117
+ })
118
+
119
+ it("maps an aliased StackView import", () => {
120
+ const input = `
121
+ import { StackView as Stack } from "@planningcenter/tapestry-react"
122
+
123
+ export default function Test() {
124
+ return <Stack axis="horizontal">Test</Stack>
125
+ }
126
+ `.trim()
127
+
128
+ const result = applyTransform(input)
129
+ expect(result).toContain('direction="row"')
130
+ })
131
+
132
+ it("returns null when there is no axis to map", () => {
133
+ const input = `
134
+ import { StackView } from "@planningcenter/tapestry-react"
135
+
136
+ export default function Test() {
137
+ return <StackView>Test</StackView>
138
+ }
139
+ `.trim()
140
+
141
+ expect(applyTransform(input)).toBe(null)
142
+ })
143
+
144
+ it("returns null when StackView is not imported from tapestry-react", () => {
145
+ const input = `
146
+ import { StackView } from "some-other-package"
147
+
148
+ export default function Test() {
149
+ return <StackView axis="horizontal">Test</StackView>
150
+ }
151
+ `.trim()
152
+
153
+ expect(applyTransform(input)).toBe(null)
154
+ })
155
+ })
@@ -0,0 +1,77 @@
1
+ import { Transform } from "jscodeshift"
2
+
3
+ import { addComment } from "../../shared/actions/addComment"
4
+ import { getAttribute } from "../../shared/actions/getAttribute"
5
+ import { resolveConstantAttributeValue } from "../../shared/actions/resolveConstantAttributeValue"
6
+ import { hasAttribute } from "../../shared/conditions/hasAttribute"
7
+ import { attributeTransformFactory } from "../../shared/transformFactories/attributeTransformFactory"
8
+
9
+ const CONSTANT_AXIS_MAP: Record<string, string> = {
10
+ HORIZONTAL: "horizontal",
11
+ VERTICAL: "vertical",
12
+ }
13
+
14
+ const AXIS_DIRECTION_MAP: Record<string, string> = {
15
+ horizontal: "row",
16
+ vertical: "column",
17
+ }
18
+
19
+ const transform: Transform = attributeTransformFactory({
20
+ condition: hasAttribute("axis"),
21
+ targetComponent: "StackView",
22
+ targetPackage: "@planningcenter/tapestry-react",
23
+ transform: (element, { j, source }) => {
24
+ const axisAttribute = getAttribute({ element, name: "axis" })
25
+ if (!axisAttribute) return false
26
+
27
+ const resolved = resolveConstantAttributeValue({
28
+ attribute: axisAttribute,
29
+ constantMap: CONSTANT_AXIS_MAP,
30
+ })
31
+ const direction = resolved ? AXIS_DIRECTION_MAP[resolved] : undefined
32
+
33
+ if (!direction) {
34
+ const value = axisAttribute.value
35
+ if (value?.type === "JSXExpressionContainer") {
36
+ const expr = value.expression
37
+ if (
38
+ expr.type === "ConditionalExpression" &&
39
+ expr.consequent.type === "StringLiteral" &&
40
+ expr.alternate.type === "StringLiteral"
41
+ ) {
42
+ const consequentDir =
43
+ AXIS_DIRECTION_MAP[expr.consequent.value as string]
44
+ const alternateDir =
45
+ AXIS_DIRECTION_MAP[expr.alternate.value as string]
46
+ if (consequentDir && alternateDir) {
47
+ axisAttribute.name.name = "direction"
48
+ axisAttribute.value = j.jsxExpressionContainer(
49
+ j.conditionalExpression(
50
+ expr.test,
51
+ j.stringLiteral(consequentDir),
52
+ j.stringLiteral(alternateDir)
53
+ )
54
+ )
55
+ return true
56
+ }
57
+ }
58
+ }
59
+
60
+ addComment({
61
+ element,
62
+ j,
63
+ scope: "axis",
64
+ source,
65
+ text: "could not migrate axis to direction automatically; convert this value to row or column manually",
66
+ })
67
+ return true
68
+ }
69
+
70
+ axisAttribute.name.name = "direction"
71
+ axisAttribute.value = j.stringLiteral(direction)
72
+
73
+ return true
74
+ },
75
+ })
76
+
77
+ export default transform
@@ -0,0 +1,147 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import transform from "./convertStyleProps"
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("convertStyleProps transform", () => {
18
+ it("moves a margin style prop to a style object", () => {
19
+ const input = `
20
+ import { StackView } from "@planningcenter/tapestry-react"
21
+
22
+ export default function Test() {
23
+ return <StackView marginTop={2}>Test</StackView>
24
+ }
25
+ `.trim()
26
+
27
+ expect(applyTransform(input)).toMatchInlineSnapshot(`
28
+ "import { StackView } from "@planningcenter/tapestry-react"
29
+
30
+ export default function Test() {
31
+ return (
32
+ <StackView style={{
33
+ marginTop: "16px"
34
+ }}>Test</StackView>
35
+ );
36
+ }"
37
+ `)
38
+ })
39
+
40
+ it("moves a padding style prop to a style object (splitStyles expands shorthand)", () => {
41
+ const input = `
42
+ import { StackView } from "@planningcenter/tapestry-react"
43
+
44
+ export default function Test() {
45
+ return <StackView paddingTop={2}>Test</StackView>
46
+ }
47
+ `.trim()
48
+
49
+ expect(applyTransform(input)).toMatchInlineSnapshot(`
50
+ "import { StackView } from "@planningcenter/tapestry-react"
51
+
52
+ export default function Test() {
53
+ return (
54
+ <StackView style={{
55
+ paddingTop: "16px"
56
+ }}>Test</StackView>
57
+ );
58
+ }"
59
+ `)
60
+ })
61
+
62
+ it("migrates non-excluded style props while leaving excluded Flex props in place", () => {
63
+ const input = `
64
+ import { StackView } from "@planningcenter/tapestry-react"
65
+
66
+ export default function Test() {
67
+ return <StackView gap={2} marginTop={2}>Test</StackView>
68
+ }
69
+ `.trim()
70
+
71
+ expect(applyTransform(input)).toMatchInlineSnapshot(`
72
+ "import { StackView } from "@planningcenter/tapestry-react"
73
+
74
+ export default function Test() {
75
+ return (
76
+ <StackView gap={2} style={{
77
+ marginTop: "16px"
78
+ }}>Test</StackView>
79
+ );
80
+ }"
81
+ `)
82
+ })
83
+
84
+ it("leaves Flex first-class props untouched", () => {
85
+ const input = `
86
+ import { StackView } from "@planningcenter/tapestry-react"
87
+
88
+ export default function Test() {
89
+ return <StackView gap={2} padding={1} direction="row" wrap="wrap" alignSelf="center" columnGap={1} basis="100%" grow={1} shrink={0}>Test</StackView>
90
+ }
91
+ `.trim()
92
+
93
+ expect(applyTransform(input)).toBe(null)
94
+ })
95
+
96
+ it.each(["grow", "shrink", "basis"] as const)(
97
+ "leaves %s untouched and emits no TODO",
98
+ (prop) => {
99
+ const value = prop === "basis" ? '"100%"' : "{1}"
100
+ const input = `
101
+ import { StackView } from "@planningcenter/tapestry-react"
102
+ export default function Test() {
103
+ return <StackView ${prop}=${value}>Test</StackView>
104
+ }
105
+ `.trim()
106
+
107
+ expect(applyTransform(input)).toBe(null)
108
+ }
109
+ )
110
+
111
+ it("leaves axis/alignment/distribution/spacing for the dedicated rename transforms", () => {
112
+ const input = `
113
+ import { StackView } from "@planningcenter/tapestry-react"
114
+
115
+ export default function Test() {
116
+ return <StackView axis="horizontal" alignment="center" distribution="center" spacing={2}>Test</StackView>
117
+ }
118
+ `.trim()
119
+
120
+ const result = applyTransform(input)
121
+ expect(result).toBe(null)
122
+ })
123
+
124
+ it("returns null when there are no style props to migrate", () => {
125
+ const input = `
126
+ import { StackView } from "@planningcenter/tapestry-react"
127
+
128
+ export default function Test() {
129
+ return <StackView>Test</StackView>
130
+ }
131
+ `.trim()
132
+
133
+ expect(applyTransform(input)).toBe(null)
134
+ })
135
+
136
+ it("returns null when StackView is not imported from tapestry-react", () => {
137
+ const input = `
138
+ import { StackView } from "some-other-package"
139
+
140
+ export default function Test() {
141
+ return <StackView marginTop={2}>Test</StackView>
142
+ }
143
+ `.trim()
144
+
145
+ expect(applyTransform(input)).toBe(null)
146
+ })
147
+ })
@@ -0,0 +1,23 @@
1
+ import { stylePropTransformFactory } from "../../shared/transformFactories/stylePropTransformFactory"
2
+
3
+ const FLEX_PROP_NAMES = [
4
+ "alignItems",
5
+ "alignSelf",
6
+ "basis",
7
+ "columnGap",
8
+ "direction",
9
+ "flex",
10
+ "gap",
11
+ "grow",
12
+ "justifyContent",
13
+ "padding",
14
+ "shrink",
15
+ "wrap",
16
+ ]
17
+
18
+ export default stylePropTransformFactory({
19
+ stylesToExclude: FLEX_PROP_NAMES,
20
+ stylesToRemove: [],
21
+ targetComponent: "StackView",
22
+ targetPackage: "@planningcenter/tapestry-react",
23
+ })
@@ -0,0 +1,202 @@
1
+ import jscodeshift from "jscodeshift"
2
+ import { describe, expect, it } from "vitest"
3
+
4
+ import transform from "./cssFlexAliasesToProps"
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("cssFlexAliasesToProps transform", () => {
18
+ it("renames flexGrow to grow", () => {
19
+ const input = `
20
+ import { StackView } from "@planningcenter/tapestry-react"
21
+ export default function Test() {
22
+ return <StackView flexGrow={1}>Test</StackView>
23
+ }
24
+ `.trim()
25
+
26
+ const result = applyTransform(input)
27
+ expect(result).toContain("grow={1}")
28
+ expect(result).not.toContain("flexGrow")
29
+ })
30
+
31
+ it("renames flexShrink to shrink", () => {
32
+ const input = `
33
+ import { StackView } from "@planningcenter/tapestry-react"
34
+ export default function Test() {
35
+ return <StackView flexShrink={0}>Test</StackView>
36
+ }
37
+ `.trim()
38
+
39
+ const result = applyTransform(input)
40
+ expect(result).toContain("shrink={0}")
41
+ expect(result).not.toContain("flexShrink")
42
+ })
43
+
44
+ it("renames flexBasis to basis", () => {
45
+ const input = `
46
+ import { StackView } from "@planningcenter/tapestry-react"
47
+ export default function Test() {
48
+ return <StackView flexBasis="0%">Test</StackView>
49
+ }
50
+ `.trim()
51
+
52
+ const result = applyTransform(input)
53
+ expect(result).toContain('basis="0%"')
54
+ expect(result).not.toContain("flexBasis")
55
+ })
56
+
57
+ it("handles all three together", () => {
58
+ const input = `
59
+ import { StackView } from "@planningcenter/tapestry-react"
60
+ export default function Test() {
61
+ return <StackView flexGrow={1} flexShrink={0} flexBasis="auto">Test</StackView>
62
+ }
63
+ `.trim()
64
+
65
+ const result = applyTransform(input)
66
+ expect(result).toContain("grow={1}")
67
+ expect(result).toContain("shrink={0}")
68
+ expect(result).toContain('basis="auto"')
69
+ expect(result).not.toContain("flexGrow")
70
+ expect(result).not.toContain("flexShrink")
71
+ expect(result).not.toContain("flexBasis")
72
+ })
73
+
74
+ it("renames flexDirection to direction", () => {
75
+ const input = `
76
+ import { StackView } from "@planningcenter/tapestry-react"
77
+ export default function Test() {
78
+ return <StackView flexDirection="row">Test</StackView>
79
+ }
80
+ `.trim()
81
+
82
+ const result = applyTransform(input)
83
+ expect(result).toContain('direction="row"')
84
+ expect(result).not.toContain("flexDirection")
85
+ expect(result).not.toContain("TODO")
86
+ })
87
+
88
+ it("renames flexWrap to wrap", () => {
89
+ const input = `
90
+ import { StackView } from "@planningcenter/tapestry-react"
91
+ export default function Test() {
92
+ return <StackView flexWrap="wrap">Test</StackView>
93
+ }
94
+ `.trim()
95
+
96
+ const result = applyTransform(input)
97
+ expect(result).toContain('wrap="wrap"')
98
+ expect(result).not.toContain("flexWrap")
99
+ expect(result).not.toContain("TODO")
100
+ })
101
+
102
+ it("migrates justifyContent to justify with value normalization", () => {
103
+ const input = `
104
+ import { StackView } from "@planningcenter/tapestry-react"
105
+ export default function Test() {
106
+ return <StackView justifyContent="flex-start">Test</StackView>
107
+ }
108
+ `.trim()
109
+
110
+ const result = applyTransform(input)
111
+ expect(result).toContain('justify="start"')
112
+ expect(result).not.toContain("justifyContent")
113
+ expect(result).not.toContain("TODO")
114
+ })
115
+
116
+ it("migrates justifyContent center without normalization", () => {
117
+ const input = `
118
+ import { StackView } from "@planningcenter/tapestry-react"
119
+ export default function Test() {
120
+ return <StackView justifyContent="center">Test</StackView>
121
+ }
122
+ `.trim()
123
+
124
+ const result = applyTransform(input)
125
+ expect(result).toContain('justify="center"')
126
+ expect(result).not.toContain("TODO")
127
+ })
128
+
129
+ it("adds a TODO for an unmappable justifyContent value", () => {
130
+ const input = `
131
+ import { StackView } from "@planningcenter/tapestry-react"
132
+ export default function Test() {
133
+ return <StackView justifyContent="stretch">Test</StackView>
134
+ }
135
+ `.trim()
136
+
137
+ const result = applyTransform(input)
138
+ expect(result).toContain("TODO")
139
+ expect(result).toContain("justifyContent")
140
+ })
141
+
142
+ it("adds a TODO for a dynamic justifyContent value", () => {
143
+ const input = `
144
+ import { StackView } from "@planningcenter/tapestry-react"
145
+ export default function Test() {
146
+ return <StackView justifyContent={myVar}>Test</StackView>
147
+ }
148
+ `.trim()
149
+
150
+ const result = applyTransform(input)
151
+ expect(result).toContain("TODO")
152
+ })
153
+
154
+ it("migrates alignItems to align with value normalization", () => {
155
+ const input = `
156
+ import { StackView } from "@planningcenter/tapestry-react"
157
+ export default function Test() {
158
+ return <StackView alignItems="flex-end">Test</StackView>
159
+ }
160
+ `.trim()
161
+
162
+ const result = applyTransform(input)
163
+ expect(result).toContain('align="end"')
164
+ expect(result).not.toContain("alignItems")
165
+ expect(result).not.toContain("TODO")
166
+ })
167
+
168
+ it("adds a TODO for an unmappable alignItems value", () => {
169
+ const input = `
170
+ import { StackView } from "@planningcenter/tapestry-react"
171
+ export default function Test() {
172
+ return <StackView alignItems="space-between">Test</StackView>
173
+ }
174
+ `.trim()
175
+
176
+ const result = applyTransform(input)
177
+ expect(result).toContain("TODO")
178
+ expect(result).toContain("alignItems")
179
+ })
180
+
181
+ it("returns null when StackView has none of the CSS alias props", () => {
182
+ const input = `
183
+ import { StackView } from "@planningcenter/tapestry-react"
184
+ export default function Test() {
185
+ return <StackView gap={2}>Test</StackView>
186
+ }
187
+ `.trim()
188
+
189
+ expect(applyTransform(input)).toBe(null)
190
+ })
191
+
192
+ it("returns null when StackView is not imported from tapestry-react", () => {
193
+ const input = `
194
+ import { StackView } from "some-other-package"
195
+ export default function Test() {
196
+ return <StackView flexGrow={1}>Test</StackView>
197
+ }
198
+ `.trim()
199
+
200
+ expect(applyTransform(input)).toBe(null)
201
+ })
202
+ })