From a434fada955613d24ef16af482d39538704f2ff0 Mon Sep 17 00:00:00 2001 From: shadcn Date: Mon, 16 Mar 2026 17:18:05 +0400 Subject: [PATCH] fix: update test coverage --- .../test/utils/transform-import.test.ts | 43 ++++++ .../apps/web/components.json | 18 +++ .../apps/web/package.json | 12 ++ .../apps/web/src/main.tsx | 1 + .../apps/web/tsconfig.json | 8 ++ .../apps/web/vite.config.ts | 3 + .../vite-monorepo-imports/package.json | 6 + .../packages/ui/components.json | 18 +++ .../packages/ui/package.json | 14 ++ .../packages/ui/src/lib/utils.ts | 3 + .../packages/ui/src/styles/globals.css | 1 + .../packages/ui/tsconfig.json | 8 ++ .../vite-monorepo-imports/pnpm-workspace.yaml | 3 + packages/tests/src/tests/add.test.ts | 124 ++++++++++++++++++ 14 files changed, 262 insertions(+) create mode 100644 packages/tests/fixtures/vite-monorepo-imports/apps/web/components.json create mode 100644 packages/tests/fixtures/vite-monorepo-imports/apps/web/package.json create mode 100644 packages/tests/fixtures/vite-monorepo-imports/apps/web/src/main.tsx create mode 100644 packages/tests/fixtures/vite-monorepo-imports/apps/web/tsconfig.json create mode 100644 packages/tests/fixtures/vite-monorepo-imports/apps/web/vite.config.ts create mode 100644 packages/tests/fixtures/vite-monorepo-imports/package.json create mode 100644 packages/tests/fixtures/vite-monorepo-imports/packages/ui/components.json create mode 100644 packages/tests/fixtures/vite-monorepo-imports/packages/ui/package.json create mode 100644 packages/tests/fixtures/vite-monorepo-imports/packages/ui/src/lib/utils.ts create mode 100644 packages/tests/fixtures/vite-monorepo-imports/packages/ui/src/styles/globals.css create mode 100644 packages/tests/fixtures/vite-monorepo-imports/packages/ui/tsconfig.json create mode 100644 packages/tests/fixtures/vite-monorepo-imports/pnpm-workspace.yaml diff --git a/packages/shadcn/test/utils/transform-import.test.ts b/packages/shadcn/test/utils/transform-import.test.ts index 4335c6806a..3c380c84aa 100644 --- a/packages/shadcn/test/utils/transform-import.test.ts +++ b/packages/shadcn/test/utils/transform-import.test.ts @@ -34,6 +34,49 @@ test('transform nested workspace folder for utils, website/src/utils', async () }) +test.each([ + { + name: "bare aliases", + aliases: { + components: "components", + ui: "components/ui", + lib: "lib", + utils: "lib/utils", + }, + buttonImport: `import { Button } from "components/ui/button"`, + utilsImport: `import { cn } from "lib/utils"`, + }, + { + name: "path-like aliases", + aliases: { + components: "website/src/components", + ui: "website/src/components/ui", + lib: "website/src/lib", + utils: "website/src/lib/utils", + }, + buttonImport: `import { Button } from "website/src/components/ui/button"`, + utilsImport: `import { cn } from "website/src/lib/utils"`, + }, +])("transform import with non-sigil aliases: $name", async ({ + aliases, + buttonImport, + utilsImport, +}) => { + const result = await transform({ + filename: "test.ts", + raw: `import { Button } from "@/registry/new-york/ui/button" +import { cn } from "@/lib/utils" +`, + config: { + tsx: true, + aliases, + }, + }) + + expect(result).toContain(buttonImport) + expect(result).toContain(utilsImport) +}) + test("transform import", async () => { expect( await transform({ diff --git a/packages/tests/fixtures/vite-monorepo-imports/apps/web/components.json b/packages/tests/fixtures/vite-monorepo-imports/apps/web/components.json new file mode 100644 index 0000000000..e664fbf6f2 --- /dev/null +++ b/packages/tests/fixtures/vite-monorepo-imports/apps/web/components.json @@ -0,0 +1,18 @@ +{ + "style": "new-york", + "tailwind": { + "config": "", + "css": "../../packages/ui/src/styles/globals.css", + "baseColor": "zinc", + "cssVariables": true + }, + "rsc": false, + "tsx": true, + "aliases": { + "components": "#components", + "ui": "@workspace/ui/components", + "lib": "#lib", + "hooks": "#hooks", + "utils": "@workspace/ui/lib/utils" + } +} diff --git a/packages/tests/fixtures/vite-monorepo-imports/apps/web/package.json b/packages/tests/fixtures/vite-monorepo-imports/apps/web/package.json new file mode 100644 index 0000000000..f86ed0e5d0 --- /dev/null +++ b/packages/tests/fixtures/vite-monorepo-imports/apps/web/package.json @@ -0,0 +1,12 @@ +{ + "name": "web", + "private": true, + "type": "module", + "imports": { + "#*": "./src/*" + }, + "dependencies": { + "@workspace/ui": "workspace:*", + "tailwindcss": "^4.2.1" + } +} diff --git a/packages/tests/fixtures/vite-monorepo-imports/apps/web/src/main.tsx b/packages/tests/fixtures/vite-monorepo-imports/apps/web/src/main.tsx new file mode 100644 index 0000000000..aceb444975 --- /dev/null +++ b/packages/tests/fixtures/vite-monorepo-imports/apps/web/src/main.tsx @@ -0,0 +1 @@ +console.log("web") diff --git a/packages/tests/fixtures/vite-monorepo-imports/apps/web/tsconfig.json b/packages/tests/fixtures/vite-monorepo-imports/apps/web/tsconfig.json new file mode 100644 index 0000000000..f89fad37f9 --- /dev/null +++ b/packages/tests/fixtures/vite-monorepo-imports/apps/web/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "module": "esnext", + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolvePackageJsonImports": true + } +} diff --git a/packages/tests/fixtures/vite-monorepo-imports/apps/web/vite.config.ts b/packages/tests/fixtures/vite-monorepo-imports/apps/web/vite.config.ts new file mode 100644 index 0000000000..15652d9d07 --- /dev/null +++ b/packages/tests/fixtures/vite-monorepo-imports/apps/web/vite.config.ts @@ -0,0 +1,3 @@ +import { defineConfig } from "vite" + +export default defineConfig({}) diff --git a/packages/tests/fixtures/vite-monorepo-imports/package.json b/packages/tests/fixtures/vite-monorepo-imports/package.json new file mode 100644 index 0000000000..4236354ef5 --- /dev/null +++ b/packages/tests/fixtures/vite-monorepo-imports/package.json @@ -0,0 +1,6 @@ +{ + "name": "vite-monorepo-imports", + "private": true, + "packageManager": "pnpm@10.0.0", + "workspaces": ["apps/*", "packages/*"] +} diff --git a/packages/tests/fixtures/vite-monorepo-imports/packages/ui/components.json b/packages/tests/fixtures/vite-monorepo-imports/packages/ui/components.json new file mode 100644 index 0000000000..70cd00c27b --- /dev/null +++ b/packages/tests/fixtures/vite-monorepo-imports/packages/ui/components.json @@ -0,0 +1,18 @@ +{ + "style": "new-york", + "tailwind": { + "config": "", + "css": "src/styles/globals.css", + "baseColor": "zinc", + "cssVariables": true + }, + "rsc": false, + "tsx": true, + "aliases": { + "components": "#components", + "ui": "#components", + "lib": "#lib", + "hooks": "#hooks", + "utils": "#lib/utils" + } +} diff --git a/packages/tests/fixtures/vite-monorepo-imports/packages/ui/package.json b/packages/tests/fixtures/vite-monorepo-imports/packages/ui/package.json new file mode 100644 index 0000000000..1d00279428 --- /dev/null +++ b/packages/tests/fixtures/vite-monorepo-imports/packages/ui/package.json @@ -0,0 +1,14 @@ +{ + "name": "@workspace/ui", + "private": true, + "type": "module", + "imports": { + "#*": "./src/*" + }, + "exports": { + "./globals.css": "./src/styles/globals.css", + "./components/*": "./src/components/*.tsx", + "./lib/*": "./src/lib/*.ts", + "./hooks/*": "./src/hooks/*.ts" + } +} diff --git a/packages/tests/fixtures/vite-monorepo-imports/packages/ui/src/lib/utils.ts b/packages/tests/fixtures/vite-monorepo-imports/packages/ui/src/lib/utils.ts new file mode 100644 index 0000000000..02903b9115 --- /dev/null +++ b/packages/tests/fixtures/vite-monorepo-imports/packages/ui/src/lib/utils.ts @@ -0,0 +1,3 @@ +export function cn(...classes: Array) { + return classes.filter(Boolean).join(" ") +} diff --git a/packages/tests/fixtures/vite-monorepo-imports/packages/ui/src/styles/globals.css b/packages/tests/fixtures/vite-monorepo-imports/packages/ui/src/styles/globals.css new file mode 100644 index 0000000000..f1d8c73cdc --- /dev/null +++ b/packages/tests/fixtures/vite-monorepo-imports/packages/ui/src/styles/globals.css @@ -0,0 +1 @@ +@import "tailwindcss"; diff --git a/packages/tests/fixtures/vite-monorepo-imports/packages/ui/tsconfig.json b/packages/tests/fixtures/vite-monorepo-imports/packages/ui/tsconfig.json new file mode 100644 index 0000000000..f89fad37f9 --- /dev/null +++ b/packages/tests/fixtures/vite-monorepo-imports/packages/ui/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "module": "esnext", + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolvePackageJsonImports": true + } +} diff --git a/packages/tests/fixtures/vite-monorepo-imports/pnpm-workspace.yaml b/packages/tests/fixtures/vite-monorepo-imports/pnpm-workspace.yaml new file mode 100644 index 0000000000..286cf7f564 --- /dev/null +++ b/packages/tests/fixtures/vite-monorepo-imports/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: + - apps/* + - packages/* diff --git a/packages/tests/src/tests/add.test.ts b/packages/tests/src/tests/add.test.ts index 9904e385d9..b1e0e84c3c 100644 --- a/packages/tests/src/tests/add.test.ts +++ b/packages/tests/src/tests/add.test.ts @@ -166,6 +166,39 @@ describe("shadcn add", () => { ).toBe("Foo Bar") }) + it("should preview add changes without writing files", async () => { + const fixturePath = await createFixtureTestDirectory("next-app-init") + + const result = await npxShadcn(fixturePath, ["add", "button", "--dry-run"]) + + expect(result.exitCode).toBe(0) + expect(result.stdout).toContain("shadcn add button (dry run)") + expect(result.stdout).toContain("components/ui/button.tsx") + expect(result.stdout).toContain("Run without --dry-run to apply.") + expect( + await fs.pathExists(path.join(fixturePath, "components/ui/button.tsx")) + ).toBe(false) + }) + + it("should show no changes for identical files with diff", async () => { + const fixturePath = await createFixtureTestDirectory("next-app-init") + + await npxShadcn(fixturePath, ["add", "button", "--yes"]) + + const result = await npxShadcn(fixturePath, [ + "add", + "button", + "--diff", + "button", + "--yes", + ]) + + expect(result.exitCode).toBe(0) + expect(result.stdout).toContain("shadcn add button (dry run)") + expect(result.stdout).toContain("components/ui/button.tsx (skip)") + expect(result.stdout).toContain("No changes.") + }) + it("should add item with target to src", async () => { const fixturePath = await createFixtureTestDirectory("vite-app") await npxShadcn(fixturePath, ["init", "--defaults"]) @@ -230,6 +263,97 @@ describe("shadcn add", () => { `) }) + it("should add monorepo components and rewrite app-local imports with package imports", async () => { + const fixturePath = await createFixtureTestDirectory("vite-monorepo-imports") + + const result = await npxShadcn( + fixturePath, + ["add", "login-03", "-c", "apps/web", "--yes"], + { timeout: 300000 } + ) + + expect(result.exitCode).toBe(0) + + expect( + await fs.pathExists( + path.join(fixturePath, "apps/web/src/components/login-form.tsx") + ) + ).toBe(true) + expect( + await fs.pathExists( + path.join(fixturePath, "packages/ui/src/components/button.tsx") + ) + ).toBe(true) + expect( + await fs.pathExists( + path.join(fixturePath, "apps/web/src/components/ui/button.tsx") + ) + ).toBe(false) + + const loginFormContent = await fs.readFile( + path.join(fixturePath, "apps/web/src/components/login-form.tsx"), + "utf-8" + ) + expect(loginFormContent).toContain( + 'import { cn } from "@workspace/ui/lib/utils"' + ) + expect(loginFormContent).toContain( + 'import { Button } from "@workspace/ui/components/button"' + ) + + const buttonContent = await fs.readFile( + path.join(fixturePath, "packages/ui/src/components/button.tsx"), + "utf-8" + ) + expect(buttonContent).toContain('import { cn } from "#lib/utils.ts"') + }, 300000) + + it("should preview monorepo adds without writing files", async () => { + const fixturePath = await createFixtureTestDirectory("vite-monorepo-imports") + + const result = await npxShadcn( + fixturePath, + ["add", "login-03", "-c", "apps/web", "--dry-run", "--yes"], + { timeout: 300000 } + ) + + expect(result.exitCode).toBe(0) + expect(result.stdout).toContain("shadcn add login-03 (dry run)") + expect(result.stdout).toContain("../../packages/ui/src/components/button.tsx") + expect(result.stdout).toContain("src/components/login-form.tsx") + expect( + await fs.pathExists( + path.join(fixturePath, "apps/web/src/components/login-form.tsx") + ) + ).toBe(false) + expect( + await fs.pathExists( + path.join(fixturePath, "packages/ui/src/components/button.tsx") + ) + ).toBe(false) + }, 300000) + + it("should show no changes for identical monorepo files with diff", async () => { + const fixturePath = await createFixtureTestDirectory("vite-monorepo-imports") + + await npxShadcn( + fixturePath, + ["add", "login-03", "-c", "apps/web", "--yes"], + { timeout: 300000 } + ) + + const result = await npxShadcn( + fixturePath, + ["add", "login-03", "-c", "apps/web", "--diff", "login-form", "--yes"], + { timeout: 300000 } + ) + + expect(result.exitCode).toBe(0) + expect(result.stdout).toContain("shadcn add login-03 (dry run)") + expect(result.stdout).toContain("src/components/login-form.tsx (skip)") + expect(result.stdout).toContain("No changes.") + }, 300000) + it("should add NOT update existing envVars", async () => { const fixturePath = await createFixtureTestDirectory("next-app") await npxShadcn(fixturePath, ["init", "--defaults"])