import { GlButton } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import mockProjects from 'test_fixtures_static/projects.json';
import { trimText } from 'helpers/text_helper';
import ProjectAvatar from '~/vue_shared/components/project_avatar.vue';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
describe('ProjectListItem component', () => {
let wrapper;
const project = JSON.parse(JSON.stringify(mockProjects))[0];
const createWrapper = ({ propsData } = {}) => {
wrapper = shallowMountExtended(ProjectListItem, {
propsData: {
project,
selected: false,
...propsData,
},
});
};
const findProjectNamespace = () => wrapper.findByTestId('project-namespace');
const findProjectName = () => wrapper.findByTestId('project-name');
it.each([true, false])('renders a checkmark correctly when selected === "%s"', (selected) => {
createWrapper({
propsData: {
selected,
},
});
expect(wrapper.findByTestId('selected-icon').exists()).toBe(selected);
});
it(`emits a "clicked" event when the button is clicked`, () => {
createWrapper();
expect(wrapper.emitted('click')).toBeUndefined();
wrapper.findComponent(GlButton).vm.$emit('click');
expect(wrapper.emitted('click')).toHaveLength(1);
});
it(`renders the project avatar`, () => {
createWrapper();
const avatar = wrapper.findComponent(ProjectAvatar);
expect(avatar.exists()).toBe(true);
expect(avatar.props()).toMatchObject({
projectId: project.id,
projectAvatarUrl: '',
projectName: project.name_with_namespace,
});
});
it(`renders a simple namespace name with a trailing slash`, () => {
createWrapper({
propsData: {
project: {
...project,
name_with_namespace: 'a / b',
},
},
});
const renderedNamespace = trimText(findProjectNamespace().text());
expect(renderedNamespace).toBe('a /');
});
it(`renders a properly truncated namespace with a trailing slash`, () => {
createWrapper({
propsData: {
project: {
...project,
name_with_namespace: 'a / b / c / d / e / f',
},
},
});
const renderedNamespace = trimText(findProjectNamespace().text());
expect(renderedNamespace).toBe('a / ... / e /');
});
it(`renders a simple namespace name of a GraphQL project`, () => {
createWrapper({
propsData: {
project: {
...project,
name_with_namespace: undefined,
nameWithNamespace: 'test',
},
},
});
const renderedNamespace = trimText(findProjectNamespace().text());
expect(renderedNamespace).toBe('test /');
});
it(`renders the project name`, () => {
createWrapper({
propsData: {
project: {
...project,
name: 'my-test-project',
},
},
});
const renderedName = trimText(findProjectName().text());
expect(renderedName).toBe('my-test-project');
});
it(`renders the project name with highlighting in the case of a search query match`, () => {
createWrapper({
propsData: {
project: {
...project,
name: 'my-test-project',
},
matcher: 'pro',
},
});
const renderedName = trimText(findProjectName().html());
const expected = 'my-test-project';
expect(renderedName).toContain(expected);
});
it('prevents search query and project name XSS', () => {
const alertSpy = jest.spyOn(window, 'alert');
createWrapper({
propsData: {
project: {
...project,
name: "my-xss-project",
},
matcher: "pro",
},
});
const renderedName = trimText(findProjectName().html());
const expected = 'my-xss-project';
expect(renderedName).toContain(expected);
expect(alertSpy).not.toHaveBeenCalled();
});
});