Commit e97fb6f7 authored by Natalia Tepluhina's avatar Natalia Tepluhina Committed by Nicolò Maria Mezzopera

Added a copy of design management app

This copy to be removed after feature flag removal
Copied unit tests for new app

- fixed an absolute path reference
Moved design management app

Moved unit tests for designs

- Copied all specs
- Fixed router spec
Fixed index spec

Fixed e2e spec for not available feature

Changed local query to provide/inject

Fixed issue_tabs feature spec

Fixed designs page spec

Fixed discussion spec

Fixed design index spec

Fixed spec for enabled FF

Updated permissions and upload spec

Fixed uploads spec

Updated snapshots for designs

Fixed specs for svg

Reverted change to smooth scrolling

Click on close design button in feature test

- add data-testid
- click on data-testid

Updated index snapshots

Removed unused meta info from route

Changed id to data-testid
parent e3aa3533
...@@ -13,13 +13,14 @@ export default { ...@@ -13,13 +13,14 @@ export default {
type: Array, type: Array,
required: true, required: true,
}, },
},
inject: {
projectPath: { projectPath: {
type: String, default: '',
required: true,
}, },
iid: { iid: {
type: String, from: 'issueIid',
required: true, defaut: '',
}, },
}, },
computed: { computed: {
......
...@@ -60,7 +60,7 @@ export default { ...@@ -60,7 +60,7 @@ export default {
}, },
mounted() { mounted() {
if (this.isNoteLinked) { if (this.isNoteLinked) {
this.$refs.anchor.$el.scrollIntoView({ behavior: 'smooth', inline: 'start' }); this.$el.scrollIntoView({ behavior: 'smooth', inline: 'start' });
} }
}, },
methods: { methods: {
...@@ -80,7 +80,7 @@ export default { ...@@ -80,7 +80,7 @@ export default {
</script> </script>
<template> <template>
<timeline-entry-item :id="`note_${noteAnchorId}`" ref="anchor" class="design-note note-form"> <timeline-entry-item :id="`note_${noteAnchorId}`" class="design-note note-form">
<user-avatar-link <user-avatar-link
:link-href="author.webUrl" :link-href="author.webUrl"
:img-src="author.avatarUrl" :img-src="author.avatarUrl"
......
...@@ -6,7 +6,6 @@ import timeagoMixin from '~/vue_shared/mixins/timeago'; ...@@ -6,7 +6,6 @@ import timeagoMixin from '~/vue_shared/mixins/timeago';
import Pagination from './pagination.vue'; import Pagination from './pagination.vue';
import DeleteButton from '../delete_button.vue'; import DeleteButton from '../delete_button.vue';
import permissionsQuery from '../../graphql/queries/design_permissions.query.graphql'; import permissionsQuery from '../../graphql/queries/design_permissions.query.graphql';
import appDataQuery from '../../graphql/queries/app_data.query.graphql';
import { DESIGNS_ROUTE_NAME } from '../../router/constants'; import { DESIGNS_ROUTE_NAME } from '../../router/constants';
export default { export default {
...@@ -55,19 +54,17 @@ export default { ...@@ -55,19 +54,17 @@ export default {
permissions: { permissions: {
createDesign: false, createDesign: false,
}, },
projectPath: '',
issueIid: null,
}; };
}, },
apollo: { inject: {
appData: { projectPath: {
query: appDataQuery, default: '',
manual: true,
result({ data: { projectPath, issueIid } }) {
this.projectPath = projectPath;
this.issueIid = issueIid;
},
}, },
issueIid: {
default: '',
},
},
apollo: {
permissions: { permissions: {
query: permissionsQuery, query: permissionsQuery,
variables() { variables() {
...@@ -102,6 +99,7 @@ export default { ...@@ -102,6 +99,7 @@ export default {
query: $route.query, query: $route.query,
}" }"
:aria-label="s__('DesignManagement|Go back to designs')" :aria-label="s__('DesignManagement|Go back to designs')"
data-testid="close-design"
class="mr-3 text-plain d-flex justify-content-center align-items-center" class="mr-3 text-plain d-flex justify-content-center align-items-center"
> >
<icon :size="18" name="close" /> <icon :size="18" name="close" />
......
query projectFullPath {
projectPath @client
issueIid @client
}
import $ from 'jquery';
import Vue from 'vue'; import Vue from 'vue';
import createRouter from './router'; import createRouter from './router';
import App from './components/app.vue'; import App from './components/app.vue';
import apolloProvider from './graphql'; import apolloProvider from './graphql';
import getDesignListQuery from './graphql/queries/get_design_list.query.graphql';
import { DESIGNS_ROUTE_NAME, ROOT_ROUTE_NAME } from './router/constants';
export default () => { export default () => {
const el = document.querySelector('.js-design-management-new'); const el = document.querySelector('.js-design-management-new');
const badge = document.querySelector('.js-designs-count');
const { issueIid, projectPath, issuePath } = el.dataset; const { issueIid, projectPath, issuePath } = el.dataset;
const router = createRouter(issuePath); const router = createRouter(issuePath);
$('.js-issue-tabs').on('shown.bs.tab', ({ target: { id } }) => {
if (id === 'designs' && router.currentRoute.name === ROOT_ROUTE_NAME) {
router.push({ name: DESIGNS_ROUTE_NAME });
} else if (id === 'discussion') {
router.push({ name: ROOT_ROUTE_NAME });
}
});
apolloProvider.clients.defaultClient.cache.writeData({ apolloProvider.clients.defaultClient.cache.writeData({
data: { data: {
projectPath,
issueIid,
activeDiscussion: { activeDiscussion: {
__typename: 'ActiveDiscussion', __typename: 'ActiveDiscussion',
id: null, id: null,
...@@ -32,25 +18,14 @@ export default () => { ...@@ -32,25 +18,14 @@ export default () => {
}, },
}); });
apolloProvider.clients.defaultClient
.watchQuery({
query: getDesignListQuery,
variables: {
fullPath: projectPath,
iid: issueIid,
atVersion: null,
},
})
.subscribe(({ data }) => {
if (badge) {
badge.textContent = data.project.issue.designCollection.designs.edges.length;
}
});
return new Vue({ return new Vue({
el, el,
router, router,
apolloProvider, apolloProvider,
provide: {
projectPath,
issueIid,
},
render(createElement) { render(createElement) {
return createElement(App); return createElement(App);
}, },
......
import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql'; import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql';
import appDataQuery from '../graphql/queries/app_data.query.graphql';
import { findVersionId } from '../utils/design_management_utils'; import { findVersionId } from '../utils/design_management_utils';
export default { export default {
apollo: { apollo: {
appData: {
query: appDataQuery,
manual: true,
result({ data: { projectPath, issueIid } }) {
this.projectPath = projectPath;
this.issueIid = issueIid;
},
},
allVersions: { allVersions: {
query: getDesignListQuery, query: getDesignListQuery,
variables() { variables() {
...@@ -24,6 +15,14 @@ export default { ...@@ -24,6 +15,14 @@ export default {
update: data => data.project.issue.designCollection.versions.edges, update: data => data.project.issue.designCollection.versions.edges,
}, },
}, },
inject: {
projectPath: {
default: '',
},
issueIid: {
default: '',
},
},
computed: { computed: {
hasValidVersion() { hasValidVersion() {
return ( return (
...@@ -55,8 +54,6 @@ export default { ...@@ -55,8 +54,6 @@ export default {
data() { data() {
return { return {
allVersions: [], allVersions: [],
projectPath: '',
issueIid: null,
}; };
}, },
}; };
...@@ -12,7 +12,6 @@ import DesignPresentation from '../../components/design_presentation.vue'; ...@@ -12,7 +12,6 @@ import DesignPresentation from '../../components/design_presentation.vue';
import DesignReplyForm from '../../components/design_notes/design_reply_form.vue'; import DesignReplyForm from '../../components/design_notes/design_reply_form.vue';
import DesignSidebar from '../../components/design_sidebar.vue'; import DesignSidebar from '../../components/design_sidebar.vue';
import getDesignQuery from '../../graphql/queries/get_design.query.graphql'; import getDesignQuery from '../../graphql/queries/get_design.query.graphql';
import appDataQuery from '../../graphql/queries/app_data.query.graphql';
import createImageDiffNoteMutation from '../../graphql/mutations/create_image_diff_note.mutation.graphql'; import createImageDiffNoteMutation from '../../graphql/mutations/create_image_diff_note.mutation.graphql';
import updateImageDiffNoteMutation from '../../graphql/mutations/update_image_diff_note.mutation.graphql'; import updateImageDiffNoteMutation from '../../graphql/mutations/update_image_diff_note.mutation.graphql';
import updateActiveDiscussionMutation from '../../graphql/mutations/update_active_discussion.mutation.graphql'; import updateActiveDiscussionMutation from '../../graphql/mutations/update_active_discussion.mutation.graphql';
...@@ -62,22 +61,12 @@ export default { ...@@ -62,22 +61,12 @@ export default {
design: {}, design: {},
comment: '', comment: '',
annotationCoordinates: null, annotationCoordinates: null,
projectPath: '',
errorMessage: '', errorMessage: '',
issueIid: '',
scale: 1, scale: 1,
resolvedDiscussionsExpanded: false, resolvedDiscussionsExpanded: false,
}; };
}, },
apollo: { apollo: {
appData: {
query: appDataQuery,
manual: true,
result({ data: { projectPath, issueIid } }) {
this.projectPath = projectPath;
this.issueIid = issueIid;
},
},
design: { design: {
query: getDesignQuery, query: getDesignQuery,
// We want to see cached design version if we have one, and fetch newer version on the background to update discussions // We want to see cached design version if we have one, and fetch newer version on the background to update discussions
......
...@@ -259,7 +259,7 @@ export default { ...@@ -259,7 +259,7 @@ export default {
</script> </script>
<template> <template>
<div> <div data-testid="designs-root">
<header v-if="showToolbar" class="row-content-block border-top-0 p-2 d-flex"> <header v-if="showToolbar" 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 /> <design-version-dropdown />
...@@ -274,8 +274,6 @@ export default { ...@@ -274,8 +274,6 @@ export default {
<design-destroyer <design-destroyer
#default="{ mutate, loading }" #default="{ mutate, loading }"
:filenames="selectedDesigns" :filenames="selectedDesigns"
:project-path="projectPath"
:iid="issueIid"
@done="onDesignDelete" @done="onDesignDelete"
@error="onDesignDeleteError" @error="onDesignDeleteError"
> >
......
export const ROOT_ROUTE_NAME = 'root';
export const DESIGNS_ROUTE_NAME = 'designs'; export const DESIGNS_ROUTE_NAME = 'designs';
export const DESIGN_ROUTE_NAME = 'design'; export const DESIGN_ROUTE_NAME = 'design';
import $ from 'jquery';
import Vue from 'vue'; import Vue from 'vue';
import VueRouter from 'vue-router'; import VueRouter from 'vue-router';
import routes from './routes'; import routes from './routes';
...@@ -16,9 +15,7 @@ export default function createRouter(base) { ...@@ -16,9 +15,7 @@ export default function createRouter(base) {
}); });
const pageEl = getPageLayoutElement(); const pageEl = getPageLayoutElement();
router.beforeEach(({ meta: { el }, name }, _, next) => { router.beforeEach(({ name }, _, next) => {
$(`#${el}`).tab('show');
// apply a fullscreen layout style in Design View (a.k.a design detail) // apply a fullscreen layout style in Design View (a.k.a design detail)
if (pageEl) { if (pageEl) {
if (name === DESIGN_ROUTE_NAME) { if (name === DESIGN_ROUTE_NAME) {
......
import Home from '../pages/index.vue'; import Home from '../pages/index.vue';
import DesignDetail from '../pages/design/index.vue'; import DesignDetail from '../pages/design/index.vue';
import { ROOT_ROUTE_NAME, DESIGNS_ROUTE_NAME, DESIGN_ROUTE_NAME } from './constants'; import { DESIGNS_ROUTE_NAME, DESIGN_ROUTE_NAME } from './constants';
export default [ export default [
{ {
name: ROOT_ROUTE_NAME, name: DESIGNS_ROUTE_NAME,
path: '/', path: '/',
component: Home, component: Home,
meta: {
el: 'discussion',
},
}, },
{ {
name: DESIGNS_ROUTE_NAME, name: DESIGN_ROUTE_NAME,
path: '/designs', path: '/designs/:id',
component: Home, component: DesignDetail,
meta: { beforeEnter(
el: 'designs',
},
children: [
{ {
name: DESIGN_ROUTE_NAME, params: { id },
path: ':id',
component: DesignDetail,
meta: {
el: 'designs',
},
beforeEnter(
{
params: { id },
},
from,
next,
) {
if (typeof id === 'string') {
next();
}
},
props: ({ params: { id } }) => ({ id }),
}, },
], from,
next,
) {
if (typeof id === 'string') {
next();
}
},
props: ({ params: { id } }) => ({ id }),
}, },
]; ];
...@@ -77,6 +77,9 @@ ...@@ -77,6 +77,9 @@
- if @issue.sentry_issue.present? - if @issue.sentry_issue.present?
#js-sentry-error-stack-trace{ data: error_details_data(@project, @issue.sentry_issue.sentry_issue_identifier) } #js-sentry-error-stack-trace{ data: error_details_data(@project, @issue.sentry_issue.sentry_issue_identifier) }
- if Feature.enabled?(:design_management_moved, @project)
= render 'projects/issues/design_management'
= render_if_exists 'projects/issues/related_issues' = render_if_exists 'projects/issues/related_issues'
#js-related-merge-requests{ data: { endpoint: expose_path(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid)), project_namespace: @project.namespace.path, project_path: @project.path } } #js-related-merge-requests{ data: { endpoint: expose_path(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid)), project_namespace: @project.namespace.path, project_path: @project.path } }
...@@ -94,6 +97,9 @@ ...@@ -94,6 +97,9 @@
#js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(@issue), notes_filters: UserPreference.notes_filters.to_json } } #js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(@issue), notes_filters: UserPreference.notes_filters.to_json } }
= render 'new_branch' if show_new_branch_button? = render 'new_branch' if show_new_branch_button?
= render 'projects/issues/tabs' - if Feature.enabled?(:design_management_moved, @project)
= render 'projects/issues/discussion'
- else
= render 'projects/issues/tabs'
= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @issue.assignees = render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @issue.assignees
...@@ -10,6 +10,7 @@ RSpec.describe 'Issue page tabs', :js do ...@@ -10,6 +10,7 @@ RSpec.describe 'Issue page tabs', :js do
describe 'discussions tab counter' do describe 'discussions tab counter' do
before do before do
allow(Ability).to receive(:allowed?) { true } allow(Ability).to receive(:allowed?) { true }
stub_feature_flags(design_management_moved: false)
end end
subject do subject do
......
...@@ -27,10 +27,6 @@ RSpec.describe 'viewing issues with design references' do ...@@ -27,10 +27,6 @@ RSpec.describe 'viewing issues with design references' do
MD MD
end end
before do
stub_feature_flags(design_management_moved: false)
end
def visit_page_with_design_references def visit_page_with_design_references
public_issue = create(:issue, project: public_project, description: description) public_issue = create(:issue, project: public_project, description: description)
visit project_issue_path(public_issue.project, public_issue) visit project_issue_path(public_issue.project, public_issue)
......
...@@ -8,34 +8,57 @@ RSpec.describe 'User paginates issue designs', :js do ...@@ -8,34 +8,57 @@ RSpec.describe 'User paginates issue designs', :js do
let(:project) { create(:project_empty_repo, :public) } let(:project) { create(:project_empty_repo, :public) }
let(:issue) { create(:issue, project: project) } let(:issue) { create(:issue, project: project) }
before do context 'design_management_moved flag disabled' do
enable_design_management before do
stub_feature_flags(design_management_moved: false) stub_feature_flags(design_management_moved: false)
enable_design_management
create_list(:design, 2, :with_file, issue: issue) create_list(:design, 2, :with_file, issue: issue)
visit project_issue_path(project, issue)
click_link 'Designs'
wait_for_requests
find('.js-design-list-item', match: :first).click
end
visit project_issue_path(project, issue) it 'paginates to next design' do
expect(find('.js-previous-design')[:disabled]).to eq('true')
click_link 'Designs' page.within(find('.js-design-header')) do
expect(page).to have_content('1 of 2')
end
wait_for_requests find('.js-next-design').click
find('.js-design-list-item', match: :first).click expect(find('.js-previous-design')[:disabled]).not_to eq('true')
end
it 'paginates to next design' do page.within(find('.js-design-header')) do
expect(find('.js-previous-design')[:disabled]).to eq('true') expect(page).to have_content('2 of 2')
end
end
end
page.within(find('.js-design-header')) do context 'design_management_moved flag enabled' do
expect(page).to have_content('1 of 2') before do
enable_design_management
create_list(:design, 2, :with_file, issue: issue)
visit project_issue_path(project, issue)
find('.js-design-list-item', match: :first).click
end end
find('.js-next-design').click it 'paginates to next design' do
expect(find('.js-previous-design')[:disabled]).to eq('true')
page.within(find('.js-design-header')) do
expect(page).to have_content('1 of 2')
end
find('.js-next-design').click
expect(find('.js-previous-design')[:disabled]).not_to eq('true') expect(find('.js-previous-design')[:disabled]).not_to eq('true')
page.within(find('.js-design-header')) do page.within(find('.js-design-header')) do
expect(page).to have_content('2 of 2') expect(page).to have_content('2 of 2')
end
end end
end end
end end
...@@ -8,18 +8,32 @@ RSpec.describe 'User design permissions', :js do ...@@ -8,18 +8,32 @@ RSpec.describe 'User design permissions', :js do
let(:project) { create(:project_empty_repo, :public) } let(:project) { create(:project_empty_repo, :public) }
let(:issue) { create(:issue, project: project) } let(:issue) { create(:issue, project: project) }
before do context 'design_management_moved flag disabled' do
enable_design_management before do
stub_feature_flags(design_management_moved: false) enable_design_management
stub_feature_flags(design_management_moved: false)
visit project_issue_path(project, issue) visit project_issue_path(project, issue)
click_link 'Designs' click_link 'Designs'
wait_for_requests wait_for_requests
end
it 'user does not have permissions to upload design' do
expect(page).not_to have_field('design_file')
end
end end
it 'user does not have permissions to upload design' do context 'design_management_moved flag enabled' do
expect(page).not_to have_field('design_file') before do
enable_design_management
visit project_issue_path(project, issue)
end
it 'user does not have permissions to upload design' do
expect(page).not_to have_field('design_file')
end
end end
end end
...@@ -13,44 +13,81 @@ RSpec.describe 'User uploads new design', :js do ...@@ -13,44 +13,81 @@ RSpec.describe 'User uploads new design', :js do
sign_in(user) sign_in(user)
end end
context "when the feature is available" do context 'design_management_moved flag disabled' do
before do context "when the feature is available" do
enable_design_management before do
stub_feature_flags(design_management_moved: false) enable_design_management
stub_feature_flags(design_management_moved: false)
visit project_issue_path(project, issue) visit project_issue_path(project, issue)
click_link 'Designs' click_link 'Designs'
wait_for_requests wait_for_requests
end end
it 'uploads designs' do
attach_file(:design_file, logo_fixture, make_visible: true)
it 'uploads designs' do expect(page).to have_selector('.js-design-list-item', count: 1)
attach_file(:design_file, logo_fixture, make_visible: true)
expect(page).to have_selector('.js-design-list-item', count: 1) within first('#designs-tab .js-design-list-item') do
expect(page).to have_content('dk.png')
end
within first('#designs-tab .js-design-list-item') do attach_file(:design_file, gif_fixture, make_visible: true)
expect(page).to have_content('dk.png')
expect(page).to have_selector('.js-design-list-item', count: 2)
end end
end
attach_file(:design_file, gif_fixture, make_visible: true) context 'when the feature is not available' do
before do
stub_feature_flags(design_management_moved: false)
visit project_issue_path(project, issue)
expect(page).to have_selector('.js-design-list-item', count: 2) click_link 'Designs'
wait_for_requests
end
it 'shows the message about requirements' do
expect(page).to have_content("To enable design management, you'll need to meet the requirements.")
end
end end
end end
context 'when the feature is not available' do context 'design_management_moved flag enabled' do
before do context "when the feature is available" do
visit project_issue_path(project, issue) before do
enable_design_management
click_link 'Designs' visit project_issue_path(project, issue)
end
it 'uploads designs' do
attach_file(:design_file, logo_fixture, make_visible: true)
expect(page).to have_selector('.js-design-list-item', count: 1)
within first('[data-testid="designs-root"] .js-design-list-item') do
expect(page).to have_content('dk.png')
end
attach_file(:design_file, gif_fixture, make_visible: true)
wait_for_requests expect(page).to have_selector('.js-design-list-item', count: 2)
end
end end
it 'shows the message about requirements' do context 'when the feature is not available' do
expect(page).to have_content("To enable design management, you'll need to meet the requirements.") before do
visit project_issue_path(project, issue)
end
it 'shows the message about requirements' do
expect(page).to have_content("To enable design management, you'll need to meet the requirements.")
end
end end
end end
......
...@@ -13,7 +13,6 @@ RSpec.describe 'Users views raw design image files' do ...@@ -13,7 +13,6 @@ RSpec.describe 'Users views raw design image files' do
before do before do
enable_design_management enable_design_management
stub_feature_flags(design_management_moved: false)
end end
it 'serves the latest design version when no ref is given' do it 'serves the latest design version when no ref is given' do
......
...@@ -9,22 +9,42 @@ RSpec.describe 'User views issue designs', :js do ...@@ -9,22 +9,42 @@ RSpec.describe 'User views issue designs', :js do
let_it_be(:issue) { create(:issue, project: project) } let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:design) { create(:design, :with_file, issue: issue) } let_it_be(:design) { create(:design, :with_file, issue: issue) }
before do context 'design_management_moved flag disabled' do
enable_design_management before do
stub_feature_flags(design_management_moved: false) enable_design_management
stub_feature_flags(design_management_moved: false)
visit project_issue_path(project, issue) visit project_issue_path(project, issue)
click_link 'Designs' click_link 'Designs'
end
it 'opens design detail' do
click_link design.filename
page.within(find('.js-design-header')) do
expect(page).to have_content(design.filename)
end
expect(page).to have_selector('.js-design-image')
end
end end
it 'opens design detail' do context 'design_management_moved flag enabled' do
click_link design.filename before do
enable_design_management
page.within(find('.js-design-header')) do visit project_issue_path(project, issue)
expect(page).to have_content(design.filename)
end end
expect(page).to have_selector('.js-design-image') it 'opens design detail' do
click_link design.filename
page.within(find('.js-design-header')) do
expect(page).to have_content(design.filename)
end
expect(page).to have_selector('.js-design-image')
end
end end
end end
...@@ -9,40 +9,78 @@ RSpec.describe 'User views issue designs', :js do ...@@ -9,40 +9,78 @@ RSpec.describe 'User views issue designs', :js do
let_it_be(:issue) { create(:issue, project: project) } let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:design) { create(:design, :with_file, issue: issue) } let_it_be(:design) { create(:design, :with_file, issue: issue) }
before do context 'design_management_moved flag disabled' do
enable_design_management
stub_feature_flags(design_management_moved: false)
end
context 'navigates from the issue view' do
before do before do
visit project_issue_path(project, issue) enable_design_management
click_link 'Designs' stub_feature_flags(design_management_moved: false)
wait_for_requests
end end
it 'fetches list of designs' do context 'navigates from the issue view' do
expect(page).to have_selector('.js-design-list-item', count: 1) before do
visit project_issue_path(project, issue)
click_link 'Designs'
wait_for_requests
end
it 'fetches list of designs' do
expect(page).to have_selector('.js-design-list-item', count: 1)
end
end end
end
context 'navigates directly to the design collection view' do context 'navigates directly to the design collection view' do
before do before do
visit designs_project_issue_path(project, issue) visit designs_project_issue_path(project, issue)
end
it 'expands the sidebar' do
expect(page).to have_selector('.layout-page.right-sidebar-expanded')
end
end end
it 'expands the sidebar' do context 'navigates directly to the individual design view' do
expect(page).to have_selector('.layout-page.right-sidebar-expanded') before do
visit designs_project_issue_path(project, issue, vueroute: design.filename)
end
it 'sees the design' do
expect(page).to have_selector('.js-design-detail')
end
end end
end end
context 'navigates directly to the individual design view' do context 'design_management_moved flag enabled' do
before do before do
visit designs_project_issue_path(project, issue, vueroute: design.filename) enable_design_management
end end
it 'sees the design' do context 'navigates from the issue view' do
expect(page).to have_selector('.js-design-detail') before do
visit project_issue_path(project, issue)
end
it 'fetches list of designs' do
expect(page).to have_selector('.js-design-list-item', count: 1)
end
end
context 'navigates directly to the design collection view' do
before do
visit designs_project_issue_path(project, issue)
end
it 'expands the sidebar' do
expect(page).to have_selector('.layout-page.right-sidebar-expanded')
end
end
context 'navigates directly to the individual design view' do
before do
visit designs_project_issue_path(project, issue, vueroute: design.filename)
end
it 'sees the design' do
expect(page).to have_selector('.js-design-detail')
end
end end
end end
end end
...@@ -12,7 +12,6 @@ RSpec.describe 'User views an SVG design that contains XSS', :js do ...@@ -12,7 +12,6 @@ RSpec.describe 'User views an SVG design that contains XSS', :js do
before do before do
enable_design_management enable_design_management
stub_feature_flags(design_management_moved: false)
visit designs_project_issue_path( visit designs_project_issue_path(
project, project,
...@@ -30,6 +29,7 @@ RSpec.describe 'User views an SVG design that contains XSS', :js do ...@@ -30,6 +29,7 @@ RSpec.describe 'User views an SVG design that contains XSS', :js do
end end
it 'displays the SVG' do it 'displays the SVG' do
find("[data-testid='close-design']").click
expect(page).to have_selector("img.design-img[alt='xss.svg']", count: 1, visible: false) expect(page).to have_selector("img.design-img[alt='xss.svg']", count: 1, visible: false)
end end
......
...@@ -61,6 +61,10 @@ describe('Design discussions component', () => { ...@@ -61,6 +61,10 @@ describe('Design discussions component', () => {
...data, ...data,
}; };
}, },
provide: {
projectPath: 'project-path',
issueIid: '1',
},
mocks: { mocks: {
$apollo, $apollo,
$route: { $route: {
......
...@@ -7,6 +7,7 @@ exports[`Design management toolbar component renders design and updated data 1`] ...@@ -7,6 +7,7 @@ exports[`Design management toolbar component renders design and updated data 1`]
<a <a
aria-label="Go back to designs" aria-label="Go back to designs"
class="mr-3 text-plain d-flex justify-content-center align-items-center" class="mr-3 text-plain d-flex justify-content-center align-items-center"
data-testid="close-design"
> >
<icon-stub <icon-stub
name="close" name="close"
......
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Design management index page designs does not render toolbar when there is no permission 1`] = ` exports[`Design management index page designs does not render toolbar when there is no permission 1`] = `
<div> <div
data-testid="designs-root"
>
<!----> <!---->
<div <div
...@@ -73,7 +75,9 @@ exports[`Design management index page designs does not render toolbar when there ...@@ -73,7 +75,9 @@ exports[`Design management index page designs does not render toolbar when there
`; `;
exports[`Design management index page designs renders designs list and header with upload button 1`] = ` exports[`Design management index page designs renders designs list and header with upload button 1`] = `
<div> <div
data-testid="designs-root"
>
<header <header
class="row-content-block border-top-0 p-2 d-flex" class="row-content-block border-top-0 p-2 d-flex"
> >
...@@ -188,7 +192,9 @@ exports[`Design management index page designs renders designs list and header wi ...@@ -188,7 +192,9 @@ exports[`Design management index page designs renders designs list and header wi
`; `;
exports[`Design management index page designs renders error 1`] = ` exports[`Design management index page designs renders error 1`] = `
<div> <div
data-testid="designs-root"
>
<!----> <!---->
<div <div
...@@ -216,7 +222,9 @@ exports[`Design management index page designs renders error 1`] = ` ...@@ -216,7 +222,9 @@ exports[`Design management index page designs renders error 1`] = `
`; `;
exports[`Design management index page designs renders loading icon 1`] = ` exports[`Design management index page designs renders loading icon 1`] = `
<div> <div
data-testid="designs-root"
>
<!----> <!---->
<div <div
...@@ -236,7 +244,9 @@ exports[`Design management index page designs renders loading icon 1`] = ` ...@@ -236,7 +244,9 @@ exports[`Design management index page designs renders loading icon 1`] = `
`; `;
exports[`Design management index page when has no designs renders empty text 1`] = ` exports[`Design management index page when has no designs renders empty text 1`] = `
<div> <div
data-testid="designs-root"
>
<!----> <!---->
<div <div
......
...@@ -10,7 +10,7 @@ exports[`Design management design index page renders design index 1`] = ` ...@@ -10,7 +10,7 @@ exports[`Design management design index page renders design index 1`] = `
<design-destroyer-stub <design-destroyer-stub
filenames="test.jpg" filenames="test.jpg"
iid="1" iid="1"
projectpath="" project-path="project-path"
/> />
<!----> <!---->
...@@ -60,7 +60,7 @@ exports[`Design management design index page renders design index 1`] = ` ...@@ -60,7 +60,7 @@ exports[`Design management design index page renders design index 1`] = `
designid="test" designid="test"
discussion="[object Object]" discussion="[object Object]"
discussionwithopenform="" discussionwithopenform=""
markdownpreviewpath="//preview_markdown?target_type=Issue" markdownpreviewpath="/project-path/preview_markdown?target_type=Issue"
noteableid="design-id" noteableid="design-id"
/> />
...@@ -108,7 +108,7 @@ exports[`Design management design index page renders design index 1`] = ` ...@@ -108,7 +108,7 @@ exports[`Design management design index page renders design index 1`] = `
designid="test" designid="test"
discussion="[object Object]" discussion="[object Object]"
discussionwithopenform="" discussionwithopenform=""
markdownpreviewpath="//preview_markdown?target_type=Issue" markdownpreviewpath="/project-path/preview_markdown?target_type=Issue"
noteableid="design-id" noteableid="design-id"
/> />
</gl-collapse-stub> </gl-collapse-stub>
...@@ -140,7 +140,7 @@ exports[`Design management design index page with error GlAlert is rendered in c ...@@ -140,7 +140,7 @@ exports[`Design management design index page with error GlAlert is rendered in c
<design-destroyer-stub <design-destroyer-stub
filenames="test.jpg" filenames="test.jpg"
iid="1" iid="1"
projectpath="" project-path="project-path"
/> />
<div <div
......
...@@ -95,9 +95,12 @@ describe('Design management design index page', () => { ...@@ -95,9 +95,12 @@ describe('Design management design index page', () => {
DesignSidebar, DesignSidebar,
DesignReplyForm, DesignReplyForm,
}, },
provide: {
issueIid: '1',
projectPath: 'project-path',
},
data() { data() {
return { return {
issueIid: '1',
activeDiscussion: { activeDiscussion: {
id: null, id: null,
source: null, source: null,
...@@ -149,7 +152,7 @@ describe('Design management design index page', () => { ...@@ -149,7 +152,7 @@ describe('Design management design index page', () => {
expect(findSidebar().props()).toEqual({ expect(findSidebar().props()).toEqual({
design, design,
markdownPreviewPath: '//preview_markdown?target_type=Issue', markdownPreviewPath: '/project-path/preview_markdown?target_type=Issue',
resolvedDiscussionsExpanded: false, resolvedDiscussionsExpanded: false,
}); });
}); });
......
...@@ -92,19 +92,23 @@ describe('Design management index page', () => { ...@@ -92,19 +92,23 @@ describe('Design management index page', () => {
}; };
wrapper = shallowMount(Index, { wrapper = shallowMount(Index, {
data() {
return {
designs,
allVersions,
permissions: {
createDesign,
},
};
},
mocks: { $apollo }, mocks: { $apollo },
localVue, localVue,
router, router,
stubs: { DesignDestroyer, ApolloMutation, ...stubs }, stubs: { DesignDestroyer, ApolloMutation, ...stubs },
attachToDocument: true, attachToDocument: true,
}); provide: {
projectPath: 'project-path',
wrapper.setData({ issueIid: '1',
designs,
allVersions,
issueIid: '1',
permissions: {
createDesign,
}, },
}); });
} }
...@@ -117,9 +121,7 @@ describe('Design management index page', () => { ...@@ -117,9 +121,7 @@ describe('Design management index page', () => {
it('renders loading icon', () => { it('renders loading icon', () => {
createComponent({ loading: true }); createComponent({ loading: true });
return wrapper.vm.$nextTick().then(() => { expect(wrapper.element).toMatchSnapshot();
expect(wrapper.element).toMatchSnapshot();
});
}); });
it('renders error', () => { it('renders error', () => {
...@@ -135,25 +137,19 @@ describe('Design management index page', () => { ...@@ -135,25 +137,19 @@ describe('Design management index page', () => {
it('renders a toolbar with buttons when there are designs', () => { it('renders a toolbar with buttons when there are designs', () => {
createComponent({ designs: mockDesigns, allVersions: [mockVersion] }); createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
return wrapper.vm.$nextTick().then(() => { expect(findToolbar().exists()).toBe(true);
expect(findToolbar().exists()).toBe(true);
});
}); });
it('renders designs list and header with upload button', () => { it('renders designs list and header with upload button', () => {
createComponent({ designs: mockDesigns, allVersions: [mockVersion] }); createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
return wrapper.vm.$nextTick().then(() => { expect(wrapper.element).toMatchSnapshot();
expect(wrapper.element).toMatchSnapshot();
});
}); });
it('does not render toolbar when there is no permission', () => { it('does not render toolbar when there is no permission', () => {
createComponent({ designs: mockDesigns, allVersions: [mockVersion], createDesign: false }); createComponent({ designs: mockDesigns, allVersions: [mockVersion], createDesign: false });
return wrapper.vm.$nextTick().then(() => { expect(wrapper.element).toMatchSnapshot();
expect(wrapper.element).toMatchSnapshot();
});
}); });
}); });
...@@ -185,7 +181,7 @@ describe('Design management index page', () => { ...@@ -185,7 +181,7 @@ describe('Design management index page', () => {
mutation: uploadDesignQuery, mutation: uploadDesignQuery,
variables: { variables: {
files: [{ name: 'test' }], files: [{ name: 'test' }],
projectPath: '', projectPath: 'project-path',
iid: '1', iid: '1',
}, },
optimisticResponse: { optimisticResponse: {
...@@ -442,9 +438,9 @@ describe('Design management index page', () => { ...@@ -442,9 +438,9 @@ describe('Design management index page', () => {
}); });
}); });
it('on latest version when has no designs does not render toolbar buttons', () => { it('on latest version when has no designs toolbar buttons are invisible', () => {
createComponent({ designs: [], allVersions: [mockVersion] }); createComponent({ designs: [], allVersions: [mockVersion] });
expect(findToolbar().exists()).toBe(false); expect(findToolbar().classes()).toContain('d-none');
}); });
describe('on non-latest version', () => { describe('on non-latest version', () => {
...@@ -535,7 +531,7 @@ describe('Design management index page', () => { ...@@ -535,7 +531,7 @@ describe('Design management index page', () => {
it('ensures fullscreen layout is not applied', () => { it('ensures fullscreen layout is not applied', () => {
createComponent(true); createComponent(true);
wrapper.vm.$router.push('/designs'); wrapper.vm.$router.push('/');
expect(mockPageEl.classList.remove).toHaveBeenCalledTimes(1); expect(mockPageEl.classList.remove).toHaveBeenCalledTimes(1);
expect(mockPageEl.classList.remove).toHaveBeenCalledWith(...DESIGN_DETAIL_LAYOUT_CLASSLIST); expect(mockPageEl.classList.remove).toHaveBeenCalledWith(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
}); });
......
...@@ -5,11 +5,7 @@ import App from '~/design_management_new/components/app.vue'; ...@@ -5,11 +5,7 @@ import App from '~/design_management_new/components/app.vue';
import Designs from '~/design_management_new/pages/index.vue'; import Designs from '~/design_management_new/pages/index.vue';
import DesignDetail from '~/design_management_new/pages/design/index.vue'; import DesignDetail from '~/design_management_new/pages/design/index.vue';
import createRouter from '~/design_management_new/router'; import createRouter from '~/design_management_new/router';
import { import { DESIGNS_ROUTE_NAME, DESIGN_ROUTE_NAME } from '~/design_management_new/router/constants';
ROOT_ROUTE_NAME,
DESIGNS_ROUTE_NAME,
DESIGN_ROUTE_NAME,
} from '~/design_management_new/router/constants';
import '~/commons/bootstrap'; import '~/commons/bootstrap';
function factory(routeArg) { function factory(routeArg) {
...@@ -49,7 +45,7 @@ describe('Design management router', () => { ...@@ -49,7 +45,7 @@ describe('Design management router', () => {
window.location.hash = ''; window.location.hash = '';
}); });
describe.each([['/'], [{ name: ROOT_ROUTE_NAME }]])('root route', routeArg => { describe.each([['/'], [{ name: DESIGNS_ROUTE_NAME }]])('root route', routeArg => {
it('pushes home component', () => { it('pushes home component', () => {
const wrapper = factory(routeArg); const wrapper = factory(routeArg);
...@@ -57,14 +53,6 @@ describe('Design management router', () => { ...@@ -57,14 +53,6 @@ describe('Design management router', () => {
}); });
}); });
describe.each([['/designs'], [{ name: DESIGNS_ROUTE_NAME }]])('designs route', routeArg => {
it('pushes designs root component', () => {
const wrapper = factory(routeArg);
expect(wrapper.find(Designs).exists()).toBe(true);
});
});
describe.each([['/designs/1'], [{ name: DESIGN_ROUTE_NAME, params: { id: '1' } }]])( describe.each([['/designs/1'], [{ name: DESIGN_ROUTE_NAME, params: { id: '1' } }]])(
'designs detail route', 'designs detail route',
routeArg => { routeArg => {
......
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