diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-16 21:09:47 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-16 21:09:47 +0300 |
commit | bf1600d157465f9408aace91073954fd5790c054 (patch) | |
tree | f317bb99330769c4eb37621c860af014810e554b /spec/frontend | |
parent | 6de7d2c195a8a7fa5702cafa4365f7a9fcac37cd (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
4 files changed, 310 insertions, 52 deletions
diff --git a/spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap b/spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap index e1db42aeb0b..8711083ad8c 100644 --- a/spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap +++ b/spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap @@ -68,7 +68,7 @@ exports[`Design note component should match the snapshot 1`] = ` </div> <div - class="note-text js-note-text" + class="note-text js-note-text md" data-qa-selector="note_content" /> diff --git a/spec/frontend/repository/components/web_ide_link_spec.js b/spec/frontend/repository/components/web_ide_link_spec.js deleted file mode 100644 index 877756db364..00000000000 --- a/spec/frontend/repository/components/web_ide_link_spec.js +++ /dev/null @@ -1,51 +0,0 @@ -import { mount } from '@vue/test-utils'; -import WebIdeLink from '~/repository/components/web_ide_link.vue'; - -describe('Web IDE link component', () => { - let wrapper; - - function createComponent(props) { - wrapper = mount(WebIdeLink, { - propsData: { ...props }, - mocks: { - $route: { - params: {}, - }, - }, - }); - } - - afterEach(() => { - wrapper.destroy(); - }); - - it('renders link to the Web IDE for a project if only projectPath is given', () => { - createComponent({ projectPath: 'gitlab-org/gitlab', refSha: 'master' }); - - expect(wrapper.attributes('href')).toBe('/-/ide/project/gitlab-org/gitlab/edit/master/-/'); - expect(wrapper.text()).toBe('Web IDE'); - }); - - it('renders link to the Web IDE for a project even if both projectPath and forkPath are given', () => { - createComponent({ - projectPath: 'gitlab-org/gitlab', - refSha: 'master', - forkPath: 'my-namespace/gitlab', - }); - - expect(wrapper.attributes('href')).toBe('/-/ide/project/gitlab-org/gitlab/edit/master/-/'); - expect(wrapper.text()).toBe('Web IDE'); - }); - - it('renders link to the forked project if it exists and cannot write to the repo', () => { - createComponent({ - projectPath: 'gitlab-org/gitlab', - refSha: 'master', - forkPath: 'my-namespace/gitlab', - canPushCode: false, - }); - - expect(wrapper.attributes('href')).toBe('/-/ide/project/my-namespace/gitlab/edit/master/-/'); - expect(wrapper.text()).toBe('Edit fork in Web IDE'); - }); -}); diff --git a/spec/frontend/vue_shared/components/actions_button_spec.js b/spec/frontend/vue_shared/components/actions_button_spec.js new file mode 100644 index 00000000000..4dde9d726d1 --- /dev/null +++ b/spec/frontend/vue_shared/components/actions_button_spec.js @@ -0,0 +1,203 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlDropdown, GlLink } from '@gitlab/ui'; +import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; +import ActionsButton from '~/vue_shared/components/actions_button.vue'; + +const TEST_ACTION = { + key: 'action1', + text: 'Sample', + secondaryText: 'Lorem ipsum.', + tooltip: '', + href: '/sample', + attrs: { 'data-test': '123' }, +}; +const TEST_ACTION_2 = { + key: 'action2', + text: 'Sample 2', + secondaryText: 'Dolar sit amit.', + tooltip: 'Dolar sit amit.', + href: '#', + attrs: { 'data-test': '456' }, +}; +const TEST_TOOLTIP = 'Lorem ipsum dolar sit'; + +describe('Actions button component', () => { + let wrapper; + + function createComponent(props) { + wrapper = shallowMount(ActionsButton, { + propsData: { ...props }, + directives: { GlTooltip: createMockDirective() }, + }); + } + + afterEach(() => { + wrapper.destroy(); + }); + + const getTooltip = child => { + const directiveBinding = getBinding(child.element, 'gl-tooltip'); + + return directiveBinding.value; + }; + const findLink = () => wrapper.find(GlLink); + const findLinkTooltip = () => getTooltip(findLink()); + const findDropdown = () => wrapper.find(GlDropdown); + const findDropdownTooltip = () => getTooltip(findDropdown()); + const parseDropdownItems = () => + findDropdown() + .findAll('gl-dropdown-item-stub,gl-dropdown-divider-stub') + .wrappers.map(x => { + if (x.is('gl-dropdown-divider-stub')) { + return { type: 'divider' }; + } + + const { isCheckItem, isChecked, secondaryText } = x.props(); + + return { + type: 'item', + isCheckItem, + isChecked, + secondaryText, + text: x.text(), + }; + }); + const clickOn = (child, evt = new Event('click')) => child.vm.$emit('click', evt); + const clickLink = (...args) => clickOn(findLink(), ...args); + const clickDropdown = (...args) => clickOn(findDropdown(), ...args); + + describe('with 1 action', () => { + beforeEach(() => { + createComponent({ actions: [TEST_ACTION] }); + }); + + it('should not render dropdown', () => { + expect(findDropdown().exists()).toBe(false); + }); + + it('should render single button', () => { + const link = findLink(); + + expect(link.attributes()).toEqual({ + class: expect.any(String), + href: TEST_ACTION.href, + ...TEST_ACTION.attrs, + }); + expect(link.text()).toBe(TEST_ACTION.text); + }); + + it('should have tooltip', () => { + expect(findLinkTooltip()).toBe(TEST_ACTION.tooltip); + }); + + it('should have attrs', () => { + expect(findLink().attributes()).toMatchObject(TEST_ACTION.attrs); + }); + + it('can click', () => { + expect(clickLink).not.toThrow(); + }); + }); + + describe('with 1 action with tooltip', () => { + it('should have tooltip', () => { + createComponent({ actions: [{ ...TEST_ACTION, tooltip: TEST_TOOLTIP }] }); + + expect(findLinkTooltip()).toBe(TEST_TOOLTIP); + }); + }); + + describe('with 1 action with handle', () => { + it('can click and trigger handle', () => { + const handleClick = jest.fn(); + createComponent({ actions: [{ ...TEST_ACTION, handle: handleClick }] }); + + const event = new Event('click'); + clickLink(event); + + expect(handleClick).toHaveBeenCalledWith(event); + }); + }); + + describe('with multiple actions', () => { + let handleAction; + + beforeEach(() => { + handleAction = jest.fn(); + + createComponent({ actions: [{ ...TEST_ACTION, handle: handleAction }, TEST_ACTION_2] }); + }); + + it('should default to selecting first action', () => { + expect(findDropdown().attributes()).toMatchObject({ + text: TEST_ACTION.text, + 'split-href': TEST_ACTION.href, + }); + }); + + it('should handle first action click', () => { + const event = new Event('click'); + + clickDropdown(event); + + expect(handleAction).toHaveBeenCalledWith(event); + }); + + it('should render dropdown items', () => { + expect(parseDropdownItems()).toEqual([ + { + type: 'item', + isCheckItem: true, + isChecked: true, + secondaryText: TEST_ACTION.secondaryText, + text: TEST_ACTION.text, + }, + { type: 'divider' }, + { + type: 'item', + isCheckItem: true, + isChecked: false, + secondaryText: TEST_ACTION_2.secondaryText, + text: TEST_ACTION_2.text, + }, + ]); + }); + + it('should select action 2 when clicked', () => { + expect(wrapper.emitted('select')).toBeUndefined(); + + const action2 = wrapper.find(`[data-testid="action_${TEST_ACTION_2.key}"]`); + action2.vm.$emit('click'); + + expect(wrapper.emitted('select')).toEqual([[TEST_ACTION_2.key]]); + }); + + it('should have tooltip value', () => { + expect(findDropdownTooltip()).toBe(TEST_ACTION.tooltip); + }); + }); + + describe('with multiple actions and selectedKey', () => { + beforeEach(() => { + createComponent({ actions: [TEST_ACTION, TEST_ACTION_2], selectedKey: TEST_ACTION_2.key }); + }); + + it('should show action 2 as selected', () => { + expect(parseDropdownItems()).toEqual([ + expect.objectContaining({ + type: 'item', + isChecked: false, + }), + { type: 'divider' }, + expect.objectContaining({ + type: 'item', + isChecked: true, + }), + ]); + }); + + it('should have tooltip value', () => { + expect(findDropdownTooltip()).toBe(TEST_ACTION_2.tooltip); + }); + }); +}); diff --git a/spec/frontend/vue_shared/components/web_ide_link_spec.js b/spec/frontend/vue_shared/components/web_ide_link_spec.js new file mode 100644 index 00000000000..57f511903d9 --- /dev/null +++ b/spec/frontend/vue_shared/components/web_ide_link_spec.js @@ -0,0 +1,106 @@ +import { shallowMount } from '@vue/test-utils'; +import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; +import WebIdeLink from '~/vue_shared/components/web_ide_link.vue'; +import ActionsButton from '~/vue_shared/components/actions_button.vue'; + +const TEST_WEB_IDE_URL = '/-/ide/project/gitlab-test/test/edit/master/-/'; +const TEST_GITPOD_URL = 'https://gitpod.test/'; + +const ACTION_WEB_IDE = { + href: TEST_WEB_IDE_URL, + key: 'webide', + secondaryText: 'Quickly and easily edit multiple files in your project.', + tooltip: '', + text: 'Web IDE', + attrs: { + 'data-qa-selector': 'web_ide_button', + }, +}; +const ACTION_WEB_IDE_FORK = { + ...ACTION_WEB_IDE, + href: '#modal-confirm-fork', + handle: expect.any(Function), +}; +const ACTION_GITPOD = { + href: TEST_GITPOD_URL, + key: 'gitpod', + secondaryText: 'Launch a ready-to-code development environment for your project.', + tooltip: 'Launch a ready-to-code development environment for your project.', + text: 'Gitpod', + attrs: { + 'data-qa-selector': 'gitpod_button', + }, +}; +const ACTION_GITPOD_ENABLE = { + ...ACTION_GITPOD, + href: '#modal-enable-gitpod', + handle: expect.any(Function), +}; + +describe('Web IDE link component', () => { + let wrapper; + + function createComponent(props) { + wrapper = shallowMount(WebIdeLink, { + propsData: { + webIdeUrl: TEST_WEB_IDE_URL, + gitpodUrl: TEST_GITPOD_URL, + ...props, + }, + }); + } + + afterEach(() => { + wrapper.destroy(); + }); + + const findActionsButton = () => wrapper.find(ActionsButton); + const findLocalStorageSync = () => wrapper.find(LocalStorageSync); + + it.each` + props | expectedActions + ${{}} | ${[ACTION_WEB_IDE]} + ${{ needsToFork: true }} | ${[ACTION_WEB_IDE_FORK]} + ${{ showWebIdeButton: false, showGitpodButton: true, gitpodEnabled: true }} | ${[ACTION_GITPOD]} + ${{ showWebIdeButton: false, showGitpodButton: true, gitpodEnabled: false }} | ${[ACTION_GITPOD_ENABLE]} + ${{ showGitpodButton: true, gitpodEnabled: false }} | ${[ACTION_WEB_IDE, ACTION_GITPOD_ENABLE]} + `('renders actions with props=$props', ({ props, expectedActions }) => { + createComponent(props); + + expect(findActionsButton().props('actions')).toEqual(expectedActions); + }); + + describe('with multiple actions', () => { + beforeEach(() => { + createComponent({ showWebIdeButton: true, showGitpodButton: true, gitpodEnabled: true }); + }); + + it('selected Web IDE by default', () => { + expect(findActionsButton().props()).toMatchObject({ + actions: [ACTION_WEB_IDE, ACTION_GITPOD], + selectedKey: ACTION_WEB_IDE.key, + }); + }); + + it('should set selection with local storage value', async () => { + expect(findActionsButton().props('selectedKey')).toBe(ACTION_WEB_IDE.key); + + findLocalStorageSync().vm.$emit('input', ACTION_GITPOD.key); + + await wrapper.vm.$nextTick(); + + expect(findActionsButton().props('selectedKey')).toBe(ACTION_GITPOD.key); + }); + + it('should update local storage when selection changes', async () => { + expect(findLocalStorageSync().props('value')).toBe(ACTION_WEB_IDE.key); + + findActionsButton().vm.$emit('select', ACTION_GITPOD.key); + + await wrapper.vm.$nextTick(); + + expect(findActionsButton().props('selectedKey')).toBe(ACTION_GITPOD.key); + expect(findLocalStorageSync().props('value')).toBe(ACTION_GITPOD.key); + }); + }); +}); |