debian-mirror-gitlab/spec/frontend/design_management/components/design_overlay_spec.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

360 lines
11 KiB
JavaScript
Raw Normal View History

2023-04-23 21:23:45 +05:30
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
2020-05-24 23:13:21 +05:30
import DesignOverlay from '~/design_management/components/design_overlay.vue';
2023-04-23 21:23:45 +05:30
import { resolvers } from '~/design_management/graphql';
import activeDiscussionQuery from '~/design_management/graphql/queries/active_discussion.query.graphql';
2020-05-24 23:13:21 +05:30
import notes from '../mock_data/notes';
2023-04-23 21:23:45 +05:30
Vue.use(VueApollo);
2020-05-24 23:13:21 +05:30
describe('Design overlay component', () => {
let wrapper;
2023-04-23 21:23:45 +05:30
let apolloProvider;
2020-05-24 23:13:21 +05:30
const mockDimensions = { width: 100, height: 100 };
2023-04-23 21:23:45 +05:30
const findOverlay = () => wrapper.find('[data-testid="design-overlay"]');
const findAllNotes = () => wrapper.findAll('[data-testid="note-pin"]');
const findCommentBadge = () => wrapper.find('[data-testid="comment-badge"]');
2021-03-08 18:12:59 +05:30
const findBadgeAtIndex = (noteIndex) => findAllNotes().at(noteIndex);
2020-11-24 15:15:51 +05:30
const findFirstBadge = () => findBadgeAtIndex(0);
const findSecondBadge = () => findBadgeAtIndex(1);
2020-05-24 23:13:21 +05:30
2022-04-04 11:22:00 +05:30
const clickAndDragBadge = async (elem, fromPoint, toPoint) => {
2023-04-23 21:23:45 +05:30
elem.vm.$emit(
'mousedown',
new MouseEvent('click', { clientX: fromPoint.x, clientY: fromPoint.y }),
);
findOverlay().trigger('mousemove', { clientX: toPoint.x, clientY: toPoint.y });
2022-04-04 11:22:00 +05:30
await nextTick();
2023-04-23 21:23:45 +05:30
elem.vm.$emit('mouseup', new MouseEvent('click', { clientX: toPoint.x, clientY: toPoint.y }));
2022-04-04 11:22:00 +05:30
await nextTick();
2020-05-24 23:13:21 +05:30
};
function createComponent(props = {}, data = {}) {
2023-04-23 21:23:45 +05:30
apolloProvider = createMockApollo([], resolvers);
apolloProvider.clients.defaultClient.writeQuery({
query: activeDiscussionQuery,
data: {
activeDiscussion: {
__typename: 'ActiveDiscussion',
id: null,
source: null,
},
},
});
wrapper = shallowMount(DesignOverlay, {
apolloProvider,
2020-05-24 23:13:21 +05:30
propsData: {
dimensions: mockDimensions,
position: {
top: '0',
left: '0',
},
2020-06-23 00:09:42 +05:30
resolvedDiscussionsExpanded: false,
2020-05-24 23:13:21 +05:30
...props,
},
data() {
return {
activeDiscussion: {
id: null,
source: null,
},
...data,
};
},
});
}
2023-04-23 21:23:45 +05:30
afterEach(() => {
apolloProvider = null;
});
2020-05-24 23:13:21 +05:30
it('should have correct inline style', () => {
createComponent();
2020-11-24 15:15:51 +05:30
expect(wrapper.attributes().style).toBe('width: 100px; height: 100px; top: 0px; left: 0px;');
2020-05-24 23:13:21 +05:30
});
2022-04-04 11:22:00 +05:30
it('should emit `openCommentForm` when clicking on overlay', async () => {
2020-05-24 23:13:21 +05:30
createComponent();
const newCoordinates = {
x: 10,
y: 10,
};
wrapper
2020-11-24 15:15:51 +05:30
.find('[data-qa-selector="design_image_button"]')
2020-05-24 23:13:21 +05:30
.trigger('mouseup', { offsetX: newCoordinates.x, offsetY: newCoordinates.y });
2022-04-04 11:22:00 +05:30
await nextTick();
expect(wrapper.emitted('openCommentForm')).toEqual([
[{ x: newCoordinates.x, y: newCoordinates.y }],
]);
2020-05-24 23:13:21 +05:30
});
describe('with notes', () => {
2020-06-23 00:09:42 +05:30
it('should render only the first note', () => {
2020-05-24 23:13:21 +05:30
createComponent({
notes,
});
2020-06-23 00:09:42 +05:30
expect(findAllNotes()).toHaveLength(1);
2020-05-24 23:13:21 +05:30
});
2020-06-23 00:09:42 +05:30
describe('with resolved discussions toggle expanded', () => {
beforeEach(() => {
createComponent({
notes,
resolvedDiscussionsExpanded: true,
});
});
it('should render all notes', () => {
expect(findAllNotes()).toHaveLength(notes.length);
});
it('should have set the correct position for each note badge', () => {
2023-04-23 21:23:45 +05:30
expect(findFirstBadge().props('position')).toEqual({
left: '10px',
top: '15px',
});
expect(findSecondBadge().props('position')).toEqual({ left: '50px', top: '50px' });
2020-06-23 00:09:42 +05:30
});
it('should apply resolved class to the resolved note pin', () => {
2023-04-23 21:23:45 +05:30
expect(findSecondBadge().props('isResolved')).toBe(true);
2020-06-23 00:09:42 +05:30
});
2020-11-24 15:15:51 +05:30
describe('when no discussion is active', () => {
it('should not apply inactive class to any pins', () => {
expect(
2021-03-08 18:12:59 +05:30
findAllNotes(0).wrappers.every((designNote) => designNote.classes('gl-bg-blue-50')),
2020-11-24 15:15:51 +05:30
).toBe(false);
2020-06-23 00:09:42 +05:30
});
2020-11-24 15:15:51 +05:30
});
describe('when a discussion is active', () => {
it.each([notes[0].discussion.notes.nodes[1], notes[0].discussion.notes.nodes[0]])(
'should not apply inactive class to the pin for the active discussion',
2022-04-04 11:22:00 +05:30
async (note) => {
2023-04-23 21:23:45 +05:30
apolloProvider.clients.defaultClient.writeQuery({
query: activeDiscussionQuery,
data: {
activeDiscussion: {
__typename: 'ActiveDiscussion',
id: note.id,
source: 'discussion',
},
2020-11-24 15:15:51 +05:30
},
});
2020-05-24 23:13:21 +05:30
2022-04-04 11:22:00 +05:30
await nextTick();
2023-04-23 21:23:45 +05:30
expect(findBadgeAtIndex(0).props('isInactive')).toBe(false);
2020-11-24 15:15:51 +05:30
},
);
2022-04-04 11:22:00 +05:30
it('should apply inactive class to all pins besides the active one', async () => {
2023-04-23 21:23:45 +05:30
apolloProvider.clients.defaultClient.writeQuery({
query: activeDiscussionQuery,
data: {
activeDiscussion: {
__typename: 'ActiveDiscussion',
id: notes[0].id,
source: 'discussion',
},
2020-11-24 15:15:51 +05:30
},
});
2022-04-04 11:22:00 +05:30
await nextTick();
2023-04-23 21:23:45 +05:30
expect(findSecondBadge().props('isInactive')).toBe(true);
expect(findFirstBadge().props('isInactive')).toBe(false);
2020-06-23 00:09:42 +05:30
});
});
2020-05-24 23:13:21 +05:30
});
2022-04-04 11:22:00 +05:30
it('should recalculate badges positions on window resize', async () => {
2020-05-24 23:13:21 +05:30
createComponent({
notes,
dimensions: {
width: 400,
height: 400,
},
});
2023-04-23 21:23:45 +05:30
expect(findFirstBadge().props('position')).toEqual({ left: '40px', top: '60px' });
2020-05-24 23:13:21 +05:30
wrapper.setProps({
dimensions: {
width: 200,
height: 200,
},
});
2022-04-04 11:22:00 +05:30
await nextTick();
2023-04-23 21:23:45 +05:30
expect(findFirstBadge().props('position')).toEqual({ left: '20px', top: '30px' });
2020-05-24 23:13:21 +05:30
});
2023-04-23 21:23:45 +05:30
it('should update active discussion when clicking a note without moving it', async () => {
2022-11-25 23:54:43 +05:30
createComponent({
notes,
dimensions: {
width: 400,
height: 400,
},
});
2023-04-23 21:23:45 +05:30
expect(findFirstBadge().props('isInactive')).toBe(null);
2020-05-24 23:13:21 +05:30
const note = notes[0];
const { position } = note;
2023-04-23 21:23:45 +05:30
findFirstBadge().vm.$emit(
'mousedown',
new MouseEvent('click', { clientX: position.x, clientY: position.y }),
);
2020-05-24 23:13:21 +05:30
2022-04-04 11:22:00 +05:30
await nextTick();
2023-04-23 21:23:45 +05:30
findFirstBadge().vm.$emit(
'mouseup',
new MouseEvent('click', { clientX: position.x, clientY: position.y }),
);
await waitForPromises();
expect(findFirstBadge().props('isInactive')).toBe(false);
2020-05-24 23:13:21 +05:30
});
});
describe('when moving notes', () => {
2022-04-04 11:22:00 +05:30
it('should emit `moveNote` event when note-moving action ends', async () => {
2020-05-24 23:13:21 +05:30
createComponent({ notes });
const note = notes[0];
const { position } = note;
const newCoordinates = { x: 20, y: 20 };
const badge = findFirstBadge();
2022-04-04 11:22:00 +05:30
await clickAndDragBadge(badge, { x: position.x, y: position.y }, newCoordinates);
expect(wrapper.emitted('moveNote')).toEqual([
[
{
noteId: notes[0].id,
discussionId: notes[0].discussion.id,
coordinates: newCoordinates,
},
],
]);
2020-05-24 23:13:21 +05:30
});
2021-01-29 00:20:46 +05:30
describe('without [repositionNote] permission', () => {
2020-06-23 00:09:42 +05:30
const mockNoteNotAuthorised = {
...notes[0],
userPermissions: {
2021-01-29 00:20:46 +05:30
repositionNote: false,
2020-06-23 00:09:42 +05:30
},
};
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
const mockNoteCoordinates = {
x: mockNoteNotAuthorised.position.x,
y: mockNoteNotAuthorised.position.y,
};
2022-04-04 11:22:00 +05:30
it('should be unable to move a note', async () => {
2020-06-23 00:09:42 +05:30
createComponent({
dimensions: mockDimensions,
notes: [mockNoteNotAuthorised],
});
const badge = findAllNotes().at(0);
2022-04-04 11:22:00 +05:30
await clickAndDragBadge(badge, { ...mockNoteCoordinates }, { x: 20, y: 20 });
// note position should not change after a click-and-drag attempt
2023-04-23 21:23:45 +05:30
expect(findFirstBadge().props('position')).toEqual({
left: `${mockNoteCoordinates.x}px`,
top: `${mockNoteCoordinates.y}px`,
});
2020-05-24 23:13:21 +05:30
});
});
});
describe('with a new form', () => {
it('should render a new comment badge', () => {
createComponent({
currentCommentForm: {
...notes[0].position,
},
});
expect(findCommentBadge().exists()).toBe(true);
2023-04-23 21:23:45 +05:30
expect(findCommentBadge().props('position')).toEqual({ left: '10px', top: '15px' });
2020-05-24 23:13:21 +05:30
});
describe('when moving the comment badge', () => {
2022-04-04 11:22:00 +05:30
it('should update badge style when note-moving action ends', async () => {
2020-05-24 23:13:21 +05:30
const { position } = notes[0];
createComponent({
currentCommentForm: {
...position,
},
});
const commentBadge = findCommentBadge();
const toPoint = { x: 20, y: 20 };
2022-04-04 11:22:00 +05:30
await clickAndDragBadge(commentBadge, { x: position.x, y: position.y }, toPoint);
2023-04-23 21:23:45 +05:30
commentBadge.vm.$emit('mouseup', new MouseEvent('click'));
2022-04-04 11:22:00 +05:30
// simulates the currentCommentForm being updated in index.vue component, and
// propagated back down to this prop
wrapper.setProps({
currentCommentForm: { height: position.height, width: position.width, ...toPoint },
});
await nextTick();
2023-04-23 21:23:45 +05:30
expect(commentBadge.props('position')).toEqual({ left: '20px', top: '20px' });
2020-05-24 23:13:21 +05:30
});
2023-04-23 21:23:45 +05:30
it('should emit `openCommentForm` event when mouseleave fired on overlay element', async () => {
const { position } = notes[0];
createComponent({
notes,
currentCommentForm: {
...position,
},
});
2020-05-24 23:13:21 +05:30
2023-04-23 21:23:45 +05:30
const newCoordinates = { x: 20, y: 20 };
2020-05-24 23:13:21 +05:30
2023-04-23 21:23:45 +05:30
await clickAndDragBadge(
findCommentBadge(),
{ x: position.x, y: position.y },
newCoordinates,
);
2020-05-24 23:13:21 +05:30
2023-04-23 21:23:45 +05:30
wrapper.trigger('mouseleave');
await nextTick();
expect(wrapper.emitted('openCommentForm')).toEqual([[newCoordinates]]);
2020-05-24 23:13:21 +05:30
});
2023-04-23 21:23:45 +05:30
it('should emit `openCommentForm` event when mouseup fired on comment badge element', async () => {
const { position } = notes[0];
createComponent({
notes,
currentCommentForm: {
...position,
},
});
2020-05-24 23:13:21 +05:30
2023-04-23 21:23:45 +05:30
const newCoordinates = { x: 20, y: 20 };
2020-05-24 23:13:21 +05:30
2023-04-23 21:23:45 +05:30
await clickAndDragBadge(
findCommentBadge(),
{ x: position.x, y: position.y },
newCoordinates,
);
2020-05-24 23:13:21 +05:30
2023-04-23 21:23:45 +05:30
expect(wrapper.emitted('openCommentForm')).toEqual([[newCoordinates]]);
});
2020-05-24 23:13:21 +05:30
});
});
});