vuetify
Version:
Vue Material Component Framework
313 lines (236 loc) • 8.84 kB
text/typescript
// Libraries
import Vue from 'vue'
// Components
import VIcon from '../VIcon'
// Utilities
import {
createLocalVue,
mount,
Wrapper,
} from '@vue/test-utils'
describe('VIcon', () => {
let mountFunction: (ctx?: object, name?: string) => Wrapper<Vue>
let localVue: typeof Vue
beforeEach(() => {
localVue = createLocalVue()
mountFunction = (ctx = {}, name = 'add') => {
return mount(VIcon, {
// https://github.com/vuejs/vue-test-utils/issues/1130
sync: false,
localVue,
context: Object.assign({
children: [name],
data: {},
props: {},
}, ctx),
})
}
})
it('should render component', () => {
const wrapper = mountFunction()
expect(wrapper.text()).toBe('add')
expect(wrapper.element.className).toBe('v-icon notranslate material-icons theme--light')
})
it('should render a colored component', () => {
const wrapper = mountFunction({ props: { color: 'green lighten-1' } })
expect(wrapper.element.classList).toContain('green--text')
expect(wrapper.element.classList).toContain('text--lighten-1')
})
it('should render a disabled component', () => {
const wrapper = mountFunction({ props: { disabled: true } })
expect(wrapper.element.classList).toContain('v-icon--disabled')
})
it('should not set font size if none provided', () => {
const wrapper = mountFunction()
expect(wrapper.element.style.fontSize).toBe('')
})
it('should render a mapped size', () => {
const SIZE_MAP = {
xSmall: '12px',
small: '16px',
large: '36px',
xLarge: '40px',
}
Object.keys(SIZE_MAP).forEach(size => {
const wrapper = mountFunction({ props: { [size]: true } })
expect(wrapper.element.style.fontSize).toBe(SIZE_MAP[size])
})
})
it('should render a specific size with String type', () => {
const wrapper = mountFunction({ props: { size: '112px' } })
expect(wrapper.element.style.fontSize).toBe('112px')
})
it('should render a specific size with Number type', () => {
const wrapper = mountFunction({ props: { size: '112' } })
expect(wrapper.element.style.fontSize).toBe('112px')
})
it('should render a left aligned component', () => {
const wrapper = mountFunction({ props: { left: true } })
expect(wrapper.element.classList).toContain('v-icon--left')
})
it('should render a right aligned component', () => {
const wrapper = mountFunction({ props: { right: true } })
expect(wrapper.element.classList).toContain('v-icon--right')
})
it('should render a component with aria-hidden attr', () => {
const wrapper = mountFunction({ attrs: { 'aria-hidden': 'foo' } })
expect(wrapper.element.getAttribute('aria-hidden')).toBe('foo')
})
it('should allow third-party icons when using <icon>- prefix', () => {
const wrapper = mountFunction({ props: {} }, 'fa-add')
expect(wrapper.text()).toBe('')
expect(wrapper.element.className).toBe('v-icon notranslate fa fa-add theme--light')
})
it('should support font awesome 5 icons when using <icon>- prefix', () => {
const wrapper = mountFunction({ props: {} }, 'fab fa-facebook')
expect(wrapper.text()).toBe('')
expect(wrapper.element.className).toBe('v-icon notranslate fab fa-facebook theme--light')
})
it('should allow the use of v-text', () => {
const wrapper = mountFunction({
domProps: { textContent: 'fa-home' },
})
expect(wrapper.text()).toBe('')
expect(wrapper.element.className).toBe('v-icon notranslate fa fa-home theme--light')
})
it('should allow the use of v-html', () => {
const wrapper = mountFunction({
domProps: { innerHTML: 'fa-home' },
})
expect(wrapper.text()).toBe('')
expect(wrapper.element.className).toBe('v-icon notranslate fa fa-home theme--light')
})
it('set font size from helper prop', async () => {
const iconFactory = size => mountFunction({
props: { [size]: true },
})
const small = iconFactory('small')
expect(small.html()).toMatchSnapshot()
const medium = iconFactory('medium')
expect(medium.html()).toMatchSnapshot()
const large = iconFactory('large')
expect(large.html()).toMatchSnapshot()
const xLarge = iconFactory('xLarge')
expect(xLarge.html()).toMatchSnapshot()
})
it('should have proper classname', () => {
const wrapper = mountFunction({
props: {
color: 'primary',
},
domProps: {
innerHTML: 'fa-lock',
},
})
expect(wrapper.element.className).toBe('v-icon notranslate fa fa-lock theme--light primary--text')
})
describe('for global icon', () => {
beforeEach(() => {
Vue.prototype.$vuetify = {
icons: {
values: {
checkboxOn: 'check_box',
prev: 'chevron_left',
},
},
}
})
it('should render MD left icon from $checkboxOn', () => {
const wrapper = mountFunction({}, '$checkboxOn')
expect(wrapper.text()).toBe('check_box')
expect(wrapper.element.className).toBe('v-icon notranslate material-icons theme--light')
})
it('should render MD left icon from $prev', () => {
const wrapper = mountFunction({}, '$prev')
expect(wrapper.text()).toBe('chevron_left')
expect(wrapper.element.className).toBe('v-icon notranslate material-icons theme--light')
})
})
it('should use an <i> tag if none provided', () => {
const wrapper = mountFunction()
expect(wrapper.element.localName).toBe('i')
})
it('sets tag from from prop if provided', () => {
const wrapper = mountFunction({ props: { tag: 'span' } })
expect(wrapper.element.localName).toBe('span')
})
describe('for component icon', () => {
const getTestComponent = () => ({
props: ['name'],
render (h) {
return h('div', {
class: 'test-component',
}, this.name)
},
})
beforeEach(() => {
Vue.prototype.$vuetify = {
icons: {
values: {
testIcon: {
component: getTestComponent(),
props: {
name: 'test icon',
},
},
},
},
}
})
it('should render component', () => {
const wrapper = mountFunction({}, '$testIcon')
expect(wrapper.text()).toBe('test icon')
expect(wrapper.html()).toMatchSnapshot()
})
it('should render a colored component', () => {
const wrapper = mountFunction({ props: { color: 'green lighten-1' } }, '$testIcon')
expect(wrapper.element.classList).toContain('green--text')
expect(wrapper.element.classList).toContain('text--lighten-1')
})
it('should render a disabled component', () => {
const wrapper = mountFunction({ props: { disabled: true } }, '$testIcon')
expect(wrapper.element.classList).toContain('v-icon--disabled')
})
it('should set font size from helper prop', async () => {
const iconFactory = size => mountFunction({
props: { [size]: true },
}, '$testIcon')
const small = iconFactory('small')
expect(small.html()).toMatchSnapshot()
const medium = iconFactory('medium')
expect(medium.html()).toMatchSnapshot()
const large = iconFactory('large')
expect(large.html()).toMatchSnapshot()
const xLarge = iconFactory('xLarge')
expect(xLarge.html()).toMatchSnapshot()
})
it('should render a left aligned component', () => {
const wrapper = mountFunction({ props: { left: true } }, '$testIcon')
expect(wrapper.element.classList).toContain('v-icon--left')
})
it('should render a right aligned component', () => {
const wrapper = mountFunction({ props: { right: true } }, '$testIcon')
expect(wrapper.element.classList).toContain('v-icon--right')
})
it('should be an accessible link', () => {
const clickHandler = jest.fn()
const wrapper = mountFunction({ on: { click: clickHandler } }, '$testIcon')
wrapper.trigger('click')
expect(wrapper.element.classList).toContain('v-icon--link')
expect(clickHandler).toHaveBeenCalled()
expect(wrapper.element.getAttribute('aria-hidden')).toBeFalsy()
expect(wrapper.element.getAttribute('type')).toBe('button')
})
it('should trim name', () => {
const wrapper = mountFunction({}, ' add ')
expect(wrapper.text()).toBe('add')
})
it('should render an svg icon', async () => {
const wrapper = mountFunction({}, 'M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z')
expect(wrapper.html()).toMatchSnapshot()
wrapper.setProps({ large: true })
await wrapper.vm.$nextTick()
expect(wrapper.html()).toMatchSnapshot()
})
})
})