import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import { Primitive } from '.'
import { defineComponent, h, markRaw } from 'vue'
describe('test Primitive functionalities', () => {
it('should render div element correctly', () => {
const wrapper = mount(Primitive)
expect(wrapper.find('div').exists()).toBe(true)
})
it('should render button element correctly', () => {
const wrapper = mount(Primitive, {
props: {
as: 'button',
},
})
expect(wrapper.find('button').exists()).toBe(true)
})
it('should by pass the comment tag', () => {
const wrapper = mount(Primitive, {
props: {
as: 'template',
},
attrs: {
'data-parent-attr': '',
},
slots: {
default: `
Child class
`,
},
})
const element = wrapper.find('div')
expect(element.attributes('data-parent-attr')).toBe('')
expect(element.attributes('data-child-attr')).toBe('')
})
it('should renders div element with custom attribute', () => {
const wrapper = mount(Primitive, {
attrs: {
type: 'button',
},
})
const element = wrapper.find('div')
expect(element.attributes('type')).toBe('button')
})
it('should renders multiple child elements', () => {
const wrapper = mount(Primitive, {
slots: {
default: '1
2
3
',
},
})
const element = wrapper.find('div')
expect(element.findAll('div').length).toBe(3)
})
// ref: https://vitest.dev/api/expect.html#tothrowerror
describe('render as template (asChild)', () => {
it('should not throw error when multiple child elements exists', () => {
const wrapper = () => mount(Primitive, {
props: {
as: 'template',
},
slots: {
default: '1
2
3
',
},
})
expect(wrapper().findAll('div').length).toBe(3)
expect(() => wrapper()).not.toThrowError(/invalid children/)
})
it('should pass custom attribute to first element', () => {
const wrapper = mount(Primitive, {
props: {
as: 'template',
type: 'button',
},
slots: {
default: '1
2
3
',
},
})
const element = wrapper.findAll('div')
expect(element[0].attributes('type')).toBe('button')
expect(element[1].attributes('type')).toBeUndefined()
expect(element[2].attributes('type')).toBeUndefined()
})
it('should merge child\'s class together', () => {
const wrapper = mount(Primitive, {
props: {
as: 'template',
},
attrs: {
class: 'parent-class',
},
slots: {
default:
'Child class
',
},
})
const element = wrapper.find('div')
expect(element.attributes('class')).toBe(
'parent-class child-class more-child-class',
)
})
it('should render the Component that passed in as', () => {
const Button = markRaw(defineComponent({
setup(props, { slots }) {
return () => h('button', { id: 'custom-button' }, slots)
},
}))
const wrapper = mount(Primitive, {
props: {
as: Button,
},
attrs: {
class: 'parent-class',
},
})
expect(wrapper.html()).toBe(
'',
)
})
it('should render the child class element tag', () => {
const wrapper = mount(Primitive, {
props: {
as: 'template',
},
slots: {
default: 'Child class',
},
})
const element = wrapper.find('a')
expect(element.exists()).toBeTruthy()
})
it('should render the child component', () => {
const ChildComponent = {
template: 'Hello world
',
}
const RootComponent = {
components: { ChildComponent, Primitive },
template: '',
}
const wrapper = mount(RootComponent, {
props: {
as: 'template',
},
})
const element = wrapper.find('div')
expect(element.html()).toBe('Hello world
')
})
it('should inherit parent attributes and the child attributes', () => {
const wrapper = mount(Primitive, {
props: {
as: 'template',
},
attrs: {
'data-parent-attr': '',
},
slots: {
default: 'Child class
',
},
})
const element = wrapper.find('div')
expect(element.attributes('data-parent-attr')).toBe('')
expect(element.attributes('data-child-attr')).toBe('')
})
it('should replace parent attributes with child\'s attributes', () => {
const wrapper = mount(Primitive, {
props: {
as: 'template',
},
attrs: {
'id': 'parent',
'data-type': 'button',
},
slots: {
default: 'Child class
',
},
})
const element = wrapper.find('div')
expect(element.attributes('data-type')).toBe('primary')
expect(element.attributes('id')).toBe('child')
})
it('\'asChild=true\' should work the same as \'as=template\'', () => {
const wrapper = mount(Primitive, {
props: {
asChild: true,
},
attrs: {
class: 'parent-class',
},
slots: {
default: '',
},
})
const element = wrapper.find('button')
expect(element.exists()).toBe(true)
expect(element.attributes('class')).toBe('parent-class child-class')
})
})
})