import ts from 'typescript' import { parseJsx } from '../__tests__/utils' import { updateKaioImports, type UpdateKaioImportsArgs } from './updateKaioImports' import { printAst } from '.' const transformInput = (sourceFile: ts.SourceFile) => (imports: UpdateKaioImportsArgs): string => { const result = ts.transform(sourceFile, [updateKaioImports(imports)]) const transformedSource = result.transformed[0] as ts.SourceFile return printAst(transformedSource) } describe('updateKaioImports()', () => { describe('remove imports', () => { it('removes listed named imports', () => { const inputAst = parseJsx(` import { Card, Well } from "@kaizen/components" `) const outputAst = parseJsx(` import { Well } from "@kaizen/components" `) expect( transformInput(inputAst)({ importsToRemove: new Map([['@kaizen/components', new Set(['Card'])]]), }), ).toEqual(printAst(outputAst)) }) it('removes listed named aliased imports', () => { const inputAst = parseJsx(` import { Card as KzCard, Well } from "@kaizen/components" `) const outputAst = parseJsx(` import { Well } from "@kaizen/components" `) expect( transformInput(inputAst)({ importsToRemove: new Map([['@kaizen/components', new Set(['Card'])]]), }), ).toEqual(printAst(outputAst)) }) it('removes import statement when all named imports are removed', () => { const inputAst = parseJsx(` import { Card } from "@kaizen/components" import { Select } from "@kaizen/components/next" `) const outputAst = parseJsx(` import { Select } from "@kaizen/components/next" `) expect( transformInput(inputAst)({ importsToRemove: new Map([['@kaizen/components', new Set(['Card'])]]), }), ).toEqual(printAst(outputAst)) }) it('does nothing if the import does not exist', () => { const inputAst = parseJsx(` import { Select } from "@kaizen/components/next" `) const outputAst = parseJsx(` import { Select } from "@kaizen/components/next" `) expect( transformInput(inputAst)({ importsToRemove: new Map([['@kaizen/components', new Set(['Card'])]]), }), ).toEqual(printAst(outputAst)) }) }) describe('add imports', () => { it('creates a new import declaration for new imports', () => { const inputAst = parseJsx(` import { Well } from "@kaizen/components" `) const outputAst = parseJsx(` import { Well } from "@kaizen/components" import { Card } from "@kaizen/components/next" `) expect( transformInput(inputAst)({ importsToAdd: new Map([ ['@kaizen/components/next', new Map([['Card', { componentName: 'Card' }]])], ]), }), ).toEqual(printAst(outputAst)) }) it('creates a new import declaration for new aliased imports', () => { const inputAst = parseJsx(` import { Well } from "@kaizen/components" `) const outputAst = parseJsx(` import { Well } from "@kaizen/components" import { Card as KzCard } from "@kaizen/components/next" `) expect( transformInput(inputAst)({ importsToAdd: new Map([ [ '@kaizen/components/next', new Map([['Card', { componentName: 'Card', alias: 'KzCard' }]]), ], ]), }), ).toEqual(printAst(outputAst)) }) it('does not add a new named import if it already exists', () => { const inputAst = parseJsx(` import { Icon } from "@kaizen/components/next" `) const outputAst = parseJsx(` import { Icon } from "@kaizen/components/next" `) expect( transformInput(inputAst)({ importsToAdd: new Map([ ['@kaizen/components/next', new Map([['Icon', { componentName: 'Icon' }]])], ]), }), ).toEqual(printAst(outputAst)) }) it('updates existing import declaration with new imports', () => { const inputAst = parseJsx(` import { Select } from "@kaizen/components/next" `) const outputAst = parseJsx(` import { Select, Card } from "@kaizen/components/next" `) expect( transformInput(inputAst)({ importsToAdd: new Map([ ['@kaizen/components/next', new Map([['Card', { componentName: 'Card' }]])], ]), }), ).toEqual(printAst(outputAst)) }) describe('insert position', () => { it('inserts the new import below @kaizen/components', () => { const inputAst = parseJsx(` import React from "react" import { Well } from "@kaizen/components" import styles from "@kaizen/components/dist/styles.css" `) const outputAst = parseJsx(` import React from "react" import { Well } from "@kaizen/components" import { Card } from "@kaizen/components/next" import styles from "@kaizen/components/dist/styles.css" `) expect( transformInput(inputAst)({ importsToAdd: new Map([ ['@kaizen/components/next', new Map([['Card', { componentName: 'Card' }]])], ]), }), ).toEqual(printAst(outputAst)) }) it('inserts the new import below the first subpath of @kaizen/components', () => { const inputAst = parseJsx(` import React from "react" import { Well } from "@kaizen/components/v1" import styles from "@kaizen/components/dist/styles.css" `) const outputAst = parseJsx(` import React from "react" import { Well } from "@kaizen/components/v1" import { Card } from "@kaizen/components/next" import styles from "@kaizen/components/dist/styles.css" `) expect( transformInput(inputAst)({ importsToAdd: new Map([ ['@kaizen/components/next', new Map([['Card', { componentName: 'Card' }]])], ]), }), ).toEqual(printAst(outputAst)) }) it('inserts at the top of the file if no pre-existing import of @kaizen/components', () => { const inputAst = parseJsx(` import React from "react" `) const outputAst = parseJsx(` import { Card } from "@kaizen/components/next" import React from "react" `) expect( transformInput(inputAst)({ importsToAdd: new Map([ ['@kaizen/components/next', new Map([['Card', { componentName: 'Card' }]])], ]), }), ).toEqual(printAst(outputAst)) }) describe('type-only imports', () => { it('creates a new type-only import declaration', () => { const inputAst = parseJsx(` import { Well } from "@kaizen/components" `) const outputAst = parseJsx(` import { Well } from "@kaizen/components" import type { Card } from "@kaizen/components/next" `) expect( transformInput(inputAst)({ importsToAdd: new Map([ [ '@kaizen/components/next', new Map([['Card', { componentName: 'Card', isTypeOnly: true }]]), ], ]), }), ).toEqual(printAst(outputAst)) }) it('adds type-only import to existing regular imports', () => { const inputAst = parseJsx(` import { Select } from "@kaizen/components/next" `) const outputAst = parseJsx(` import { Select, type Card } from "@kaizen/components/next" `) expect( transformInput(inputAst)({ importsToAdd: new Map([ [ '@kaizen/components/next', new Map([['Card', { componentName: 'Card', isTypeOnly: true }]]), ], ]), }), ).toEqual(printAst(outputAst)) }) it('adds type-only import to existing type-only imports', () => { const inputAst = parseJsx(` import type { CardProps } from "@kaizen/components/next" `) const outputAst = parseJsx(` import type { CardProps, type ButtonProps } from "@kaizen/components/next" `) expect( transformInput(inputAst)({ importsToAdd: new Map([ [ '@kaizen/components/next', new Map([['ButtonProps', { componentName: 'ButtonProps', isTypeOnly: true }]]), ], ]), }), ).toEqual(printAst(outputAst)) }) it('adds mix of type-only and regular imports', () => { const inputAst = parseJsx(` import { Select } from "@kaizen/components/next" `) const outputAst = parseJsx(` import { Select, type CardProps, Button } from "@kaizen/components/next" `) expect( transformInput(inputAst)({ importsToAdd: new Map([ [ '@kaizen/components/next', new Map([ ['CardProps', { componentName: 'CardProps', isTypeOnly: true }], ['Button', { componentName: 'Button', isTypeOnly: false }], ]), ], ]), }), ).toEqual(printAst(outputAst)) }) }) }) }) })