import {
FileType,
InMemoryFileRecord,
ProjectPluginStructure,
ProjectUIDL,
UIDLElementNode,
} from '@teleporthq/teleport-types'
import { NextDragDropProjectPlugin } from '../src/drag-drop/project-plugin'
import { NextKanbanProjectPlugin } from '../src/kanban/project-plugin'
const APP_CONTENT = `import './style.css'
export default function MyApp({ Component, pageProps }) {
return
}
`
const elementNode = (elementType: string, children: UIDLElementNode[] = []): UIDLElementNode => ({
type: 'element',
content: {
elementType,
children,
},
})
const buildStructure = (pageChildren: UIDLElementNode[]): ProjectPluginStructure => {
const files = new Map()
files.set('_app', {
path: ['pages'],
files: [{ name: '_app', fileType: FileType.JS, content: APP_CONTENT }],
})
const uidl = {
name: 'test',
root: {
name: 'App',
node: elementNode('container', pageChildren),
},
components: {},
} as unknown as ProjectUIDL
return {
uidl,
files,
dependencies: {},
devDependencies: {},
} as unknown as ProjectPluginStructure
}
describe('NextDragDropProjectPlugin', () => {
const plugin = new NextDragDropProjectPlugin()
it('is a no-op for projects without drag-and-drop primitives', async () => {
const structure = buildStructure([elementNode('container')])
await plugin.runAfter(structure)
expect(structure.files.has('tq-drag-drop-component')).toBe(false)
expect(structure.dependencies['@dnd-kit/core']).toBeUndefined()
})
it.each(['thq-drag-area', 'thq-draggable', 'thq-droppable', 'thq-sortable', 'thq-sortable-item'])(
'emits the wrapper file and dnd-kit deps when %s is used',
async (primitive) => {
const structure = buildStructure([elementNode(primitive)])
await plugin.runAfter(structure)
const record = structure.files.get('tq-drag-drop-component')
expect(record?.path).toEqual(['components'])
expect(record?.files[0].name).toBe('tq-drag-drop')
expect(record?.files[0].content).toContain('export const TqDragArea')
expect(record?.files[0].content).toContain('export const TqSortable')
expect(structure.dependencies['@dnd-kit/core']).toBe('^6.3.1')
expect(structure.dependencies['@dnd-kit/sortable']).toBe('^10.0.0')
expect(structure.dependencies['@dnd-kit/utilities']).toBe('^3.2.2')
}
)
it('detects primitives nested deep in the tree', async () => {
const structure = buildStructure([
elementNode('container', [elementNode('container', [elementNode('thq-sortable')])]),
])
await plugin.runAfter(structure)
expect(structure.files.has('tq-drag-drop-component')).toBe(true)
})
})
describe('NextKanbanProjectPlugin', () => {
const plugin = new NextKanbanProjectPlugin()
it('is a no-op for projects without a kanban board', async () => {
const structure = buildStructure([elementNode('container')])
await plugin.runAfter(structure)
expect(structure.files.has('tq-kanban-component')).toBe(false)
expect(structure.files.has('tq-kanban-npmrc')).toBe(false)
expect(structure.dependencies['@asseinfo/react-kanban']).toBeUndefined()
const appContent = structure.files.get('_app')?.files[0].content as string
expect(appContent).toBe(APP_CONTENT)
})
it('emits the wrapper, dependency, stylesheet import and .npmrc when used', async () => {
const structure = buildStructure([elementNode('kanban-node')])
await plugin.runAfter(structure)
const componentRecord = structure.files.get('tq-kanban-component')
expect(componentRecord?.path).toEqual(['components'])
expect(componentRecord?.files[0].name).toBe('tq-kanban')
expect(componentRecord?.files[0].content).toContain(
"dynamic(() => import('@asseinfo/react-kanban')"
)
expect(componentRecord?.files[0].content).toContain('ssr: false')
expect(componentRecord?.files[0].content).toContain('initialBoard')
const npmrcRecord = structure.files.get('tq-kanban-npmrc')
expect(npmrcRecord?.path).toEqual([])
expect(npmrcRecord?.files[0].name).toBe('.npmrc')
expect(npmrcRecord?.files[0].fileType).toBeUndefined()
expect(npmrcRecord?.files[0].content).toContain('legacy-peer-deps=true')
expect(structure.dependencies['@asseinfo/react-kanban']).toBe('2.2.0')
const appContent = structure.files.get('_app')?.files[0].content as string
expect(appContent).toContain("import '@asseinfo/react-kanban/dist/styles.css'")
expect(appContent.indexOf('@asseinfo/react-kanban/dist/styles.css')).toBeLessThan(
appContent.indexOf('./style.css')
)
})
it('is idempotent when run twice', async () => {
const structure = buildStructure([elementNode('kanban-node')])
await plugin.runAfter(structure)
await plugin.runAfter(structure)
const appContent = structure.files.get('_app')?.files[0].content as string
expect(appContent.match(/@asseinfo\/react-kanban\/dist\/styles\.css/g)).toHaveLength(1)
})
})