import ts from 'typescript' import { parseJsx } from '../__tests__/utils/parseJsx' import { createProp, createStyleProp } from './createProp' import { printAst } from './printAst' import { transformSource, type TransformSourceArgs } from './transformSource' import { updateJsxElementWithNewProps } from './updateJsxElementWithNewProps' export const mockTransformer: ts.TransformerFactory = (context) => (rootNode) => { const visit = (node: ts.Node): ts.Node => { if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) { const newAttributes = node.attributes.properties.map((attr) => { if (ts.isJsxAttribute(attr)) { return createProp(`${attr.name.getText()}New`, attr.initializer) } return attr }) return updateJsxElementWithNewProps(node, newAttributes) } return ts.visitEachChild(node, visit, context) } return ts.visitNode(rootNode, visit) as ts.SourceFile } const testCreateProp = (sourceFile: TransformSourceArgs['sourceFile']): string => transformSource({ sourceFile, transformers: [mockTransformer], }) describe('createProp()', () => { it('creates a prop with the pre-existing value', () => { const inputAst = parseJsx('') const outputAst = parseJsx('') expect(testCreateProp(inputAst)).toEqual(printAst(outputAst)) }) it('creates a prop and transforms true to undefined', () => { const inputAst = parseJsx(` export const TestComponent = () => ( <> ) `) const outputAst = parseJsx(` export const TestComponent = () => ( <> ) `) expect(testCreateProp(inputAst)).toEqual(printAst(outputAst)) }) }) export const styleTransformer: ts.TransformerFactory = (context) => (rootNode) => { const visit = (node: ts.Node): ts.Node => { if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) { const newAttributes = node.attributes.properties.map((attr) => { if (ts.isJsxAttribute(attr)) { if (attr.name.getText() === 'replaceWithExistingValue') { return createStyleProp({ width: attr.initializer! }) } if (attr.name.getText() === 'replaceWithStringValue') { return createStyleProp({ width: '100px' }) } if (attr.name.getText() === 'replaceWithNumberValue') { return createStyleProp({ width: 100 }) } } return attr }) return updateJsxElementWithNewProps(node, newAttributes) } return ts.visitEachChild(node, visit, context) } return ts.visitNode(rootNode, visit) as ts.SourceFile } const testCreateStyleProp = (sourceFile: TransformSourceArgs['sourceFile']): string => transformSource({ sourceFile, transformers: [styleTransformer], }) describe('createStyleProp()', () => { it('creates a style prop with a string value', () => { const inputAst = parseJsx('') const outputAst = parseJsx('') expect(testCreateStyleProp(inputAst)).toEqual(printAst(outputAst)) }) it('creates a style prop with a number value', () => { const inputAst = parseJsx('') const outputAst = parseJsx('') expect(testCreateStyleProp(inputAst)).toEqual(printAst(outputAst)) }) it('creates a style prop with a pre-existing value', () => { const inputAst = parseJsx(` export const TestComponent = () => ( <> ) `) const outputAst = parseJsx(` export const TestComponent = () => ( <> ) `) expect(testCreateStyleProp(inputAst)).toEqual(printAst(outputAst)) }) })