diff options
Diffstat (limited to 'spec/frontend/vue_shared/components')
17 files changed, 452 insertions, 40 deletions
diff --git a/spec/frontend/vue_shared/components/color_picker/color_picker_spec.js b/spec/frontend/vue_shared/components/color_picker/color_picker_spec.js index c8fe6c3131c..d30f36ec63c 100644 --- a/spec/frontend/vue_shared/components/color_picker/color_picker_spec.js +++ b/spec/frontend/vue_shared/components/color_picker/color_picker_spec.js @@ -13,6 +13,7 @@ describe('ColorPicker', () => { }; const setColor = '#000000'; + const invalidText = 'Please enter a valid hex (#RRGGBB or #RGB) color value'; const label = () => wrapper.find(GlFormGroup).attributes('label'); const colorPreview = () => wrapper.find('[data-testid="color-preview"]'); const colorPicker = () => wrapper.find(GlFormInput); @@ -28,8 +29,6 @@ describe('ColorPicker', () => { '#428BCA': 'Moderate blue', '#44AD8E': 'Lime green', }; - - createComponent(shallowMount); }); afterEach(() => { @@ -38,6 +37,8 @@ describe('ColorPicker', () => { describe('label', () => { it('hides the label if the label is not passed', () => { + createComponent(shallowMount); + expect(label()).toBe(''); }); @@ -55,43 +56,37 @@ describe('ColorPicker', () => { expect(colorPreview().attributes('style')).toBe(undefined); expect(colorPicker().attributes('value')).toBe(undefined); expect(colorInput().props('value')).toBe(''); + expect(colorPreview().attributes('class')).toContain('gl-inset-border-1-gray-400'); }); it('has a color set on initialization', () => { - createComponent(shallowMount, { setColor }); + createComponent(mount, { value: setColor }); - expect(wrapper.vm.$data.selectedColor).toBe(setColor); + expect(colorInput().props('value')).toBe(setColor); }); it('emits input event from component when a color is selected', async () => { createComponent(); await colorInput().setValue(setColor); - expect(wrapper.emitted().input[0]).toEqual([setColor]); + expect(wrapper.emitted().input[0]).toStrictEqual([setColor]); }); it('trims spaces from submitted colors', async () => { createComponent(); await colorInput().setValue(` ${setColor} `); - expect(wrapper.vm.$data.selectedColor).toBe(setColor); + expect(wrapper.emitted().input[0]).toStrictEqual([setColor]); + expect(colorPreview().attributes('class')).toContain('gl-inset-border-1-gray-400'); + expect(colorInput().attributes('class')).not.toContain('is-invalid'); }); - it('shows invalid feedback when an invalid color is used', async () => { - createComponent(); - await colorInput().setValue('abcd'); - - expect(invalidFeedback().text()).toBe( - 'Please enter a valid hex (#RRGGBB or #RGB) color value', - ); - expect(wrapper.emitted().input).toBe(undefined); - }); - - it('shows an invalid feedback border on the preview when an invalid color is used', async () => { - createComponent(); - await colorInput().setValue('abcd'); + it('shows invalid feedback when the state is marked as invalid', async () => { + createComponent(mount, { invalidFeedback: invalidText, state: false }); + expect(invalidFeedback().text()).toBe(invalidText); expect(colorPreview().attributes('class')).toContain('gl-inset-border-1-red-500'); + expect(colorInput().attributes('class')).toContain('is-invalid'); }); }); @@ -100,14 +95,14 @@ describe('ColorPicker', () => { createComponent(); await colorInput().setValue(setColor); - expect(wrapper.vm.$data.selectedColor).toBe(setColor); + expect(wrapper.emitted().input[0]).toStrictEqual([setColor]); }); it('has color picker value entered', async () => { createComponent(); await colorPicker().setValue(setColor); - expect(wrapper.vm.$data.selectedColor).toBe(setColor); + expect(wrapper.emitted().input[0]).toStrictEqual([setColor]); }); }); @@ -132,7 +127,7 @@ describe('ColorPicker', () => { createComponent(); await presetColors().at(0).trigger('click'); - expect(wrapper.vm.$data.selectedColor).toBe(setColor); + expect(wrapper.emitted().input[0]).toStrictEqual([setColor]); }); }); }); diff --git a/spec/frontend/vue_shared/components/editor_lite_spec.js b/spec/frontend/vue_shared/components/editor_lite_spec.js index 70fdd8e24a5..9298851d143 100644 --- a/spec/frontend/vue_shared/components/editor_lite_spec.js +++ b/spec/frontend/vue_shared/components/editor_lite_spec.js @@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils'; import { nextTick } from 'vue'; import EditorLite from '~/vue_shared/components/editor_lite.vue'; import Editor from '~/editor/editor_lite'; +import { EDITOR_READY_EVENT } from '~/editor/constants'; jest.mock('~/editor/editor_lite'); @@ -110,13 +111,13 @@ describe('Editor Lite component', () => { expect(wrapper.emitted().input).toEqual([[value]]); }); - it('emits editor-ready event when the Editor Lite is ready', async () => { + it('emits EDITOR_READY_EVENT event when the Editor Lite is ready', async () => { const el = wrapper.find({ ref: 'editor' }).element; - expect(wrapper.emitted()['editor-ready']).toBeUndefined(); + expect(wrapper.emitted()[EDITOR_READY_EVENT]).toBeUndefined(); - await el.dispatchEvent(new Event('editor-ready')); + await el.dispatchEvent(new Event(EDITOR_READY_EVENT)); - expect(wrapper.emitted()['editor-ready']).toBeDefined(); + expect(wrapper.emitted()[EDITOR_READY_EVENT]).toBeDefined(); }); it('component API `getEditor()` returns the editor instance', () => { diff --git a/spec/frontend/vue_shared/components/file_row_spec.js b/spec/frontend/vue_shared/components/file_row_spec.js index bd6a18bf704..92690f6fc37 100644 --- a/spec/frontend/vue_shared/components/file_row_spec.js +++ b/spec/frontend/vue_shared/components/file_row_spec.js @@ -1,6 +1,6 @@ -import { file } from 'jest/ide/helpers'; import { shallowMount } from '@vue/test-utils'; import { nextTick } from 'vue'; +import { file } from 'jest/ide/helpers'; import FileRow from '~/vue_shared/components/file_row.vue'; import FileHeader from '~/vue_shared/components/file_row_header.vue'; import FileIcon from '~/vue_shared/components/file_icon.vue'; diff --git a/spec/frontend/vue_shared/components/gfm_autocomplete/__snapshots__/utils_spec.js.snap b/spec/frontend/vue_shared/components/gfm_autocomplete/__snapshots__/utils_spec.js.snap index d8e6e37bb89..5f55502567b 100644 --- a/spec/frontend/vue_shared/components/gfm_autocomplete/__snapshots__/utils_spec.js.snap +++ b/spec/frontend/vue_shared/components/gfm_autocomplete/__snapshots__/utils_spec.js.snap @@ -21,10 +21,10 @@ exports[`gfm_autocomplete/utils labels config shows the title in the menu item 1 exports[`gfm_autocomplete/utils members config shows an avatar character, name, parent name, and count in the menu item for a group 1`] = ` " <div class=\\"gl-display-flex gl-align-items-center\\"> - <div class=\\"gl-avatar gl-avatar-s24 gl-flex-shrink-0 gl-rounded-small + <div class=\\"gl-avatar gl-avatar-s32 gl-flex-shrink-0 gl-rounded-small gl-display-flex gl-align-items-center gl-justify-content-center\\" aria-hidden=\\"true\\"> G</div> - <div class=\\"gl-font-sm gl-line-height-normal gl-ml-3\\"> + <div class=\\"gl-line-height-normal gl-ml-4\\"> <div>1-1s <script>alert('hi')</script> (2)</div> <div class=\\"gl-text-gray-700\\">GitLab Support Team</div> </div> @@ -36,8 +36,8 @@ exports[`gfm_autocomplete/utils members config shows an avatar character, name, exports[`gfm_autocomplete/utils members config shows the avatar, name and username in the menu item for a user 1`] = ` " <div class=\\"gl-display-flex gl-align-items-center\\"> - <img class=\\"gl-avatar gl-avatar-s24 gl-flex-shrink-0 gl-avatar-circle\\" src=\\"/uploads/-/system/user/avatar/123456/avatar.png\\" alt=\\"\\" /> - <div class=\\"gl-font-sm gl-line-height-normal gl-ml-3\\"> + <img class=\\"gl-avatar gl-avatar-s32 gl-flex-shrink-0 gl-avatar-circle\\" src=\\"/uploads/-/system/user/avatar/123456/avatar.png\\" alt=\\"\\" /> + <div class=\\"gl-line-height-normal gl-ml-4\\"> <div>My Name <script>alert('hi')</script></div> <div class=\\"gl-text-gray-700\\">@myusername</div> </div> diff --git a/spec/frontend/vue_shared/components/gl_countdown_spec.js b/spec/frontend/vue_shared/components/gl_countdown_spec.js index fcc5c0cd310..82d18c7fd3f 100644 --- a/spec/frontend/vue_shared/components/gl_countdown_spec.js +++ b/spec/frontend/vue_shared/components/gl_countdown_spec.js @@ -1,5 +1,5 @@ -import mountComponent from 'helpers/vue_mount_component_helper'; import Vue from 'vue'; +import mountComponent from 'helpers/vue_mount_component_helper'; import GlCountdown from '~/vue_shared/components/gl_countdown.vue'; describe('GlCountdown', () => { diff --git a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js index 6802499ed52..81518e67377 100644 --- a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js +++ b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js @@ -3,6 +3,7 @@ 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'; +import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants'; const localVue = createLocalVue(); localVue.use(Vuex); @@ -129,7 +130,7 @@ describe('GlModalVuex', () => { wrapper.vm .$nextTick() .then(() => { - expect(rootEmit).toHaveBeenCalledWith('bv::show::modal', TEST_MODAL_ID); + expect(rootEmit).toHaveBeenCalledWith(BV_SHOW_MODAL, TEST_MODAL_ID); }) .then(done) .catch(done.fail); @@ -146,7 +147,7 @@ describe('GlModalVuex', () => { wrapper.vm .$nextTick() .then(() => { - expect(rootEmit).toHaveBeenCalledWith('bv::hide::modal', TEST_MODAL_ID); + expect(rootEmit).toHaveBeenCalledWith(BV_HIDE_MODAL, TEST_MODAL_ID); }) .then(done) .catch(done.fail); diff --git a/spec/frontend/vue_shared/components/help_popover_spec.js b/spec/frontend/vue_shared/components/help_popover_spec.js new file mode 100644 index 00000000000..112085e91e1 --- /dev/null +++ b/spec/frontend/vue_shared/components/help_popover_spec.js @@ -0,0 +1,65 @@ +import { mount } from '@vue/test-utils'; +import { GlButton, GlPopover } from '@gitlab/ui'; +import HelpPopover from '~/vue_shared/components/help_popover.vue'; + +describe('HelpPopover', () => { + let wrapper; + const title = 'popover <strong>title</strong>'; + const content = 'popover <b>content</b>'; + + const findQuestionButton = () => wrapper.find(GlButton); + const findPopover = () => wrapper.find(GlPopover); + const buildWrapper = (options = {}) => { + wrapper = mount(HelpPopover, { + propsData: { + options: { + title, + content, + ...options, + }, + }, + }); + }; + + beforeEach(() => { + buildWrapper(); + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('renders a link button with an icon question', () => { + expect(findQuestionButton().props()).toMatchObject({ + icon: 'question', + variant: 'link', + }); + expect(findQuestionButton().attributes().tabindex).toBe('0'); + }); + + it('renders popover that uses the question button as target', () => { + expect(findPopover().props().target()).toBe(findQuestionButton().vm.$el); + }); + + it('triggers popover on hover and focus', () => { + expect(findPopover().props().triggers).toBe('hover focus'); + }); + + it('allows rendering title with HTML tags', () => { + expect(findPopover().find('strong').exists()).toBe(true); + }); + + it('allows rendering content with HTML tags', () => { + expect(findPopover().find('b').exists()).toBe(true); + }); + + it('binds other popover options to the popover instance', () => { + const placement = 'bottom'; + + wrapper.destroy(); + buildWrapper({ placement }); + + expect(findPopover().props().placement).toBe(placement); + }); +}); diff --git a/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js b/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js index ffcb891c4fc..8143196c6e8 100644 --- a/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js +++ b/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js @@ -1,8 +1,8 @@ import Vue from 'vue'; import { shallowMount } from '@vue/test-utils'; -import { mockMilestone } from 'jest/boards/mock_data'; import { GlIcon } from '@gitlab/ui'; +import { mockMilestone } from 'jest/boards/mock_data'; import IssueMilestone from '~/vue_shared/components/issue/issue_milestone.vue'; const createComponent = (milestone = mockMilestone) => { diff --git a/spec/frontend/vue_shared/components/markdown/field_spec.js b/spec/frontend/vue_shared/components/markdown/field_spec.js index a2ce6f40193..97cc22e1418 100644 --- a/spec/frontend/vue_shared/components/markdown/field_spec.js +++ b/spec/frontend/vue_shared/components/markdown/field_spec.js @@ -1,7 +1,7 @@ import { mount } from '@vue/test-utils'; -import { TEST_HOST, FIXTURES_PATH } from 'spec/test_constants'; import AxiosMockAdapter from 'axios-mock-adapter'; import $ from 'jquery'; +import { TEST_HOST, FIXTURES_PATH } from 'spec/test_constants'; import MarkdownField from '~/vue_shared/components/markdown/field.vue'; import axios from '~/lib/utils/axios_utils'; diff --git a/spec/frontend/vue_shared/components/modal_copy_button_spec.js b/spec/frontend/vue_shared/components/modal_copy_button_spec.js index ca9f8ff54d4..97d4313b89e 100644 --- a/spec/frontend/vue_shared/components/modal_copy_button_spec.js +++ b/spec/frontend/vue_shared/components/modal_copy_button_spec.js @@ -1,5 +1,6 @@ import { shallowMount, createWrapper } from '@vue/test-utils'; import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue'; +import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants'; describe('modal copy button', () => { let wrapper; @@ -31,7 +32,7 @@ describe('modal copy button', () => { return wrapper.vm.$nextTick().then(() => { expect(wrapper.emitted().success).not.toBeEmpty(); expect(document.execCommand).toHaveBeenCalledWith('copy'); - expect(root.emitted('bv::hide::tooltip')).toEqual([['test-id']]); + expect(root.emitted(BV_HIDE_TOOLTIP)).toEqual([['test-id']]); }); }); it("should propagate the clipboard error event if execCommand doesn't work", () => { diff --git a/spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js index 0e6f951bd53..594b1ab9d78 100644 --- a/spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js +++ b/spec/frontend/vue_shared/components/rich_content_editor/toolbar_item_spec.js @@ -1,6 +1,6 @@ import { shallowMount } from '@vue/test-utils'; -import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import { GlIcon } from '@gitlab/ui'; +import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import ToolbarItem from '~/vue_shared/components/rich_content_editor/toolbar_item.vue'; describe('Toolbar Item', () => { diff --git a/spec/frontend/vue_shared/components/runner_instructions/mock_data.js b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js new file mode 100644 index 00000000000..01f7f3d49c7 --- /dev/null +++ b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js @@ -0,0 +1,107 @@ +export const mockGraphqlRunnerPlatforms = { + data: { + runnerPlatforms: { + nodes: [ + { + name: 'linux', + humanReadableName: 'Linux', + architectures: { + nodes: [ + { + name: 'amd64', + downloadLocation: + 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64', + __typename: 'RunnerArchitecture', + }, + { + name: '386', + downloadLocation: + 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-386', + __typename: 'RunnerArchitecture', + }, + { + name: 'arm', + downloadLocation: + 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm', + __typename: 'RunnerArchitecture', + }, + { + name: 'arm64', + downloadLocation: + 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm64', + __typename: 'RunnerArchitecture', + }, + ], + __typename: 'RunnerArchitectureConnection', + }, + __typename: 'RunnerPlatform', + }, + { + name: 'osx', + humanReadableName: 'macOS', + architectures: { + nodes: [ + { + name: 'amd64', + downloadLocation: + 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64', + __typename: 'RunnerArchitecture', + }, + ], + __typename: 'RunnerArchitectureConnection', + }, + __typename: 'RunnerPlatform', + }, + { + name: 'windows', + humanReadableName: 'Windows', + architectures: { + nodes: [ + { + name: 'amd64', + downloadLocation: + 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-amd64.exe', + __typename: 'RunnerArchitecture', + }, + { + name: '386', + downloadLocation: + 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-386.exe', + __typename: 'RunnerArchitecture', + }, + ], + __typename: 'RunnerArchitectureConnection', + }, + __typename: 'RunnerPlatform', + }, + { + name: 'docker', + humanReadableName: 'Docker', + architectures: null, + __typename: 'RunnerPlatform', + }, + { + name: 'kubernetes', + humanReadableName: 'Kubernetes', + architectures: null, + __typename: 'RunnerPlatform', + }, + ], + __typename: 'RunnerPlatformConnection', + }, + project: { id: 'gid://gitlab/Project/1', __typename: 'Project' }, + group: null, + }, +}; + +export const mockGraphqlInstructions = { + data: { + runnerSetup: { + installInstructions: + "# Download the binary for your system\nsudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64\n\n# Give it permissions to execute\nsudo chmod +x /usr/local/bin/gitlab-runner\n\n# Create a GitLab CI user\nsudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash\n\n# Install and run as service\nsudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner\nsudo gitlab-runner start\n", + registerInstructions: + 'sudo gitlab-runner register --url http://192.168.1.81:3000/ --registration-token GE5gsjeep_HAtBf9s3Yz', + __typename: 'RunnerSetup', + }, + }, +}; diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js new file mode 100644 index 00000000000..6e2ba603e04 --- /dev/null +++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js @@ -0,0 +1,113 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import VueApollo from 'vue-apollo'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import RunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue'; +import getRunnerPlatforms from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_platforms.query.graphql'; +import getRunnerSetupInstructions from '~/vue_shared/components/runner_instructions/graphql/queries/get_runner_setup.query.graphql'; + +import { mockGraphqlRunnerPlatforms, mockGraphqlInstructions } from './mock_data'; + +const projectPath = 'gitlab-org/gitlab'; +const localVue = createLocalVue(); +localVue.use(VueApollo); + +describe('RunnerInstructions component', () => { + let wrapper; + let fakeApollo; + + const findModalButton = () => wrapper.find('[data-testid="show-modal-button"]'); + const findPlatformButtons = () => wrapper.findAll('[data-testid="platform-button"]'); + const findArchitectureDropdownItems = () => + wrapper.findAll('[data-testid="architecture-dropdown-item"]'); + const findBinaryInstructionsSection = () => wrapper.find('[data-testid="binary-instructions"]'); + const findRunnerInstructionsSection = () => wrapper.find('[data-testid="runner-instructions"]'); + + beforeEach(async () => { + const requestHandlers = [ + [getRunnerPlatforms, jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms)], + [getRunnerSetupInstructions, jest.fn().mockResolvedValue(mockGraphqlInstructions)], + ]; + + fakeApollo = createMockApollo(requestHandlers); + + wrapper = shallowMount(RunnerInstructions, { + provide: { + projectPath, + }, + localVue, + apolloProvider: fakeApollo, + }); + + await wrapper.vm.$nextTick(); + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('should show the "Show Runner installation instructions" button', () => { + const button = findModalButton(); + + expect(button.exists()).toBe(true); + expect(button.text()).toBe('Show Runner installation instructions'); + }); + + it('should contain a number of platforms buttons', () => { + const buttons = findPlatformButtons(); + + expect(buttons).toHaveLength(mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes.length); + }); + + it('should contain a number of dropdown items for the architecture options', () => { + const platformButton = findPlatformButtons().at(0); + platformButton.vm.$emit('click'); + + return wrapper.vm.$nextTick(() => { + const dropdownItems = findArchitectureDropdownItems(); + + expect(dropdownItems).toHaveLength( + mockGraphqlRunnerPlatforms.data.runnerPlatforms.nodes[0].architectures.nodes.length, + ); + }); + }); + + it('should display the binary installation instructions for a selected architecture', async () => { + const platformButton = findPlatformButtons().at(0); + platformButton.vm.$emit('click'); + + await wrapper.vm.$nextTick(); + + const dropdownItem = findArchitectureDropdownItems().at(0); + dropdownItem.vm.$emit('click'); + + await wrapper.vm.$nextTick(); + + const runner = findBinaryInstructionsSection(); + + expect(runner.text()).toMatch('sudo chmod +x /usr/local/bin/gitlab-runner'); + expect(runner.text()).toMatch( + `sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash`, + ); + expect(runner.text()).toMatch( + 'sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner', + ); + expect(runner.text()).toMatch('sudo gitlab-runner start'); + }); + + it('should display the runner register instructions for a selected architecture', async () => { + const platformButton = findPlatformButtons().at(0); + platformButton.vm.$emit('click'); + + await wrapper.vm.$nextTick(); + + const dropdownItem = findArchitectureDropdownItems().at(0); + dropdownItem.vm.$emit('click'); + + await wrapper.vm.$nextTick(); + + const runner = findRunnerInstructionsSection(); + + expect(runner.text()).toMatch(mockGraphqlInstructions.data.runnerSetup.registerInstructions); + }); +}); diff --git a/spec/frontend/vue_shared/components/settings/__snapshots__/settings_block_spec.js.snap b/spec/frontend/vue_shared/components/settings/__snapshots__/settings_block_spec.js.snap new file mode 100644 index 00000000000..51b8aa162bc --- /dev/null +++ b/spec/frontend/vue_shared/components/settings/__snapshots__/settings_block_spec.js.snap @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Settings Block renders the correct markup 1`] = ` +<section + class="settings no-animate" +> + <div + class="settings-header" + > + <h4> + <div + data-testid="title-slot" + /> + </h4> + + <gl-button-stub + buttontextclasses="" + category="primary" + icon="" + size="medium" + variant="default" + > + + Expand + + </gl-button-stub> + + <p> + <div + data-testid="description-slot" + /> + </p> + </div> + + <div + class="settings-content" + > + <div + data-testid="default-slot" + /> + </div> +</section> +`; diff --git a/spec/frontend/vue_shared/components/settings/settings_block_spec.js b/spec/frontend/vue_shared/components/settings/settings_block_spec.js new file mode 100644 index 00000000000..b550c4cfcc3 --- /dev/null +++ b/spec/frontend/vue_shared/components/settings/settings_block_spec.js @@ -0,0 +1,86 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlButton } from '@gitlab/ui'; +import component from '~/vue_shared/components/settings/settings_block.vue'; + +describe('Settings Block', () => { + let wrapper; + + const mountComponent = (propsData) => { + wrapper = shallowMount(component, { + propsData, + slots: { + title: '<div data-testid="title-slot"></div>', + description: '<div data-testid="description-slot"></div>', + default: '<div data-testid="default-slot"></div>', + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + const findDefaultSlot = () => wrapper.find('[data-testid="default-slot"]'); + const findTitleSlot = () => wrapper.find('[data-testid="title-slot"]'); + const findDescriptionSlot = () => wrapper.find('[data-testid="description-slot"]'); + const findExpandButton = () => wrapper.find(GlButton); + + it('renders the correct markup', () => { + mountComponent(); + + expect(wrapper.element).toMatchSnapshot(); + }); + + it('has a default slot', () => { + mountComponent(); + + expect(findDefaultSlot().exists()).toBe(true); + }); + + it('has a title slot', () => { + mountComponent(); + + expect(findTitleSlot().exists()).toBe(true); + }); + + it('has a description slot', () => { + mountComponent(); + + expect(findDescriptionSlot().exists()).toBe(true); + }); + + describe('expanded behaviour', () => { + it('is collapsed by default', () => { + mountComponent(); + + expect(wrapper.classes('expanded')).toBe(false); + }); + + it('adds expanded class when the expand button is clicked', async () => { + mountComponent(); + + expect(wrapper.classes('expanded')).toBe(false); + expect(findExpandButton().text()).toBe('Expand'); + + await findExpandButton().vm.$emit('click'); + + expect(wrapper.classes('expanded')).toBe(true); + expect(findExpandButton().text()).toBe('Collapse'); + }); + + it('is expanded when `defaultExpanded` is true no matter what', async () => { + mountComponent({ defaultExpanded: true }); + + expect(wrapper.classes('expanded')).toBe(true); + + await findExpandButton().vm.$emit('click'); + + expect(wrapper.classes('expanded')).toBe(true); + + await findExpandButton().vm.$emit('click'); + + expect(wrapper.classes('expanded')).toBe(true); + }); + }); +}); diff --git a/spec/frontend/vue_shared/components/todo_button_spec.js b/spec/frontend/vue_shared/components/todo_button_spec.js index 1f8a214d632..2066c3bd671 100644 --- a/spec/frontend/vue_shared/components/todo_button_spec.js +++ b/spec/frontend/vue_shared/components/todo_button_spec.js @@ -33,7 +33,7 @@ describe('Todo Button', () => { it.each` label | isTodo ${'Mark as done'} | ${true} - ${'Add a To Do'} | ${false} + ${'Add a to do'} | ${false} `('sets correct label when isTodo is $isTodo', ({ label, isTodo }) => { createComponent({ isTodo }); diff --git a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js index d151cd15bc4..3eae707daf8 100644 --- a/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js +++ b/spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js @@ -1,7 +1,7 @@ import { each } from 'lodash'; -import { trimText } from 'helpers/text_helper'; import { shallowMount } from '@vue/test-utils'; import { GlLink } from '@gitlab/ui'; +import { trimText } from 'helpers/text_helper'; import { TEST_HOST } from 'spec/test_constants'; import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue'; |