Commit 404eab8b authored by Natalia Tepluhina's avatar Natalia Tepluhina Committed by Kushal Pandya

Fixed designs to display correct version

- persisted version as router query parameter;
- implemented errors on incorrect version;
- refactored mixins to separate versions from project
parent ba46f030
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import createFlash from '~/flash'; import createFlash from '~/flash';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue'; import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import allVersionsMixin from '../../mixins/all_versions';
import createNoteMutation from '../../graphql/mutations/createNote.mutation.graphql'; import createNoteMutation from '../../graphql/mutations/createNote.mutation.graphql';
import getDesignQuery from '../../graphql/queries/getDesign.query.graphql'; import getDesignQuery from '../../graphql/queries/getDesign.query.graphql';
import DesignNote from './design_note.vue'; import DesignNote from './design_note.vue';
...@@ -14,6 +15,7 @@ export default { ...@@ -14,6 +15,7 @@ export default {
ReplyPlaceholder, ReplyPlaceholder,
DesignReplyForm, DesignReplyForm,
}, },
mixins: [allVersionsMixin],
props: { props: {
discussion: { discussion: {
type: Object, type: Object,
...@@ -67,6 +69,7 @@ export default { ...@@ -67,6 +69,7 @@ export default {
query: getDesignQuery, query: getDesignQuery,
variables: { variables: {
id: this.designId, id: this.designId,
version: this.designsVersion,
}, },
}); });
const currentDiscussion = extractCurrentDiscussion( const currentDiscussion = extractCurrentDiscussion(
......
...@@ -42,7 +42,11 @@ export default { ...@@ -42,7 +42,11 @@ export default {
<template> <template>
<router-link <router-link
:to="{ name: 'design', params: { id: name } }" :to="{
name: 'design',
params: { id: name },
query: $route.query,
}"
class="card cursor-pointer text-plain js-design-list-item design-list-item" class="card cursor-pointer text-plain js-design-list-item design-list-item"
> >
<div class="card-body p-0 d-flex align-items-center overflow-hidden"> <div class="card-body p-0 d-flex align-items-center overflow-hidden">
......
...@@ -47,7 +47,10 @@ export default { ...@@ -47,7 +47,10 @@ export default {
<template> <template>
<header class="d-flex w-100 p-2 bg-white align-items-center js-design-header"> <header class="d-flex w-100 p-2 bg-white align-items-center js-design-header">
<router-link <router-link
:to="{ name: 'designs' }" :to="{
name: 'designs',
query: $route.query,
}"
:aria-label="s__('DesignManagement|Go back to designs')" :aria-label="s__('DesignManagement|Go back to designs')"
class="mr-3 text-plain" class="mr-3 text-plain"
> >
......
...@@ -24,7 +24,11 @@ export default { ...@@ -24,7 +24,11 @@ export default {
designLink() { designLink() {
if (!this.design) return {}; if (!this.design) return {};
return { name: 'design', params: { id: this.design.filename } }; return {
name: 'design',
params: { id: this.design.filename },
query: this.$route.query,
};
}, },
}, },
}; };
......
<script> <script>
import UploadButton from './button.vue'; import UploadButton from './button.vue';
import allVersionsMixin from '../../mixins/all_versions';
import DesignVersionDropdown from './design_version_dropdown.vue'; import DesignVersionDropdown from './design_version_dropdown.vue';
export default { export default {
...@@ -8,7 +7,6 @@ export default { ...@@ -8,7 +7,6 @@ export default {
UploadButton, UploadButton,
DesignVersionDropdown, DesignVersionDropdown,
}, },
mixins: [allVersionsMixin],
props: { props: {
isSaving: { isSaving: {
type: Boolean, type: Boolean,
...@@ -30,7 +28,7 @@ export default { ...@@ -30,7 +28,7 @@ export default {
<template> <template>
<header class="row-content-block border-top-0 p-2 d-flex"> <header class="row-content-block border-top-0 p-2 d-flex">
<div class="d-flex justify-content-between align-items-center w-100"> <div class="d-flex justify-content-between align-items-center w-100">
<design-version-dropdown :all-versions="allVersions" /> <design-version-dropdown />
<upload-button v-if="canUploadDesign" :is-saving="isSaving" @upload="onFileUploadChange" /> <upload-button v-if="canUploadDesign" :is-saving="isSaving" @upload="onFileUploadChange" />
</div> </div>
</header> </header>
......
import Vue from 'vue'; import Vue from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
import createDefaultClient from '~/lib/graphql'; import createDefaultClient from '~/lib/graphql';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import appDataQuery from './graphql/queries/appData.query.graphql'; import appDataQuery from './graphql/queries/appData.query.graphql';
import projectQuery from './graphql/queries/project.query.graphql'; import projectQuery from './graphql/queries/project.query.graphql';
const genericErrorMessage = s__(
'DesignManagement|An error occurred while loading designs. Please try again.',
);
Vue.use(VueApollo); Vue.use(VueApollo);
const defaultClient = createDefaultClient({ const defaultClient = createDefaultClient(
Query: { {
design(ctx, { id }, { cache, client }) { Query: {
const { projectPath, issueIid } = cache.readQuery({ query: appDataQuery }); design(ctx, { id, version }, { cache, client }) {
return client const { projectPath, issueIid } = cache.readQuery({ query: appDataQuery });
.query({ return client
query: projectQuery, .query({
variables: { fullPath: projectPath, iid: issueIid }, query: projectQuery,
}) variables: {
.then(({ data, errors }) => { fullPath: projectPath,
if (errors) { iid: issueIid,
createFlash( atVersion: version,
s__('DesignManagement|An error occurred while loading designs. Please try again.'), },
})
.then(({ data }) => {
const edge = data.project.issue.designs.designs.edges.find(
({ node }) => node.filename === id,
); );
throw new Error(errors); return edge.node;
} })
const edge = data.project.issue.designs.designs.edges.find( .catch(() => {
({ node }) => node.filename === id, createFlash(genericErrorMessage);
); });
return edge.node; },
})
.catch(() => {
createFlash(
s__('DesignManagement|An error occurred while loading designs. Please try again.'),
);
});
}, },
}, },
}); // This config is added temporarily to resolve an issue with duplicate design IDs.
// Should be removed as soon as https://gitlab.com/gitlab-org/gitlab-ee/issues/13495 is resolved
{
cacheConfig: {
dataIdFromObject: object => {
// eslint-disable-next-line no-underscore-dangle, @gitlab/i18n/no-non-i18n-strings
if (object.__typename === 'Design') {
return object.id && object.image ? `${object.id}-${object.image}` : null;
}
return defaultDataIdFromObject(object);
},
},
},
);
export default new VueApollo({ export default new VueApollo({
defaultClient, defaultClient,
......
#import "../fragments/designList.fragment.graphql" #import "../fragments/designList.fragment.graphql"
query getDesign($id: String!) { query getDesign($id: String!, $version: String) {
design(id: $id) @client { design(id: $id, version: $version) @client {
...DesignListItem ...DesignListItem
} }
} }
#import "../fragments/designList.fragment.graphql"
query getVersionDesigns($fullPath: ID!, $iid: String!, $atVersion: ID!) {
project(fullPath: $fullPath) {
id
issue(iid: $iid) {
iid
designs {
designs(atVersion: $atVersion) {
edges {
node {
...DesignListItem
}
}
}
}
}
}
}
#import "../fragments/designList.fragment.graphql" #import "../fragments/designList.fragment.graphql"
query project($fullPath: ID!, $iid: String!) { query project($fullPath: ID!, $iid: String!, $atVersion: ID) {
project(fullPath: $fullPath) { project(fullPath: $fullPath) {
id id
issue(iid: $iid) { issue(iid: $iid) {
designs { designs {
designs { designs(atVersion: $atVersion) {
edges { edges {
node { node {
...DesignListItem ...DesignListItem
......
...@@ -32,6 +32,7 @@ export default () => { ...@@ -32,6 +32,7 @@ export default () => {
variables: { variables: {
fullPath: projectPath, fullPath: projectPath,
iid: issueIid, iid: issueIid,
atVersion: null,
}, },
}) })
.subscribe(({ data }) => { .subscribe(({ data }) => {
......
import appDataQuery from '../graphql/queries/appData.query.graphql'; import createFlash from '~/flash';
import getVersionDesignsQuery from '../graphql/queries/getVersionDesigns.query.graphql'; import { s__ } from '~/locale';
import projectQuery from '../graphql/queries/project.query.graphql'; import projectQuery from '../graphql/queries/project.query.graphql';
import { extractNodes } from '../utils/design_management_utils'; import { extractNodes } from '../utils/design_management_utils';
import allVersionsMixin from './all_versions';
export default { export default {
mixins: [allVersionsMixin],
apollo: { apollo: {
appData: {
query: appDataQuery,
manual: true,
result({ data: { projectPath, issueIid } }) {
this.projectPath = projectPath;
this.issueIid = issueIid;
},
},
designs: { designs: {
query: projectQuery, query: projectQuery,
variables() { variables() {
return { return {
fullPath: this.projectPath, fullPath: this.projectPath,
iid: this.issueIid, iid: this.issueIid,
atVersion: this.designsVersion,
}; };
}, },
update: data => extractNodes(data.project.issue.designs.designs), update: data => extractNodes(data.project.issue.designs.designs),
error() { error() {
this.error = true; this.error = true;
}, },
}, result() {
versionDesigns: { if (this.$route.query.version && !this.hasValidVersion) {
query: getVersionDesignsQuery, createFlash(
fetchPolicy: 'no-cache', s__(
variables() { 'DesignManagement|Requested design version does not exist. Showing latest version instead',
return { ),
fullPath: this.projectPath, );
iid: this.issueIid, this.$router.replace({ name: 'designs', query: { version: undefined } });
atVersion: `gid://gitlab/DesignManagement::Version/${this.$route.query.version}`, }
};
},
skip() {
this.$apollo.queries.versionDesigns.skip = !this.hasValidVersion();
}, },
update: data => extractNodes(data.project.issue.designs.designs),
}, },
}, },
data() { data() {
return { return {
designs: [], designs: [],
error: false, error: false,
projectPath: '',
issueIid: null,
versionDesigns: [],
}; };
}, },
methods: {
hasValidVersion() {
if (Object.keys(this.$route.query).length === 0) {
return false;
}
return this.allVersions.some(version => version.node.id.endsWith(this.$route.query.version));
},
},
}; };
import projectQuery from '../graphql/queries/project.query.graphql';
import appDataQuery from '../graphql/queries/appData.query.graphql';
export default { export default {
props: { apollo: {
appData: {
query: appDataQuery,
manual: true,
result({ data: { projectPath, issueIid } }) {
this.projectPath = projectPath;
this.issueIid = issueIid;
},
},
allVersions: { allVersions: {
type: Array, query: projectQuery,
required: true, variables() {
return {
fullPath: this.projectPath,
iid: this.issueIid,
atVersion: null,
};
},
update: data => data.project.issue.designs.versions.edges,
},
},
computed: {
hasValidVersion() {
return (
this.$route.query.version &&
this.allVersions &&
this.allVersions.some(version => version.node.id.endsWith(this.$route.query.version))
);
}, },
designsVersion() {
return this.hasValidVersion
? `gid://gitlab/DesignManagement::Version/${this.$route.query.version}`
: null;
},
},
data() {
return {
allVersions: [],
projectPath: '',
issueIid: null,
};
}, },
}; };
...@@ -3,6 +3,7 @@ import Mousetrap from 'mousetrap'; ...@@ -3,6 +3,7 @@ import Mousetrap from 'mousetrap';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { GlLoadingIcon } from '@gitlab/ui'; import { GlLoadingIcon } from '@gitlab/ui';
import allVersionsMixin from '../../mixins/all_versions';
import Toolbar from '../../components/toolbar/index.vue'; import Toolbar from '../../components/toolbar/index.vue';
import DesignImage from '../../components/image.vue'; import DesignImage from '../../components/image.vue';
import DesignOverlay from '../../components/design_overlay.vue'; import DesignOverlay from '../../components/design_overlay.vue';
...@@ -10,7 +11,6 @@ import DesignDiscussion from '../../components/design_notes/design_discussion.vu ...@@ -10,7 +11,6 @@ import DesignDiscussion from '../../components/design_notes/design_discussion.vu
import DesignReplyForm from '../../components/design_notes/design_reply_form.vue'; import DesignReplyForm from '../../components/design_notes/design_reply_form.vue';
import getDesignQuery from '../../graphql/queries/getDesign.query.graphql'; import getDesignQuery from '../../graphql/queries/getDesign.query.graphql';
import createImageDiffNoteMutation from '../../graphql/mutations/createImageDiffNote.mutation.graphql'; import createImageDiffNoteMutation from '../../graphql/mutations/createImageDiffNote.mutation.graphql';
import appDataQuery from '../../graphql/queries/appData.query.graphql';
import { extractDiscussions } from '../../utils/design_management_utils'; import { extractDiscussions } from '../../utils/design_management_utils';
export default { export default {
...@@ -22,6 +22,7 @@ export default { ...@@ -22,6 +22,7 @@ export default {
DesignReplyForm, DesignReplyForm,
GlLoadingIcon, GlLoadingIcon,
}, },
mixins: [allVersionsMixin],
props: { props: {
id: { id: {
type: String, type: String,
...@@ -47,20 +48,18 @@ export default { ...@@ -47,20 +48,18 @@ export default {
variables() { variables() {
return { return {
id: this.id, id: this.id,
version: this.designsVersion,
}; };
}, },
result({ data }) { result({ data }) {
if (!data) { if (!data) {
createFlash(s__('DesignManagement|Could not find design, please try again.')); createFlash(s__('DesignManagement|Could not find design, please try again.'));
this.$router.push('/designs'); this.$router.push({ name: 'designs' });
}
if (this.$route.query.version && !this.hasValidVersion) {
createFlash(s__('DesignManagement|Requested design version does not exist'));
this.$router.push({ name: 'designs' });
} }
},
},
appData: {
query: appDataQuery,
manual: true,
result({ data: { projectPath } }) {
this.projectPath = projectPath;
}, },
}, },
}, },
...@@ -120,6 +119,7 @@ export default { ...@@ -120,6 +119,7 @@ export default {
query: getDesignQuery, query: getDesignQuery,
variables: { variables: {
id: this.id, id: this.id,
version: this.designsVersion,
}, },
}); });
const newDiscussion = { const newDiscussion = {
...@@ -175,9 +175,10 @@ export default { ...@@ -175,9 +175,10 @@ export default {
this.overlayDimensions.height = position.height; this.overlayDimensions.height = position.height;
}, },
closeDesign() { closeDesign() {
// This needs to be changed to take a design version into account as soon as this.$router.push({
// https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/15119 is merged name: 'designs',
this.$router.push('/designs'); query: this.$route.query,
});
}, },
}, },
beforeRouteUpdate(to, from, next) { beforeRouteUpdate(to, from, next) {
......
...@@ -33,16 +33,6 @@ export default { ...@@ -33,16 +33,6 @@ export default {
}, },
update: data => data.project.issue.userPermissions, update: data => data.project.issue.userPermissions,
}, },
allVersions: {
query: projectQuery,
variables() {
return {
fullPath: this.projectPath,
iid: this.issueIid,
};
},
update: data => data.project.issue.designs.versions.edges,
},
}, },
data() { data() {
return { return {
...@@ -50,7 +40,6 @@ export default { ...@@ -50,7 +40,6 @@ export default {
createDesign: false, createDesign: false,
}, },
isSaving: false, isSaving: false,
allVersions: [],
}; };
}, },
computed: { computed: {
...@@ -66,9 +55,6 @@ export default { ...@@ -66,9 +55,6 @@ export default {
hasDesigns() { hasDesigns() {
return this.designs.length > 0; return this.designs.length > 0;
}, },
hasVersion() {
return this.hasValidVersion();
},
}, },
methods: { methods: {
onUploadDesign(files) { onUploadDesign(files) {
...@@ -132,7 +118,7 @@ export default { ...@@ -132,7 +118,7 @@ export default {
update: (store, { data: { designManagementUpload } }) => { update: (store, { data: { designManagementUpload } }) => {
const data = store.readQuery({ const data = store.readQuery({
query: projectQuery, query: projectQuery,
variables: { fullPath: this.projectPath, iid: this.issueIid }, variables: { fullPath: this.projectPath, iid: this.issueIid, atVersion: null },
}); });
const newDesigns = data.project.issue.designs.designs.edges.reduce((acc, design) => { const newDesigns = data.project.issue.designs.designs.edges.reduce((acc, design) => {
...@@ -189,7 +175,7 @@ export default { ...@@ -189,7 +175,7 @@ export default {
store.writeQuery({ store.writeQuery({
query: projectQuery, query: projectQuery,
variables: { fullPath: this.projectPath, iid: this.issueIid }, variables: { fullPath: this.projectPath, iid: this.issueIid, atVersion: null },
data: newQueryData, data: newQueryData,
}); });
}, },
...@@ -204,7 +190,7 @@ export default { ...@@ -204,7 +190,7 @@ export default {
}, },
}) })
.then(() => { .then(() => {
this.$router.push('/designs'); this.$router.push({ name: 'designs' });
}) })
.catch(e => { .catch(e => {
createFlash(s__('DesignManagement|Error uploading a new design. Please try again')); createFlash(s__('DesignManagement|Error uploading a new design. Please try again'));
...@@ -232,7 +218,6 @@ export default { ...@@ -232,7 +218,6 @@ export default {
<div v-else-if="error" class="alert alert-danger"> <div v-else-if="error" class="alert alert-danger">
{{ __('An error occurred while loading designs. Please try again.') }} {{ __('An error occurred while loading designs. Please try again.') }}
</div> </div>
<design-list v-else-if="hasVersion" :designs="versionDesigns" />
<design-list v-else-if="hasDesigns" :designs="designs" /> <design-list v-else-if="hasDesigns" :designs="designs" />
<gl-empty-state <gl-empty-state
v-else v-else
......
---
title: Resolve Design viewer does not respect version
merge_request: 15119
author:
type: fixed
...@@ -2,16 +2,17 @@ import { shallowMount } from '@vue/test-utils'; ...@@ -2,16 +2,17 @@ import { shallowMount } from '@vue/test-utils';
import DesignImage from 'ee/design_management/components/image.vue'; import DesignImage from 'ee/design_management/components/image.vue';
describe('Design management large image component', () => { describe('Design management large image component', () => {
let vm; let wrapper;
function createComponent(propsData) { function createComponent(propsData) {
vm = shallowMount(DesignImage, { wrapper = shallowMount(DesignImage, {
sync: false,
propsData, propsData,
}); });
} }
afterEach(() => { afterEach(() => {
vm.destroy(); wrapper.destroy();
}); });
it('renders loading state', () => { it('renders loading state', () => {
...@@ -19,7 +20,7 @@ describe('Design management large image component', () => { ...@@ -19,7 +20,7 @@ describe('Design management large image component', () => {
isLoading: true, isLoading: true,
}); });
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('renders image', () => { it('renders image', () => {
...@@ -29,6 +30,6 @@ describe('Design management large image component', () => { ...@@ -29,6 +30,6 @@ describe('Design management large image component', () => {
name: 'test', name: 'test',
}); });
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
}); });
...@@ -10,10 +10,11 @@ const createMockDesign = id => ({ ...@@ -10,10 +10,11 @@ const createMockDesign = id => ({
}); });
describe('Design management list component', () => { describe('Design management list component', () => {
let vm; let wrapper;
function createComponent() { function createComponent() {
vm = shallowMount(List, { wrapper = shallowMount(List, {
sync: false,
propsData: { propsData: {
designs: [createMockDesign(1), createMockDesign(2)], designs: [createMockDesign(1), createMockDesign(2)],
}, },
...@@ -21,12 +22,12 @@ describe('Design management list component', () => { ...@@ -21,12 +22,12 @@ describe('Design management list component', () => {
} }
afterEach(() => { afterEach(() => {
vm.destroy(); wrapper.destroy();
}); });
it('renders list', () => { it('renders list', () => {
createComponent(); createComponent();
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
}); });
import { shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueRouter from 'vue-router';
import Item from 'ee/design_management/components/list/item.vue'; import Item from 'ee/design_management/components/list/item.vue';
const localVue = createLocalVue();
localVue.use(VueRouter);
const router = new VueRouter();
describe('Design management list item component', () => { describe('Design management list item component', () => {
let vm; let wrapper;
function createComponent(commentsCount = 1) { function createComponent(commentsCount = 1) {
vm = shallowMount(Item, { wrapper = shallowMount(Item, {
sync: false,
localVue,
router,
propsData: { propsData: {
id: 1, id: 1,
name: 'test', name: 'test',
...@@ -18,24 +26,24 @@ describe('Design management list item component', () => { ...@@ -18,24 +26,24 @@ describe('Design management list item component', () => {
} }
afterEach(() => { afterEach(() => {
vm.destroy(); wrapper.destroy();
}); });
it('renders item with single comment', () => { it('renders item with single comment', () => {
createComponent(); createComponent();
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('renders item with multiple comments', () => { it('renders item with multiple comments', () => {
createComponent(2); createComponent(2);
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('hides comment count', () => { it('hides comment count', () => {
createComponent(0); createComponent(0);
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
}); });
import { shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueRouter from 'vue-router';
import Toolbar from 'ee/design_management/components/toolbar/index.vue'; import Toolbar from 'ee/design_management/components/toolbar/index.vue';
const localVue = createLocalVue();
localVue.use(VueRouter);
const router = new VueRouter();
const RouterLinkStub = { const RouterLinkStub = {
props: { props: {
to: { to: {
...@@ -13,13 +18,16 @@ const RouterLinkStub = { ...@@ -13,13 +18,16 @@ const RouterLinkStub = {
}; };
describe('Design management toolbar component', () => { describe('Design management toolbar component', () => {
let vm; let wrapper;
function createComponent(isLoading = false) { function createComponent(isLoading = false) {
const updatedAt = new Date(); const updatedAt = new Date();
updatedAt.setHours(updatedAt.getHours() - 1); updatedAt.setHours(updatedAt.getHours() - 1);
vm = shallowMount(Toolbar, { wrapper = shallowMount(Toolbar, {
sync: false,
localVue,
router,
propsData: { propsData: {
id: '1', id: '1',
isLoading, isLoading,
...@@ -38,16 +46,19 @@ describe('Design management toolbar component', () => { ...@@ -38,16 +46,19 @@ describe('Design management toolbar component', () => {
it('renders design and updated data', () => { it('renders design and updated data', () => {
createComponent(); createComponent();
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('links back to designs list', () => { it('links back to designs list', () => {
createComponent(); createComponent();
const link = vm.find('a'); const link = wrapper.find('a');
expect(link.props('to')).toEqual({ expect(link.props('to')).toEqual({
name: 'designs', name: 'designs',
query: {
version: undefined,
},
}); });
}); });
}); });
import { shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueRouter from 'vue-router';
import PaginationButton from 'ee/design_management/components/toolbar/pagination_button.vue'; import PaginationButton from 'ee/design_management/components/toolbar/pagination_button.vue';
const localVue = createLocalVue();
localVue.use(VueRouter);
const router = new VueRouter();
describe('Design management pagination button component', () => { describe('Design management pagination button component', () => {
let vm; let wrapper;
function createComponent(design = null) { function createComponent(design = null) {
vm = shallowMount(PaginationButton, { wrapper = shallowMount(PaginationButton, {
sync: false,
localVue,
router,
propsData: { propsData: {
design, design,
title: 'Test title', title: 'Test title',
...@@ -16,34 +24,37 @@ describe('Design management pagination button component', () => { ...@@ -16,34 +24,37 @@ describe('Design management pagination button component', () => {
} }
afterEach(() => { afterEach(() => {
vm.destroy(); wrapper.destroy();
}); });
it('disables button when no design is passed', () => { it('disables button when no design is passed', () => {
createComponent(); createComponent();
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('renders router-link', () => { it('renders router-link', () => {
createComponent({ id: '2' }); createComponent({ id: '2' });
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
describe('designLink', () => { describe('designLink', () => {
it('returns empty link when design is null', () => { it('returns empty link when design is null', () => {
createComponent(); createComponent();
expect(vm.vm.designLink).toEqual({}); expect(wrapper.vm.designLink).toEqual({});
}); });
it('returns design link', () => { it('returns design link', () => {
createComponent({ id: '2', filename: 'test' }); createComponent({ id: '2', filename: 'test' });
expect(vm.vm.designLink).toEqual({ wrapper.vm.$router.replace('/root/test-project/issues/1/designs/test?version=1');
expect(wrapper.vm.designLink).toEqual({
name: 'design', name: 'design',
params: { id: 'test' }, params: { id: 'test' },
query: { version: '1' },
}); });
}); });
}); });
......
...@@ -2,10 +2,10 @@ import { shallowMount } from '@vue/test-utils'; ...@@ -2,10 +2,10 @@ import { shallowMount } from '@vue/test-utils';
import Pagination from 'ee/design_management/components/toolbar/pagination.vue'; import Pagination from 'ee/design_management/components/toolbar/pagination.vue';
describe('Design management pagination component', () => { describe('Design management pagination component', () => {
let vm; let wrapper;
function createComponent() { function createComponent() {
vm = shallowMount(Pagination, { wrapper = shallowMount(Pagination, {
propsData: { propsData: {
id: '2', id: '2',
}, },
...@@ -17,18 +17,18 @@ describe('Design management pagination component', () => { ...@@ -17,18 +17,18 @@ describe('Design management pagination component', () => {
}); });
afterEach(() => { afterEach(() => {
vm.destroy(); wrapper.destroy();
}); });
it('hides components when designs are empty', () => { it('hides components when designs are empty', () => {
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('renders pagination buttons', () => { it('renders pagination buttons', () => {
vm.setData({ wrapper.setData({
designs: [{ id: '1' }, { id: '2' }], designs: [{ id: '1' }, { id: '2' }],
}); });
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
}); });
...@@ -9,9 +9,7 @@ exports[`Design management upload form component hides button if cant upload 1`] ...@@ -9,9 +9,7 @@ exports[`Design management upload form component hides button if cant upload 1`]
<div <div
class="d-flex justify-content-between align-items-center w-100" class="d-flex justify-content-between align-items-center w-100"
> >
<designversiondropdown-stub <designversiondropdown-stub />
all-versions=""
/>
<!----> <!---->
</div> </div>
...@@ -27,9 +25,7 @@ exports[`Design management upload form component renders upload design button 1` ...@@ -27,9 +25,7 @@ exports[`Design management upload form component renders upload design button 1`
<div <div
class="d-flex justify-content-between align-items-center w-100" class="d-flex justify-content-between align-items-center w-100"
> >
<designversiondropdown-stub <designversiondropdown-stub />
all-versions=""
/>
<uploadbutton-stub /> <uploadbutton-stub />
</div> </div>
......
...@@ -2,10 +2,11 @@ import { shallowMount } from '@vue/test-utils'; ...@@ -2,10 +2,11 @@ import { shallowMount } from '@vue/test-utils';
import UploadButton from 'ee/design_management/components/upload/button.vue'; import UploadButton from 'ee/design_management/components/upload/button.vue';
describe('Design management upload button component', () => { describe('Design management upload button component', () => {
let vm; let wrapper;
function createComponent(isSaving = false, isInverted = false) { function createComponent(isSaving = false, isInverted = false) {
vm = shallowMount(UploadButton, { wrapper = shallowMount(UploadButton, {
sync: false,
propsData: { propsData: {
isSaving, isSaving,
isInverted, isInverted,
...@@ -14,36 +15,38 @@ describe('Design management upload button component', () => { ...@@ -14,36 +15,38 @@ describe('Design management upload button component', () => {
} }
afterEach(() => { afterEach(() => {
vm.destroy(); wrapper.destroy();
}); });
it('renders upload design button', () => { it('renders upload design button', () => {
createComponent(); createComponent();
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('renders inverted upload design button', () => { it('renders inverted upload design button', () => {
createComponent(false, true); createComponent(false, true);
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('renders loading icon', () => { it('renders loading icon', () => {
createComponent(true); createComponent(true);
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
describe('onFileUploadChange', () => { describe('onFileUploadChange', () => {
it('emits upload event', () => { it('emits upload event', () => {
createComponent(); createComponent();
jest.spyOn(vm.find({ ref: 'fileUpload' }).element, 'files', 'get').mockReturnValue('test'); jest
.spyOn(wrapper.find({ ref: 'fileUpload' }).element, 'files', 'get')
.mockReturnValue('test');
vm.vm.onFileUploadChange('test'); wrapper.vm.onFileUploadChange('test');
expect(vm.emitted().upload[0]).toEqual(['test']); expect(wrapper.emitted().upload[0]).toEqual(['test']);
}); });
}); });
...@@ -51,9 +54,9 @@ describe('Design management upload button component', () => { ...@@ -51,9 +54,9 @@ describe('Design management upload button component', () => {
it('triggers click on input', () => { it('triggers click on input', () => {
createComponent(); createComponent();
const clickSpy = jest.spyOn(vm.find({ ref: 'fileUpload' }).element, 'click'); const clickSpy = jest.spyOn(wrapper.find({ ref: 'fileUpload' }).element, 'click');
vm.vm.openFileUpload(); wrapper.vm.openFileUpload();
expect(clickSpy).toHaveBeenCalled(); expect(clickSpy).toHaveBeenCalled();
}); });
......
...@@ -17,11 +17,14 @@ describe('Design management design version dropdown component', () => { ...@@ -17,11 +17,14 @@ describe('Design management design version dropdown component', () => {
propsData: { propsData: {
projectPath: '', projectPath: '',
issueIid: '', issueIid: '',
allVersions: mockAllVersions,
}, },
localVue, localVue,
router, router,
}); });
wrapper.setData({
allVersions: mockAllVersions,
});
} }
afterEach(() => { afterEach(() => {
......
...@@ -2,43 +2,43 @@ import { shallowMount } from '@vue/test-utils'; ...@@ -2,43 +2,43 @@ import { shallowMount } from '@vue/test-utils';
import UploadForm from 'ee/design_management/components/upload/form.vue'; import UploadForm from 'ee/design_management/components/upload/form.vue';
describe('Design management upload form component', () => { describe('Design management upload form component', () => {
let vm; let wrapper;
function createComponent(isSaving = false, canUploadDesign = true) { function createComponent(isSaving = false, canUploadDesign = true) {
vm = shallowMount(UploadForm, { wrapper = shallowMount(UploadForm, {
sync: false,
propsData: { propsData: {
isSaving, isSaving,
canUploadDesign, canUploadDesign,
projectPath: '', projectPath: '',
issueIid: '', issueIid: '',
allVersions: [],
}, },
}); });
} }
afterEach(() => { afterEach(() => {
vm.destroy(); wrapper.destroy();
}); });
it('renders upload design button', () => { it('renders upload design button', () => {
createComponent(); createComponent();
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('hides button if cant upload', () => { it('hides button if cant upload', () => {
createComponent(false, false); createComponent(false, false);
expect(vm.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
describe('onFileUploadChange', () => { describe('onFileUploadChange', () => {
it('emits upload event', () => { it('emits upload event', () => {
createComponent(); createComponent();
vm.vm.onFileUploadChange('test'); wrapper.vm.onFileUploadChange('test');
expect(vm.emitted().upload[0]).toEqual(['test']); expect(wrapper.emitted().upload[0]).toEqual(['test']);
}); });
}); });
}); });
...@@ -6,7 +6,15 @@ import uploadDesignQuery from 'ee/design_management/graphql/mutations/uploadDesi ...@@ -6,7 +6,15 @@ import uploadDesignQuery from 'ee/design_management/graphql/mutations/uploadDesi
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(VueRouter); localVue.use(VueRouter);
const router = new VueRouter(); const router = new VueRouter({
routes: [
{
name: 'designs',
path: '/designs',
component: Index,
},
],
});
describe('Design management index page', () => { describe('Design management index page', () => {
let mutate; let mutate;
......
...@@ -4990,6 +4990,12 @@ msgstr "" ...@@ -4990,6 +4990,12 @@ msgstr ""
msgid "DesignManagement|Go to previous design" msgid "DesignManagement|Go to previous design"
msgstr "" msgstr ""
msgid "DesignManagement|Requested design version does not exist"
msgstr ""
msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
msgstr ""
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again." msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr "" msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment