@mozaic-ds/vue
Version:
Mozaic-Vue is the Vue.js implementation of ADEO Design system
210 lines (179 loc) • 6.94 kB
text/typescript
import { mount } from '@vue/test-utils';
import { describe, it, expect } from 'vitest';
import MNavigationIndicator from './MNavigationIndicator.vue';
const PauseCircle24 = {
name: 'PauseCircle24',
template: '<span data-testid="pause-icon"></span>',
};
const PlayCircle24 = {
name: 'PlayCircle24',
template: '<span data-testid="play-icon"></span>',
};
const MButton = {
name: 'MButton',
props: ['size', 'iconPosition', 'ghost'],
template: `
<button data-testid="m-button">
<slot />
<slot name="icon" />
<slot />
</button>
`,
};
const MIconButton = {
name: 'MIconButton',
props: ['size', 'ghost'],
template: `<button data-testid="m-icon-button"><slot name="icon" /></button>`,
};
describe('MNavigationIndicator.vue', () => {
it('renders the correct number of steps', () => {
const wrapper = mount(MNavigationIndicator, {
props: { steps: 4, modelValue: 0 },
global: {
stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 },
},
});
const items = wrapper.findAll('.mc-navigation-indicator__item');
expect(items).toHaveLength(4);
});
it('applies active class to the current step', () => {
const wrapper = mount(MNavigationIndicator, {
props: { steps: 5, modelValue: 2 },
global: {
stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 },
},
});
const stepButtons = wrapper.findAll(
'.mc-navigation-indicator__list .mc-navigation-indicator__button',
);
expect(stepButtons[2].classes()).toContain(
'mc-navigation-indicator__button--active',
);
});
it('emits update:modelValue when a step is clicked', async () => {
const wrapper = mount(MNavigationIndicator, {
props: { steps: 3, modelValue: 0 },
global: {
stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 },
},
});
const stepButtons = wrapper.findAll(
'.mc-navigation-indicator__list .mc-navigation-indicator__button',
);
await stepButtons[1].trigger('click');
const emitted = wrapper.emitted('update:modelValue');
expect(emitted).toBeTruthy();
expect(emitted![0][0]).toBe(1);
});
it('does not emit update:modelValue when a wrong key is pressed', async () => {
const wrapper = mount(MNavigationIndicator, {
props: { steps: 3, modelValue: 0 },
global: {
stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 },
},
});
const stepButtons = wrapper.findAll(
'.mc-navigation-indicator__list .mc-navigation-indicator__button',
);
await stepButtons[2].trigger('keydown', { key: 'Esc' });
const emitted = wrapper.emitted('update:modelValue');
expect(emitted).toBeFalsy();
});
it('does not render action button when player is false', () => {
const wrapper = mount(MNavigationIndicator, {
props: { steps: 2, modelValue: 0, player: false },
global: {
stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 },
},
});
expect(wrapper.find('[data-testid="m-button"]').exists()).toBe(false);
expect(wrapper.find('[data-testid="m-icon-button"]').exists()).toBe(false);
});
it('renders icon-only button when no label is defined', () => {
const wrapper = mount(MNavigationIndicator, {
props: { steps: 2, modelValue: 0, action: 'resume' },
global: {
stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 },
},
});
expect(wrapper.find('[data-testid="m-icon-button"]').exists()).toBe(true);
expect(wrapper.find('[data-testid="play-icon"]').exists()).toBe(true);
});
it('renders labeled button with correct label and pause icon when action is pause', () => {
const wrapper = mount(MNavigationIndicator, {
props: { steps: 2, modelValue: 0, label: 'Pause', action: 'pause' },
global: {
stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 },
},
});
const button = wrapper.find('[data-testid="m-button"]');
expect(button.exists()).toBe(true);
expect(button.text()).toContain('Pause');
expect(wrapper.find('[data-testid="pause-icon"]').exists()).toBe(true);
});
it('renders a navigation landmark with an aria-label', () => {
const wrapper = mount(MNavigationIndicator, {
props: { steps: 3, modelValue: 0 },
global: {
stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 },
},
});
const navigation = wrapper.find('nav[aria-label="Navigation steps"]');
expect(navigation.exists()).toBe(true);
expect(navigation.attributes('aria-label')).toBe('Navigation steps');
});
it('player icon button has aria-label reflecting action state', () => {
const wrapperPause = mount(MNavigationIndicator, {
props: { steps: 2, modelValue: 0, action: 'pause' },
global: { stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 } },
});
expect(
wrapperPause
.find('[data-testid="m-icon-button"]')
.attributes('aria-label'),
).toBe('Pause');
const wrapperResume = mount(MNavigationIndicator, {
props: { steps: 2, modelValue: 0, action: 'resume' },
global: { stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 } },
});
expect(
wrapperResume
.find('[data-testid="m-icon-button"]')
.attributes('aria-label'),
).toBe('Resume');
});
it('gives each step button an action-oriented aria-label', () => {
const wrapper = mount(MNavigationIndicator, {
props: { steps: 3, modelValue: 1 },
global: {
stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 },
},
});
const buttons = wrapper.findAll('.mc-navigation-indicator__button');
expect(buttons[0].attributes('aria-label')).toBe('Go to step 1 of 3');
expect(buttons[1].attributes('aria-label')).toBe('Current step, 2 of 3');
expect(buttons[2].attributes('aria-label')).toBe('Go to step 3 of 3');
});
it('sets aria-current="step" only on the active step button', () => {
const wrapper = mount(MNavigationIndicator, {
props: { steps: 3, modelValue: 1 },
global: {
stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 },
},
});
const buttons = wrapper.findAll('.mc-navigation-indicator__button');
expect(buttons[1].attributes('aria-current')).toBe('step');
expect(buttons[0].attributes('aria-current')).not.toBe('step');
expect(buttons[2].attributes('aria-current')).not.toBe('step');
});
it('emits "action" when the player button is clicked', async () => {
const wrapper = mount(MNavigationIndicator, {
props: { steps: 2, modelValue: 0, action: 'resume' },
global: {
stubs: { MButton, MIconButton, PauseCircle24, PlayCircle24 },
},
});
await wrapper.find('[data-testid="m-icon-button"]').trigger('click');
expect(wrapper.emitted('action')).toBeTruthy();
});
});