diff options
Diffstat (limited to 'spec/frontend/vue_shared')
3 files changed, 408 insertions, 0 deletions
diff --git a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js new file mode 100644 index 00000000000..4b7636041b6 --- /dev/null +++ b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js @@ -0,0 +1,151 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import Vuex from 'vuex'; +import { GlModal } from '@gitlab/ui'; +import GlModalVuex from '~/vue_shared/components/gl_modal_vuex.vue'; +import createState from '~/vuex_shared/modules/modal/state'; + +const localVue = createLocalVue(); +localVue.use(Vuex); + +const TEST_SLOT = 'Lorem ipsum modal dolar sit.'; +const TEST_MODAL_ID = 'my-modal-id'; +const TEST_MODULE = 'myModal'; + +describe('GlModalVuex', () => { + let wrapper; + let state; + let actions; + + const factory = (options = {}) => { + const store = new Vuex.Store({ + modules: { + [TEST_MODULE]: { + namespaced: true, + state, + actions, + }, + }, + }); + + const propsData = { + modalId: TEST_MODAL_ID, + modalModule: TEST_MODULE, + ...options.propsData, + }; + + wrapper = shallowMount(localVue.extend(GlModalVuex), { + ...options, + localVue, + store, + propsData, + }); + }; + + beforeEach(() => { + state = createState(); + + actions = { + show: jest.fn(), + hide: jest.fn(), + }; + }); + + it('renders gl-modal', () => { + factory({ + slots: { + default: `<div>${TEST_SLOT}</div>`, + }, + }); + const glModal = wrapper.find(GlModal); + + expect(glModal.props('modalId')).toBe(TEST_MODAL_ID); + expect(glModal.text()).toContain(TEST_SLOT); + }); + + it('passes props through to gl-modal', () => { + const title = 'Test Title'; + const okVariant = 'success'; + + factory({ + propsData: { + title, + okTitle: title, + okVariant, + }, + }); + const glModal = wrapper.find(GlModal); + + expect(glModal.attributes('title')).toEqual(title); + expect(glModal.attributes('oktitle')).toEqual(title); + expect(glModal.attributes('okvariant')).toEqual(okVariant); + }); + + it('passes listeners through to gl-modal', () => { + const ok = jest.fn(); + + factory({ + listeners: { ok }, + }); + + const glModal = wrapper.find(GlModal); + glModal.vm.$emit('ok'); + + expect(ok).toHaveBeenCalledTimes(1); + }); + + it('calls vuex action on show', () => { + expect(actions.show).not.toHaveBeenCalled(); + + factory(); + + const glModal = wrapper.find(GlModal); + glModal.vm.$emit('shown'); + + expect(actions.show).toHaveBeenCalledTimes(1); + }); + + it('calls vuex action on hide', () => { + expect(actions.hide).not.toHaveBeenCalled(); + + factory(); + + const glModal = wrapper.find(GlModal); + glModal.vm.$emit('hidden'); + + expect(actions.hide).toHaveBeenCalledTimes(1); + }); + + it('calls bootstrap show when isVisible changes', done => { + state.isVisible = false; + + factory(); + const rootEmit = jest.spyOn(wrapper.vm.$root, '$emit'); + + state.isVisible = true; + + localVue + .nextTick() + .then(() => { + expect(rootEmit).toHaveBeenCalledWith('bv::show::modal', TEST_MODAL_ID); + }) + .then(done) + .catch(done.fail); + }); + + it('calls bootstrap hide when isVisible changes', done => { + state.isVisible = true; + + factory(); + const rootEmit = jest.spyOn(wrapper.vm.$root, '$emit'); + + state.isVisible = false; + + localVue + .nextTick() + .then(() => { + expect(rootEmit).toHaveBeenCalledWith('bv::hide::modal', TEST_MODAL_ID); + }) + .then(done) + .catch(done.fail); + }); +}); diff --git a/spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js b/spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js new file mode 100644 index 00000000000..3c5e7500ba7 --- /dev/null +++ b/spec/frontend/vue_shared/components/markdown/suggestion_diff_spec.js @@ -0,0 +1,101 @@ +import Vue from 'vue'; +import SuggestionDiffComponent from '~/vue_shared/components/markdown/suggestion_diff.vue'; +import { selectDiffLines } from '~/vue_shared/components/lib/utils/diff_utils'; + +const MOCK_DATA = { + canApply: true, + suggestion: { + id: 1, + diff_lines: [ + { + can_receive_suggestion: false, + line_code: null, + meta_data: null, + new_line: null, + old_line: 5, + rich_text: '-test', + text: '-test', + type: 'old', + }, + { + can_receive_suggestion: true, + line_code: null, + meta_data: null, + new_line: 5, + old_line: null, + rich_text: '+new test', + text: '+new test', + type: 'new', + }, + { + can_receive_suggestion: true, + line_code: null, + meta_data: null, + new_line: 5, + old_line: null, + rich_text: '+new test2', + text: '+new test2', + type: 'new', + }, + ], + }, + helpPagePath: 'path_to_docs', +}; + +const lines = selectDiffLines(MOCK_DATA.suggestion.diff_lines); +const newLines = lines.filter(line => line.type === 'new'); + +describe('Suggestion Diff component', () => { + let vm; + + beforeEach(done => { + const Component = Vue.extend(SuggestionDiffComponent); + + vm = new Component({ + propsData: MOCK_DATA, + }).$mount(); + + Vue.nextTick(done); + }); + + describe('init', () => { + it('renders a suggestion header', () => { + expect(vm.$el.querySelector('.js-suggestion-diff-header')).not.toBeNull(); + }); + + it('renders a diff table with syntax highlighting', () => { + expect(vm.$el.querySelector('.md-suggestion-diff.js-syntax-highlight.code')).not.toBeNull(); + }); + + it('renders the oldLineNumber', () => { + const fromLine = vm.$el.querySelector('.old_line').innerHTML; + + expect(parseInt(fromLine, 10)).toBe(lines[0].old_line); + }); + + it('renders the oldLineContent', () => { + const fromContent = vm.$el.querySelector('.line_content.old').innerHTML; + + expect(fromContent.includes(lines[0].text)).toBe(true); + }); + + it('renders new lines', () => { + const newLinesElements = vm.$el.querySelectorAll('.line_holder.new'); + + newLinesElements.forEach((line, i) => { + expect(newLinesElements[i].innerHTML.includes(newLines[i].new_line)).toBe(true); + expect(newLinesElements[i].innerHTML.includes(newLines[i].text)).toBe(true); + }); + }); + }); + + describe('applySuggestion', () => { + it('emits apply event when applySuggestion is called', () => { + const callback = () => {}; + jest.spyOn(vm, '$emit').mockImplementation(() => {}); + vm.applySuggestion(callback); + + expect(vm.$emit).toHaveBeenCalledWith('apply', { suggestionId: vm.suggestion.id, callback }); + }); + }); +}); diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js new file mode 100644 index 00000000000..9f0cdc651b6 --- /dev/null +++ b/spec/frontend/vue_shared/components/user_avatar/user_avatar_list_spec.js @@ -0,0 +1,156 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import { GlButton } from '@gitlab/ui'; +import { TEST_HOST } from 'spec/test_constants'; +import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue'; +import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; + +const TEST_IMAGE_SIZE = 7; +const TEST_BREAKPOINT = 5; +const TEST_EMPTY_MESSAGE = 'Lorem ipsum empty'; +const DEFAULT_EMPTY_MESSAGE = 'None'; + +const createUser = id => ({ + id, + name: 'Lorem', + web_url: `${TEST_HOST}/${id}`, + avatar_url: `${TEST_HOST}/${id}/avatar`, +}); +const createList = n => + Array(n) + .fill(1) + .map((x, id) => createUser(id)); + +const localVue = createLocalVue(); + +describe('UserAvatarList', () => { + let props; + let wrapper; + + const factory = (options = {}) => { + const propsData = { + ...props, + ...options.propsData, + }; + + wrapper = shallowMount(localVue.extend(UserAvatarList), { + ...options, + localVue, + propsData, + }); + }; + + const clickButton = () => { + const button = wrapper.find(GlButton); + button.vm.$emit('click'); + }; + + beforeEach(() => { + props = { imgSize: TEST_IMAGE_SIZE }; + }); + + afterEach(() => { + wrapper.destroy(); + }); + + describe('empty text', () => { + it('shows when items are empty', () => { + factory({ propsData: { items: [] } }); + + expect(wrapper.text()).toContain(DEFAULT_EMPTY_MESSAGE); + }); + + it('does not show when items are not empty', () => { + factory({ propsData: { items: createList(1) } }); + + expect(wrapper.text()).not.toContain(DEFAULT_EMPTY_MESSAGE); + }); + + it('can be set in props', () => { + factory({ propsData: { items: [], emptyText: TEST_EMPTY_MESSAGE } }); + + expect(wrapper.text()).toContain(TEST_EMPTY_MESSAGE); + }); + }); + + describe('with no breakpoint', () => { + beforeEach(() => { + props.breakpoint = 0; + }); + + it('renders avatars', () => { + const items = createList(20); + factory({ propsData: { items } }); + + const links = wrapper.findAll(UserAvatarLink); + const linkProps = links.wrappers.map(x => x.props()); + + expect(linkProps).toEqual( + items.map(x => + expect.objectContaining({ + linkHref: x.web_url, + imgSrc: x.avatar_url, + imgAlt: x.name, + tooltipText: x.name, + imgSize: TEST_IMAGE_SIZE, + }), + ), + ); + }); + }); + + describe('with breakpoint and length equal to breakpoint', () => { + beforeEach(() => { + props.breakpoint = TEST_BREAKPOINT; + props.items = createList(TEST_BREAKPOINT); + }); + + it('renders all avatars if length is <= breakpoint', () => { + factory(); + + const links = wrapper.findAll(UserAvatarLink); + + expect(links.length).toEqual(props.items.length); + }); + + it('does not show button', () => { + factory(); + + expect(wrapper.find(GlButton).exists()).toBe(false); + }); + }); + + describe('with breakpoint and length greater than breakpoint', () => { + beforeEach(() => { + props.breakpoint = TEST_BREAKPOINT; + props.items = createList(TEST_BREAKPOINT + 1); + }); + + it('renders avatars up to breakpoint', () => { + factory(); + + const links = wrapper.findAll(UserAvatarLink); + + expect(links.length).toEqual(TEST_BREAKPOINT); + }); + + describe('with expand clicked', () => { + beforeEach(() => { + factory(); + clickButton(); + }); + + it('renders all avatars', () => { + const links = wrapper.findAll(UserAvatarLink); + + expect(links.length).toEqual(props.items.length); + }); + + it('with collapse clicked, it renders avatars up to breakpoint', () => { + clickButton(); + const links = wrapper.findAll(UserAvatarLink); + + expect(links.length).toEqual(TEST_BREAKPOINT); + }); + }); + }); +}); |