Commit 8b3b26eb authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'epic-confidential' into 'master'

Toggle epic confidential

See merge request gitlab-org/gitlab!37678
parents e9dd17cd c776b8c6
...@@ -136,6 +136,8 @@ export default { ...@@ -136,6 +136,8 @@ export default {
} }
window.addEventListener('hashchange', this.handleHashChanged); window.addEventListener('hashchange', this.handleHashChanged);
eventHub.$on('notesApp.updateIssuableConfidentiality', this.setConfidentiality);
}, },
updated() { updated() {
this.$nextTick(() => { this.$nextTick(() => {
...@@ -146,6 +148,7 @@ export default { ...@@ -146,6 +148,7 @@ export default {
beforeDestroy() { beforeDestroy() {
this.stopPolling(); this.stopPolling();
window.removeEventListener('hashchange', this.handleHashChanged); window.removeEventListener('hashchange', this.handleHashChanged);
eventHub.$off('notesApp.updateIssuableConfidentiality', this.setConfidentiality);
}, },
methods: { methods: {
...mapActions([ ...mapActions([
...@@ -164,6 +167,7 @@ export default { ...@@ -164,6 +167,7 @@ export default {
'startTaskList', 'startTaskList',
'convertToDiscussion', 'convertToDiscussion',
'stopPolling', 'stopPolling',
'setConfidentiality',
]), ]),
discussionIsIndividualNoteAndNotConverted(discussion) { discussionIsIndividualNoteAndNotConverted(discussion) {
return discussion.individual_note && !this.convertedDisscussionIds.includes(discussion.id); return discussion.individual_note && !this.convertedDisscussionIds.includes(discussion.id);
......
...@@ -21,29 +21,6 @@ import Api from '~/api'; ...@@ -21,29 +21,6 @@ import Api from '~/api';
let eTagPoll; let eTagPoll;
export const updateConfidentialityOnIssue = ({ commit, getters }, { confidential, fullPath }) => {
const { iid } = getters.getNoteableData;
return utils.gqClient
.mutate({
mutation: updateIssueConfidentialMutation,
variables: {
input: {
projectPath: fullPath,
iid: String(iid),
confidential,
},
},
})
.then(({ data }) => {
const {
issueSetConfidential: { issue },
} = data;
commit(types.SET_ISSUE_CONFIDENTIAL, issue.confidential);
});
};
export const updateLockedAttribute = ({ commit, getters }, { locked, fullPath }) => { export const updateLockedAttribute = ({ commit, getters }, { locked, fullPath }) => {
const { iid, targetType } = getters.getNoteableData; const { iid, targetType } = getters.getNoteableData;
...@@ -712,3 +689,29 @@ export const updateAssignees = ({ commit }, assignees) => { ...@@ -712,3 +689,29 @@ export const updateAssignees = ({ commit }, assignees) => {
export const updateDiscussionPosition = ({ commit }, updatedPosition) => { export const updateDiscussionPosition = ({ commit }, updatedPosition) => {
commit(types.UPDATE_DISCUSSION_POSITION, updatedPosition); commit(types.UPDATE_DISCUSSION_POSITION, updatedPosition);
}; };
export const updateConfidentialityOnIssuable = (
{ getters, commit },
{ confidential, fullPath },
) => {
const { iid } = getters.getNoteableData;
return utils.gqClient
.mutate({
mutation: updateIssueConfidentialMutation,
variables: {
input: {
projectPath: fullPath,
iid: String(iid),
confidential,
},
},
})
.then(({ data }) => {
const {
issueSetConfidential: { issue },
} = data;
setConfidentiality({ commit }, issue.confidential);
});
};
<script> <script>
import { mapState, mapActions } from 'vuex'; import { mapState } from 'vuex';
import { __ } from '~/locale'; import { __, sprintf } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip'; import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '~/sidebar/event_hub'; import eventHub from '~/sidebar/event_hub';
...@@ -23,9 +23,10 @@ export default { ...@@ -23,9 +23,10 @@ export default {
required: true, required: true,
type: Boolean, type: Boolean,
}, },
service: { issuableType: {
required: true, required: false,
type: Object, type: String,
default: 'issue',
}, },
}, },
data() { data() {
...@@ -34,13 +35,25 @@ export default { ...@@ -34,13 +35,25 @@ export default {
}; };
}, },
computed: { computed: {
...mapState({ confidential: ({ noteableData }) => noteableData.confidential }), ...mapState({
confidential: ({ noteableData, confidential }) => {
if (noteableData) {
return noteableData.confidential;
}
return Boolean(confidential);
},
}),
confidentialityIcon() { confidentialityIcon() {
return this.confidential ? 'eye-slash' : 'eye'; return this.confidential ? 'eye-slash' : 'eye';
}, },
tooltipLabel() { tooltipLabel() {
return this.confidential ? __('Confidential') : __('Not confidential'); return this.confidential ? __('Confidential') : __('Not confidential');
}, },
confidentialText() {
return sprintf(__('This %{issuableType} is confidential'), {
issuableType: this.issuableType,
});
},
}, },
created() { created() {
eventHub.$on('closeConfidentialityForm', this.toggleForm); eventHub.$on('closeConfidentialityForm', this.toggleForm);
...@@ -49,7 +62,6 @@ export default { ...@@ -49,7 +62,6 @@ export default {
eventHub.$off('closeConfidentialityForm', this.toggleForm); eventHub.$off('closeConfidentialityForm', this.toggleForm);
}, },
methods: { methods: {
...mapActions(['setConfidentiality']),
toggleForm() { toggleForm() {
this.edit = !this.edit; this.edit = !this.edit;
}, },
...@@ -86,7 +98,12 @@ export default { ...@@ -86,7 +98,12 @@ export default {
> >
</div> </div>
<div class="value sidebar-item-value hide-collapsed"> <div class="value sidebar-item-value hide-collapsed">
<edit-form v-if="edit" :is-confidential="confidential" :full-path="fullPath" /> <edit-form
v-if="edit"
:confidential="confidential"
:full-path="fullPath"
:issuable-type="issuableType"
/>
<div v-if="!confidential" class="no-value sidebar-item-value" data-testid="not-confidential"> <div v-if="!confidential" class="no-value sidebar-item-value" data-testid="not-confidential">
<icon :size="16" name="eye" aria-hidden="true" class="sidebar-item-icon inline" /> <icon :size="16" name="eye" aria-hidden="true" class="sidebar-item-icon inline" />
{{ __('Not confidential') }} {{ __('Not confidential') }}
...@@ -98,7 +115,7 @@ export default { ...@@ -98,7 +115,7 @@ export default {
aria-hidden="true" aria-hidden="true"
class="sidebar-item-icon inline is-active" class="sidebar-item-icon inline is-active"
/> />
{{ __('This issue is confidential') }} {{ confidentialText }}
</div> </div>
</div> </div>
</div> </div>
......
<script> <script>
import editFormButtons from './edit_form_buttons.vue'; import editFormButtons from './edit_form_buttons.vue';
import { s__ } from '../../../locale'; import { __, sprintf } from '../../../locale';
export default { export default {
components: { components: {
editFormButtons, editFormButtons,
}, },
props: { props: {
isConfidential: { confidential: {
required: true, required: true,
type: Boolean, type: Boolean,
}, },
...@@ -15,16 +15,32 @@ export default { ...@@ -15,16 +15,32 @@ export default {
required: true, required: true,
type: String, type: String,
}, },
issuableType: {
required: true,
type: String,
},
}, },
computed: { computed: {
confidentialityOnWarning() { confidentialityOnWarning() {
return s__( const accessLevel = __('at least Reporter access');
'confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue.',
return sprintf(
__(
'You are going to turn on the confidentiality. This means that only team members with %{accessLevel} are able to see and leave comments on the %{issuableType}.',
),
{ issuableType: this.issuableType, accessLevel: `<strong>${accessLevel}</strong>` },
false,
); );
}, },
confidentialityOffWarning() { confidentialityOffWarning() {
return s__( const accessLevel = __('everyone');
'confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue.',
return sprintf(
__(
'You are going to turn off the confidentiality. This means %{accessLevel} will be able to see and leave a comment on this %{issuableType}.',
),
{ issuableType: this.issuableType, accessLevel: `<strong>${accessLevel}</strong>` },
false,
); );
}, },
}, },
...@@ -35,9 +51,9 @@ export default { ...@@ -35,9 +51,9 @@ export default {
<div class="dropdown show"> <div class="dropdown show">
<div class="dropdown-menu sidebar-item-warning-message"> <div class="dropdown-menu sidebar-item-warning-message">
<div> <div>
<p v-if="!isConfidential" v-html="confidentialityOnWarning"></p> <p v-if="!confidential" v-html="confidentialityOnWarning"></p>
<p v-else v-html="confidentialityOffWarning"></p> <p v-else v-html="confidentialityOffWarning"></p>
<edit-form-buttons :full-path="fullPath" /> <edit-form-buttons :full-path="fullPath" :confidential="confidential" />
</div> </div>
</div> </div>
</div> </div>
......
<script> <script>
import $ from 'jquery'; import $ from 'jquery';
import { GlLoadingIcon } from '@gitlab/ui'; import { GlLoadingIcon } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex'; import { mapActions } from 'vuex';
import { __ } from '~/locale'; import { __ } from '~/locale';
import Flash from '~/flash'; import Flash from '~/flash';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
...@@ -15,6 +15,10 @@ export default { ...@@ -15,6 +15,10 @@ export default {
required: true, required: true,
type: String, type: String,
}, },
confidential: {
required: true,
type: Boolean,
},
}, },
data() { data() {
return { return {
...@@ -22,7 +26,6 @@ export default { ...@@ -22,7 +26,6 @@ export default {
}; };
}, },
computed: { computed: {
...mapState({ confidential: ({ noteableData }) => noteableData.confidential }),
toggleButtonText() { toggleButtonText() {
if (this.isLoading) { if (this.isLoading) {
return __('Applying'); return __('Applying');
...@@ -32,7 +35,7 @@ export default { ...@@ -32,7 +35,7 @@ export default {
}, },
}, },
methods: { methods: {
...mapActions(['updateConfidentialityOnIssue']), ...mapActions(['updateConfidentialityOnIssuable']),
closeForm() { closeForm() {
eventHub.$emit('closeConfidentialityForm'); eventHub.$emit('closeConfidentialityForm');
$(this.$el).trigger('hidden.gl.dropdown'); $(this.$el).trigger('hidden.gl.dropdown');
...@@ -41,9 +44,14 @@ export default { ...@@ -41,9 +44,14 @@ export default {
this.isLoading = true; this.isLoading = true;
const confidential = !this.confidential; const confidential = !this.confidential;
this.updateConfidentialityOnIssue({ confidential, fullPath: this.fullPath }) this.updateConfidentialityOnIssuable({ confidential, fullPath: this.fullPath })
.catch(() => { .then(() => {
Flash(__('Something went wrong trying to change the confidentiality of this issue')); eventHub.$emit('updateIssuableConfidentiality', confidential);
})
.catch(err => {
Flash(
err || __('Something went wrong trying to change the confidentiality of this issue'),
);
}) })
.finally(() => { .finally(() => {
this.closeForm(); this.closeForm();
......
...@@ -12,6 +12,10 @@ import SidebarDatePickerCollapsed from '~/vue_shared/components/sidebar/collapse ...@@ -12,6 +12,10 @@ import SidebarDatePickerCollapsed from '~/vue_shared/components/sidebar/collapse
import SidebarLabels from './sidebar_items/sidebar_labels.vue'; import SidebarLabels from './sidebar_items/sidebar_labels.vue';
import SidebarParticipants from '~/sidebar/components/participants/participants.vue'; import SidebarParticipants from '~/sidebar/components/participants/participants.vue';
import SidebarSubscription from './sidebar_items/sidebar_subscription.vue'; import SidebarSubscription from './sidebar_items/sidebar_subscription.vue';
import ConfidentialIssueSidebar from '~/sidebar/components/confidential/confidential_issue_sidebar.vue';
import notesEventHub from '~/notes/event_hub';
import sidebarEventHub from '~/sidebar/event_hub';
import { dateTypes } from '../constants'; import { dateTypes } from '../constants';
...@@ -26,6 +30,7 @@ export default { ...@@ -26,6 +30,7 @@ export default {
AncestorsTree, AncestorsTree,
SidebarParticipants, SidebarParticipants,
SidebarSubscription, SidebarSubscription,
ConfidentialIssueSidebar,
}, },
computed: { computed: {
...mapState([ ...mapState([
...@@ -45,6 +50,7 @@ export default { ...@@ -45,6 +50,7 @@ export default {
'dueDateFromMilestones', 'dueDateFromMilestones',
'epicStartDateSaveInProgress', 'epicStartDateSaveInProgress',
'epicDueDateSaveInProgress', 'epicDueDateSaveInProgress',
'fullPath',
]), ]),
...mapGetters([ ...mapGetters([
'isUserSignedIn', 'isUserSignedIn',
...@@ -63,6 +69,10 @@ export default { ...@@ -63,6 +69,10 @@ export default {
mounted() { mounted() {
this.toggleSidebarFlag(epicUtils.getCollapsedGutter()); this.toggleSidebarFlag(epicUtils.getCollapsedGutter());
this.fetchEpicDetails(); this.fetchEpicDetails();
sidebarEventHub.$on('updateIssuableConfidentiality', this.updateEpicConfidentiality);
},
beforeDestroy() {
sidebarEventHub.$off('updateIssuableConfidentiality', this.updateEpicConfidentiality);
}, },
methods: { methods: {
...mapActions([ ...mapActions([
...@@ -118,6 +128,9 @@ export default { ...@@ -118,6 +128,9 @@ export default {
dateTypeIsFixed: true, dateTypeIsFixed: true,
}); });
}, },
updateEpicConfidentiality(confidential) {
notesEventHub.$emit('notesApp.updateIssuableConfidentiality', confidential);
},
}, },
}; };
</script> </script>
...@@ -190,6 +203,13 @@ export default { ...@@ -190,6 +203,13 @@ export default {
<div v-if="allowSubEpics" class="block ancestors"> <div v-if="allowSubEpics" class="block ancestors">
<ancestors-tree :ancestors="ancestors" :is-fetching="false" /> <ancestors-tree :ancestors="ancestors" :is-fetching="false" />
</div> </div>
<confidential-issue-sidebar
:is-editable="canUpdate"
:full-path="fullPath"
issuable-type="epic"
/>
<div class="block participants"> <div class="block participants">
<sidebar-participants <sidebar-participants
:participants="participants" :participants="participants"
......
...@@ -194,6 +194,36 @@ export const saveDate = ({ state, dispatch }, { dateType, dateTypeIsFixed, newDa ...@@ -194,6 +194,36 @@ export const saveDate = ({ state, dispatch }, { dateType, dateTypeIsFixed, newDa
}); });
}; };
export const updateConfidentialityOnIssuable = ({ state, commit }, { confidential }) => {
const updateEpicInput = {
iid: `${state.epicIid}`,
groupPath: state.fullPath,
confidential,
};
return epicUtils.gqClient
.mutate({
mutation: updateEpic,
variables: {
updateEpicInput,
},
})
.then(({ data }) => {
if (!data?.updateEpic?.errors.length) {
commit(types.SET_EPIC_CONFIDENTIAL, confidential);
} else {
const errMsg =
data?.updateEpic?.errors[0]?.replace(/Confidential /, '') ||
s__('Epics|Unable to perform this action');
throw errMsg;
}
})
.catch(error => {
flash(error);
throw error;
});
};
/** /**
* Methods to handle Epic labels selection from sidebar * Methods to handle Epic labels selection from sidebar
*/ */
......
...@@ -30,3 +30,5 @@ export const REQUEST_EPIC_CREATE_FAILURE = 'REQUEST_EPIC_CREATE_FAILURE'; ...@@ -30,3 +30,5 @@ export const REQUEST_EPIC_CREATE_FAILURE = 'REQUEST_EPIC_CREATE_FAILURE';
export const REQUEST_EPIC_LABELS_SELECT = 'REQUEST_EPIC_LABELS_SELECT'; export const REQUEST_EPIC_LABELS_SELECT = 'REQUEST_EPIC_LABELS_SELECT';
export const RECEIVE_EPIC_LABELS_SELECT_SUCCESS = 'RECEIVE_EPIC_LABELS_SELECT_SUCCESS'; export const RECEIVE_EPIC_LABELS_SELECT_SUCCESS = 'RECEIVE_EPIC_LABELS_SELECT_SUCCESS';
export const RECEIVE_EPIC_LABELS_SELECT_FAILURE = 'RECEIVE_EPIC_LABELS_SELECT_FAILURE'; export const RECEIVE_EPIC_LABELS_SELECT_FAILURE = 'RECEIVE_EPIC_LABELS_SELECT_FAILURE';
export const SET_EPIC_CONFIDENTIAL = 'SET_EPIC_CONFIDENTIAL';
...@@ -121,4 +121,7 @@ export default { ...@@ -121,4 +121,7 @@ export default {
[types.RECEIVE_EPIC_LABELS_SELECT_FAILURE](state) { [types.RECEIVE_EPIC_LABELS_SELECT_FAILURE](state) {
state.epicLabelsSelectInProgress = false; state.epicLabelsSelectInProgress = false;
}, },
[types.SET_EPIC_CONFIDENTIAL](state, confidential) {
state.confidential = confidential;
},
}; };
---
title: Toggle epic confidential
merge_request: 37678
author:
type: added
...@@ -1238,4 +1238,63 @@ describe('Epic Store Actions', () => { ...@@ -1238,4 +1238,63 @@ describe('Epic Store Actions', () => {
}); });
}); });
}); });
describe('updateConfidentialityOnIssuable', () => {
let mock;
const mockUpdateConfidentialMutationRes = {
updateEpic: {
clientMutationId: null,
errors: [],
__typename: 'UpdateEpicPayload',
},
};
const data = {
confidential: true,
};
beforeEach(() => {
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.restore();
});
it('commits SET_EPIC_CONFIDENTIAL when request is successful', done => {
mock.onPut(/(.*)/).replyOnce(200, {});
jest.spyOn(epicUtils.gqClient, 'mutate').mockResolvedValue({
data: mockUpdateConfidentialMutationRes,
});
testAction(
actions.updateConfidentialityOnIssuable,
{ ...data },
state,
[{ payload: true, type: 'SET_EPIC_CONFIDENTIAL' }],
[],
done,
);
});
it("doesn't commit/dispatch and throws error when request fails", done => {
mock.onPut(/(.*)/).replyOnce(500, {});
const errors = ['bar'];
jest.spyOn(epicUtils.gqClient, 'mutate').mockResolvedValue({
data: {
updateEpic: {
...mockUpdateConfidentialMutationRes,
errors,
},
},
});
testAction(actions.updateConfidentialityOnIssuable, { ...data }, state, [], [])
.catch(err => {
expect(err).toEqual('bar');
})
.finally(done);
});
});
}); });
...@@ -422,4 +422,18 @@ describe('Epic Store Mutations', () => { ...@@ -422,4 +422,18 @@ describe('Epic Store Mutations', () => {
expect(state.epicLabelsSelectInProgress).toBe(false); expect(state.epicLabelsSelectInProgress).toBe(false);
}); });
}); });
describe('SET_EPIC_CONFIDENTIAL', () => {
it('Should set `confidential` flag on state to `true`', () => {
const state = {
confidential: false,
};
const confidential = true;
mutations[types.SET_EPIC_CONFIDENTIAL](state, confidential);
expect(state.confidential).toBe(true);
});
});
}); });
...@@ -9584,6 +9584,9 @@ msgstr "" ...@@ -9584,6 +9584,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic." msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "" msgstr ""
msgid "Epics|Unable to perform this action"
msgstr ""
msgid "Epics|Unable to save epic. Please try again" msgid "Epics|Unable to save epic. Please try again"
msgstr "" msgstr ""
...@@ -24656,6 +24659,9 @@ msgstr "" ...@@ -24656,6 +24659,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment." msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "" msgstr ""
msgid "This %{issuableType} is confidential"
msgstr ""
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment." msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr "" msgstr ""
...@@ -24860,9 +24866,6 @@ msgstr "" ...@@ -24860,9 +24866,6 @@ msgstr ""
msgid "This is your current session" msgid "This is your current session"
msgstr "" msgstr ""
msgid "This issue is confidential"
msgstr ""
msgid "This issue is currently blocked by the following issues: %{issues}." msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr "" msgstr ""
...@@ -27663,6 +27666,12 @@ msgstr "" ...@@ -27663,6 +27666,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?" msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "" msgstr ""
msgid "You are going to turn off the confidentiality. This means %{accessLevel} will be able to see and leave a comment on this %{issuableType}."
msgstr ""
msgid "You are going to turn on the confidentiality. This means that only team members with %{accessLevel} are able to see and leave comments on the %{issuableType}."
msgstr ""
msgid "You are not allowed to push into this branch. Create another branch or open a merge request." msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr "" msgstr ""
...@@ -28391,6 +28400,9 @@ msgstr "" ...@@ -28391,6 +28400,9 @@ msgstr ""
msgid "assign yourself" msgid "assign yourself"
msgstr "" msgstr ""
msgid "at least Reporter access"
msgstr ""
msgid "at risk" msgid "at risk"
msgstr "" msgstr ""
...@@ -28672,12 +28684,6 @@ msgstr "" ...@@ -28672,12 +28684,6 @@ msgstr ""
msgid "committed" msgid "committed"
msgstr "" msgstr ""
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
msgstr ""
msgid "connecting" msgid "connecting"
msgstr "" msgstr ""
...@@ -28787,6 +28793,9 @@ msgstr "" ...@@ -28787,6 +28793,9 @@ msgstr ""
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command." msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr "" msgstr ""
msgid "everyone"
msgstr ""
msgid "exceeds the limit of %{bytes} bytes" msgid "exceeds the limit of %{bytes} bytes"
msgstr "" msgstr ""
......
...@@ -1221,7 +1221,7 @@ describe('Actions Notes Store', () => { ...@@ -1221,7 +1221,7 @@ describe('Actions Notes Store', () => {
}); });
}); });
describe('updateConfidentialityOnIssue', () => { describe('updateConfidentialityOnIssuable', () => {
state = { noteableData: { confidential: false } }; state = { noteableData: { confidential: false } };
const iid = '1'; const iid = '1';
const projectPath = 'full/path'; const projectPath = 'full/path';
...@@ -1236,13 +1236,13 @@ describe('Actions Notes Store', () => { ...@@ -1236,13 +1236,13 @@ describe('Actions Notes Store', () => {
}); });
it('calls gqClient mutation one time', () => { it('calls gqClient mutation one time', () => {
actions.updateConfidentialityOnIssue({ commit: () => {}, state, getters }, actionArgs); actions.updateConfidentialityOnIssuable({ commit: () => {}, state, getters }, actionArgs);
expect(utils.gqClient.mutate).toHaveBeenCalledTimes(1); expect(utils.gqClient.mutate).toHaveBeenCalledTimes(1);
}); });
it('calls gqClient mutation with the correct values', () => { it('calls gqClient mutation with the correct values', () => {
actions.updateConfidentialityOnIssue({ commit: () => {}, state, getters }, actionArgs); actions.updateConfidentialityOnIssuable({ commit: () => {}, state, getters }, actionArgs);
expect(utils.gqClient.mutate).toHaveBeenCalledWith({ expect(utils.gqClient.mutate).toHaveBeenCalledWith({
mutation: updateIssueConfidentialMutation, mutation: updateIssueConfidentialMutation,
...@@ -1255,7 +1255,7 @@ describe('Actions Notes Store', () => { ...@@ -1255,7 +1255,7 @@ describe('Actions Notes Store', () => {
const commitSpy = jest.fn(); const commitSpy = jest.fn();
return actions return actions
.updateConfidentialityOnIssue({ commit: commitSpy, state, getters }, actionArgs) .updateConfidentialityOnIssuable({ commit: commitSpy, state, getters }, actionArgs)
.then(() => { .then(() => {
expect(commitSpy).toHaveBeenCalledWith( expect(commitSpy).toHaveBeenCalledWith(
mutationTypes.SET_ISSUE_CONFIDENTIAL, mutationTypes.SET_ISSUE_CONFIDENTIAL,
......
...@@ -44,9 +44,11 @@ describe('Edit Form Buttons', () => { ...@@ -44,9 +44,11 @@ describe('Edit Form Buttons', () => {
describe('when isLoading', () => { describe('when isLoading', () => {
beforeEach(() => { beforeEach(() => {
createComponent({}); createComponent({
props: {
wrapper.vm.$store.state.noteableData.confidential = false; confidential: false,
},
});
}); });
it('renders "Applying" in the toggle button', () => { it('renders "Applying" in the toggle button', () => {
...@@ -68,6 +70,9 @@ describe('Edit Form Buttons', () => { ...@@ -68,6 +70,9 @@ describe('Edit Form Buttons', () => {
data: { data: {
isLoading: false, isLoading: false,
}, },
props: {
confidential: false,
},
}); });
expect(findConfidentialToggle().text()).toBe('Turn On'); expect(findConfidentialToggle().text()).toBe('Turn On');
...@@ -80,9 +85,10 @@ describe('Edit Form Buttons', () => { ...@@ -80,9 +85,10 @@ describe('Edit Form Buttons', () => {
data: { data: {
isLoading: false, isLoading: false,
}, },
props: {
confidential: true,
},
}); });
wrapper.vm.$store.state.noteableData.confidential = true;
}); });
it('renders on or off text based on confidentiality', () => { it('renders on or off text based on confidentiality', () => {
...@@ -92,13 +98,12 @@ describe('Edit Form Buttons', () => { ...@@ -92,13 +98,12 @@ describe('Edit Form Buttons', () => {
describe('when succeeds', () => { describe('when succeeds', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ data: { isLoading: false } }); createComponent({ data: { isLoading: false }, props: { confidential: true } });
wrapper.vm.$store.state.noteableData.confidential = true;
findConfidentialToggle().trigger('click'); findConfidentialToggle().trigger('click');
}); });
it('dispatches the correct action', () => { it('dispatches the correct action', () => {
expect(store.dispatch).toHaveBeenCalledWith('updateConfidentialityOnIssue', { expect(store.dispatch).toHaveBeenCalledWith('updateConfidentialityOnIssuable', {
confidential: false, confidential: false,
fullPath: '', fullPath: '',
}); });
...@@ -115,15 +120,21 @@ describe('Edit Form Buttons', () => { ...@@ -115,15 +120,21 @@ describe('Edit Form Buttons', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('closeConfidentialityForm'); expect(eventHub.$emit).toHaveBeenCalledWith('closeConfidentialityForm');
}); });
}); });
it('emits updateOnConfidentiality event', () => {
return waitForPromises().then(() => {
expect(eventHub.$emit).toHaveBeenCalledWith('updateIssuableConfidentiality', false);
});
});
}); });
describe('when fails', () => { describe('when fails', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ createComponent({
data: { isLoading: false }, data: { isLoading: false },
props: { confidential: true },
resolved: false, resolved: false,
}); });
wrapper.vm.$store.state.noteableData.confidential = true;
findConfidentialToggle().trigger('click'); findConfidentialToggle().trigger('click');
}); });
......
...@@ -12,6 +12,7 @@ describe('Edit Form Dropdown', () => { ...@@ -12,6 +12,7 @@ describe('Edit Form Dropdown', () => {
...props, ...props,
isLoading: false, isLoading: false,
fullPath: '', fullPath: '',
issuableType: 'issue',
}, },
}); });
}; };
...@@ -24,7 +25,7 @@ describe('Edit Form Dropdown', () => { ...@@ -24,7 +25,7 @@ describe('Edit Form Dropdown', () => {
describe('when not confidential', () => { describe('when not confidential', () => {
it('renders "You are going to turn off the confidentiality." in the ', () => { it('renders "You are going to turn off the confidentiality." in the ', () => {
createComponent({ createComponent({
isConfidential: false, confidential: false,
toggleForm, toggleForm,
updateConfidentialAttribute, updateConfidentialAttribute,
}); });
...@@ -36,7 +37,7 @@ describe('Edit Form Dropdown', () => { ...@@ -36,7 +37,7 @@ describe('Edit Form Dropdown', () => {
describe('when confidential', () => { describe('when confidential', () => {
it('renders on or off text based on confidentiality', () => { it('renders on or off text based on confidentiality', () => {
createComponent({ createComponent({
isConfidential: true, confidential: true,
toggleForm, toggleForm,
updateConfidentialAttribute, updateConfidentialAttribute,
}); });
......
...@@ -2,9 +2,9 @@ import { shallowMount } from '@vue/test-utils'; ...@@ -2,9 +2,9 @@ import { shallowMount } from '@vue/test-utils';
import { mockTracking, triggerEvent } from 'helpers/tracking_helper'; import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
import ConfidentialIssueSidebar from '~/sidebar/components/confidential/confidential_issue_sidebar.vue'; import ConfidentialIssueSidebar from '~/sidebar/components/confidential/confidential_issue_sidebar.vue';
import EditForm from '~/sidebar/components/confidential/edit_form.vue'; import EditForm from '~/sidebar/components/confidential/edit_form.vue';
import SidebarService from '~/sidebar/services/sidebar_service';
import createStore from '~/notes/stores'; import createStore from '~/notes/stores';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper'; import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import * as types from '~/notes/stores/mutation_types';
jest.mock('~/flash'); jest.mock('~/flash');
jest.mock('~/sidebar/services/sidebar_service'); jest.mock('~/sidebar/services/sidebar_service');
...@@ -19,14 +19,12 @@ describe('Confidential Issue Sidebar Block', () => { ...@@ -19,14 +19,12 @@ describe('Confidential Issue Sidebar Block', () => {
const createComponent = ({ propsData, data = {} }) => { const createComponent = ({ propsData, data = {} }) => {
const store = createStore(); const store = createStore();
const service = new SidebarService();
wrapper = shallowMount(ConfidentialIssueSidebar, { wrapper = shallowMount(ConfidentialIssueSidebar, {
store, store,
data() { data() {
return data; return data;
}, },
propsData: { propsData: {
service,
iid: '', iid: '',
fullPath: '', fullPath: '',
...propsData, ...propsData,
...@@ -115,4 +113,47 @@ describe('Confidential Issue Sidebar Block', () => { ...@@ -115,4 +113,47 @@ describe('Confidential Issue Sidebar Block', () => {
}); });
}); });
}); });
describe('computed confidential', () => {
beforeEach(() => {
createComponent({
propsData: {
isEditable: true,
},
});
});
it('returns false when noteableData is not present', () => {
wrapper.vm.$store.commit(types.SET_NOTEABLE_DATA, null);
expect(wrapper.vm.confidential).toBe(false);
});
it('returns true when noteableData has confidential attr as true', () => {
wrapper.vm.$store.commit(types.SET_NOTEABLE_DATA, {});
wrapper.vm.$store.commit(types.SET_ISSUE_CONFIDENTIAL, true);
expect(wrapper.vm.confidential).toBe(true);
});
it('returns false when noteableData has confidential attr as false', () => {
wrapper.vm.$store.commit(types.SET_NOTEABLE_DATA, {});
wrapper.vm.$store.commit(types.SET_ISSUE_CONFIDENTIAL, false);
expect(wrapper.vm.confidential).toBe(false);
});
it('returns true when confidential attr is true', () => {
wrapper.vm.$store.commit(types.SET_NOTEABLE_DATA, {});
wrapper.vm.$store.commit(types.SET_ISSUE_CONFIDENTIAL, true);
expect(wrapper.vm.confidential).toBe(true);
});
it('returns false when confidential attr is false', () => {
wrapper.vm.$store.commit(types.SET_NOTEABLE_DATA, {});
wrapper.vm.$store.commit(types.SET_ISSUE_CONFIDENTIAL, false);
expect(wrapper.vm.confidential).toBe(false);
});
});
}); });
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