@mozaic-ds/vue
Version:
Mozaic-Vue is the Vue.js implementation of ADEO Design system
139 lines (116 loc) • 4.53 kB
text/typescript
import { mount } from '@vue/test-utils';
import { describe, it, expect, vi, beforeAll, afterAll } from 'vitest';
import MCarousel from './MCarousel.vue';
import MIconButton from '../iconbutton/MIconButton.vue';
import ChevronLeft20 from '@mozaic-ds/icons-vue/src/components/ChevronLeft20/ChevronLeft20.vue';
import ChevronRight20 from '@mozaic-ds/icons-vue/src/components/ChevronRight20/ChevronRight20.vue';
/* eslint-disable @typescript-eslint/no-explicit-any */
class MockIntersectionObserver {
callback: any;
options: any;
constructor(callback: any, options?: any) {
this.callback = callback;
this.options = options;
}
observe = vi.fn();
unobserve = vi.fn();
disconnect = vi.fn();
}
describe('MCarousel component', () => {
let originalObserver: any;
beforeAll(() => {
originalObserver = global.IntersectionObserver;
global.IntersectionObserver = MockIntersectionObserver as any;
Object.defineProperty(window.HTMLElement.prototype, 'scrollIntoView', {
value: vi.fn(),
writable: true,
});
});
afterAll(() => {
global.IntersectionObserver = originalObserver;
});
const mockChildren = [
'<div class="slide">Slide 1</div>',
'<div class="slide">Slide 2</div>',
'<div class="slide">Slide 3</div>',
];
const mountCarousel = (options = {}) =>
mount(MCarousel, {
attachTo: document.body,
slots: {
default: mockChildren.join(''),
header: '<h2 id="mc-carousel__title">Carousel Header</h2>',
},
...options,
});
it('renders correctly with header and default slot', () => {
const wrapper = mountCarousel();
expect(wrapper.find('.mc-carousel__headings').text()).toContain(
'Carousel Header',
);
expect(wrapper.findAll('.slide')).toHaveLength(3);
});
it('renders navigation buttons with correct aria labels', () => {
const wrapper = mountCarousel({
props: {
previousButtonAriaLabel: 'Go back',
nextButtonAriaLabel: 'Go forward',
},
});
const buttons = wrapper.findAllComponents(MIconButton);
expect(buttons).toHaveLength(2);
expect(buttons[0].attributes('aria-label')).toBe('Go back');
expect(buttons[1].attributes('aria-label')).toBe('Go forward');
});
it('renders default aria labels when not provided', () => {
const wrapper = mountCarousel();
const buttons = wrapper.findAllComponents(MIconButton);
expect(buttons[0].attributes('aria-label')).toBe('previous');
expect(buttons[1].attributes('aria-label')).toBe('next');
});
it('renders icon components inside navigation buttons', () => {
const wrapper = mountCarousel();
expect(wrapper.findComponent(ChevronLeft20).exists()).toBe(true);
expect(wrapper.findComponent(ChevronRight20).exists()).toBe(true);
});
it('disables the previous button when on the first slide', () => {
const wrapper = mountCarousel();
const [prevButton] = wrapper.findAllComponents(MIconButton);
expect(prevButton.props('disabled')).toBe(true);
});
it('scrolls to next slide when goNext is called', async () => {
const scrollIntoViewMock = vi.fn();
(window.HTMLElement.prototype.scrollIntoView as any) = scrollIntoViewMock;
const wrapper = mountCarousel();
const vm = wrapper.vm as any;
vi.spyOn(vm, 'getCarouselChildren').mockReturnValue([
{ scrollIntoView: scrollIntoViewMock },
{ scrollIntoView: scrollIntoViewMock },
{ scrollIntoView: scrollIntoViewMock },
]);
vm.goNext();
expect(scrollIntoViewMock).toHaveBeenCalled();
});
it('scrolls to previous slide when goPrevious is called', async () => {
const scrollIntoViewMock = vi.fn();
(window.HTMLElement.prototype.scrollIntoView as any) = scrollIntoViewMock;
const wrapper = mountCarousel();
const vm = wrapper.vm as any;
vi.spyOn(vm, 'getCarouselChildren').mockReturnValue([
{ scrollIntoView: scrollIntoViewMock },
{ scrollIntoView: scrollIntoViewMock },
{ scrollIntoView: scrollIntoViewMock },
]);
vm.goNext();
vm.goNext();
vm.goPrevious();
expect(scrollIntoViewMock).toHaveBeenCalled();
});
it('sets correct ARIA attributes on main container', () => {
const wrapper = mountCarousel();
const container = wrapper.find('.mc-carousel');
expect(container.attributes('role')).toBe('group');
expect(container.attributes('aria-roledescription')).toBe('carousel');
expect(container.attributes('aria-labelledby')).toBe('mc-carousel__title');
});
});