diff options
Diffstat (limited to 'spec/frontend/design_management/components/upload')
7 files changed, 964 insertions, 0 deletions
diff --git a/spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap b/spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap new file mode 100644 index 00000000000..185bf4a48f7 --- /dev/null +++ b/spec/frontend/design_management/components/upload/__snapshots__/button_spec.js.snap @@ -0,0 +1,79 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Design management upload button component renders inverted upload design button 1`] = ` +<div + isinverted="true" +> + <gl-deprecated-button-stub + size="md" + title="Adding a design with the same filename replaces the file in a new version." + variant="success" + > + + Add designs + + <!----> + </gl-deprecated-button-stub> + + <input + accept="image/*" + class="hide" + multiple="multiple" + name="design_file" + type="file" + /> +</div> +`; + +exports[`Design management upload button component renders loading icon 1`] = ` +<div> + <gl-deprecated-button-stub + disabled="true" + size="md" + title="Adding a design with the same filename replaces the file in a new version." + variant="success" + > + + Add designs + + <gl-loading-icon-stub + class="ml-1" + color="orange" + inline="true" + label="Loading" + size="sm" + /> + </gl-deprecated-button-stub> + + <input + accept="image/*" + class="hide" + multiple="multiple" + name="design_file" + type="file" + /> +</div> +`; + +exports[`Design management upload button component renders upload design button 1`] = ` +<div> + <gl-deprecated-button-stub + size="md" + title="Adding a design with the same filename replaces the file in a new version." + variant="success" + > + + Add designs + + <!----> + </gl-deprecated-button-stub> + + <input + accept="image/*" + class="hide" + multiple="multiple" + name="design_file" + type="file" + /> +</div> +`; diff --git a/spec/frontend/design_management/components/upload/__snapshots__/design_dropzone_spec.js.snap b/spec/frontend/design_management/components/upload/__snapshots__/design_dropzone_spec.js.snap new file mode 100644 index 00000000000..0737b9729a2 --- /dev/null +++ b/spec/frontend/design_management/components/upload/__snapshots__/design_dropzone_spec.js.snap @@ -0,0 +1,455 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Design management dropzone component when dragging renders correct template when drag event contains files 1`] = ` +<div + class="w-100 position-relative" +> + <button + class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3" + > + <div + class="d-flex-center flex-column text-center" + > + <gl-icon-stub + class="mb-4" + name="doc-new" + size="48" + /> + + <p> + <gl-sprintf-stub + message="%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}." + /> + </p> + </div> + </button> + + <input + accept="image/*" + class="hide" + multiple="multiple" + name="design_file" + type="file" + /> + + <transition-stub + name="design-dropzone-fade" + > + <div + class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white" + style="" + > + <div + class="mw-50 text-center" + style="display: none;" + > + <h3> + Oh no! + </h3> + + <span> + You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico. + </span> + </div> + + <div + class="mw-50 text-center" + style="" + > + <h3> + Incoming! + </h3> + + <span> + Drop your designs to start your upload. + </span> + </div> + </div> + </transition-stub> +</div> +`; + +exports[`Design management dropzone component when dragging renders correct template when drag event contains files and text 1`] = ` +<div + class="w-100 position-relative" +> + <button + class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3" + > + <div + class="d-flex-center flex-column text-center" + > + <gl-icon-stub + class="mb-4" + name="doc-new" + size="48" + /> + + <p> + <gl-sprintf-stub + message="%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}." + /> + </p> + </div> + </button> + + <input + accept="image/*" + class="hide" + multiple="multiple" + name="design_file" + type="file" + /> + + <transition-stub + name="design-dropzone-fade" + > + <div + class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white" + style="" + > + <div + class="mw-50 text-center" + style="display: none;" + > + <h3> + Oh no! + </h3> + + <span> + You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico. + </span> + </div> + + <div + class="mw-50 text-center" + style="" + > + <h3> + Incoming! + </h3> + + <span> + Drop your designs to start your upload. + </span> + </div> + </div> + </transition-stub> +</div> +`; + +exports[`Design management dropzone component when dragging renders correct template when drag event contains text 1`] = ` +<div + class="w-100 position-relative" +> + <button + class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3" + > + <div + class="d-flex-center flex-column text-center" + > + <gl-icon-stub + class="mb-4" + name="doc-new" + size="48" + /> + + <p> + <gl-sprintf-stub + message="%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}." + /> + </p> + </div> + </button> + + <input + accept="image/*" + class="hide" + multiple="multiple" + name="design_file" + type="file" + /> + + <transition-stub + name="design-dropzone-fade" + > + <div + class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white" + style="" + > + <div + class="mw-50 text-center" + > + <h3> + Oh no! + </h3> + + <span> + You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico. + </span> + </div> + + <div + class="mw-50 text-center" + style="display: none;" + > + <h3> + Incoming! + </h3> + + <span> + Drop your designs to start your upload. + </span> + </div> + </div> + </transition-stub> +</div> +`; + +exports[`Design management dropzone component when dragging renders correct template when drag event is empty 1`] = ` +<div + class="w-100 position-relative" +> + <button + class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3" + > + <div + class="d-flex-center flex-column text-center" + > + <gl-icon-stub + class="mb-4" + name="doc-new" + size="48" + /> + + <p> + <gl-sprintf-stub + message="%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}." + /> + </p> + </div> + </button> + + <input + accept="image/*" + class="hide" + multiple="multiple" + name="design_file" + type="file" + /> + + <transition-stub + name="design-dropzone-fade" + > + <div + class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white" + style="" + > + <div + class="mw-50 text-center" + > + <h3> + Oh no! + </h3> + + <span> + You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico. + </span> + </div> + + <div + class="mw-50 text-center" + style="display: none;" + > + <h3> + Incoming! + </h3> + + <span> + Drop your designs to start your upload. + </span> + </div> + </div> + </transition-stub> +</div> +`; + +exports[`Design management dropzone component when dragging renders correct template when dragging stops 1`] = ` +<div + class="w-100 position-relative" +> + <button + class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3" + > + <div + class="d-flex-center flex-column text-center" + > + <gl-icon-stub + class="mb-4" + name="doc-new" + size="48" + /> + + <p> + <gl-sprintf-stub + message="%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}." + /> + </p> + </div> + </button> + + <input + accept="image/*" + class="hide" + multiple="multiple" + name="design_file" + type="file" + /> + + <transition-stub + name="design-dropzone-fade" + > + <div + class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white" + style="display: none;" + > + <div + class="mw-50 text-center" + > + <h3> + Oh no! + </h3> + + <span> + You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico. + </span> + </div> + + <div + class="mw-50 text-center" + style="display: none;" + > + <h3> + Incoming! + </h3> + + <span> + Drop your designs to start your upload. + </span> + </div> + </div> + </transition-stub> +</div> +`; + +exports[`Design management dropzone component when no slot provided renders default dropzone card 1`] = ` +<div + class="w-100 position-relative" +> + <button + class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3" + > + <div + class="d-flex-center flex-column text-center" + > + <gl-icon-stub + class="mb-4" + name="doc-new" + size="48" + /> + + <p> + <gl-sprintf-stub + message="%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}." + /> + </p> + </div> + </button> + + <input + accept="image/*" + class="hide" + multiple="multiple" + name="design_file" + type="file" + /> + + <transition-stub + name="design-dropzone-fade" + > + <div + class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white" + style="display: none;" + > + <div + class="mw-50 text-center" + > + <h3> + Oh no! + </h3> + + <span> + You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico. + </span> + </div> + + <div + class="mw-50 text-center" + style="display: none;" + > + <h3> + Incoming! + </h3> + + <span> + Drop your designs to start your upload. + </span> + </div> + </div> + </transition-stub> +</div> +`; + +exports[`Design management dropzone component when slot provided renders dropzone with slot content 1`] = ` +<div + class="w-100 position-relative" +> + <div> + dropzone slot + </div> + + <transition-stub + name="design-dropzone-fade" + > + <div + class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white" + style="display: none;" + > + <div + class="mw-50 text-center" + > + <h3> + Oh no! + </h3> + + <span> + You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico. + </span> + </div> + + <div + class="mw-50 text-center" + style="display: none;" + > + <h3> + Incoming! + </h3> + + <span> + Drop your designs to start your upload. + </span> + </div> + </div> + </transition-stub> +</div> +`; diff --git a/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap b/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap new file mode 100644 index 00000000000..00f1a40dfb2 --- /dev/null +++ b/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap @@ -0,0 +1,111 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Design management design version dropdown component renders design version dropdown button 1`] = ` +<gl-dropdown-stub + class="design-version-dropdown" + issueiid="" + projectpath="" + text="Showing Latest Version" + variant="link" +> + <gl-dropdown-item-stub> + <router-link-stub + class="d-flex js-version-link" + to="[object Object]" + > + <div + class="flex-grow-1 ml-2" + > + <div> + <strong> + Version 2 + + <span> + (latest) + </span> + </strong> + </div> + </div> + + <i + class="fa fa-check pull-right" + /> + </router-link-stub> + </gl-dropdown-item-stub> + <gl-dropdown-item-stub> + <router-link-stub + class="d-flex js-version-link" + to="[object Object]" + > + <div + class="flex-grow-1 ml-2" + > + <div> + <strong> + Version 1 + + <!----> + </strong> + </div> + </div> + + <!----> + </router-link-stub> + </gl-dropdown-item-stub> +</gl-dropdown-stub> +`; + +exports[`Design management design version dropdown component renders design version list 1`] = ` +<gl-dropdown-stub + class="design-version-dropdown" + issueiid="" + projectpath="" + text="Showing Latest Version" + variant="link" +> + <gl-dropdown-item-stub> + <router-link-stub + class="d-flex js-version-link" + to="[object Object]" + > + <div + class="flex-grow-1 ml-2" + > + <div> + <strong> + Version 2 + + <span> + (latest) + </span> + </strong> + </div> + </div> + + <i + class="fa fa-check pull-right" + /> + </router-link-stub> + </gl-dropdown-item-stub> + <gl-dropdown-item-stub> + <router-link-stub + class="d-flex js-version-link" + to="[object Object]" + > + <div + class="flex-grow-1 ml-2" + > + <div> + <strong> + Version 1 + + <!----> + </strong> + </div> + </div> + + <!----> + </router-link-stub> + </gl-dropdown-item-stub> +</gl-dropdown-stub> +`; diff --git a/spec/frontend/design_management/components/upload/button_spec.js b/spec/frontend/design_management/components/upload/button_spec.js new file mode 100644 index 00000000000..c0a9693dc37 --- /dev/null +++ b/spec/frontend/design_management/components/upload/button_spec.js @@ -0,0 +1,59 @@ +import { shallowMount } from '@vue/test-utils'; +import UploadButton from '~/design_management/components/upload/button.vue'; + +describe('Design management upload button component', () => { + let wrapper; + + function createComponent(isSaving = false, isInverted = false) { + wrapper = shallowMount(UploadButton, { + propsData: { + isSaving, + isInverted, + }, + }); + } + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders upload design button', () => { + createComponent(); + + expect(wrapper.element).toMatchSnapshot(); + }); + + it('renders inverted upload design button', () => { + createComponent(false, true); + + expect(wrapper.element).toMatchSnapshot(); + }); + + it('renders loading icon', () => { + createComponent(true); + + expect(wrapper.element).toMatchSnapshot(); + }); + + describe('onFileUploadChange', () => { + it('emits upload event', () => { + createComponent(); + + wrapper.vm.onFileUploadChange({ target: { files: 'test' } }); + + expect(wrapper.emitted().upload[0]).toEqual(['test']); + }); + }); + + describe('openFileUpload', () => { + it('triggers click on input', () => { + createComponent(); + + const clickSpy = jest.spyOn(wrapper.find('input').element, 'click'); + + wrapper.vm.openFileUpload(); + + expect(clickSpy).toHaveBeenCalled(); + }); + }); +}); diff --git a/spec/frontend/design_management/components/upload/design_dropzone_spec.js b/spec/frontend/design_management/components/upload/design_dropzone_spec.js new file mode 100644 index 00000000000..9b86b5b2878 --- /dev/null +++ b/spec/frontend/design_management/components/upload/design_dropzone_spec.js @@ -0,0 +1,132 @@ +import { shallowMount } from '@vue/test-utils'; +import DesignDropzone from '~/design_management/components/upload/design_dropzone.vue'; +import createFlash from '~/flash'; + +jest.mock('~/flash'); + +describe('Design management dropzone component', () => { + let wrapper; + + const mockDragEvent = ({ types = ['Files'], files = [] }) => { + return { dataTransfer: { types, files } }; + }; + + const findDropzoneCard = () => wrapper.find('.design-dropzone-card'); + + function createComponent({ slots = {}, data = {} } = {}) { + wrapper = shallowMount(DesignDropzone, { + slots, + data() { + return data; + }, + }); + } + + afterEach(() => { + wrapper.destroy(); + }); + + describe('when slot provided', () => { + it('renders dropzone with slot content', () => { + createComponent({ + slots: { + default: ['<div>dropzone slot</div>'], + }, + }); + + expect(wrapper.element).toMatchSnapshot(); + }); + }); + + describe('when no slot provided', () => { + it('renders default dropzone card', () => { + createComponent(); + + expect(wrapper.element).toMatchSnapshot(); + }); + + it('triggers click event on file input element when clicked', () => { + createComponent(); + const clickSpy = jest.spyOn(wrapper.find('input').element, 'click'); + + findDropzoneCard().trigger('click'); + expect(clickSpy).toHaveBeenCalled(); + }); + }); + + describe('when dragging', () => { + it.each` + description | eventPayload + ${'is empty'} | ${{}} + ${'contains text'} | ${mockDragEvent({ types: ['text'] })} + ${'contains files and text'} | ${mockDragEvent({ types: ['Files', 'text'] })} + ${'contains files'} | ${mockDragEvent({ types: ['Files'] })} + `('renders correct template when drag event $description', ({ eventPayload }) => { + createComponent(); + + wrapper.trigger('dragenter', eventPayload); + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.element).toMatchSnapshot(); + }); + }); + + it('renders correct template when dragging stops', () => { + createComponent(); + + wrapper.trigger('dragenter'); + return wrapper.vm + .$nextTick() + .then(() => { + wrapper.trigger('dragleave'); + return wrapper.vm.$nextTick(); + }) + .then(() => { + expect(wrapper.element).toMatchSnapshot(); + }); + }); + }); + + describe('when dropping', () => { + it('emits upload event', () => { + createComponent(); + const mockFile = { name: 'test', type: 'image/jpg' }; + const mockEvent = mockDragEvent({ files: [mockFile] }); + + wrapper.trigger('dragenter', mockEvent); + return wrapper.vm + .$nextTick() + .then(() => { + wrapper.trigger('drop', mockEvent); + return wrapper.vm.$nextTick(); + }) + .then(() => { + expect(wrapper.emitted().change[0]).toEqual([[mockFile]]); + }); + }); + }); + + describe('ondrop', () => { + const mockData = { dragCounter: 1, isDragDataValid: true }; + + describe('when drag data is valid', () => { + it('emits upload event for valid files', () => { + createComponent({ data: mockData }); + + const mockFile = { type: 'image/jpg' }; + const mockEvent = mockDragEvent({ files: [mockFile] }); + + wrapper.vm.ondrop(mockEvent); + expect(wrapper.emitted().change[0]).toEqual([[mockFile]]); + }); + + it('calls createFlash when files are invalid', () => { + createComponent({ data: mockData }); + + const mockEvent = mockDragEvent({ files: [{ type: 'audio/midi' }] }); + + wrapper.vm.ondrop(mockEvent); + expect(createFlash).toHaveBeenCalledTimes(1); + }); + }); + }); +}); diff --git a/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js new file mode 100644 index 00000000000..7521b9fad2a --- /dev/null +++ b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js @@ -0,0 +1,114 @@ +import { shallowMount } from '@vue/test-utils'; +import DesignVersionDropdown from '~/design_management/components/upload/design_version_dropdown.vue'; +import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; +import mockAllVersions from './mock_data/all_versions'; + +const LATEST_VERSION_ID = 3; +const PREVIOUS_VERSION_ID = 2; + +const designRouteFactory = versionId => ({ + path: `/designs?version=${versionId}`, + query: { + version: `${versionId}`, + }, +}); + +const MOCK_ROUTE = { + path: '/designs', + query: {}, +}; + +describe('Design management design version dropdown component', () => { + let wrapper; + + function createComponent({ maxVersions = -1, $route = MOCK_ROUTE } = {}) { + wrapper = shallowMount(DesignVersionDropdown, { + propsData: { + projectPath: '', + issueIid: '', + }, + mocks: { + $route, + }, + stubs: ['router-link'], + }); + + wrapper.setData({ + allVersions: maxVersions > -1 ? mockAllVersions.slice(0, maxVersions) : mockAllVersions, + }); + } + + afterEach(() => { + wrapper.destroy(); + }); + + const findVersionLink = index => wrapper.findAll('.js-version-link').at(index); + + it('renders design version dropdown button', () => { + createComponent(); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.element).toMatchSnapshot(); + }); + }); + + it('renders design version list', () => { + createComponent(); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.element).toMatchSnapshot(); + }); + }); + + describe('selected version name', () => { + it('has "latest" on most recent version item', () => { + createComponent(); + + return wrapper.vm.$nextTick().then(() => { + expect(findVersionLink(0).text()).toContain('latest'); + }); + }); + }); + + describe('versions list', () => { + it('displays latest version text by default', () => { + createComponent(); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing Latest Version'); + }); + }); + + it('displays latest version text when only 1 version is present', () => { + createComponent({ maxVersions: 1 }); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing Latest Version'); + }); + }); + + it('displays version text when the current version is not the latest', () => { + createComponent({ $route: designRouteFactory(PREVIOUS_VERSION_ID) }); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.find(GlDropdown).attributes('text')).toBe(`Showing Version #1`); + }); + }); + + it('displays latest version text when the current version is the latest', () => { + createComponent({ $route: designRouteFactory(LATEST_VERSION_ID) }); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing Latest Version'); + }); + }); + + it('should have the same length as apollo query', () => { + createComponent(); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.findAll(GlDropdownItem)).toHaveLength(wrapper.vm.allVersions.length); + }); + }); + }); +}); diff --git a/spec/frontend/design_management/components/upload/mock_data/all_versions.js b/spec/frontend/design_management/components/upload/mock_data/all_versions.js new file mode 100644 index 00000000000..e76bbd261bd --- /dev/null +++ b/spec/frontend/design_management/components/upload/mock_data/all_versions.js @@ -0,0 +1,14 @@ +export default [ + { + node: { + id: 'gid://gitlab/DesignManagement::Version/3', + sha: '0945756378e0b1588b9dd40d5a6b99e8b7198f55', + }, + }, + { + node: { + id: 'gid://gitlab/DesignManagement::Version/2', + sha: '5b063fef0cd7213b312db65b30e24f057df21b20', + }, + }, +]; |