spec/frontend/todos/components/todo_item_body_spec.js (133 lines of code) (raw):
import { shallowMount } from '@vue/test-utils';
import { GlLink, GlAvatar, GlAvatarLink } from '@gitlab/ui';
import TodoItemBody from '~/todos/components/todo_item_body.vue';
import {
TODO_ACTION_TYPE_ADDED_APPROVER,
TODO_ACTION_TYPE_APPROVAL_REQUIRED,
TODO_ACTION_TYPE_ASSIGNED,
TODO_ACTION_TYPE_BUILD_FAILED,
TODO_ACTION_TYPE_DIRECTLY_ADDRESSED,
TODO_ACTION_TYPE_MARKED,
TODO_ACTION_TYPE_MEMBER_ACCESS_REQUESTED,
TODO_ACTION_TYPE_MENTIONED,
TODO_ACTION_TYPE_MERGE_TRAIN_REMOVED,
TODO_ACTION_TYPE_OKR_CHECKIN_REQUESTED,
TODO_ACTION_TYPE_REVIEW_REQUESTED,
TODO_ACTION_TYPE_REVIEW_SUBMITTED,
TODO_ACTION_TYPE_UNMERGEABLE,
TODO_ACTION_TYPE_SSH_KEY_EXPIRED,
TODO_ACTION_TYPE_SSH_KEY_EXPIRING_SOON,
TODO_ACTION_TYPE_DUO_PRO_ACCESS_GRANTED,
TODO_ACTION_TYPE_DUO_ENTERPRISE_ACCESS_GRANTED,
TODO_ACTION_TYPE_DUO_CORE_ACCESS_GRANTED,
} from '~/todos/constants';
import { SAML_HIDDEN_TODO } from '../mock_data';
describe('TodoItemBody', () => {
let wrapper;
const createComponent = (todoExtras = {}, otherProps = {}) => {
wrapper = shallowMount(TodoItemBody, {
propsData: {
currentUserId: '1',
todo: {
author: {
id: '2',
name: 'John Doe',
webUrl: '/john',
avatarUrl: '/avatar.png',
},
action: TODO_ACTION_TYPE_ASSIGNED,
targetEntity: {
name: 'Foo',
},
...todoExtras,
},
isHiddenBySaml: false,
...otherProps,
},
});
};
it('renders author avatar', () => {
createComponent();
expect(wrapper.findComponent(GlAvatarLink).exists()).toBe(true);
expect(wrapper.findComponent(GlAvatar).props('src')).toBe('/avatar.png');
});
it('renders author name with link', () => {
createComponent();
const authorLink = wrapper.findComponent(GlLink);
expect(authorLink.text()).toBe('John Doe');
expect(authorLink.attributes('href')).toBe('/john');
});
describe('correct text for actionName', () => {
it.each`
actionName | text | showsAuthor
${TODO_ACTION_TYPE_ADDED_APPROVER} | ${'created a merge request you can approve.'} | ${true}
${TODO_ACTION_TYPE_APPROVAL_REQUIRED} | ${'created a merge request you can approve.'} | ${true}
${TODO_ACTION_TYPE_ASSIGNED} | ${'assigned you.'} | ${true}
${TODO_ACTION_TYPE_BUILD_FAILED} | ${'The pipeline failed.'} | ${false}
${TODO_ACTION_TYPE_DIRECTLY_ADDRESSED} | ${'mentioned you.'} | ${true}
${TODO_ACTION_TYPE_MARKED} | ${'added a to-do item'} | ${true}
${TODO_ACTION_TYPE_MEMBER_ACCESS_REQUESTED} | ${'has requested access to group Foo'} | ${true}
${TODO_ACTION_TYPE_MENTIONED} | ${'mentioned you.'} | ${true}
${TODO_ACTION_TYPE_MERGE_TRAIN_REMOVED} | ${'Removed from Merge Train.'} | ${false}
${TODO_ACTION_TYPE_OKR_CHECKIN_REQUESTED} | ${'requested an OKR update for Foo'} | ${true}
${TODO_ACTION_TYPE_REVIEW_REQUESTED} | ${'requested a review.'} | ${true}
${TODO_ACTION_TYPE_REVIEW_SUBMITTED} | ${'reviewed your merge request.'} | ${true}
${TODO_ACTION_TYPE_UNMERGEABLE} | ${'Could not merge.'} | ${false}
${TODO_ACTION_TYPE_SSH_KEY_EXPIRED} | ${'Your SSH key has expired.'} | ${false}
${TODO_ACTION_TYPE_SSH_KEY_EXPIRING_SOON} | ${'Your SSH key is expiring soon.'} | ${false}
${TODO_ACTION_TYPE_DUO_PRO_ACCESS_GRANTED} | ${'You now have access to AI-native features. Learn how to set up Code Suggestions and Chat in your IDE.'} | ${false}
${TODO_ACTION_TYPE_DUO_ENTERPRISE_ACCESS_GRANTED} | ${'You now have access to AI-native features. Learn how to set up Code Suggestions and Chat in your IDE.'} | ${false}
${TODO_ACTION_TYPE_DUO_CORE_ACCESS_GRANTED} | ${'You now have access to AI-native features. Learn how to set up Code Suggestions and Chat in your IDE.'} | ${false}
`('renders "$text" for the "$actionName" action', ({ actionName, text, showsAuthor }) => {
createComponent({ action: actionName, memberAccessType: 'group' });
expect(wrapper.text()).toContain(text);
expect(wrapper.text().includes('John Doe')).toBe(showsAuthor);
});
});
describe('when todo is hidden by SAML', () => {
it('hides the author as "Someone" with a link to the todo', () => {
createComponent({}, { todo: SAML_HIDDEN_TODO, isHiddenBySaml: true });
const authorLink = wrapper.findComponent(GlLink);
expect(authorLink.text()).toBe('Someone');
expect(authorLink.attributes('href')).toBe(SAML_HIDDEN_TODO.targetUrl);
expect(wrapper.findComponent(GlAvatarLink).attributes('href')).toBe(
SAML_HIDDEN_TODO.targetUrl,
);
expect(wrapper.findComponent(GlAvatar).props('src')).toBe(gon.default_avatar_url);
});
});
it.each([
TODO_ACTION_TYPE_DUO_ENTERPRISE_ACCESS_GRANTED,
TODO_ACTION_TYPE_DUO_PRO_ACCESS_GRANTED,
TODO_ACTION_TYPE_DUO_CORE_ACCESS_GRANTED,
])('when todo action is `%s`, avatar is not shown', (action) => {
createComponent({ action });
expect(wrapper.findComponent(GlAvatarLink).exists()).toBe(false);
});
describe('when todo has a note', () => {
it('renders note text', () => {
createComponent({ note: { bodyFirstLineHtml: '<p>This is a note</p>' } });
expect(wrapper.html()).toContain('<span>This is a note</span>');
});
it('does not render actionName', () => {
createComponent({ note: { bodyFirstLineHtml: '<p>This is a note</p>' } });
expect(wrapper.vm.actionName).toBeNull();
});
});
describe('when current user is the author', () => {
it('renders "You" instead of author name', () => {
createComponent({ author: { id: '2' } }, { currentUserId: '2' });
expect(wrapper.text()).toContain('You');
});
it('renders correct text for self-assigned action', () => {
createComponent(
{
author: { id: '2' },
action: TODO_ACTION_TYPE_ASSIGNED,
},
{ currentUserId: '2' },
);
expect(wrapper.text()).toContain('assigned to yourself.');
});
});
});