test: improve testing for cli

This commit is contained in:
zernonia 2023-09-18 21:27:44 +08:00
parent 9a325676d0
commit afcdbf99a3
20 changed files with 339 additions and 487 deletions

View File

@ -17,7 +17,6 @@ To use utility classes for theming set `tailwind.cssVariables` to `false` in you
```json {8} title="components.json" ```json {8} title="components.json"
{ {
"style": "default", "style": "default",
"rsc": true,
"tailwind": { "tailwind": {
"config": "tailwind.config.js", "config": "tailwind.config.js",
"css": "app/globals.css", "css": "app/globals.css",
@ -43,7 +42,6 @@ To use CSS variables for theming set `tailwind.cssVariables` to `true` in your `
```json {8} title="components.json" ```json {8} title="components.json"
{ {
"style": "default", "style": "default",
"rsc": true,
"tailwind": { "tailwind": {
"config": "tailwind.config.js", "config": "tailwind.config.js",
"css": "app/globals.css", "css": "app/globals.css",

View File

@ -24,12 +24,6 @@
}, },
"required": ["config", "css", "baseColor", "cssVariables"] "required": ["config", "css", "baseColor", "cssVariables"]
}, },
"rsc": {
"type": "boolean"
},
"tsx": {
"type": "boolean"
},
"aliases": { "aliases": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -43,5 +37,5 @@
"required": ["utils", "components"] "required": ["utils", "components"]
} }
}, },
"required": ["style", "tailwind", "rsc", "aliases"] "required": ["style", "tailwind", "aliases"]
} }

View File

@ -8,6 +8,7 @@ import template from 'lodash.template'
import ora from 'ora' import ora from 'ora'
import prompts from 'prompts' import prompts from 'prompts'
import * as z from 'zod' import * as z from 'zod'
import { transform as transformByDetype } from 'detype'
import * as templates from '../utils/templates' import * as templates from '../utils/templates'
import { import {
getRegistryBaseColor, getRegistryBaseColor,
@ -28,7 +29,6 @@ import {
rawConfigSchema, rawConfigSchema,
resolveConfigPaths, resolveConfigPaths,
} from '../utils/get-config' } from '../utils/get-config'
import { transformByDetype } from '../utils/transformers/transform-sfc'
const PROJECT_DEPENDENCIES = { const PROJECT_DEPENDENCIES = {
base: [ base: [
@ -37,11 +37,6 @@ const PROJECT_DEPENDENCIES = {
'clsx', 'clsx',
'tailwind-merge', 'tailwind-merge',
], ],
vue: [
'tailwindcss',
'postcss',
'autoprefixer',
],
nuxt: [ nuxt: [
'@nuxtjs/tailwindcss', '@nuxtjs/tailwindcss',
], ],
@ -276,7 +271,7 @@ export async function runInit(cwd: string, config: Config) {
config.framework === 'nuxt' ? PROJECT_DEPENDENCIES.nuxt : PROJECT_DEPENDENCIES.vue, config.framework === 'nuxt' ? PROJECT_DEPENDENCIES.nuxt : PROJECT_DEPENDENCIES.vue,
).concat( ).concat(
config.style === 'new-york' ? [] : ['lucide-vue-next'], config.style === 'new-york' ? [] : ['lucide-vue-next'],
) ).filter(Boolean)
await execa( await execa(
packageManager, packageManager,

View File

@ -24,14 +24,14 @@ export const rawConfigSchema = z
.object({ .object({
$schema: z.string().optional(), $schema: z.string().optional(),
style: z.string(), style: z.string(),
typescript: z.boolean().default(false), typescript: z.boolean().default(true),
tailwind: z.object({ tailwind: z.object({
config: z.string(), config: z.string(),
css: z.string(), css: z.string(),
baseColor: z.string(), baseColor: z.string(),
cssVariables: z.boolean().default(true), cssVariables: z.boolean().default(true),
}), }),
framework: z.string(), framework: z.string().default('Vite'),
aliases: z.object({ aliases: z.object({
components: z.string(), components: z.string(),
utils: z.string(), utils: z.string(),
@ -96,8 +96,8 @@ export async function resolveConfigPaths(cwd: string, config: RawConfig) {
resolvedPaths: { resolvedPaths: {
tailwindConfig: path.resolve(cwd, config.tailwind.config), tailwindConfig: path.resolve(cwd, config.tailwind.config),
tailwindCss: path.resolve(cwd, config.tailwind.css), tailwindCss: path.resolve(cwd, config.tailwind.css),
utils: await resolveImport(config.aliases.utils, tsConfig), utils: resolveImport(config.aliases.utils, tsConfig),
components: await resolveImport(config.aliases.components, tsConfig), components: resolveImport(config.aliases.components, tsConfig),
}, },
}) })
} }

View File

@ -6,6 +6,8 @@ import type * as z from 'zod'
import type { Config } from '@/src/utils/get-config' import type { Config } from '@/src/utils/get-config'
import type { registryBaseColorSchema } from '@/src/utils/registry/schema' import type { registryBaseColorSchema } from '@/src/utils/registry/schema'
import { transformCssVars } from '@/src/utils/transformers/transform-css-vars' import { transformCssVars } from '@/src/utils/transformers/transform-css-vars'
import { transformImport } from '@/src/utils/transformers/transform-import'
import { transformSFC } from '@/src/utils/transformers/transform-sfc'
export interface TransformOpts { export interface TransformOpts {
filename: string filename: string
@ -22,6 +24,7 @@ export type Transformer<Output = SourceFile> = (
const transformers: Transformer[] = [ const transformers: Transformer[] = [
transformCssVars, transformCssVars,
transformImport,
] ]
const project = new Project({ const project = new Project({
@ -36,14 +39,14 @@ async function createTempSourceFile(filename: string) {
export async function transform(opts: TransformOpts) { export async function transform(opts: TransformOpts) {
const tempFile = await createTempSourceFile(opts.filename) const tempFile = await createTempSourceFile(opts.filename)
const sourceFile = project.createSourceFile(tempFile, opts.raw, { const sourceFile = project.createSourceFile(tempFile, opts.raw, {
scriptKind: ScriptKind.TSX, scriptKind: ScriptKind.Unknown,
}) })
for (const transformer of transformers) for (const transformer of transformers)
transformer({ sourceFile, ...opts }) transformer({ sourceFile, ...opts })
// return await transformJsx({ return await transformSFC({
// sourceFile, sourceFile,
// ...opts, ...opts,
// }) })
} }

View File

@ -14,7 +14,12 @@ export const transformCssVars: Transformer = async ({
sourceFile.getDescendantsOfKind(SyntaxKind.StringLiteral).forEach((node) => { sourceFile.getDescendantsOfKind(SyntaxKind.StringLiteral).forEach((node) => {
const value = node.getText() const value = node.getText()
if (value) {
if (value.includes('cn(')) {
const splitted = value.split('\'').map(i => applyColorMapping(i, baseColor.inlineColors))
node.replaceWithText(`${splitted.join('\'')}`)
}
else if (value) {
const valueWithColorMapping = applyColorMapping( const valueWithColorMapping = applyColorMapping(
value.replace(/"/g, ''), value.replace(/"/g, ''),
baseColor.inlineColors, baseColor.inlineColors,

View File

@ -1,49 +1,32 @@
import MagicString from 'magic-string' import type { Transformer } from '@/src/utils/transformers'
import type { z } from 'zod'
import type { Config } from '../get-config'
import type { registryBaseColorSchema } from '../registry/schema'
export interface TransformOpts { export const transformImport: Transformer = async ({ sourceFile, config }) => {
filename: string const importDeclarations = sourceFile.getImportDeclarations()
raw: string
config: Config for (const importDeclaration of importDeclarations) {
baseColor?: z.infer<typeof registryBaseColorSchema> const moduleSpecifier = importDeclaration.getModuleSpecifierValue()
// Replace @/registry/[style] with the components alias.
if (moduleSpecifier.startsWith('@/registry/')) {
importDeclaration.setModuleSpecifier(
moduleSpecifier.replace(
/^@\/registry\/[^/]+/,
config.aliases.components,
),
)
}
// Replace `import { cn } from "@/lib/utils"`
if (moduleSpecifier === '@/lib/utils') {
const namedImports = importDeclaration.getNamedImports()
const cnImport = namedImports.find(i => i.getName() === 'cn')
if (cnImport) {
importDeclaration.setModuleSpecifier(
moduleSpecifier.replace(/^@\/lib\/utils/, config.aliases.utils),
)
}
}
}
return sourceFile
} }
export function transformImport(content: string, config: Config) {
const s = new MagicString(content)
s.replaceAll(/@\/registry\/[^/]+/g, config.aliases.components)
s.replaceAll(/@\/lib\/utils/g, config.aliases.utils)
return s.toString()
}
// export const transformImport: Transformer = async ({ sourceFile, config }) => {
// const importDeclarations = sourceFile.getImportDeclarations()
// for (const importDeclaration of importDeclarations) {
// const moduleSpecifier = importDeclaration.getModuleSpecifierValue()
// // Replace @/registry/[style] with the components alias.
// if (moduleSpecifier.startsWith('@/registry/')) {
// importDeclaration.setModuleSpecifier(
// moduleSpecifier.replace(
// /^@\/registry\/[^/]+/,
// config.aliases.components,
// ),
// )
// }
// // Replace `import { cn } from "@/lib/utils"`
// if (moduleSpecifier === '@/lib/utils') {
// const namedImports = importDeclaration.getNamedImports()
// const cnImport = namedImports.find(i => i.getName() === 'cn')
// if (cnImport) {
// importDeclaration.setModuleSpecifier(
// moduleSpecifier.replace(/^@\/lib\/utils/, config.aliases.utils),
// )
// }
// }
// }
// return sourceFile
// }

View File

@ -1,25 +1,18 @@
import { createRequire } from 'node:module' import { createRequire } from 'node:module'
import { type SourceFile, SyntaxKind } from 'ts-morph'
import { transform as transformByDetype } from 'detype'
import type { Config } from '../get-config' import type { Config } from '../get-config'
import { transformImport } from './transform-import' import { transformImport } from './transform-import'
import type { Transformer } from '@/src/utils/transformers'
const require = createRequire(import.meta.url) export const transformSFC: Transformer<string> = async ({ sourceFile, config }) => {
const { transform } = require('detype') const output = sourceFile?.getFullText()
if (config?.typescript)
return output
export async function transformByDetype(content: string, filename: string) { const clean = await transformByDetype(output, 'app.vue', {
return await transform(content, filename, {
removeTsComments: true, removeTsComments: true,
}) })
}
interface File { return clean
name: string
content: string
}
export async function transformSFC(file: File, config: Config) {
let content = transformImport(file.content, config)
if (!config.typescript)
content = await transformByDetype(content, file.name)
return content
} }

View File

@ -63,7 +63,8 @@ test('init config-full', async () => {
expect(mockWriteFile).toHaveBeenNthCalledWith( expect(mockWriteFile).toHaveBeenNthCalledWith(
3, 3,
expect.stringMatching(/src\/lib\/utils.ts$/), expect.stringMatching(/src\/lib\/utils.ts$/),
expect.stringContaining('import { type ClassValue, clsx } from "clsx"'), // eslint-disable-next-line @typescript-eslint/quotes
expect.stringContaining("import { type ClassValue, clsx } from 'clsx'"),
'utf8', 'utf8',
) )
expect(execa).toHaveBeenCalledWith( expect(execa).toHaveBeenCalledWith(
@ -74,7 +75,6 @@ test('init config-full', async () => {
'class-variance-authority', 'class-variance-authority',
'clsx', 'clsx',
'tailwind-merge', 'tailwind-merge',
'@radix-ui/react-icons',
], ],
{ {
cwd: targetDir, cwd: targetDir,
@ -85,75 +85,75 @@ test('init config-full', async () => {
mockWriteFile.mockRestore() mockWriteFile.mockRestore()
}) })
test('init config-partial', async () => { // test('init config-partial', async () => {
vi.spyOn(getPackageManger, 'getPackageManager').mockResolvedValue('npm') // vi.spyOn(getPackageManger, 'getPackageManager').mockResolvedValue('npm')
vi.spyOn(registry, 'getRegistryBaseColor').mockResolvedValue({ // vi.spyOn(registry, 'getRegistryBaseColor').mockResolvedValue({
inlineColors: {}, // inlineColors: {},
cssVars: {}, // cssVars: {},
inlineColorsTemplate: // inlineColorsTemplate:
'@tailwind base;\n@tailwind components;\n@tailwind utilities;\n', // '@tailwind base;\n@tailwind components;\n@tailwind utilities;\n',
cssVarsTemplate: // cssVarsTemplate:
'@tailwind base;\n@tailwind components;\n@tailwind utilities;\n', // '@tailwind base;\n@tailwind components;\n@tailwind utilities;\n',
}) // })
const mockMkdir = vi.spyOn(fs.promises, 'mkdir').mockResolvedValue(undefined) // const mockMkdir = vi.spyOn(fs.promises, 'mkdir').mockResolvedValue(undefined)
const mockWriteFile = vi.spyOn(fs.promises, 'writeFile').mockResolvedValue() // const mockWriteFile = vi.spyOn(fs.promises, 'writeFile').mockResolvedValue()
const targetDir = path.resolve(__dirname, '../fixtures/config-partial') // const targetDir = path.resolve(__dirname, '../fixtures/config-partial')
const config = await getConfig(targetDir) // const config = await getConfig(targetDir)
await runInit(targetDir, config!) // await runInit(targetDir, config!)
expect(mockMkdir).toHaveBeenNthCalledWith( // expect(mockMkdir).toHaveBeenNthCalledWith(
1, // 1,
expect.stringMatching(/src\/assets\/css$/), // expect.stringMatching(/src\/assets\/css$/),
expect.anything(), // expect.anything(),
) // )
expect(mockMkdir).toHaveBeenNthCalledWith( // expect(mockMkdir).toHaveBeenNthCalledWith(
2, // 2,
expect.stringMatching(/lib$/), // expect.stringMatching(/lib$/),
expect.anything(), // expect.anything(),
) // )
expect(mockMkdir).toHaveBeenNthCalledWith( // expect(mockMkdir).toHaveBeenNthCalledWith(
3, // 3,
expect.stringMatching(/components$/), // expect.stringMatching(/components$/),
expect.anything(), // expect.anything(),
) // )
expect(mockWriteFile).toHaveBeenNthCalledWith( // expect(mockWriteFile).toHaveBeenNthCalledWith(
1, // 1,
expect.stringMatching(/tailwind.config.ts$/), // expect.stringMatching(/tailwind.config.ts$/),
expect.stringContaining('/** @type {import(\'tailwindcss\').Config} */'), // expect.stringContaining('/** @type {import(\'tailwindcss\').Config} */'),
'utf8', // 'utf8',
) // )
expect(mockWriteFile).toHaveBeenNthCalledWith( // expect(mockWriteFile).toHaveBeenNthCalledWith(
2, // 2,
expect.stringMatching(/src\/assets\/css\/tailwind.css$/), // expect.stringMatching(/src\/assets\/css\/tailwind.css$/),
expect.stringContaining('@tailwind base'), // expect.stringContaining('@tailwind base'),
'utf8', // 'utf8',
) // )
expect(mockWriteFile).toHaveBeenNthCalledWith( // expect(mockWriteFile).toHaveBeenNthCalledWith(
3, // 3,
expect.stringMatching(/utils.ts$/), // expect.stringMatching(/utils.ts$/),
expect.stringContaining('import { type ClassValue, clsx } from "clsx"'), // expect.stringContaining('import { type ClassValue, clsx } from "clsx"'),
'utf8', // 'utf8',
) // )
expect(execa).toHaveBeenCalledWith( // expect(execa).toHaveBeenCalledWith(
'npm', // 'npm',
[ // [
'install', // 'install',
'tailwindcss-animate', // 'tailwindcss-animate',
'class-variance-authority', // 'class-variance-authority',
'clsx', // 'clsx',
'tailwind-merge', // 'tailwind-merge',
'lucide-react', // 'lucide-react',
], // ],
{ // {
cwd: targetDir, // cwd: targetDir,
}, // },
) // )
mockMkdir.mockRestore() // mockMkdir.mockRestore()
mockWriteFile.mockRestore() // mockWriteFile.mockRestore()
}) // })
afterEach(() => { afterEach(() => {
vi.resetAllMocks() vi.resetAllMocks()

View File

@ -1,12 +1,11 @@
{ {
"style": "default", "style": "new-york",
"tailwind": { "tailwind": {
"config": "tailwind.config.ts", "config": "tailwind.config.ts",
"css": "src/app/globals.css", "css": "src/app/globals.css",
"baseColor": "zinc", "baseColor": "zinc",
"cssVariables": true "cssVariables": true
}, },
"rsc": false,
"aliases": { "aliases": {
"utils": "~/lib/utils", "utils": "~/lib/utils",
"components": "~/components" "components": "~/components"

View File

@ -1,25 +1,22 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`transform css vars 1`] = ` exports[`transform css vars 1`] = `
"import * as React from \\"react\\" "<script setup lang=\\"ts\\"></script>
export function Foo() { <template>
return <div class=\\"bg-background hover:bg-muted text-primary-foreground sm:focus:text-accent-foreground\\">foo</div> <div class=\\"bg-background hover:bg-muted text-primary-foreground sm:focus:text-accent-foreground\\">foo</div>
}\\" </template>\\""
"
`; `;
exports[`transform css vars 2`] = ` exports[`transform css vars 2`] = `
"import * as React from \\"react\\" "<script setup lang=\\"ts\\"></script>
export function Foo() { <template>
return <div class=\\"bg-white hover:bg-stone-100 text-stone-50 sm:focus:text-stone-900 dark:bg-stone-950 dark:hover:bg-stone-800 dark:text-stone-900 dark:sm:focus:text-stone-50\\">foo</div> <div class=\\"bg-white hover:bg-stone-100 text-stone-50 sm:focus:text-stone-900 dark:bg-stone-950 dark:hover:bg-stone-800 dark:text-stone-900 dark:sm:focus:text-stone-50\\">foo</div>
}\\"\\" </template>\\""
"
`; `;
exports[`transform css vars 3`] = ` exports[`transform css vars 3`] = `
"import * as React from \\"react\\" "<script setup lang=\\"ts\\"></script>
export function Foo() { <template>
return <div class={cn(\\"bg-white hover:bg-stone-100 dark:bg-stone-950 dark:hover:bg-stone-800\\", true && \\"text-stone-50 sm:focus:text-stone-900 dark:text-stone-900 dark:sm:focus:text-stone-50\\")}>foo</div> <div :class=\\"cn( 'bg-white hover:bg-stone-100 dark:bg-stone-950 dark:hover:bg-stone-800', true && 'text-stone-50 sm:focus:text-stone-900 dark:text-stone-900 dark:sm:focus:text-stone-50')\\" >foo</div>
}\\"\\" </template>\\""
"
`; `;

View File

@ -1,8 +1,7 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`transform import 1`] = ` exports[`transform import 1`] = `
"import * as React from \\"react\\" "import { Foo } from \\"bar\\"
import { Foo } from \\"bar\\"
import { Button } from \\"@/components/ui/button\\" import { Button } from \\"@/components/ui/button\\"
import { Label} from \\"ui/label\\" import { Label} from \\"ui/label\\"
import { Box } from \\"@/components/box\\" import { Box } from \\"@/components/box\\"
@ -12,23 +11,21 @@ import { Foo } from \\"bar\\"
`; `;
exports[`transform import 2`] = ` exports[`transform import 2`] = `
"import * as React from \\"react\\" "import { Foo } from \\"bar\\"
import { Foo } from \\"bar\\" import { Button } from \\"~/src/components/ui/button\\"
import { Button } from \\"~/src/components/ui/button\\" import { Label} from \\"ui/label\\"
import { Label} from \\"ui/label\\" import { Box } from \\"~/src/components/box\\"
import { Box } from \\"~/src/components/box\\"
import { cn, foo, bar } from \\"~/lib\\" import { cn, foo, bar } from \\"~/lib\\"
import { bar } from \\"@/lib/utils/bar\\" import { bar } from \\"@/lib/utils/bar\\"
" "
`; `;
exports[`transform import 3`] = ` exports[`transform import 3`] = `
"import * as React from \\"react\\" "import { Foo } from \\"bar\\"
import { Foo } from \\"bar\\" import { Button } from \\"~/src/components/ui/button\\"
import { Button } from \\"~/src/components/ui/button\\" import { Label} from \\"ui/label\\"
import { Label} from \\"ui/label\\" import { Box } from \\"~/src/components/box\\"
import { Box } from \\"~/src/components/box\\"
import { cn } from \\"~/src/utils\\" import { cn } from \\"~/src/utils\\"
import { bar } from \\"@/lib/utils/bar\\" import { bar } from \\"@/lib/utils/bar\\"

View File

@ -1,31 +0,0 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`transform rsc 1`] = `
"import * as React from \\"react\\"
import { Foo } from \\"bar\\"
"
`;
exports[`transform rsc 2`] = `
"\\"use client\\"
import * as React from \\"react\\"
import { Foo } from \\"bar\\"
"
`;
exports[`transform rsc 3`] = `
" import * as React from \\"react\\"
import { Foo } from \\"bar\\"
"
`;
exports[`transform rsc 4`] = `
"\\"use foo\\"
import * as React from \\"react\\"
import { Foo } from \\"bar\\"
\\"use client\\"
"
`;

View File

@ -2,7 +2,7 @@ import { describe, expect, test } from 'vitest'
import { import {
applyColorMapping, applyColorMapping,
splitclass, splitClassName,
} from '../../src/utils/transformers/transform-css-vars' } from '../../src/utils/transformers/transform-css-vars'
import baseColor from '../fixtures/colors/slate.json' import baseColor from '../fixtures/colors/slate.json'
@ -44,8 +44,8 @@ describe('split class', () => {
input: 'sm:focus:text-accent-foreground/30', input: 'sm:focus:text-accent-foreground/30',
output: ['sm:focus', 'text-accent-foreground', '30'], output: ['sm:focus', 'text-accent-foreground', '30'],
}, },
])('splitclass($input) -> $output', ({ input, output }) => { ])('splitClassName($input) -> $output', ({ input, output }) => {
expect(splitclass(input)).toStrictEqual(output) expect(splitClassName(input)).toStrictEqual(output)
}) })
}) })

View File

@ -12,18 +12,18 @@ test('get raw config', async () => {
await getRawConfig(path.resolve(__dirname, '../fixtures/config-partial')), await getRawConfig(path.resolve(__dirname, '../fixtures/config-partial')),
).toEqual({ ).toEqual({
style: 'default', style: 'default',
framework: 'Vite',
tailwind: { tailwind: {
config: './tailwind.config.ts', config: './tailwind.config.ts',
css: './src/assets/css/tailwind.css', css: './src/assets/css/tailwind.css',
baseColor: 'neutral', baseColor: 'neutral',
cssVariables: false, cssVariables: false,
}, },
rsc: false,
tsx: true,
aliases: { aliases: {
components: '@/components', components: '@/components',
utils: '@/lib/utils', utils: '@/lib/utils',
}, },
typescript: true,
}) })
expect( expect(
@ -50,12 +50,11 @@ test('get config', async () => {
baseColor: 'neutral', baseColor: 'neutral',
cssVariables: false, cssVariables: false,
}, },
rsc: false,
tsx: true,
aliases: { aliases: {
components: '@/components', components: '@/components',
utils: '@/lib/utils', utils: '@/lib/utils',
}, },
framework: 'Vite',
resolvedPaths: { resolvedPaths: {
tailwindConfig: path.resolve( tailwindConfig: path.resolve(
__dirname, __dirname,
@ -78,14 +77,13 @@ test('get config', async () => {
'./lib/utils', './lib/utils',
), ),
}, },
typescript: true,
}) })
expect( expect(
await getConfig(path.resolve(__dirname, '../fixtures/config-full')), await getConfig(path.resolve(__dirname, '../fixtures/config-full')),
).toEqual({ ).toEqual({
style: 'new-york', style: 'new-york',
rsc: false,
tsx: true,
tailwind: { tailwind: {
config: 'tailwind.config.ts', config: 'tailwind.config.ts',
baseColor: 'zinc', baseColor: 'zinc',
@ -96,6 +94,7 @@ test('get config', async () => {
components: '~/components', components: '~/components',
utils: '~/lib/utils', utils: '~/lib/utils',
}, },
framework: 'Vite',
resolvedPaths: { resolvedPaths: {
tailwindConfig: path.resolve( tailwindConfig: path.resolve(
__dirname, __dirname,
@ -118,41 +117,40 @@ test('get config', async () => {
'./src/lib/utils', './src/lib/utils',
), ),
}, },
typescript: true,
}) })
expect( // expect(
await getConfig(path.resolve(__dirname, '../fixtures/config-jsx')), // await getConfig(path.resolve(__dirname, '../fixtures/config-jsx')),
).toEqual({ // ).toEqual({
style: 'default', // style: 'default',
tailwind: { // tailwind: {
config: './tailwind.config.js', // config: './tailwind.config.js',
css: './src/assets/css/tailwind.css', // css: './src/assets/css/tailwind.css',
baseColor: 'neutral', // baseColor: 'neutral',
cssVariables: false, // cssVariables: false,
}, // },
rsc: false, // aliases: {
tsx: false, // components: '@/components',
aliases: { // utils: '@/lib/utils',
components: '@/components', // },
utils: '@/lib/utils', // resolvedPaths: {
}, // tailwindConfig: path.resolve(
resolvedPaths: { // __dirname,
tailwindConfig: path.resolve( // '../fixtures/config-jsx',
__dirname, // 'tailwind.config.js',
'../fixtures/config-jsx', // ),
'tailwind.config.js', // tailwindCss: path.resolve(
), // __dirname,
tailwindCss: path.resolve( // '../fixtures/config-jsx',
__dirname, // './src/assets/css/tailwind.css',
'../fixtures/config-jsx', // ),
'./src/assets/css/tailwind.css', // components: path.resolve(
), // __dirname,
components: path.resolve( // '../fixtures/config-jsx',
__dirname, // './components',
'../fixtures/config-jsx', // ),
'./components', // utils: path.resolve(__dirname, '../fixtures/config-jsx', './lib/utils'),
), // },
utils: path.resolve(__dirname, '../fixtures/config-jsx', './lib/utils'), // })
},
})
}) })

View File

@ -6,7 +6,7 @@ import { resolveImport } from '../../src/utils/resolve-import'
test('resolve import', async () => { test('resolve import', async () => {
expect( expect(
await resolveImport('@/foo/bar', { resolveImport('@/foo/bar', {
absoluteBaseUrl: '/Users/shadcn/Projects/foobar', absoluteBaseUrl: '/Users/shadcn/Projects/foobar',
paths: { paths: {
'@/*': ['./src/*'], '@/*': ['./src/*'],
@ -17,7 +17,7 @@ test('resolve import', async () => {
).toEqual('/Users/shadcn/Projects/foobar/src/foo/bar') ).toEqual('/Users/shadcn/Projects/foobar/src/foo/bar')
expect( expect(
await resolveImport('~/components/foo/bar/baz', { resolveImport('~/components/foo/bar/baz', {
absoluteBaseUrl: '/Users/shadcn/Projects/foobar', absoluteBaseUrl: '/Users/shadcn/Projects/foobar',
paths: { paths: {
'@/*': ['./src/*'], '@/*': ['./src/*'],
@ -28,7 +28,7 @@ test('resolve import', async () => {
).toEqual('/Users/shadcn/Projects/foobar/src/components/foo/bar/baz') ).toEqual('/Users/shadcn/Projects/foobar/src/components/foo/bar/baz')
expect( expect(
await resolveImport('components/foo/bar', { resolveImport('components/foo/bar', {
absoluteBaseUrl: '/Users/shadcn/Projects/foobar', absoluteBaseUrl: '/Users/shadcn/Projects/foobar',
paths: { paths: {
'components/*': ['./src/app/components/*'], 'components/*': ['./src/app/components/*'],
@ -39,7 +39,7 @@ test('resolve import', async () => {
).toEqual('/Users/shadcn/Projects/foobar/src/app/components/foo/bar') ).toEqual('/Users/shadcn/Projects/foobar/src/app/components/foo/bar')
expect( expect(
await resolveImport('lib/utils', { resolveImport('lib/utils', {
absoluteBaseUrl: '/Users/shadcn/Projects/foobar', absoluteBaseUrl: '/Users/shadcn/Projects/foobar',
paths: { paths: {
'components/*': ['./src/app/components/*'], 'components/*': ['./src/app/components/*'],
@ -52,30 +52,30 @@ test('resolve import', async () => {
test('resolve import with base url', async () => { test('resolve import with base url', async () => {
const cwd = path.resolve(__dirname, '../fixtures/with-base-url') const cwd = path.resolve(__dirname, '../fixtures/with-base-url')
const config = (await loadConfig(cwd)) as ConfigLoaderSuccessResult const config = (loadConfig(cwd)) as ConfigLoaderSuccessResult
expect(await resolveImport('@/components/ui', config)).toEqual( expect(resolveImport('@/components/ui', config)).toEqual(
path.resolve(cwd, 'components/ui'), path.resolve(cwd, 'components/ui'),
) )
expect(await resolveImport('@/lib/utils', config)).toEqual( expect(resolveImport('@/lib/utils', config)).toEqual(
path.resolve(cwd, 'lib/utils'), path.resolve(cwd, 'lib/utils'),
) )
expect(await resolveImport('foo/bar', config)).toEqual( expect(resolveImport('foo/bar', config)).toEqual(
path.resolve(cwd, 'foo/bar'), path.resolve(cwd, 'foo/bar'),
) )
}) })
test('resolve import without base url', async () => { test('resolve import without base url', async () => {
const cwd = path.resolve(__dirname, '../fixtures/without-base-url') const cwd = path.resolve(__dirname, '../fixtures/without-base-url')
const config = (await loadConfig(cwd)) as ConfigLoaderSuccessResult const config = (loadConfig(cwd)) as ConfigLoaderSuccessResult
expect(await resolveImport('~/components/ui', config)).toEqual( expect(resolveImport('~/components/ui', config)).toEqual(
path.resolve(cwd, 'components/ui'), path.resolve(cwd, 'components/ui'),
) )
expect(await resolveImport('~/lib/utils', config)).toEqual( expect(resolveImport('~/lib/utils', config)).toEqual(
path.resolve(cwd, 'lib/utils'), path.resolve(cwd, 'lib/utils'),
) )
expect(await resolveImport('foo/bar', config)).toEqual( expect(resolveImport('foo/bar', config)).toEqual(
path.resolve(cwd, 'foo/bar'), path.resolve(cwd, 'foo/bar'),
) )
}) })

View File

@ -1,75 +1,69 @@
// import { expect, test } from 'vitest' import { expect, test } from 'vitest'
// import { transform } from '../../src/utils/transformers' import { transform } from '../../src/utils/transformers'
// import stone from '../fixtures/colors/stone.json' import stone from '../fixtures/colors/stone.json'
// test('transform css vars', async () => { test('transform css vars', async () => {
// expect( expect(
// await transform({ await transform({
// filename: 'test.ts', filename: 'app.vue',
// raw: `import * as React from "react" raw: `<script setup lang="ts"></script>
// export function Foo() { <template>
// return <div class="bg-background hover:bg-muted text-primary-foreground sm:focus:text-accent-foreground">foo</div> <div class="bg-background hover:bg-muted text-primary-foreground sm:focus:text-accent-foreground">foo</div>
// }" </template>"`,
// `, config: {
// config: { tailwind: {
// tsx: true, baseColor: 'stone',
// tailwind: { cssVariables: true,
// baseColor: 'stone', },
// cssVariables: true, aliases: {
// }, components: '@/components',
// aliases: { utils: '@/lib/utils',
// components: '@/components', },
// utils: '@/lib/utils', },
// }, baseColor: stone,
// }, }),
// baseColor: stone, ).toMatchSnapshot()
// }),
// ).toMatchSnapshot()
// expect( expect(
// await transform({ await transform({
// filename: 'test.ts', filename: 'app.vue',
// raw: `import * as React from "react" raw: `<script setup lang="ts"></script>
// export function Foo() { <template>
// return <div class="bg-background hover:bg-muted text-primary-foreground sm:focus:text-accent-foreground">foo</div> <div class="bg-background hover:bg-muted text-primary-foreground sm:focus:text-accent-foreground">foo</div>
// }" </template>"`,
// `, config: {
// config: { tailwind: {
// tsx: true, baseColor: 'stone',
// tailwind: { cssVariables: false,
// baseColor: 'stone', },
// cssVariables: false, aliases: {
// }, components: '@/components',
// aliases: { utils: '@/lib/utils',
// components: '@/components', },
// utils: '@/lib/utils', },
// }, baseColor: stone,
// }, }),
// baseColor: stone, ).toMatchSnapshot()
// }),
// ).toMatchSnapshot()
// expect( expect(
// await transform({ await transform({
// filename: 'test.ts', filename: 'app.vue',
// raw: `import * as React from "react" raw: `<script setup lang="ts"></script>
// export function Foo() { <template>
// return <div class={cn("bg-background hover:bg-muted", true && "text-primary-foreground sm:focus:text-accent-foreground")}>foo</div> <div :class="cn('bg-background hover:bg-muted', true && 'text-primary-foreground sm:focus:text-accent-foreground')">foo</div>
// }" </template>"`,
// `, config: {
// config: { tailwind: {
// tsx: true, baseColor: 'stone',
// tailwind: { cssVariables: false,
// baseColor: 'stone', },
// cssVariables: false, aliases: {
// }, components: '@/components',
// aliases: { utils: '@/lib/utils',
// components: '@/components', },
// utils: '@/lib/utils', },
// }, baseColor: stone,
// }, }),
// baseColor: stone, ).toMatchSnapshot()
// }), })
// ).toMatchSnapshot()
// })

View File

@ -1,74 +1,67 @@
// import { expect, test } from 'vitest' import { expect, test } from 'vitest'
import { transform } from '../../src/utils/transformers'
// import { transform } from '../../src/utils/transformers' test('transform import', async () => {
expect(
await transform({
filename: 'app.vue',
raw: `import { Foo } from "bar"
import { Button } from "@/registry/new-york/ui/button"
import { Label} from "ui/label"
import { Box } from "@/registry/new-york/box"
// test('transform import', async () => { import { cn } from "@/lib/utils"
// expect( `,
// await transform({ config: {
// filename: 'test.ts', tailwind: {
// raw: `import * as React from "react" baseColor: 'neutral',
// import { Foo } from "bar" cssVariables: true,
// import { Button } from "@/registry/new-york/ui/button" },
// import { Label} from "ui/label" aliases: {
// import { Box } from "@/registry/new-york/box" components: '@/components',
utils: '@/lib/utils',
},
},
}),
).toMatchSnapshot()
// import { cn } from "@/lib/utils" expect(
// `, await transform({
// config: { filename: 'app.vue',
// tsx: true, raw: `import { Foo } from "bar"
// tailwind: { import { Button } from "@/registry/new-york/ui/button"
// baseColor: 'neutral', import { Label} from "ui/label"
// cssVariables: true, import { Box } from "@/registry/new-york/box"
// },
// aliases: {
// components: '@/components',
// utils: '@/lib/utils',
// },
// },
// }),
// ).toMatchSnapshot()
// expect( import { cn, foo, bar } from "@/lib/utils"
// await transform({ import { bar } from "@/lib/utils/bar"
// filename: 'test.ts', `,
// raw: `import * as React from "react" config: {
// import { Foo } from "bar" aliases: {
// import { Button } from "@/registry/new-york/ui/button" components: '~/src/components',
// import { Label} from "ui/label" utils: '~/lib',
// import { Box } from "@/registry/new-york/box" },
},
}),
).toMatchSnapshot()
// import { cn, foo, bar } from "@/lib/utils" expect(
// import { bar } from "@/lib/utils/bar" await transform({
// `, filename: 'app.vue',
// config: { raw: `import { Foo } from "bar"
// tsx: true, import { Button } from "@/registry/new-york/ui/button"
// aliases: { import { Label} from "ui/label"
// components: '~/src/components', import { Box } from "@/registry/new-york/box"
// utils: '~/lib',
// },
// },
// }),
// ).toMatchSnapshot()
// expect( import { cn } from "@/lib/utils"
// await transform({ import { bar } from "@/lib/utils/bar"
// filename: 'test.ts', `,
// raw: `import * as React from "react" config: {
// import { Foo } from "bar" aliases: {
// import { Button } from "@/registry/new-york/ui/button" components: '~/src/components',
// import { Label} from "ui/label" utils: '~/src/utils',
// import { Box } from "@/registry/new-york/box" },
},
// import { cn } from "@/lib/utils" }),
// import { bar } from "@/lib/utils/bar" ).toMatchSnapshot()
// `, })
// config: {
// tsx: true,
// aliases: {
// components: '~/src/components',
// utils: '~/src/utils',
// },
// },
// }),
// ).toMatchSnapshot()
// })

View File

@ -1,65 +0,0 @@
// import { expect, test } from 'vitest'
// import { transform } from '../../src/utils/transformers'
// test('transform rsc', async () => {
// expect(
// await transform({
// filename: 'test.ts',
// raw: `import * as React from "react"
// import { Foo } from "bar"
// `,
// config: {
// tsx: true,
// rsc: true,
// },
// }),
// ).toMatchSnapshot()
// expect(
// await transform({
// filename: 'test.ts',
// raw: `"use client"
// import * as React from "react"
// import { Foo } from "bar"
// `,
// config: {
// tsx: true,
// rsc: true,
// },
// }),
// ).toMatchSnapshot()
// expect(
// await transform({
// filename: 'test.ts',
// raw: `"use client"
// import * as React from "react"
// import { Foo } from "bar"
// `,
// config: {
// tsx: true,
// rsc: false,
// },
// }),
// ).toMatchSnapshot()
// expect(
// await transform({
// filename: 'test.ts',
// raw: `"use foo"
// import * as React from "react"
// import { Foo } from "bar"
// "use client"
// `,
// config: {
// tsx: true,
// rsc: false,
// },
// }),
// ).toMatchSnapshot()
// })

View File

@ -1,18 +1,17 @@
import { readFileSync } from 'node:fs' import { readFileSync } from 'node:fs'
import { resolve } from 'node:path' import { resolve } from 'node:path'
import { describe, expect, test } from 'vitest' import { describe, expect, test } from 'vitest'
import { transformSFC } from '../../src/utils/transformers/transform-sfc' import { transform } from '../../src/utils/transformers'
describe('transformSFC', () => { describe('transformSFC', () => {
const appVuePath = resolve(__dirname, '../fixtures/transform-sfc/app.vue') const appVuePath = resolve(__dirname, '../fixtures/transform-sfc/app.vue')
const content = readFileSync(appVuePath, 'utf-8') const content = readFileSync(appVuePath, 'utf-8')
test('basic', async () => { test('basic', async () => {
const result = await transformSFC({ const result = await transform({
name: 'app.vue', filename: 'app.vue',
content, raw: content,
}, { config: {},
typescript: false, })
} as any)
expect(result).toMatchSnapshot() expect(result).toMatchSnapshot()
}) })
}) })