UNPKG

@mozaic-ds/vue

Version:

Mozaic-Vue is the Vue.js implementation of ADEO Design system

204 lines (169 loc) 7.13 kB
import { shallowMount, mount } from '@vue/test-utils'; import { describe, it, expect } from 'vitest'; import { nextTick } from 'vue'; import MStarRating from './MStarRating.vue'; import StarFilled24 from '@mozaic-ds/icons-vue/src/components/StarFilled24/StarFilled24.vue'; import StarHalf24 from '@mozaic-ds/icons-vue/src/components/StarHalf24/StarHalf24.vue'; function mockRect(el: Element, { left = 0, width = 100 } = {}) { Object.defineProperty(el, 'getBoundingClientRect', { value: () => ({ left, width, top: 0, bottom: 0, right: left + width, height: 0, }), configurable: true, }); } describe('MStarRating', () => { it('renders 5 stars by default', () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 0 } }); const stars = wrapper.findAll('.mc-star-rating__icon'); expect(stars.length).toBe(5); }); it('renders 1 star when compact mode is enabled', () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 0, compact: true }, }); const stars = wrapper.findAll('.mc-star-rating__icon'); expect(stars.length).toBe(1); }); it('does not render half star on input mode', async () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 0, readonly: false }, }); const stars = wrapper.findAll('.mc-star-rating__icon'); const first = stars[0]; mockRect(first.element, { left: 0, width: 100 }); await first.trigger('mousemove', { clientX: 10 }); expect(wrapper.findComponent(StarHalf24).exists()).toBe(false); }); it('render half star on readonly mode if possible', () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 1.5, readonly: true }, }); const filledStars = wrapper.findAllComponents(StarFilled24); const halfStars = wrapper.findAllComponents(StarHalf24); expect(filledStars.length).toBe(1); expect(halfStars.length).toBe(1); }); it('emits update:modelValue with the correct value when clicking a star', async () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 2, readonly: false }, }); const stars = wrapper.findAll('.mc-star-rating__icon'); const first = stars[0]; mockRect(first.element, { left: 0, width: 100 }); await first.trigger('click', { clientX: 10 }); const emitted = wrapper.emitted('update:modelValue') || []; expect(emitted.length).toBe(1); expect(emitted[0][0]).toBe(1); }); it('emits the correct values when pressing ArrowRight', async () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 2, readonly: false }, }); const ratingInput = wrapper.find('.mc-star-rating__wrapper'); await ratingInput.trigger('keydown', { key: 'ArrowRight' }); const emitted = wrapper.emitted('update:modelValue') || []; expect(emitted.length).toBe(1); expect(emitted[0][0]).toBe(3); }); it('emits the correct values when pressing ArrowLeft', async () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 2, readonly: false }, }); const ratingInput = wrapper.find('.mc-star-rating__wrapper'); await ratingInput.trigger('keydown', { key: 'ArrowLeft' }); const emitted = wrapper.emitted('update:modelValue') || []; expect(emitted.length).toBe(1); expect(emitted[0][0]).toBe(1); }); it('does not do anything if the wrong key is pressed', async () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 2, readonly: false }, }); const ratingInput = wrapper.find('.mc-star-rating__wrapper'); await ratingInput.trigger('keydown', { key: 'ArrowUp' }); const emitted = wrapper.emitted('update:modelValue') || []; expect(emitted.length).toBe(0); }); it('resets hover to null on mouseleave (aria-label falls back to modelValue)', async () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 2, size: 'm', readonly: false }, }); const stars = wrapper.findAll('.mc-star-rating__icon'); const first = stars[0]; mockRect(first.element, { left: 0, width: 100 }); await first.trigger('mousemove', { clientX: 10 }); await nextTick(); // aria-label should reflect hovered value (0.5) not modelValue (2) const root = wrapper.find('[role="slider"]'); expect(root.attributes('aria-label')).toContain('1'); // trigger mouseleave on root, hover should be cleared and aria-label revert to modelValue await root.trigger('mouseleave'); await nextTick(); expect(root.attributes('aria-label')).toContain('2'); }); it('resets hover to null on blur (aria-label falls back to modelValue)', async () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 3, size: 'm', readonly: false }, }); const stars = wrapper.findAll('.mc-star-rating__icon'); const secondStar = stars[1]; mockRect(secondStar.element, { left: 0, width: 100 }); const root = wrapper.find('[role="slider"]'); await root.trigger('focus'); await secondStar.trigger('mousemove', { clientX: 10 }); await nextTick(); expect(root.attributes('aria-label')).toContain('2'); // blur should clear hover and revert aria-label to modelValue (3) await root.trigger('blur'); await nextTick(); expect(root.attributes('aria-label')).toContain('3'); }); it('renders information text when text prop is provided', () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 3, text: 'Note publique' }, }); const info = wrapper.find('.mc-star-rating__info'); expect(info.exists()).toBe(true); expect(info.text()).toBe('Note publique'); }); it('renders href when href prop is provided and text is not', () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 2, href: '/voir' }, }); const info = wrapper.find('.mc-star-rating__info'); expect(info.exists()).toBe(true); expect(info.text()).toBe('/voir'); }); it('does not render info span when neither text nor href is provided', () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 1 }, }); const info = wrapper.find('.mc-star-rating__info'); expect(info.exists()).toBe(false); }); it('renders router-link when href and router are provided', () => { const wrapper = mount(MStarRating, { props: { modelValue: 3, href: '/path', router: true }, global: { stubs: ['router-link'] }, }); expect(wrapper.element.tagName.toLowerCase()).toBe('router-link-stub'); }); it('renders an anchor when href is provided and router is falsy', () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 2, href: '#', router: false }, }); expect(wrapper.element.tagName.toLowerCase()).toBe('a'); }); it('renders a div when no href is provided', () => { const wrapper = shallowMount(MStarRating, { props: { modelValue: 1 }, }); expect(wrapper.element.tagName.toLowerCase()).toBe('div'); }); });