@gitlab/ui
Version:
GitLab UI Components
218 lines (177 loc) • 6 kB
JavaScript
import { shallowMount } from '@vue/test-utils';
import { mockPathItems } from './data';
import GlPath from './path.vue';
const SELECTED_CLASS_INDIGO = 'gl-path-active-item-indigo';
const SELECTED_CLASS_GREEN = 'gl-path-active-item-green';
const BACKGROUND_COLOR_WHITE = 'white';
const BACKGROUND_COLOR_LIGHT_GRAY = '#f0f0f0';
describe('Path', () => {
let wrapper;
const createComponent = (props = {}, options = {}) => {
return shallowMount(GlPath, {
propsData: {
items: mockPathItems,
...props,
},
...options,
});
};
const pathNav = () => {
return wrapper.find('[data-testid="gl-path-nav"]').element;
};
const listItems = () => {
return wrapper.vm.$refs.pathListItems;
};
const pathItemAt = (index) => {
return listItems()[index].children[0];
};
const pathItemTextAt = (index) => {
return pathItemAt(index).textContent;
};
const clickItemAt = (index) => {
pathItemAt(index).click();
};
beforeEach(() => {
wrapper = createComponent();
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
describe('theme selection', () => {
describe('default', () => {
it('applies the indigo theme', () => {
expect(pathItemAt(0).classList).toContain(SELECTED_CLASS_INDIGO);
});
});
describe('with a theme specified', () => {
beforeEach(() => {
wrapper = createComponent({ theme: 'green' });
});
it('sets the correct theme', () => {
expect(pathItemAt(0).classList).toContain(SELECTED_CLASS_GREEN);
});
});
});
describe('background color selection', () => {
describe('with no background color specified', () => {
it('displays the default background color', () => {
expect(pathNav().style.getPropertyValue('--path-bg-color')).toBe(BACKGROUND_COLOR_WHITE);
});
});
describe('with a background color specified', () => {
beforeEach(() => {
wrapper = createComponent({ backgroundColor: BACKGROUND_COLOR_LIGHT_GRAY });
});
it('sets the correct background color', () => {
expect(pathNav().style.getPropertyValue('--path-bg-color')).toBe(
BACKGROUND_COLOR_LIGHT_GRAY
);
});
});
});
describe('renders the list of items', () => {
it('renders the correct number of items', () => {
expect(listItems().length).toBe(mockPathItems.length);
});
it('renders the items in the correct order', () => {
expect(pathItemTextAt(0)).toContain(mockPathItems[0].title);
expect(pathItemTextAt(4)).toContain(mockPathItems[4].title);
expect(pathItemTextAt(9)).toContain(mockPathItems[9].title);
});
describe('with metrics', () => {
beforeEach(() => {
const data = mockPathItems;
data[0].metric = '12d';
wrapper = createComponent({ items: data });
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
it('renders the inline metric', () => {
expect(pathItemTextAt(0)).toContain(mockPathItems[0].title);
expect(pathItemTextAt(0)).toContain(mockPathItems[0].metric);
});
});
describe('with icons', () => {
const iconName = 'home';
beforeEach(() => {
const data = mockPathItems;
data[0].icon = iconName;
wrapper = createComponent({ items: data });
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
it('renders the inline icon', () => {
const icon = wrapper.find('[data-testid="gl-path-item-icon"]');
expect(icon.exists()).toBe(true);
expect(icon.props('name')).toBe(iconName);
});
});
});
describe('renders the correct selected item', () => {
describe('with no selected item passed in', () => {
it('selects the first item', () => {
expect(pathItemAt(0).classList).toContain(SELECTED_CLASS_INDIGO);
});
});
describe('with a specifically selected item passed in', () => {
beforeEach(() => {
const data = mockPathItems;
data[3].selected = true;
wrapper = createComponent({ items: data });
});
it('selects the correct item', () => {
expect(pathItemAt(3).classList).toContain(SELECTED_CLASS_INDIGO);
});
});
describe('with multiple selected items passed in', () => {
beforeEach(() => {
const data = mockPathItems;
data[3].selected = true;
data[5].selected = true;
wrapper = createComponent({ items: data });
});
it('selects the first selected option', () => {
expect(pathItemAt(3).classList).toContain(SELECTED_CLASS_INDIGO);
expect(pathItemAt(5).classList).not.toContain(SELECTED_CLASS_INDIGO);
});
});
});
describe('event handling', () => {
describe('when an item is clicked', () => {
it('emits the selected event with the correct data', () => {
clickItemAt(1);
clickItemAt(4);
clickItemAt(6);
expect(wrapper.emitted('selected')).toEqual([
[mockPathItems[1]],
[mockPathItems[4]],
[mockPathItems[6]],
]);
});
});
});
describe('slots', () => {
beforeEach(() => {
wrapper = createComponent(null, {
scopedSlots: {
default: `
<div
:data-pathid="props.pathId"
data-testid="path-item-slot-content">
{{ props.pathItem.title }}
</div>
`,
},
});
});
it('contains all elements passed into the default slot', () => {
mockPathItems.forEach((item, index) => {
const pathItem = wrapper.findAll('[data-testid="path-item-slot-content"]').at(index);
expect(pathItem.text()).toBe(item.title);
expect(pathItem.attributes('data-pathid')).toContain('path-');
});
});
});
});