mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-28 15:14:12 +00:00
796 lines
19 KiB
TypeScript
796 lines
19 KiB
TypeScript
import {
|
|
nestSpreadProperties,
|
|
transformTailwindConfig,
|
|
unnestSpreadProperties,
|
|
} from "@/src/utils/initializers/initialize-tailwind-config"
|
|
import { Project, SyntaxKind } from "ts-morph"
|
|
import { beforeEach, describe, expect, test } from "vitest"
|
|
|
|
const SHARED_CONFIG = {
|
|
$schema: "https://ui.shadcn.com/schema.json",
|
|
style: "new-york",
|
|
rsc: true,
|
|
tsx: true,
|
|
tailwind: {
|
|
config: "tailwind.config.ts",
|
|
css: "app/globals.css",
|
|
baseColor: "slate",
|
|
cssVariables: true,
|
|
},
|
|
aliases: {
|
|
components: "@/components",
|
|
utils: "@/lib/utils",
|
|
},
|
|
resolvedPaths: {
|
|
tailwindConfig: "tailwind.config.ts",
|
|
tailwindCss: "app/globals.css",
|
|
components: "./components",
|
|
utils: "./lib/utils",
|
|
ui: "./components/ui",
|
|
},
|
|
}
|
|
|
|
describe("transformTailwindConfig -> darkMode property", () => {
|
|
test("should add darkMode property if not in config", async () => {
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
backgroundImage: {
|
|
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
|
"gradient-conic":
|
|
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
|
},
|
|
},
|
|
},
|
|
plugins: [],
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
properties: [
|
|
{
|
|
name: "darkMode",
|
|
value: "class",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`/** @type {import('tailwindcss').Config} */
|
|
|
|
export default {
|
|
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
|
theme: {
|
|
extend: {},
|
|
},
|
|
plugins: [],
|
|
}
|
|
`,
|
|
{
|
|
properties: [
|
|
{
|
|
name: "darkMode",
|
|
value: "class",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`/** @type {import('tailwindcss').Config} */
|
|
const foo = {
|
|
bar: 'baz',
|
|
}
|
|
|
|
export default {
|
|
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
|
theme: {
|
|
extend: {},
|
|
},
|
|
plugins: [],
|
|
}
|
|
`,
|
|
{
|
|
properties: [
|
|
{
|
|
name: "darkMode",
|
|
value: "class",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
})
|
|
|
|
test("should append class to darkMode property if existing array", async () => {
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
darkMode: ["selector"],
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
backgroundImage: {
|
|
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
|
"gradient-conic":
|
|
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
|
},
|
|
},
|
|
},
|
|
plugins: [],
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
properties: [
|
|
{
|
|
name: "darkMode",
|
|
value: "class",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
})
|
|
|
|
test("should preserve quote kind", async () => {
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
darkMode: ['selector', '[data-mode="dark"]'],
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
backgroundImage: {
|
|
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
|
"gradient-conic":
|
|
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
|
},
|
|
},
|
|
},
|
|
plugins: [],
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
properties: [
|
|
{
|
|
name: "darkMode",
|
|
value: "class",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
})
|
|
|
|
test("should convert string to array and add class if darkMode is string", async () => {
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
darkMode: "selector",
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
backgroundImage: {
|
|
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
|
"gradient-conic":
|
|
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
|
},
|
|
},
|
|
},
|
|
plugins: [],
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
properties: [
|
|
{
|
|
name: "darkMode",
|
|
value: "class",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
})
|
|
|
|
test("should work with multiple darkMode selectors", async () => {
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
darkMode: ['variant', [
|
|
'@media (prefers-color-scheme: dark) { &:not(.light *) }',
|
|
'&:is(.dark *)',
|
|
]],
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
backgroundImage: {
|
|
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
|
"gradient-conic":
|
|
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
|
},
|
|
},
|
|
},
|
|
plugins: [],
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
properties: [
|
|
{
|
|
name: "darkMode",
|
|
value: "class",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
})
|
|
|
|
test("should not add darkMode property if already in config", async () => {
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
darkMode: ['class'],
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
backgroundImage: {
|
|
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
|
"gradient-conic":
|
|
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
|
},
|
|
},
|
|
},
|
|
plugins: [],
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
properties: [
|
|
{
|
|
name: "darkMode",
|
|
value: "class",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
darkMode: ['class', 'selector'],
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
backgroundImage: {
|
|
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
|
"gradient-conic":
|
|
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
|
},
|
|
},
|
|
},
|
|
plugins: [],
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
properties: [
|
|
{
|
|
name: "darkMode",
|
|
value: "class",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
})
|
|
})
|
|
|
|
describe("transformTailwindConfig -> plugin", () => {
|
|
test("should add plugin if not in config", async () => {
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
backgroundImage: {
|
|
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
|
"gradient-conic":
|
|
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
plugins: ["tailwindcss-animate"],
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
})
|
|
|
|
test("should append plugin to existing array", async () => {
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
backgroundImage: {
|
|
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
|
"gradient-conic":
|
|
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
|
},
|
|
},
|
|
},
|
|
plugins: [require("@tailwindcss/typography")],
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
plugins: ["tailwindcss-animate"],
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
})
|
|
|
|
test("should not add plugin if already in config", async () => {
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
backgroundImage: {
|
|
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
|
"gradient-conic":
|
|
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
|
},
|
|
},
|
|
},
|
|
plugins: [require("@tailwindcss/typography"), require("tailwindcss-animate")],
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
plugins: ["tailwindcss-animate"],
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
})
|
|
})
|
|
|
|
describe("transformTailwindConfig -> theme", () => {
|
|
// test("should add theme if not in config", async () => {
|
|
// expect(
|
|
// await transformTailwindConfig(
|
|
// `import type { Config } from 'tailwindcss'
|
|
|
|
// const config: Config = {
|
|
// content: [
|
|
// "./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
// "./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
// "./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
// ],
|
|
// }
|
|
// export default config
|
|
// `,
|
|
// {
|
|
// theme: {
|
|
// extend: {
|
|
// colors: {
|
|
// background: "hsl(var(--background))",
|
|
// foreground: "hsl(var(--foreground))",
|
|
// primary: {
|
|
// DEFAULT: "hsl(var(--primary))",
|
|
// foreground: "hsl(var(--primary-foreground))",
|
|
// },
|
|
// },
|
|
// },
|
|
// },
|
|
// },
|
|
// {
|
|
// config: SHARED_CONFIG,
|
|
// }
|
|
// )
|
|
// ).toMatchSnapshot()
|
|
// })
|
|
|
|
test("should merge existing theme", async () => {
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
colors: {
|
|
background: "hsl(var(--background))",
|
|
foreground: "hsl(var(--foreground))",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
theme: {
|
|
extend: {
|
|
colors: {
|
|
primary: {
|
|
DEFAULT: "hsl(var(--primary))",
|
|
foreground: "hsl(var(--primary-foreground))",
|
|
},
|
|
card: {
|
|
DEFAULT: "hsl(var(--card))",
|
|
foreground: "hsl(var(--card-foreground))",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
})
|
|
|
|
test("should keep spread assignments", async () => {
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
colors: {
|
|
...defaultColors,
|
|
background: "hsl(var(--background))",
|
|
foreground: "hsl(var(--foreground))",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
theme: {
|
|
extend: {
|
|
colors: {
|
|
primary: {
|
|
DEFAULT: "hsl(var(--primary))",
|
|
foreground: "hsl(var(--primary-foreground))",
|
|
},
|
|
card: {
|
|
DEFAULT: "hsl(var(--card))",
|
|
foreground: "hsl(var(--card-foreground))",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
})
|
|
|
|
test("should handle multiple properties", async () => {
|
|
expect(
|
|
await transformTailwindConfig(
|
|
`import type { Config } from 'tailwindcss'
|
|
|
|
const config: Config = {
|
|
content: [
|
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
],
|
|
theme: {
|
|
extend: {
|
|
fontFamily: {
|
|
sans: ["var(--font-geist-sans)", ...fontFamily.sans],
|
|
mono: ["var(--font-mono)", ...fontFamily.mono],
|
|
},
|
|
colors: {
|
|
...defaultColors,
|
|
background: "hsl(var(--background))",
|
|
foreground: "hsl(var(--foreground))",
|
|
},
|
|
boxShadow: {
|
|
...defaultBoxShadow,
|
|
"3xl": "0 35px 60px -15px rgba(0, 0, 0, 0.3)",
|
|
},
|
|
borderRadius: {
|
|
"3xl": "2rem",
|
|
},
|
|
animation: {
|
|
...defaultAnimation,
|
|
"spin-slow": "spin 3s linear infinite",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
export default config
|
|
`,
|
|
{
|
|
theme: {
|
|
extend: {
|
|
fontFamily: {
|
|
heading: ["var(--font-geist-sans)"],
|
|
},
|
|
colors: {
|
|
border: "hsl(var(--border))",
|
|
input: "hsl(var(--input))",
|
|
ring: "hsl(var(--ring))",
|
|
primary: {
|
|
DEFAULT: "hsl(var(--primary))",
|
|
foreground: "hsl(var(--primary-foreground))",
|
|
},
|
|
card: {
|
|
DEFAULT: "hsl(var(--card))",
|
|
foreground: "hsl(var(--card-foreground))",
|
|
},
|
|
},
|
|
borderRadius: {
|
|
lg: "var(--radius)",
|
|
md: "calc(var(--radius) - 2px)",
|
|
sm: "calc(var(--radius) - 4px)",
|
|
},
|
|
animation: {
|
|
"accordion-down": "accordion-down 0.2s ease-out",
|
|
"accordion-up": "accordion-up 0.2s ease-out",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
config: SHARED_CONFIG,
|
|
}
|
|
)
|
|
).toMatchSnapshot()
|
|
})
|
|
})
|
|
|
|
describe("nestSpreadProperties", () => {
|
|
let project: Project
|
|
|
|
beforeEach(() => {
|
|
project = new Project({ useInMemoryFileSystem: true })
|
|
})
|
|
|
|
function testTransformation(input: string, expected: string) {
|
|
const sourceFile = project.createSourceFile(
|
|
"test.ts",
|
|
`const config = ${input};`
|
|
)
|
|
const configObject = sourceFile.getFirstDescendantByKind(
|
|
SyntaxKind.ObjectLiteralExpression
|
|
)
|
|
if (!configObject) throw new Error("Config object not found")
|
|
|
|
nestSpreadProperties(configObject)
|
|
|
|
const result = configObject.getText()
|
|
expect(result.replace(/\s+/g, "")).toBe(expected.replace(/\s+/g, ""))
|
|
}
|
|
|
|
test("should nest spread properties", () => {
|
|
testTransformation(
|
|
`{ theme: { ...foo, bar: { ...baz, one: "two" }, other: { a: "b", ...c } } }`,
|
|
`{ theme: { ___foo: "...foo", bar: { ___baz: "...baz", one: "two" }, other: { a: "b", ___c: "...c" } } }`
|
|
)
|
|
})
|
|
|
|
test("should handle mixed property assignments", () => {
|
|
testTransformation(
|
|
`{ ...foo, a: 1, b() {}, ...bar, c: { ...baz } }`,
|
|
`{ ___foo: "...foo", a: 1, b() {}, ___bar: "...bar", c: { ___baz: "...baz" } }`
|
|
)
|
|
})
|
|
|
|
test("should handle objects with only spread properties", () => {
|
|
testTransformation(
|
|
`{ ...foo, ...bar, ...baz }`,
|
|
`{ ___foo: "...foo", ___bar: "...bar", ___baz: "...baz" }`
|
|
)
|
|
})
|
|
|
|
test("should handle property name conflicts", () => {
|
|
testTransformation(`{ foo: 1, ...foo }`, `{ foo: 1, ___foo: "...foo" }`)
|
|
})
|
|
|
|
test("should handle shorthand property names", () => {
|
|
testTransformation(`{ a, ...foo, b }`, `{ a, ___foo: "...foo", b }`)
|
|
})
|
|
|
|
test("should handle computed property names", () => {
|
|
testTransformation(
|
|
`{ ["computed"]: 1, ...foo }`,
|
|
`{ ["computed"]: 1, ___foo: "...foo" }`
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("unnestSpreadProperties", () => {
|
|
let project: Project
|
|
|
|
beforeEach(() => {
|
|
project = new Project({ useInMemoryFileSystem: true })
|
|
})
|
|
|
|
function testTransformation(input: string, expected: string) {
|
|
const sourceFile = project.createSourceFile(
|
|
"test.ts",
|
|
`const config = ${input};`
|
|
)
|
|
const configObject = sourceFile.getFirstDescendantByKind(
|
|
SyntaxKind.ObjectLiteralExpression
|
|
)
|
|
if (!configObject) throw new Error("Config object not found")
|
|
|
|
unnestSpreadProperties(configObject)
|
|
|
|
const result = configObject.getText()
|
|
expect(result.replace(/\s+/g, "")).toBe(expected.replace(/\s+/g, ""))
|
|
}
|
|
|
|
test("should nest spread properties", () => {
|
|
testTransformation(
|
|
`{ theme: { ___foo: "...foo", bar: { ___baz: "...baz", one: "two" }, other: { a: "b", ___c: "...c" } } }`,
|
|
`{ theme: { ...foo, bar: { ...baz, one: "two" }, other: { a: "b", ...c } } }`
|
|
)
|
|
})
|
|
|
|
test("should handle mixed property assignments", () => {
|
|
testTransformation(
|
|
`{ ___foo: "...foo", a: 1, b() {}, ___bar: "...bar", c: { ___baz: "...baz" } }`,
|
|
`{ ...foo, a: 1, b() {}, ...bar, c: { ...baz } }`
|
|
)
|
|
})
|
|
|
|
test("should handle objects with only spread properties", () => {
|
|
testTransformation(
|
|
`{ ___foo: "...foo", ___bar: "...bar", ___baz: "...baz" }`,
|
|
`{ ...foo, ...bar, ...baz }`
|
|
)
|
|
})
|
|
|
|
test("should handle property name conflicts", () => {
|
|
testTransformation(`{ foo: 1, ___foo: "...foo" }`, `{ foo: 1, ...foo }`)
|
|
})
|
|
|
|
test("should handle shorthand property names", () => {
|
|
testTransformation(`{ a, ___foo: "...foo", b }`, `{ a, ...foo, b }`)
|
|
})
|
|
|
|
test("should handle computed property names", () => {
|
|
testTransformation(
|
|
`{ ["computed"]: 1, ___foo: "...foo" }`,
|
|
`{ ["computed"]: 1, ...foo }`
|
|
)
|
|
})
|
|
})
|