Commit 3f2e13f4 authored by Phil Hughes's avatar Phil Hughes

Merge branch '219260-show-confidential-icon-in-epics' into 'master'

Add confidentiality icon and context in Epics

Closes #219260

See merge request gitlab-org/gitlab!34443
parents 8d4aa787 b85cc6b7
......@@ -17,7 +17,7 @@ import {
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import * as constants from '../constants';
import eventHub from '../event_hub';
import issueWarning from '../../vue_shared/components/issue/issue_warning.vue';
import NoteableWarning from '../../vue_shared/components/notes/noteable_warning.vue';
import markdownField from '../../vue_shared/components/markdown/field.vue';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import loadingButton from '../../vue_shared/components/loading_button.vue';
......@@ -28,8 +28,7 @@ import issuableStateMixin from '../mixins/issuable_state';
export default {
name: 'CommentForm',
components: {
issueWarning,
epicWarning: () => import('ee_component/vue_shared/components/epic/epic_warning.vue'),
NoteableWarning,
noteSignedOutWidget,
discussionLockedWidget,
markdownField,
......@@ -350,14 +349,15 @@ export default {
<form ref="commentForm" class="new-note common-note-form gfm-form js-main-target-form">
<div class="error-alert"></div>
<issue-warning
v-if="hasWarning(getNoteableData) && isIssueType"
<noteable-warning
v-if="hasWarning(getNoteableData)"
:is-locked="isLocked(getNoteableData)"
:is-confidential="isConfidential(getNoteableData)"
:locked-issue-docs-path="lockedIssueDocsPath"
:confidential-issue-docs-path="confidentialIssueDocsPath"
:noteable-type="noteableType"
:locked-noteable-docs-path="lockedIssueDocsPath"
:confidential-noteable-docs-path="confidentialIssueDocsPath"
/>
<epic-warning :is-confidential="isConfidential(getNoteableData)" />
<markdown-field
ref="markdownField"
:is-submitting="isSubmitting"
......@@ -374,16 +374,14 @@ export default {
dir="auto"
:disabled="isSubmitting"
name="note[note]"
class="note-textarea js-vue-comment-form js-note-text
js-gfm-input js-autosize markdown-area js-vue-textarea qa-comment-input"
class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area js-vue-textarea qa-comment-input"
data-supports-quick-actions="true"
:aria-label="__('Description')"
:placeholder="__('Write a comment or drag your files here…')"
@keydown.up="editCurrentUserLastNote()"
@keydown.meta.enter="handleSave()"
@keydown.ctrl.enter="handleSave()"
>
</textarea>
></textarea>
</markdown-field>
<gl-alert
v-if="isToggleBlockedIssueWarning"
......@@ -417,13 +415,11 @@ js-gfm-input js-autosize markdown-area js-vue-textarea qa-comment-input"
</gl-alert>
<div class="note-form-actions">
<div
class="btn-group
append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
class="btn-group append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
>
<button
:disabled="isSubmitButtonDisabled"
class="btn btn-success js-comment-button js-comment-submit-button
qa-comment-button"
class="btn btn-success js-comment-button js-comment-submit-button qa-comment-button"
type="submit"
:data-track-label="trackingLabel"
data-track-event="click_button"
......@@ -440,7 +436,7 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
data-toggle="dropdown"
:aria-label="__('Open comment type dropdown')"
>
<i aria-hidden="true" class="fa fa-caret-down toggle-icon"> </i>
<i aria-hidden="true" class="fa fa-caret-down toggle-icon"></i>
</button>
<ul class="note-type-dropdown dropdown-open-top dropdown-menu">
......@@ -450,7 +446,7 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
class="btn btn-transparent"
@click.prevent="setNoteType('comment')"
>
<i aria-hidden="true" class="fa fa-check icon"> </i>
<i aria-hidden="true" class="fa fa-check icon"></i>
<div class="description">
<strong>{{ __('Comment') }}</strong>
<p>
......@@ -470,7 +466,7 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
class="btn btn-transparent qa-discussion-option"
@click.prevent="setNoteType('discussion')"
>
<i aria-hidden="true" class="fa fa-check icon"> </i>
<i aria-hidden="true" class="fa fa-check icon"></i>
<div class="description">
<strong>{{ __('Start thread') }}</strong>
<p>{{ startDiscussionDescription }}</p>
......
......@@ -2,7 +2,7 @@
import { mapGetters, mapActions, mapState } from 'vuex';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
import issueWarning from '../../vue_shared/components/issue/issue_warning.vue';
import NoteableWarning from '../../vue_shared/components/notes/noteable_warning.vue';
import markdownField from '../../vue_shared/components/markdown/field.vue';
import issuableStateMixin from '../mixins/issuable_state';
import resolvable from '../mixins/resolvable';
......@@ -12,7 +12,7 @@ import { getDraft, updateDraft } from '~/lib/utils/autosave';
export default {
name: 'NoteForm',
components: {
issueWarning,
NoteableWarning,
markdownField,
},
mixins: [issuableStateMixin, resolvable],
......@@ -303,12 +303,12 @@ export default {
></div>
<div class="flash-container timeline-content"></div>
<form :data-line-code="lineCode" class="edit-note common-note-form js-quick-submit gfm-form">
<issue-warning
<noteable-warning
v-if="hasWarning(getNoteableData)"
:is-locked="isLocked(getNoteableData)"
:is-confidential="isConfidential(getNoteableData)"
:locked-issue-docs-path="lockedIssueDocsPath"
:confidential-issue-docs-path="confidentialIssueDocsPath"
:locked-noteable-docs-path="lockedIssueDocsPath"
:confidential-noteable-docs-path="confidentialIssueDocsPath"
/>
<markdown-field
......
......@@ -8,6 +8,18 @@ function buildDocsLinkStart(path) {
return `<a href="${escape(path)}" target="_blank" rel="noopener noreferrer">`;
}
const NoteableType = {
Issue: 'issue',
Epic: 'epic',
MergeRequest: 'merge_request',
};
const NoteableTypeText = {
[NoteableType.Issue]: __('issue'),
[NoteableType.Epic]: __('epic'),
[NoteableType.MergeRequest]: __('merge request'),
};
export default {
components: {
icon,
......@@ -24,12 +36,17 @@ export default {
default: false,
required: false,
},
lockedIssueDocsPath: {
noteableType: {
type: String,
required: false,
default: NoteableType.Issue,
},
lockedNoteableDocsPath: {
type: String,
required: false,
default: '',
},
confidentialIssueDocsPath: {
confidentialNoteableDocsPath: {
type: String,
required: false,
default: '',
......@@ -45,19 +62,33 @@ export default {
isLockedAndConfidential() {
return this.isConfidential && this.isLocked;
},
noteableTypeText() {
return NoteableTypeText[this.noteableType];
},
confidentialAndLockedDiscussionText() {
return sprintf(
__(
'This issue is %{confidentialLinkStart}confidential%{linkEnd} and %{lockedLinkStart}locked%{linkEnd}.',
'This %{noteableTypeText} is %{confidentialLinkStart}confidential%{linkEnd} and %{lockedLinkStart}locked%{linkEnd}.',
),
{
confidentialLinkStart: buildDocsLinkStart(this.confidentialIssueDocsPath),
lockedLinkStart: buildDocsLinkStart(this.lockedIssueDocsPath),
noteableTypeText: this.noteableTypeText,
confidentialLinkStart: buildDocsLinkStart(this.confidentialNoteableDocsPath),
lockedLinkStart: buildDocsLinkStart(this.lockedNoteableDocsPath),
linkEnd: '</a>',
},
false,
);
},
confidentialContextText() {
return sprintf(__('This is a confidential %{noteableTypeText}.'), {
noteableTypeText: this.noteableTypeText,
});
},
lockedContextText() {
return sprintf(__('This %{noteableTypeText} is locked.'), {
noteableTypeText: this.noteableTypeText,
});
},
},
};
</script>
......@@ -73,19 +104,15 @@ export default {
</span>
<span v-else-if="isConfidential" ref="confidential">
{{ __('This is a confidential issue.') }}
{{ confidentialContextText }}
{{ __('People without permission will never get a notification.') }}
<gl-link :href="confidentialIssueDocsPath" target="_blank">
{{ __('Learn more') }}
</gl-link>
<gl-link :href="confidentialNoteableDocsPath" target="_blank">{{ __('Learn more') }}</gl-link>
</span>
<span v-else-if="isLocked" ref="locked">
{{ __('This issue is locked.') }}
{{ lockedContextText }}
{{ __('Only project members can comment.') }}
<gl-link :href="lockedIssueDocsPath" target="_blank">
{{ __('Learn more') }}
</gl-link>
<gl-link :href="lockedNoteableDocsPath" target="_blank">{{ __('Learn more') }}</gl-link>
</span>
</div>
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
import { GlDeprecatedButton } from '@gitlab/ui';
import { GlDeprecatedButton, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
......@@ -17,7 +16,7 @@ export default {
tooltip,
},
components: {
Icon,
GlIcon,
GlDeprecatedButton,
UserAvatarLink,
TimeagoTooltip,
......@@ -32,6 +31,7 @@ export default {
'author',
'created',
'canUpdate',
'confidential',
]),
...mapGetters(['isEpicOpen']),
statusIcon() {
......@@ -82,10 +82,13 @@ export default {
:class="{ 'status-box-open': isEpicOpen, 'status-box-issue-closed': !isEpicOpen }"
class="issuable-status-box status-box"
>
<icon :name="statusIcon" class="d-block d-sm-none" />
<gl-icon :name="statusIcon" class="d-block d-sm-none" />
<span class="d-none d-sm-block">{{ statusText }}</span>
</div>
<div class="issuable-meta">
<div v-if="confidential" class="issuable-warning-icon inline">
<gl-icon name="eye-slash" class="icon" />
</div>
{{ __('Opened') }}
<timeago-tooltip :time="created" />
{{ __('by') }}
......@@ -110,15 +113,13 @@ export default {
:loading="epicStatusChangeInProgress"
:class="actionButtonClass"
@click="toggleEpicStatus(isEpicOpen)"
>{{ actionButtonText }}</gl-deprecated-button
>
{{ actionButtonText }}
</gl-deprecated-button>
</div>
<gl-deprecated-button
:aria-label="__('Toggle sidebar')"
variant="secondary"
class="float-right d-block d-sm-none
gutter-toggle issuable-gutter-toggle js-sidebar-toggle"
class="float-right d-block d-sm-none gutter-toggle issuable-gutter-toggle js-sidebar-toggle"
type="button"
@click="toggleSidebar({ sidebarCollapsed })"
>
......
......@@ -56,6 +56,7 @@ export default () => ({
ancestors: [],
participants: [],
subscribed: false,
confidential: false,
// Create Epic Props
newEpicTitle: '',
......
<script>
import { mapGetters } from 'vuex';
import { GlIcon, GlLink } from '@gitlab/ui';
import * as constants from '~/notes/constants';
export default {
components: {
GlIcon,
GlLink,
},
props: {
isConfidential: {
type: Boolean,
default: false,
required: false,
},
},
computed: {
...mapGetters(['getNoteableDataByProp']),
isNoteableTypeEpic() {
return this.getNoteableDataByProp('noteableType') === constants.EPIC_NOTEABLE_TYPE;
},
confidentialEpicDocsPath() {
return this.getNoteableDataByProp('confidential_epics_docs_path');
},
},
};
</script>
<template>
<div v-if="isNoteableTypeEpic && isConfidential" ref="epicWarning" class="issuable-note-warning">
<gl-icon name="eye-slash" :size="16" class="icon" />
<span ref="confidential">
{{ __('This is a confidential epic.') }}
{{ __('People without permission will never get a notification.') }}
<gl-link :href="confidentialEpicDocsPath" target="_blank">
{{ __('Learn more') }}
</gl-link>
</span>
</div>
</template>
......@@ -23,6 +23,7 @@ module EE
data[:epicLinksEndpoint] = group_epic_links_path(parent, issuable)
data[:fullPath] = parent.full_path
data[:projectsEndpoint] = expose_path(api_v4_groups_projects_path(id: parent.id))
data[:confidential] = issuable.confidential
end
data
......
......@@ -7,6 +7,9 @@
.issuable-main-info
.issue-title.title
%span.issue-title-text{ data: { qa_selector: 'epic_title_text' } }
- if epic.confidential?
%span.has-tooltip{ title: _('Confidential') }
= confidential_icon(epic)
= link_to epic.title, epic_path(epic)
.issuable-info
%span.issuable-reference
......
import Vue from 'vue';
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import EpicHeader from 'ee/epic/components/epic_header.vue';
import createStore from 'ee/epic/store';
import { statusType } from 'ee/epic/constants';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import { mockEpicMeta, mockEpicData } from '../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('EpicHeaderComponent', () => {
let wrapper;
let vm;
let store;
beforeEach(() => {
const Component = Vue.extend(EpicHeader);
store = createStore();
store.dispatch('setEpicMeta', mockEpicMeta);
store.dispatch('setEpicData', mockEpicData);
vm = mountComponentWithStore(Component, {
wrapper = shallowMount(EpicHeader, {
localVue,
store,
});
vm = wrapper.vm;
});
afterEach(() => {
vm.$destroy();
wrapper.destroy();
});
describe('computed', () => {
......@@ -96,21 +105,29 @@ describe('EpicHeaderComponent', () => {
});
it('renders epic status icon and text elements', () => {
const statusEl = vm.$el.querySelector('.issuable-status-box');
const statusEl = wrapper.find('.issuable-status-box');
expect(statusEl).not.toBeNull();
expect(
statusEl.querySelector('svg.ic-issue-open-m use').getAttribute('xlink:href'),
).toContain('issue-open-m');
expect(statusEl.exists()).toBe(true);
expect(statusEl.find(GlIcon).props('name')).toBe('issue-open-m');
expect(statusEl.find('span').text()).toBe('Open');
});
it('renders confidential icon when `confidential` prop is true', () => {
vm.$store.state.confidential = true;
expect(statusEl.querySelector('span').innerText.trim()).toBe('Open');
return Vue.nextTick(() => {
const iconEl = wrapper.find('.issuable-warning-icon').find(GlIcon);
expect(iconEl.exists()).toBe(true);
expect(iconEl.props('name')).toBe('eye-slash');
});
});
it('renders epic author details element', () => {
const metaEl = vm.$el.querySelector('.issuable-meta');
const metaEl = wrapper.find('.issuable-meta');
expect(metaEl).not.toBeNull();
expect(metaEl.querySelector('strong a.user-avatar-link')).not.toBeNull();
expect(metaEl.exists()).toBe(true);
expect(metaEl.find(TimeagoTooltip).exists()).toBe(true);
expect(metaEl.find(UserAvatarLink).exists()).toBe(true);
});
it('renders action buttons element', () => {
......@@ -122,13 +139,13 @@ describe('EpicHeaderComponent', () => {
});
it('renders toggle sidebar button element', () => {
const toggleButtonEl = vm.$el.querySelector('button.js-sidebar-toggle');
const toggleButtonEl = wrapper.find('.js-sidebar-toggle');
expect(toggleButtonEl).not.toBeNull();
expect(toggleButtonEl.getAttribute('aria-label')).toBe('Toggle sidebar');
expect(toggleButtonEl.classList.contains('d-block')).toBe(true);
expect(toggleButtonEl.classList.contains('d-sm-none')).toBe(true);
expect(toggleButtonEl.classList.contains('gutter-toggle')).toBe(true);
expect(toggleButtonEl.exists()).toBe(true);
expect(toggleButtonEl.attributes('aria-label')).toBe('Toggle sidebar');
expect(toggleButtonEl.classes()).toEqual(
expect.arrayContaining([('d-block', 'd-sm-none', 'gutter-toggle')]),
);
});
it('renders GitLab team member badge when `author.isGitlabEmployee` is `true`', () => {
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Epic Warning Component when noteable type is epic epic is confidential renders information about confidential epic 1`] = `
<span>
This is a confidential epic.
People without permission will never get a notification.
<gl-link-stub
target="_blank"
>
Learn more
</gl-link-stub>
</span>
`;
import { shallowMount } from '@vue/test-utils';
import EpicWarning from 'ee/vue_shared/components/epic/epic_warning.vue';
import { store } from '~/notes/stores';
import { GlIcon } from '@gitlab/ui';
describe('Epic Warning Component', () => {
let wrapper;
const findIcon = () => wrapper.find(GlIcon);
const findConfidentialBlock = () => wrapper.find({ ref: 'confidential' });
const findEpicWarning = () => wrapper.find({ ref: 'epicWarning' });
const createComponent = (props, isNoteableEpic = true) => {
wrapper = shallowMount(EpicWarning, {
store,
propsData: {
...props,
},
computed: {
isNoteableTypeEpic() {
return isNoteableEpic;
},
},
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('when noteable type is epic', () => {
describe('epic is not confidential', () => {
beforeEach(() => {
createComponent({ isConfidential: false });
});
it('does not render warning icon', () => {
expect(findIcon().exists()).toBe(false);
});
it('does not render information about epic issue', () => {
expect(findConfidentialBlock().exists()).toBe(false);
});
});
describe('epic is confidential', () => {
beforeEach(() => {
createComponent({ isConfidential: true });
});
it('renders information about confidential epic', () => {
expect(findConfidentialBlock().exists()).toBe(true);
expect(findConfidentialBlock().element).toMatchSnapshot();
});
it('renders warning icon', () => {
expect(findIcon().exists()).toBe(true);
});
});
});
describe('when noteable type is not epic', () => {
beforeEach(() => {
createComponent({ isConfidential: true }, false);
});
it('does not render itself', () => {
expect(findEpicWarning().exists()).toBe(false);
});
});
});
......@@ -13,8 +13,13 @@ RSpec.describe IssuablesHelper do
end
context 'for an epic' do
let_it_be(:epic) { create(:epic, author: user, description: 'epic text', confidential: true) }
before do
stub_feature_flags(confidential_epics: true)
end
it 'returns the correct data' do
epic = create(:epic, author: user, description: 'epic text')
@group = epic.group
expected_data = {
......@@ -35,10 +40,11 @@ RSpec.describe IssuablesHelper do
groupPath: @group.path,
initialTitleHtml: epic.title,
initialTitleText: epic.title,
initialDescriptionHtml: '<p dir="auto">epic text</p>',
initialDescriptionHtml: '<p data-sourcepos="1:1-1:9" dir="auto">epic text</p>',
initialDescriptionText: 'epic text',
initialTaskStatus: '0 of 0 tasks completed',
projectsEndpoint: "/api/v4/groups/#{@group.id}/projects"
projectsEndpoint: "/api/v4/groups/#{@group.id}/projects",
confidential: epic.confidential
}
expect(helper.issuable_initial_data(epic)).to eq(expected_data)
end
......
......@@ -22837,6 +22837,12 @@ msgstr ""
msgid "This %{issuable} is locked. Only <strong>project members</strong> can comment."
msgstr ""
msgid "This %{noteableTypeText} is %{confidentialLinkStart}confidential%{linkEnd} and %{lockedLinkStart}locked%{linkEnd}."
msgstr ""
msgid "This %{noteableTypeText} is locked."
msgstr ""
msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
msgstr ""
......@@ -22984,10 +22990,7 @@ msgstr ""
msgid "This is a Work in Progress"
msgstr ""
msgid "This is a confidential epic."
msgstr ""
msgid "This is a confidential issue."
msgid "This is a confidential %{noteableTypeText}."
msgstr ""
msgid "This is a delayed job to run in %{remainingTime}"
......@@ -23014,9 +23017,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
msgid "This issue is %{confidentialLinkStart}confidential%{linkEnd} and %{lockedLinkStart}locked%{linkEnd}."
msgstr ""
msgid "This issue is confidential"
msgstr ""
......@@ -23026,9 +23026,6 @@ msgstr ""
msgid "This issue is in a child epic of the filtered epic"
msgstr ""
msgid "This issue is locked."
msgstr ""
msgid "This job depends on other jobs with expired/erased artifacts: %{invalid_dependencies}"
msgstr ""
......@@ -26852,6 +26849,9 @@ msgstr ""
msgid "entries cannot contain HTML tags"
msgstr ""
msgid "epic"
msgstr ""
msgid "error"
msgstr ""
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Issue Warning Component when issue is confidential but not locked renders information about confidential issue 1`] = `
exports[`Issue Warning Component when issue is locked but not confidential renders information about locked issue 1`] = `
<span>
This issue is locked.
Only project members can comment.
<gl-link-stub
href="locked-path"
target="_blank"
>
Learn more
</gl-link-stub>
</span>
`;
exports[`Issue Warning Component when noteable is confidential but not locked renders information about confidential issue 1`] = `
<span>
This is a confidential issue.
......@@ -10,14 +25,12 @@ exports[`Issue Warning Component when issue is confidential but not locked rende
href="confidential-path"
target="_blank"
>
Learn more
Learn more
</gl-link-stub>
</span>
`;
exports[`Issue Warning Component when issue is locked and confidential renders information about locked and confidential issue 1`] = `
exports[`Issue Warning Component when noteable is locked and confidential renders information about locked and confidential noteable 1`] = `
<span>
<span>
This issue is
......@@ -43,20 +56,3 @@ exports[`Issue Warning Component when issue is locked and confidential renders i
</span>
`;
exports[`Issue Warning Component when issue is locked but not confidential renders information about locked issue 1`] = `
<span>
This issue is locked.
Only project members can comment.
<gl-link-stub
href="locked-path"
target="_blank"
>
Learn more
</gl-link-stub>
</span>
`;
import { shallowMount } from '@vue/test-utils';
import IssueWarning from '~/vue_shared/components/issue/issue_warning.vue';
import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue';
import Icon from '~/vue_shared/components/icon.vue';
describe('Issue Warning Component', () => {
let wrapper;
const findIcon = () => wrapper.find(Icon);
const findLockedBlock = () => wrapper.find({ ref: 'locked' });
const findConfidentialBlock = () => wrapper.find({ ref: 'confidential' });
const findLockedAndConfidentialBlock = () => wrapper.find({ ref: 'lockedAndConfidential' });
const findIcon = (w = wrapper) => w.find(Icon);
const findLockedBlock = (w = wrapper) => w.find({ ref: 'locked' });
const findConfidentialBlock = (w = wrapper) => w.find({ ref: 'confidential' });
const findLockedAndConfidentialBlock = (w = wrapper) => w.find({ ref: 'lockedAndConfidential' });
const createComponent = props => {
wrapper = shallowMount(IssueWarning, {
const createComponent = props =>
shallowMount(NoteableWarning, {
propsData: {
...props,
},
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
});
describe('when issue is locked but not confidential', () => {
beforeEach(() => {
createComponent({
wrapper = createComponent({
isLocked: true,
lockedIssueDocsPath: 'locked-path',
lockedNoteableDocsPath: 'locked-path',
isConfidential: false,
});
});
......@@ -50,12 +51,12 @@ describe('Issue Warning Component', () => {
});
});
describe('when issue is confidential but not locked', () => {
describe('when noteable is confidential but not locked', () => {
beforeEach(() => {
createComponent({
wrapper = createComponent({
isLocked: false,
isConfidential: true,
confidentialIssueDocsPath: 'confidential-path',
confidentialNoteableDocsPath: 'confidential-path',
});
});
......@@ -68,24 +69,24 @@ describe('Issue Warning Component', () => {
expect(wrapper.find(Icon).exists()).toBe(true);
});
it('does not render information about locked issue', () => {
it('does not render information about locked noteable', () => {
expect(findLockedBlock().exists()).toBe(false);
});
it('does not render information about locked and confidential issue', () => {
it('does not render information about locked and confidential noteable', () => {
expect(findLockedAndConfidentialBlock().exists()).toBe(false);
});
});
describe('when issue is locked and confidential', () => {
describe('when noteable is locked and confidential', () => {
beforeEach(() => {
createComponent({
wrapper = createComponent({
isLocked: true,
isConfidential: true,
});
});
it('renders information about locked and confidential issue', () => {
it('renders information about locked and confidential noteable', () => {
expect(findLockedAndConfidentialBlock().exists()).toBe(true);
expect(findLockedAndConfidentialBlock().element).toMatchSnapshot();
});
......@@ -94,12 +95,99 @@ describe('Issue Warning Component', () => {
expect(wrapper.find(Icon).exists()).toBe(false);
});
it('does not render information about locked issue', () => {
it('does not render information about locked noteable', () => {
expect(findLockedBlock().exists()).toBe(false);
});
it('does not render information about confidential issue', () => {
it('does not render information about confidential noteable', () => {
expect(findConfidentialBlock().exists()).toBe(false);
});
});
describe('when noteableType prop is defined', () => {
let wrapperLocked;
let wrapperConfidential;
let wrapperLockedAndConfidential;
beforeEach(() => {
wrapperLocked = createComponent({
isLocked: true,
isConfidential: false,
});
wrapperConfidential = createComponent({
isLocked: false,
isConfidential: true,
});
wrapperLockedAndConfidential = createComponent({
isLocked: true,
isConfidential: true,
});
});
afterEach(() => {
wrapperLocked.destroy();
wrapperConfidential.destroy();
wrapperLockedAndConfidential.destroy();
});
it('renders confidential & locked messages with noteable "issue"', () => {
expect(findLockedBlock(wrapperLocked).text()).toContain('This issue is locked.');
expect(findConfidentialBlock(wrapperConfidential).text()).toContain(
'This is a confidential issue.',
);
expect(findLockedAndConfidentialBlock(wrapperLockedAndConfidential).text()).toContain(
'This issue is confidential and locked.',
);
});
it('renders confidential & locked messages with noteable "epic"', async () => {
wrapperLocked.setProps({
noteableType: 'epic',
});
wrapperConfidential.setProps({
noteableType: 'epic',
});
wrapperLockedAndConfidential.setProps({
noteableType: 'epic',
});
await wrapperLocked.vm.$nextTick();
expect(findLockedBlock(wrapperLocked).text()).toContain('This epic is locked.');
await wrapperConfidential.vm.$nextTick();
expect(findConfidentialBlock(wrapperConfidential).text()).toContain(
'This is a confidential epic.',
);
await wrapperLockedAndConfidential.vm.$nextTick();
expect(findLockedAndConfidentialBlock(wrapperLockedAndConfidential).text()).toContain(
'This epic is confidential and locked.',
);
});
it('renders confidential & locked messages with noteable "merge request"', async () => {
wrapperLocked.setProps({
noteableType: 'merge_request',
});
wrapperConfidential.setProps({
noteableType: 'merge_request',
});
wrapperLockedAndConfidential.setProps({
noteableType: 'merge_request',
});
await wrapperLocked.vm.$nextTick();
expect(findLockedBlock(wrapperLocked).text()).toContain('This merge request is locked.');
await wrapperConfidential.vm.$nextTick();
expect(findConfidentialBlock(wrapperConfidential).text()).toContain(
'This is a confidential merge request.',
);
await wrapperLockedAndConfidential.vm.$nextTick();
expect(findLockedAndConfidentialBlock(wrapperLockedAndConfidential).text()).toContain(
'This merge request is confidential and locked.',
);
});
});
});
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