Skip to content
Snippets Groups Projects
Commit f1e55de9 authored by Tristan Read's avatar Tristan Read :three:
Browse files

Merge branch '409018-cleanup-deprecate-vulns-feedback-fe' into 'master'

Remove deprecateVulnerabilitiesFeedback feature flag

See merge request !124130



Merged-by: default avatarTristan Read <tread@gitlab.com>
Approved-by: Lorenz van Herwaarden's avatarLorenz van Herwaarden <lvanherwaarden@gitlab.com>
Approved-by: default avatarTristan Read <tread@gitlab.com>
Co-authored-by: default avatarMalcolm Locke <mlocke@gitlab.com>
parents 6a9a546d 5002e054
No related branches found
No related tags found
1 merge request!124130Remove deprecateVulnerabilitiesFeedback feature flag
Pipeline #906395314 failed
Pipeline: E2E GDK

#906406551

    Showing
    with 266 additions and 1057 deletions
    ...@@ -49,27 +49,16 @@ export default { ...@@ -49,27 +49,16 @@ export default {
    return location && (location.image || location.file || location.path); return location && (location.image || location.file || location.path);
    }, },
    dismissalData() { dismissalData() {
    return this.glFeatures.deprecateVulnerabilitiesFeedback return getDismissalTransitionForVulnerability(this.vulnerability);
    ? getDismissalTransitionForVulnerability(this.vulnerability)
    : this.vulnerability.dismissal_feedback;
    }, },
    dismissalComment() { dismissalComment() {
    // state_transitions has a comment string, dismissal_feedback has a comment_details object. return this.dismissalData?.comment;
    return this.glFeatures.deprecateVulnerabilitiesFeedback
    ? this.dismissalData?.comment
    : this.dismissalData?.comment_details;
    }, },
    issueData() { issueData() {
    return this.glFeatures.deprecateVulnerabilitiesFeedback return getCreatedIssueForVulnerability(this.vulnerability);
    ? getCreatedIssueForVulnerability(this.vulnerability)
    : this.vulnerability.issue_feedback;
    }, },
    hasIssue() { hasIssue() {
    // Issues can be deleted. After an issue is deleted, issue_feedback will still be an object, but it won't have return Boolean(this.issueData);
    // an issue_iid. issue_links however will remove the object from the array. Once we enable and remove the
    // deprecate_vulnerabilities_feedback feature flag, it's no longer necessary to check for issue_iid, and this
    // computed property can be deleted in favor of checking whether issueData is truthy instead.
    return Boolean(this.issueData?.issue_iid);
    }, },
    canDismissVulnerability() { canDismissVulnerability() {
    const path = this.vulnerability.create_vulnerability_feedback_dismissal_path; const path = this.vulnerability.create_vulnerability_feedback_dismissal_path;
    ......
    ...@@ -10,7 +10,6 @@ import download from '~/lib/utils/downloader'; ...@@ -10,7 +10,6 @@ import download from '~/lib/utils/downloader';
    import { s__, n__, sprintf } from '~/locale'; import { s__, n__, sprintf } from '~/locale';
    import toast from '~/vue_shared/plugins/global_toast'; import toast from '~/vue_shared/plugins/global_toast';
    import { import {
    FEEDBACK_TYPE_DISMISSAL,
    FEEDBACK_TYPE_ISSUE, FEEDBACK_TYPE_ISSUE,
    FEEDBACK_TYPE_MERGE_REQUEST, FEEDBACK_TYPE_MERGE_REQUEST,
    } from '~/vue_shared/security_reports/constants'; } from '~/vue_shared/security_reports/constants';
    ...@@ -235,20 +234,7 @@ export const dismissSelectedVulnerabilities = ( ...@@ -235,20 +234,7 @@ export const dismissSelectedVulnerabilities = (
    dispatch('requestDismissSelectedVulnerabilities'); dispatch('requestDismissSelectedVulnerabilities');
    const promises = dismissibleVulnerabilities.map((vulnerability) => const promises = dismissibleVulnerabilities.map((vulnerability) =>
    gon.features.deprecateVulnerabilitiesFeedback dismissFinding(vulnerability, comment),
    ? dismissFinding(vulnerability, comment)
    : axios.post(vulnerability.create_vulnerability_feedback_dismissal_path, {
    vulnerability_feedback: {
    category: vulnerability.report_type,
    comment,
    feedback_type: FEEDBACK_TYPE_DISMISSAL,
    project_fingerprint: vulnerability.project_fingerprint,
    finding_uuid: vulnerability.uuid,
    vulnerability_data: {
    id: vulnerability.id,
    },
    },
    }),
    ); );
    return Promise.all(promises) return Promise.all(promises)
    ...@@ -317,9 +303,7 @@ export const dismissVulnerability = ( ...@@ -317,9 +303,7 @@ export const dismissVulnerability = (
    text: s__('SecurityReports|Undo dismiss'), text: s__('SecurityReports|Undo dismiss'),
    onClick: (e, toastObject) => { onClick: (e, toastObject) => {
    const shouldRevertDismiss = Boolean( const shouldRevertDismiss = Boolean(
    gon.features.deprecateVulnerabilitiesFeedback getDismissalTransitionForVulnerability(vulnerability),
    ? getDismissalTransitionForVulnerability(vulnerability)
    : vulnerability.dismissal_feedback,
    ); );
    if (shouldRevertDismiss) { if (shouldRevertDismiss) {
    ...@@ -333,22 +317,7 @@ export const dismissVulnerability = ( ...@@ -333,22 +317,7 @@ export const dismissVulnerability = (
    } }
    : {}; : {};
    const action = gon.features.deprecateVulnerabilitiesFeedback const action = dismissFinding(vulnerability, comment);
    ? dismissFinding(vulnerability, comment)
    : axios.post(vulnerability.create_vulnerability_feedback_dismissal_path, {
    vulnerability_feedback: {
    category: vulnerability.report_type,
    comment,
    feedback_type: FEEDBACK_TYPE_DISMISSAL,
    pipeline_id: state.pipelineId,
    project_fingerprint: vulnerability.project_fingerprint,
    finding_uuid: vulnerability.uuid,
    vulnerability_data: {
    ...vulnerability,
    category: vulnerability.report_type,
    },
    },
    });
    action action
    .then(({ data }) => { .then(({ data }) => {
    ...@@ -388,12 +357,7 @@ export const receiveDismissVulnerabilityError = ({ commit }, { flashError }) => ...@@ -388,12 +357,7 @@ export const receiveDismissVulnerabilityError = ({ commit }, { flashError }) =>
    export const addDismissalComment = ({ dispatch }, { vulnerability, comment }) => { export const addDismissalComment = ({ dispatch }, { vulnerability, comment }) => {
    dispatch('requestAddDismissalComment'); dispatch('requestAddDismissalComment');
    const dismissalFeedback = vulnerability.dismissal_feedback; const isEditingComment = Boolean(getDismissalTransitionForVulnerability(vulnerability).comment);
    const isEditingComment = Boolean(
    gon.features.deprecateVulnerabilitiesFeedback
    ? getDismissalTransitionForVulnerability(vulnerability).comment
    : dismissalFeedback.comment_details?.comment,
    );
    const toastMsg = isEditingComment const toastMsg = isEditingComment
    ? sprintf(s__("SecurityReports|Comment edited on '%{vulnerabilityName}'"), { ? sprintf(s__("SecurityReports|Comment edited on '%{vulnerabilityName}'"), {
    ...@@ -403,13 +367,7 @@ export const addDismissalComment = ({ dispatch }, { vulnerability, comment }) => ...@@ -403,13 +367,7 @@ export const addDismissalComment = ({ dispatch }, { vulnerability, comment }) =>
    vulnerabilityName: vulnerability.name, vulnerabilityName: vulnerability.name,
    }); });
    const action = gon.features.deprecateVulnerabilitiesFeedback const action = dismissFinding(vulnerability, comment);
    ? dismissFinding(vulnerability, comment)
    : axios.patch(dismissalFeedback.destroy_vulnerability_feedback_dismissal_path, {
    project_id: dismissalFeedback.project_id,
    id: dismissalFeedback.id,
    comment,
    });
    action action
    .then(({ data }) => { .then(({ data }) => {
    ...@@ -424,17 +382,11 @@ export const addDismissalComment = ({ dispatch }, { vulnerability, comment }) => ...@@ -424,17 +382,11 @@ export const addDismissalComment = ({ dispatch }, { vulnerability, comment }) =>
    export const deleteDismissalComment = ({ dispatch }, { vulnerability }) => { export const deleteDismissalComment = ({ dispatch }, { vulnerability }) => {
    dispatch('requestDeleteDismissalComment'); dispatch('requestDeleteDismissalComment');
    const dismissalFeedback = vulnerability.dismissal_feedback;
    const toastMsg = sprintf(s__("SecurityReports|Comment deleted on '%{vulnerabilityName}'"), { const toastMsg = sprintf(s__("SecurityReports|Comment deleted on '%{vulnerabilityName}'"), {
    vulnerabilityName: vulnerability.name, vulnerabilityName: vulnerability.name,
    }); });
    const action = gon.features.deprecateVulnerabilitiesFeedback const action = dismissFinding(vulnerability, '');
    ? dismissFinding(vulnerability, '')
    : axios.patch(dismissalFeedback.destroy_vulnerability_feedback_dismissal_path, {
    project_id: dismissalFeedback.project_id,
    comment: '',
    });
    action action
    .then(({ data }) => { .then(({ data }) => {
    ...@@ -482,12 +434,10 @@ export const hideDismissalDeleteButtons = ({ commit }) => { ...@@ -482,12 +434,10 @@ export const hideDismissalDeleteButtons = ({ commit }) => {
    export const revertDismissVulnerability = ({ dispatch }, { vulnerability, flashError }) => { export const revertDismissVulnerability = ({ dispatch }, { vulnerability, flashError }) => {
    dispatch('requestUndoDismiss'); dispatch('requestUndoDismiss');
    const action = gon.features.deprecateVulnerabilitiesFeedback const action = defaultClient.mutate({
    ? defaultClient.mutate({ mutation: revertFindingToDetectedMutation,
    mutation: revertFindingToDetectedMutation, variables: { uuid: vulnerability.uuid },
    variables: { uuid: vulnerability.uuid }, });
    })
    : axios.delete(vulnerability.dismissal_feedback.destroy_vulnerability_feedback_dismissal_path);
    return action return action
    .then(({ data }) => { .then(({ data }) => {
    ......
    ...@@ -61,9 +61,7 @@ export default { ...@@ -61,9 +61,7 @@ export default {
    Vue.set(state.modal, 'error', null); Vue.set(state.modal, 'error', null);
    }, },
    [types.RECEIVE_CREATE_ISSUE_SUCCESS](state, payload) { [types.RECEIVE_CREATE_ISSUE_SUCCESS](state, payload) {
    const url = gon.features.deprecateVulnerabilitiesFeedback const url = getCreatedIssueForVulnerability(payload).issue_url;
    ? getCreatedIssueForVulnerability(payload).issue_url
    : payload.issue_url;
    // We don't cancel the loading state here because we're navigating away from the page // We don't cancel the loading state here because we're navigating away from the page
    visitUrl(url); visitUrl(url);
    ...@@ -80,15 +78,8 @@ export default { ...@@ -80,15 +78,8 @@ export default {
    const vulnerability = state.vulnerabilities.find((vuln) => const vulnerability = state.vulnerabilities.find((vuln) =>
    isSameVulnerability(vuln, payload.vulnerability), isSameVulnerability(vuln, payload.vulnerability),
    ); );
    // When the feature flag is on, the payload is the entire updated vulnerability. When it's off, the payload is only const updated = payload.data.securityFindingDismiss.securityFinding.vulnerability;
    // the dismissal feedback object. updateFindingFromGraphqlResponse(vulnerability, updated);
    if (gon.features.deprecateVulnerabilitiesFeedback) {
    const updated = payload.data.securityFindingDismiss.securityFinding.vulnerability;
    updateFindingFromGraphqlResponse(vulnerability, updated);
    } else {
    vulnerability.state = 'dismissed';
    vulnerability.dismissal_feedback = payload.data;
    }
    state.isDismissingVulnerability = false; state.isDismissingVulnerability = false;
    Vue.set(state.modal.vulnerability, 'isDismissed', true); Vue.set(state.modal.vulnerability, 'isDismissed', true);
    ...@@ -139,12 +130,8 @@ export default { ...@@ -139,12 +130,8 @@ export default {
    isSameVulnerability(vuln, payload.vulnerability), isSameVulnerability(vuln, payload.vulnerability),
    ); );
    if (vulnerability) { if (vulnerability) {
    if (gon.features.deprecateVulnerabilitiesFeedback) { const updated = payload.data.securityFindingDismiss.securityFinding.vulnerability;
    const updated = payload.data.securityFindingDismiss.securityFinding.vulnerability; updateFindingFromGraphqlResponse(vulnerability, updated);
    updateFindingFromGraphqlResponse(vulnerability, updated);
    } else {
    vulnerability.dismissal_feedback = payload.data;
    }
    state.isDismissingVulnerability = false; state.isDismissingVulnerability = false;
    Vue.set(state.modal.vulnerability, 'isDismissed', true); Vue.set(state.modal.vulnerability, 'isDismissed', true);
    ...@@ -161,12 +148,8 @@ export default { ...@@ -161,12 +148,8 @@ export default {
    [types.RECEIVE_DELETE_DISMISSAL_COMMENT_SUCCESS](state, payload) { [types.RECEIVE_DELETE_DISMISSAL_COMMENT_SUCCESS](state, payload) {
    const vulnerability = state.vulnerabilities.find((vuln) => vuln.id === payload.id); const vulnerability = state.vulnerabilities.find((vuln) => vuln.id === payload.id);
    if (vulnerability) { if (vulnerability) {
    if (gon.features.deprecateVulnerabilitiesFeedback) { const updated = payload.data.securityFindingDismiss.securityFinding.vulnerability;
    const updated = payload.data.securityFindingDismiss.securityFinding.vulnerability; updateFindingFromGraphqlResponse(vulnerability, updated);
    updateFindingFromGraphqlResponse(vulnerability, updated);
    } else {
    vulnerability.dismissal_feedback = payload.data;
    }
    state.isDismissingVulnerability = false; state.isDismissingVulnerability = false;
    Vue.set(state.modal.vulnerability, 'isDismissed', true); Vue.set(state.modal.vulnerability, 'isDismissed', true);
    ...@@ -184,15 +167,8 @@ export default { ...@@ -184,15 +167,8 @@ export default {
    const vulnerability = state.vulnerabilities.find((vuln) => const vulnerability = state.vulnerabilities.find((vuln) =>
    isSameVulnerability(vuln, payload.vulnerability), isSameVulnerability(vuln, payload.vulnerability),
    ); );
    // When the feature flag is on, the payload is the entire updated vulnerability. When it's off, the payload is only const updated = payload.data.securityFindingRevertToDetected.securityFinding.vulnerability;
    // the dismissal feedback object. updateFindingFromGraphqlResponse(vulnerability, updated);
    if (gon.features.deprecateVulnerabilitiesFeedback) {
    const updated = payload.data.securityFindingRevertToDetected.securityFinding.vulnerability;
    updateFindingFromGraphqlResponse(vulnerability, updated);
    } else {
    vulnerability.state = 'detected';
    vulnerability.dismissal_feedback = null;
    }
    state.isDismissingVulnerability = false; state.isDismissingVulnerability = false;
    Vue.set(state.modal.vulnerability, 'isDismissed', false); Vue.set(state.modal.vulnerability, 'isDismissed', false);
    ...@@ -216,9 +192,7 @@ export default { ...@@ -216,9 +192,7 @@ export default {
    Vue.set(state.modal, 'error', null); Vue.set(state.modal, 'error', null);
    }, },
    [types.RECEIVE_CREATE_MERGE_REQUEST_SUCCESS](state, payload) { [types.RECEIVE_CREATE_MERGE_REQUEST_SUCCESS](state, payload) {
    const url = gon.features.deprecateVulnerabilitiesFeedback const url = payload.merge_request_links.at(-1).merge_request_path;
    ? payload.merge_request_links.at(-1).merge_request_path
    : payload.merge_request_path;
    // We don't cancel the loading state here because we're navigating away from the page // We don't cancel the loading state here because we're navigating away from the page
    visitUrl(url); visitUrl(url);
    }, },
    ......
    ...@@ -83,7 +83,7 @@ export default { ...@@ -83,7 +83,7 @@ export default {
    }, },
    result({ data }) { result({ data }) {
    const finding = data.project.pipeline.securityReportFinding; const finding = data.project.pipeline.securityReportFinding;
    const { mergeRequest, stateComment, dismissedBy, dismissedAt, vulnerability } = finding; const { mergeRequest, vulnerability } = finding;
    if (mergeRequest) { if (mergeRequest) {
    this.$set(this.modalData.vulnerability, 'hasMergeRequest', true); this.$set(this.modalData.vulnerability, 'hasMergeRequest', true);
    ...@@ -95,11 +95,7 @@ export default { ...@@ -95,11 +95,7 @@ export default {
    merge_request_iid: mergeRequest.iid, merge_request_iid: mergeRequest.iid,
    }; };
    if (this.glFeatures.deprecateVulnerabilitiesFeedback) { this.modalData.vulnerability.merge_request_links = [mergeRequestData];
    this.modalData.vulnerability.merge_request_links = [mergeRequestData];
    } else {
    this.modalData.vulnerability.merge_request_feedback = mergeRequestData;
    }
    } }
    const issue = finding.issueLinks?.nodes.find((x) => x.linkType === 'CREATED')?.issue; const issue = finding.issueLinks?.nodes.find((x) => x.linkType === 'CREATED')?.issue;
    ...@@ -114,26 +110,12 @@ export default { ...@@ -114,26 +110,12 @@ export default {
    link_type: 'created', link_type: 'created',
    }; };
    if (this.glFeatures.deprecateVulnerabilitiesFeedback) { this.modalData.vulnerability.issue_links = [issueData];
    this.modalData.vulnerability.issue_links = [issueData];
    } else {
    this.modalData.vulnerability.issue_feedback = issueData;
    }
    } }
    if (this.glFeatures.deprecateVulnerabilitiesFeedback) { this.modalData.vulnerability.state_transitions = vulnerability
    this.modalData.vulnerability.state_transitions = vulnerability ? vulnerability.stateTransitions.nodes.map(convertObjectPropsToSnakeCase)
    ? vulnerability.stateTransitions.nodes.map(convertObjectPropsToSnakeCase) : [];
    : [];
    } else if (dismissedAt) {
    this.$set(this.modalData.vulnerability, 'dismissal_feedback', {
    comment_details: stateComment
    ? { comment: stateComment, comment_author: dismissedBy }
    : null,
    author: dismissedBy,
    created_at: finding.dismissedAt,
    });
    }
    }, },
    skip() { skip() {
    return !this.modalData; return !this.modalData;
    ...@@ -398,9 +380,7 @@ export default { ...@@ -398,9 +380,7 @@ export default {
    }, },
    }) })
    .then(({ data }) => { .then(({ data }) => {
    const url = this.glFeatures.deprecateVulnerabilitiesFeedback const url = getCreatedIssueForVulnerability(data).issue_url;
    ? getCreatedIssueForVulnerability(data).issue_url
    : data.issue_url;
    visitUrl(url); visitUrl(url);
    }) })
    ...@@ -508,9 +488,7 @@ export default { ...@@ -508,9 +488,7 @@ export default {
    const finding = this.modalData.vulnerability; const finding = this.modalData.vulnerability;
    const isEditingDismissalContent = Boolean( const isEditingDismissalContent = Boolean(
    this.glFeatures.deprecateVulnerabilitiesFeedback getDismissalTransitionForVulnerability(finding).comment,
    ? getDismissalTransitionForVulnerability(finding).comment
    : finding.dismissal_feedback?.comment_details?.comment,
    ); );
    const errorMsg = s__('SecurityReports|There was an error adding the comment.'); const errorMsg = s__('SecurityReports|There was an error adding the comment.');
    ...@@ -564,9 +542,7 @@ export default { ...@@ -564,9 +542,7 @@ export default {
    }, },
    }) })
    .then(({ data }) => { .then(({ data }) => {
    const url = this.glFeatures.deprecateVulnerabilitiesFeedback const url = data.merge_request_links.at(-1).merge_request_path;
    ? data.merge_request_links.at(-1).merge_request_path
    : data.merge_request_path;
    visitUrl(url); visitUrl(url);
    }) })
    ......
    ...@@ -102,42 +102,30 @@ export default { ...@@ -102,42 +102,30 @@ export default {
    return this.modal.vulnerability; return this.modal.vulnerability;
    }, },
    issueData() { issueData() {
    return this.glFeatures.deprecateVulnerabilitiesFeedback return getCreatedIssueForVulnerability(this.vulnerability);
    ? getCreatedIssueForVulnerability(this.vulnerability)
    : this.vulnerability?.issue_feedback;
    }, },
    hasIssue() { hasIssue() {
    // Issues can be deleted. After an issue is deleted, issue_feedback will still be an object, but it won't have return Boolean(this.issueData);
    // an issue_iid. issue_links however will remove the object from the array. Once we enable and remove the
    // deprecate_vulnerabilities_feedback feature flag, it's no longer necessary to check for issue_iid, and this
    // computed property can be deleted in favor of checking whether issueData is truthy instead.
    return Boolean(this.issueData?.issue_iid);
    }, },
    mergeRequestData() { mergeRequestData() {
    return this.glFeatures.deprecateVulnerabilitiesFeedback return this.vulnerability?.merge_request_links?.at(-1);
    ? this.vulnerability?.merge_request_links?.at(-1)
    : this.vulnerability?.merge_request_feedback;
    }, },
    dismissalData() { dismissalData() {
    if (this.glFeatures.deprecateVulnerabilitiesFeedback) { const transition = getDismissalTransitionForVulnerability(this.vulnerability);
    const transition = getDismissalTransitionForVulnerability(this.vulnerability);
    if (!transition) { if (!transition) {
    return null; return null;
    }
    const commentDetails = transition.comment
    ? { comment: transition.comment, comment_author: transition.author }
    : null;
    // Return the dismissal data in the format the dismissal note expects.
    return {
    author: transition.author,
    created_at: transition.created_at,
    comment_details: commentDetails,
    };
    } }
    return this.vulnerability?.dismissalFeedback || this.vulnerability?.dismissal_feedback; const commentDetails = transition.comment
    ? { comment: transition.comment, comment_author: transition.author }
    : null;
    // Return the dismissal data in the format the dismissal note expects.
    return {
    author: transition.author,
    created_at: transition.created_at,
    comment_details: commentDetails,
    };
    }, },
    isEditingDismissalComment() { isEditingDismissalComment() {
    return this.dismissalData && this.modal.isCommentingOnDismissal; return this.dismissalData && this.modal.isCommentingOnDismissal;
    ......
    ...@@ -110,9 +110,7 @@ export default { ...@@ -110,9 +110,7 @@ export default {
    : null; : null;
    }, },
    mergeRequest() { mergeRequest() {
    return this.glFeatures.deprecateVulnerabilitiesFeedback return this.vulnerability.mergeRequestLinks.at(-1);
    ? this.vulnerability.mergeRequestLinks.at(-1)
    : this.vulnerability.mergeRequestFeedback;
    }, },
    }, },
    watch: { watch: {
    ......
    ...@@ -79,9 +79,7 @@ export default { ...@@ -79,9 +79,7 @@ export default {
    return this.vulnerability.remediations?.[0]?.diff?.length > 0; return this.vulnerability.remediations?.[0]?.diff?.length > 0;
    }, },
    mergeRequest() { mergeRequest() {
    return this.glFeatures.deprecateVulnerabilitiesFeedback return this.vulnerability.mergeRequestLinks.at(-1);
    ? this.vulnerability.mergeRequestLinks.at(-1)
    : this.vulnerability.mergeRequestFeedback;
    }, },
    canCreateMergeRequest() { canCreateMergeRequest() {
    return !this.mergeRequest && this.vulnerability.createMrUrl && this.hasRemediation; return !this.mergeRequest && this.vulnerability.createMrUrl && this.hasRemediation;
    ...@@ -194,9 +192,7 @@ export default { ...@@ -194,9 +192,7 @@ export default {
    }, },
    }) })
    .then(({ data }) => { .then(({ data }) => {
    const mergeRequestPath = this.glFeatures.deprecateVulnerabilitiesFeedback const mergeRequestPath = data.merge_request_links.at(-1).merge_request_path;
    ? data.merge_request_links.at(-1).merge_request_path
    : data.merge_request_path;
    redirectTo(mergeRequestPath); // eslint-disable-line import/no-deprecated redirectTo(mergeRequestPath); // eslint-disable-line import/no-deprecated
    }) })
    ......
    ...@@ -21,19 +21,12 @@ describe('Security Dashboard Table Row', () => { ...@@ -21,19 +21,12 @@ describe('Security Dashboard Table Row', () => {
    let wrapper; let wrapper;
    let store; let store;
    const createComponent = ( const createComponent = (mountFunc, { props = {} } = {}) => {
    mountFunc,
    { props = {} } = {},
    { deprecateVulnerabilitiesFeedback = true } = {},
    ) => {
    wrapper = mountFunc(SecurityDashboardTableRow, { wrapper = mountFunc(SecurityDashboardTableRow, {
    store, store,
    propsData: { propsData: {
    ...props, ...props,
    }, },
    provide: {
    glFeatures: { deprecateVulnerabilitiesFeedback },
    },
    }); });
    }; };
    ...@@ -169,34 +162,6 @@ describe('Security Dashboard Table Row', () => { ...@@ -169,34 +162,6 @@ describe('Security Dashboard Table Row', () => {
    ); );
    }); });
    describe('vulnerability dismissal - deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    let vulnerability;
    beforeEach(() => {
    vulnerability = cloneDeep(mockDataVulnerabilities[0]);
    });
    it.each`
    dismissalFeedback | isLabelShown | isIconShown
    ${{}} | ${true} | ${false}
    ${{ comment_details: {} }} | ${true} | ${true}
    ${null} | ${false} | ${false}
    `(
    'shows dismissal badge: $isLabelShown, shows dismissal comment icon: $isIconShown',
    ({ dismissalFeedback, isLabelShown, isIconShown }) => {
    vulnerability.dismissal_feedback = dismissalFeedback;
    createComponent(
    shallowMountExtended,
    { props: { vulnerability } },
    { deprecateVulnerabilitiesFeedback: false },
    );
    expect(findDismissalLabel().exists()).toBe(isLabelShown);
    expect(findDismissalCommentIcon().exists()).toBe(isIconShown);
    },
    );
    });
    describe('with created issue', () => { describe('with created issue', () => {
    const vulnerability = mockDataVulnerabilities[3]; const vulnerability = mockDataVulnerabilities[3];
    ...@@ -208,41 +173,6 @@ describe('Security Dashboard Table Row', () => { ...@@ -208,41 +173,6 @@ describe('Security Dashboard Table Row', () => {
    projectName: vulnerability.project.name, projectName: vulnerability.project.name,
    }); });
    }); });
    it('does not show the vulnerability issue link if there is no issue iid', () => {
    const vuln = cloneDeep(vulnerability);
    vuln.issue_links[0].issue_iid = null;
    createComponent(shallowMount, { props: { vulnerability: vuln } });
    expect(findVulnerabilityIssueLink().exists()).toBe(false);
    });
    describe('deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    it('shows the vulnerability issue link with the expected props', () => {
    createComponent(
    shallowMount,
    { props: { vulnerability } },
    { deprecateVulnerabilitiesFeedback: false },
    );
    expect(findVulnerabilityIssueLink().props()).toMatchObject({
    issue: vulnerability.issue_feedback,
    projectName: vulnerability.project.name,
    });
    });
    it('does not show the vulnerability issue link if there is no issue iid', () => {
    const vuln = cloneDeep(vulnerability);
    vuln.issue_feedback.issue_iid = null;
    createComponent(
    shallowMount,
    { props: { vulnerability: vuln } },
    { deprecateVulnerabilitiesFeedback: false },
    );
    expect(findVulnerabilityIssueLink().exists()).toBe(false);
    });
    });
    }); });
    describe('with no created issue', () => { describe('with no created issue', () => {
    ......
    ...@@ -28,10 +28,6 @@ jest.mock('jquery', () => () => ({ ...@@ -28,10 +28,6 @@ jest.mock('jquery', () => () => ({
    })); }));
    describe('vulnerability actions', () => { describe('vulnerability actions', () => {
    beforeEach(() => {
    gon.features = { deprecateVulnerabilitiesFeedback: true };
    });
    describe('vulnerabilities count actions', () => { describe('vulnerabilities count actions', () => {
    let state; let state;
    ...@@ -637,78 +633,6 @@ describe('vulnerability actions', () => { ...@@ -637,78 +633,6 @@ describe('vulnerability actions', () => {
    checkToastMessage, checkToastMessage,
    ); );
    }); });
    describe('deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    beforeEach(() => {
    gon.features.deprecateVulnerabilitiesFeedback = false;
    mock
    .onPost(vulnerability.create_vulnerability_feedback_dismissal_path)
    .replyOnce(HTTP_STATUS_OK, data);
    });
    it('should dispatch the request and success actions', () => {
    return testAction(
    actions.dismissVulnerability,
    { vulnerability, comment },
    {},
    [],
    [
    { type: 'requestDismissVulnerability' },
    { type: 'closeDismissalCommentBox' },
    {
    type: 'receiveDismissVulnerabilitySuccess',
    payload: { data, vulnerability },
    },
    ],
    );
    });
    it('should show the dismissal toast message', () => {
    const checkToastMessage = () => {
    expect(toast).toHaveBeenCalledTimes(1);
    };
    return testAction(
    actions.dismissVulnerability,
    { vulnerability, comment },
    {},
    [],
    [
    { type: 'requestDismissVulnerability' },
    { type: 'closeDismissalCommentBox' },
    {
    type: 'receiveDismissVulnerabilitySuccess',
    payload: { data, vulnerability },
    },
    ],
    checkToastMessage,
    );
    });
    });
    });
    describe('on error', () => {
    beforeEach(() => {
    gon.features = { deprecateVulnerabilitiesFeedback: false };
    mock
    .onPost(vulnerability.create_vulnerability_feedback_dismissal_path)
    .replyOnce(HTTP_STATUS_NOT_FOUND, {});
    });
    it('should dispatch the request and error actions', () => {
    const flashError = false;
    return testAction(
    actions.dismissVulnerability,
    { vulnerability, flashError },
    {},
    [],
    [
    { type: 'requestDismissVulnerability' },
    { type: 'receiveDismissVulnerabilityError', payload: { flashError } },
    ],
    );
    });
    }); });
    describe('with dismissed vulnerabilities hidden', () => { describe('with dismissed vulnerabilities hidden', () => {
    ...@@ -771,63 +695,6 @@ describe('vulnerability actions', () => { ...@@ -771,63 +695,6 @@ describe('vulnerability actions', () => {
    ], ],
    ); );
    }); });
    describe('deprecateVulnerabilitiesFeedback feature flag is disabled', () => {
    beforeEach(() => {
    gon.features.deprecateVulnerabilitiesFeedback = false;
    mock
    .onPost(vulnerability.create_vulnerability_feedback_dismissal_path)
    .replyOnce(HTTP_STATUS_OK, data);
    it('should show the dismissal toast message and refresh vulnerabilities', () => {
    const checkToastMessage = () => {
    const [message, options] = toast.mock.calls[0];
    expect(toast).toHaveBeenCalledTimes(1);
    expect(message).toContain('Turn off the hide dismissed toggle to view');
    expect(Object.keys(options.action)).toHaveLength(2);
    };
    return testAction(
    actions.dismissVulnerability,
    { vulnerability, comment },
    state,
    [],
    [
    { type: 'requestDismissVulnerability' },
    { type: 'closeDismissalCommentBox' },
    {
    type: 'receiveDismissVulnerabilitySuccess',
    payload: { data, vulnerability },
    },
    { type: 'fetchVulnerabilities', payload: { page: 1 } },
    ],
    checkToastMessage,
    );
    });
    it('should load the previous page if there are no more vulnerabilities on the current one and page > 1', () => {
    state.vulnerabilities = [mockDataVulnerabilities[0]];
    state.pageInfo.page = 3;
    return testAction(
    actions.dismissVulnerability,
    { vulnerability, comment },
    state,
    [],
    [
    { type: 'requestDismissVulnerability' },
    { type: 'closeDismissalCommentBox' },
    {
    type: 'receiveDismissVulnerabilitySuccess',
    payload: { data, vulnerability },
    },
    { type: 'fetchVulnerabilities', payload: { page: 2 } },
    ],
    );
    });
    });
    });
    }); });
    }); });
    ...@@ -871,7 +738,6 @@ describe('vulnerability actions', () => { ...@@ -871,7 +738,6 @@ describe('vulnerability actions', () => {
    describe('addDismissalComment', () => { describe('addDismissalComment', () => {
    const vulnerability = mockDataVulnerabilities[2]; const vulnerability = mockDataVulnerabilities[2];
    const data = { vulnerability }; const data = { vulnerability };
    const url = vulnerability.destroy_vulnerability_feedback_dismissal_path;
    const comment = 'Well, we’re back in the car again.'; const comment = 'Well, we’re back in the car again.';
    let mock; let mock;
    ...@@ -915,41 +781,6 @@ describe('vulnerability actions', () => { ...@@ -915,41 +781,6 @@ describe('vulnerability actions', () => {
    ], ],
    ); );
    }); });
    describe('deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    beforeEach(() => {
    gon.features.deprecateVulnerabilitiesFeedback = false;
    mock.onPatch(url).replyOnce(HTTP_STATUS_OK, data);
    });
    it('should dispatch the request and success actions', () => {
    return testAction(
    actions.addDismissalComment,
    { vulnerability, comment },
    {},
    [],
    [
    { type: 'requestAddDismissalComment' },
    { type: 'closeDismissalCommentBox' },
    { type: 'receiveAddDismissalCommentSuccess', payload: { data, vulnerability } },
    ],
    );
    });
    it('should show the add dismissal toast message', () => {
    return testAction(
    actions.addDismissalComment,
    { vulnerability, comment },
    {},
    [],
    [
    { type: 'requestAddDismissalComment' },
    { type: 'closeDismissalCommentBox' },
    { type: 'receiveAddDismissalCommentSuccess', payload: { data, vulnerability } },
    ],
    );
    });
    });
    }); });
    describe('on error', () => { describe('on error', () => {
    ...@@ -964,19 +795,6 @@ describe('vulnerability actions', () => { ...@@ -964,19 +795,6 @@ describe('vulnerability actions', () => {
    [{ type: 'requestAddDismissalComment' }, { type: 'receiveAddDismissalCommentError' }], [{ type: 'requestAddDismissalComment' }, { type: 'receiveAddDismissalCommentError' }],
    ); );
    }); });
    it('should dispatch the request and error actions - deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    gon.features.deprecateVulnerabilitiesFeedback = false;
    mock.onPatch(url).replyOnce(HTTP_STATUS_NOT_FOUND);
    return testAction(
    actions.addDismissalComment,
    { vulnerability, comment },
    {},
    [],
    [{ type: 'requestAddDismissalComment' }, { type: 'receiveAddDismissalCommentError' }],
    );
    });
    }); });
    describe('receiveAddDismissalCommentSuccess', () => { describe('receiveAddDismissalCommentSuccess', () => {
    ...@@ -1007,7 +825,6 @@ describe('vulnerability actions', () => { ...@@ -1007,7 +825,6 @@ describe('vulnerability actions', () => {
    describe('deleteDismissalComment', () => { describe('deleteDismissalComment', () => {
    const vulnerability = mockDataVulnerabilities[2]; const vulnerability = mockDataVulnerabilities[2];
    const data = { vulnerability }; const data = { vulnerability };
    const url = vulnerability.dismissal_feedback.destroy_vulnerability_feedback_dismissal_path;
    let mock; let mock;
    beforeEach(() => { beforeEach(() => {
    ...@@ -1056,47 +873,6 @@ describe('vulnerability actions', () => { ...@@ -1056,47 +873,6 @@ describe('vulnerability actions', () => {
    ], ],
    ); );
    }); });
    describe('deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    beforeEach(() => {
    gon.features.deprecateVulnerabilitiesFeedback = false;
    mock.onPatch(url).replyOnce(HTTP_STATUS_OK, data);
    });
    it('should dispatch the request and success actions', () => {
    return testAction(
    actions.deleteDismissalComment,
    { vulnerability },
    {},
    [],
    [
    { type: 'requestDeleteDismissalComment' },
    { type: 'closeDismissalCommentBox' },
    {
    type: 'receiveDeleteDismissalCommentSuccess',
    payload: { data, id: vulnerability.id },
    },
    ],
    );
    });
    it('should show the delete dismissal comment toast message', () => {
    return testAction(
    actions.deleteDismissalComment,
    { vulnerability },
    {},
    [],
    [
    { type: 'requestDeleteDismissalComment' },
    { type: 'closeDismissalCommentBox' },
    {
    type: 'receiveDeleteDismissalCommentSuccess',
    payload: { data, id: vulnerability.id },
    },
    ],
    );
    });
    });
    }); });
    describe('on error', () => { describe('on error', () => {
    ...@@ -1114,22 +890,6 @@ describe('vulnerability actions', () => { ...@@ -1114,22 +890,6 @@ describe('vulnerability actions', () => {
    ], ],
    ); );
    }); });
    it('should dispatch the request and error actions - deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    gon.features.deprecateVulnerabilitiesFeedback = false;
    mock.onPatch(url).replyOnce(HTTP_STATUS_NOT_FOUND);
    return testAction(
    actions.deleteDismissalComment,
    { vulnerability },
    {},
    [],
    [
    { type: 'requestDeleteDismissalComment' },
    { type: 'receiveDeleteDismissalCommentError' },
    ],
    );
    });
    }); });
    describe('receiveDeleteDismissalCommentSuccess', () => { describe('receiveDeleteDismissalCommentSuccess', () => {
    ...@@ -1377,7 +1137,6 @@ describe('vulnerability actions', () => { ...@@ -1377,7 +1137,6 @@ describe('vulnerability actions', () => {
    describe('revert vulnerability dismissal', () => { describe('revert vulnerability dismissal', () => {
    describe('revertDismissVulnerability', () => { describe('revertDismissVulnerability', () => {
    const vulnerability = mockDataVulnerabilities[2]; const vulnerability = mockDataVulnerabilities[2];
    const url = vulnerability.dismissal_feedback.destroy_vulnerability_feedback_dismissal_path;
    let mock; let mock;
    beforeEach(() => { beforeEach(() => {
    ...@@ -1404,22 +1163,6 @@ describe('vulnerability actions', () => { ...@@ -1404,22 +1163,6 @@ describe('vulnerability actions', () => {
    ], ],
    ); );
    }); });
    it('should dispatch the request and success actions - deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    gon.features.deprecateVulnerabilitiesFeedback = false;
    mock.onDelete(url).replyOnce(HTTP_STATUS_OK);
    return testAction(
    actions.revertDismissVulnerability,
    { vulnerability },
    {},
    [],
    [
    { type: 'requestUndoDismiss' },
    { type: 'receiveUndoDismissSuccess', payload: { vulnerability } },
    ],
    );
    });
    }); });
    describe('on error', () => { describe('on error', () => {
    ......
    ...@@ -25,7 +25,6 @@ describe('vulnerabilities module mutations', () => { ...@@ -25,7 +25,6 @@ describe('vulnerabilities module mutations', () => {
    let state; let state;
    beforeEach(() => { beforeEach(() => {
    gon.features = { deprecateVulnerabilitiesFeedback: true };
    state = createState(); state = createState();
    }); });
    ...@@ -179,14 +178,6 @@ describe('vulnerabilities module mutations', () => { ...@@ -179,14 +178,6 @@ describe('vulnerabilities module mutations', () => {
    expect(visitUrl).toHaveBeenCalledWith(path); expect(visitUrl).toHaveBeenCalledWith(path);
    }); });
    it('should visit the issue URL - deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    gon.features = { deprecateVulnerabilitiesFeedback: false };
    const payload = { issue_url: 'fakepath.html' };
    mutations[types.RECEIVE_CREATE_ISSUE_SUCCESS](state, payload);
    expect(visitUrl).toHaveBeenCalledWith(payload.issue_url);
    });
    }); });
    describe('RECEIVE_CREATE_ISSUE_ERROR', () => { describe('RECEIVE_CREATE_ISSUE_ERROR', () => {
    ...@@ -225,15 +216,6 @@ describe('vulnerabilities module mutations', () => { ...@@ -225,15 +216,6 @@ describe('vulnerabilities module mutations', () => {
    expect(visitUrl).toHaveBeenCalledWith(path); expect(visitUrl).toHaveBeenCalledWith(path);
    }); });
    it('should visit the merge request URL - deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    gon.features = { deprecateVulnerabilitiesFeedback: false };
    const path = 'fakepath.html';
    const payload = { merge_request_path: path };
    mutations[types.RECEIVE_CREATE_MERGE_REQUEST_SUCCESS](state, payload);
    expect(visitUrl).toHaveBeenCalledWith(path);
    });
    }); });
    describe('RECEIVE_CREATE_MERGE_REQUEST_ERROR', () => { describe('RECEIVE_CREATE_MERGE_REQUEST_ERROR', () => {
    ...@@ -266,53 +248,27 @@ describe('vulnerabilities module mutations', () => { ...@@ -266,53 +248,27 @@ describe('vulnerabilities module mutations', () => {
    describe('RECEIVE_DISMISS_VULNERABILITY_SUCCESS', () => { describe('RECEIVE_DISMISS_VULNERABILITY_SUCCESS', () => {
    let vulnerability; let vulnerability;
    let data;
    beforeEach(() => { beforeEach(() => {
    state.vulnerabilities = mockData; state.vulnerabilities = mockData;
    [vulnerability] = mockData; [vulnerability] = mockData;
    }); mutations[types.RECEIVE_DISMISS_VULNERABILITY_SUCCESS](state, {
    vulnerability,
    describe('deprecateVulnerabilitiesFeedback feature flag enabled', () => { data: GRAPHQL_DISMISS_MUTATION_RESPONSE,
    beforeEach(() => {
    mutations[types.RECEIVE_DISMISS_VULNERABILITY_SUCCESS](state, {
    vulnerability,
    data: GRAPHQL_DISMISS_MUTATION_RESPONSE,
    });
    });
    it('should set the dismissal feedback on the passed vulnerability', () => {
    expect(vulnerability.state).toBe(EXPECTED_DISMISSAL_STATE);
    expect(vulnerability.state_transitions).toEqual(EXPECTED_DISMISSAL_TRANSITIONS);
    });
    it('should set isDismissingVulnerability to false', () => {
    expect(state.isDismissingVulnerability).toBe(false);
    });
    it('should set isDismissed on the modal vulnerability to be true', () => {
    expect(state.modal.vulnerability.isDismissed).toBe(true);
    }); });
    }); });
    describe('deprecateVulnerabilitiesFeedback feature flag disabled', () => { it('should set the dismissal feedback on the passed vulnerability', () => {
    beforeEach(() => { expect(vulnerability.state).toBe(EXPECTED_DISMISSAL_STATE);
    data = { name: 'dismissal feedback' }; expect(vulnerability.state_transitions).toEqual(EXPECTED_DISMISSAL_TRANSITIONS);
    gon.features = { deprecateVulnerabilitiesFeedback: false }; });
    mutations[types.RECEIVE_DISMISS_VULNERABILITY_SUCCESS](state, { vulnerability, data });
    });
    it('should set the dismissal feedback on the passed vulnerability', () => {
    expect(vulnerability.dismissal_feedback).toEqual(data);
    });
    it('should set isDismissingVulnerability to false', () => { it('should set isDismissingVulnerability to false', () => {
    expect(state.isDismissingVulnerability).toBe(false); expect(state.isDismissingVulnerability).toBe(false);
    }); });
    it('should set isDismissed on the modal vulnerability to be true', () => { it('should set isDismissed on the modal vulnerability to be true', () => {
    expect(state.modal.vulnerability.isDismissed).toBe(true); expect(state.modal.vulnerability.isDismissed).toBe(true);
    });
    }); });
    }); });
    ...@@ -446,54 +402,25 @@ describe('vulnerabilities module mutations', () => { ...@@ -446,54 +402,25 @@ describe('vulnerabilities module mutations', () => {
    describe('RECEIVE_DELETE_DISMISSAL_COMMENT_SUCCESS', () => { describe('RECEIVE_DELETE_DISMISSAL_COMMENT_SUCCESS', () => {
    beforeEach(() => { beforeEach(() => {
    state.vulnerabilities = mockData; state.vulnerabilities = mockData;
    }); mutations[types.RECEIVE_DELETE_DISMISSAL_COMMENT_SUCCESS](state, {
    id: state.vulnerabilities[0].id,
    describe('deprecateVulnerabilitiesFeedback feature flag enabled', () => { data: GRAPHQL_DISMISS_MUTATION_RESPONSE,
    beforeEach(() => {
    mutations[types.RECEIVE_DELETE_DISMISSAL_COMMENT_SUCCESS](state, {
    id: state.vulnerabilities[0].id,
    data: GRAPHQL_DISMISS_MUTATION_RESPONSE,
    });
    });
    it('should update the vulnerability state and state_transitions with payload data', () => {
    const vulnerability = state.vulnerabilities[0];
    expect(vulnerability.state).toBe(EXPECTED_DISMISSAL_STATE);
    expect(vulnerability.state_transitions).toEqual(EXPECTED_DISMISSAL_TRANSITIONS);
    });
    it('should set isDismissingVulnerability to false', () => {
    expect(state.isDismissingVulnerability).toBe(false);
    });
    it('should set isDismissed on the modal vulnerability to be true', () => {
    expect(state.modal.vulnerability.isDismissed).toBe(true);
    }); });
    }); });
    describe('deprecateVulnerabilitiesFeedback feature flag disabled', () => { it('should update the vulnerability state and state_transitions with payload data', () => {
    const data = {}; const vulnerability = state.vulnerabilities[0];
    beforeEach(() => { expect(vulnerability.state).toBe(EXPECTED_DISMISSAL_STATE);
    gon.features.deprecateVulnerabilitiesFeedback = false; expect(vulnerability.state_transitions).toEqual(EXPECTED_DISMISSAL_TRANSITIONS);
    mutations[types.RECEIVE_DELETE_DISMISSAL_COMMENT_SUCCESS](state, { });
    id: state.vulnerabilities[0].id,
    data,
    });
    });
    it('should set the dismissal feedback to the payload data', () => {
    expect(state.vulnerabilities[0].dismissal_feedback).toEqual(data);
    });
    it('should set isDismissingVulnerability to false', () => { it('should set isDismissingVulnerability to false', () => {
    expect(state.isDismissingVulnerability).toBe(false); expect(state.isDismissingVulnerability).toBe(false);
    }); });
    it('should set isDismissed on the modal vulnerability to be true', () => { it('should set isDismissed on the modal vulnerability to be true', () => {
    expect(state.modal.vulnerability.isDismissed).toBe(true); expect(state.modal.vulnerability.isDismissed).toBe(true);
    });
    }); });
    }); });
    ...@@ -548,54 +475,25 @@ describe('vulnerabilities module mutations', () => { ...@@ -548,54 +475,25 @@ describe('vulnerabilities module mutations', () => {
    describe('RECEIVE_ADD_DISMISSAL_COMMENT_SUCCESS', () => { describe('RECEIVE_ADD_DISMISSAL_COMMENT_SUCCESS', () => {
    beforeEach(() => { beforeEach(() => {
    state.vulnerabilities = mockData; state.vulnerabilities = mockData;
    }); mutations[types.RECEIVE_ADD_DISMISSAL_COMMENT_SUCCESS](state, {
    vulnerability: state.vulnerabilities[0],
    describe('deprecateVulnerabilitiesFeedback feature flag enabled', () => { data: GRAPHQL_DISMISS_MUTATION_RESPONSE,
    beforeEach(() => {
    mutations[types.RECEIVE_ADD_DISMISSAL_COMMENT_SUCCESS](state, {
    vulnerability: state.vulnerabilities[0],
    data: GRAPHQL_DISMISS_MUTATION_RESPONSE,
    });
    });
    it('should update the vulnerability state and state_transitions with payload data', () => {
    const vulnerability = state.vulnerabilities[0];
    expect(vulnerability.state).toBe(EXPECTED_DISMISSAL_STATE);
    expect(vulnerability.state_transitions).toEqual(EXPECTED_DISMISSAL_TRANSITIONS);
    });
    it('should set isDismissingVulnerability to false', () => {
    expect(state.isDismissingVulnerability).toBe(false);
    });
    it('should set isDismissed on the modal vulnerability to be true', () => {
    expect(state.modal.vulnerability.isDismissed).toBe(true);
    }); });
    }); });
    describe('deprecateVulnerabilitiesFeedback feature flag disabled', () => { it('should update the vulnerability state and state_transitions with payload data', () => {
    const data = {}; const vulnerability = state.vulnerabilities[0];
    beforeEach(() => {
    gon.features.deprecateVulnerabilitiesFeedback = false;
    mutations[types.RECEIVE_ADD_DISMISSAL_COMMENT_SUCCESS](state, {
    vulnerability: state.vulnerabilities[0],
    data,
    });
    });
    it('should set the dismissal feedback on the passed vulnerability', () => { expect(vulnerability.state).toBe(EXPECTED_DISMISSAL_STATE);
    expect(state.vulnerabilities[0].dismissal_feedback).toEqual(data); expect(vulnerability.state_transitions).toEqual(EXPECTED_DISMISSAL_TRANSITIONS);
    }); });
    it('should set isDismissingVulnerability to false', () => { it('should set isDismissingVulnerability to false', () => {
    expect(state.isDismissingVulnerability).toBe(false); expect(state.isDismissingVulnerability).toBe(false);
    }); });
    it('should set isDismissed on the modal vulnerability to be true', () => { it('should set isDismissed on the modal vulnerability to be true', () => {
    expect(state.modal.vulnerability.isDismissed).toBe(true); expect(state.modal.vulnerability.isDismissed).toBe(true);
    });
    }); });
    }); });
    ...@@ -634,57 +532,33 @@ describe('vulnerabilities module mutations', () => { ...@@ -634,57 +532,33 @@ describe('vulnerabilities module mutations', () => {
    beforeEach(() => { beforeEach(() => {
    state.vulnerabilities = mockData; state.vulnerabilities = mockData;
    [vulnerability] = mockData; [vulnerability] = mockData;
    }); mutations[types.RECEIVE_REVERT_DISMISSAL_SUCCESS](state, {
    vulnerability,
    describe('deprecateVulnerabilitiesFeedback feature flag enabled', () => { data: {
    beforeEach(() => { securityFindingRevertToDetected: {
    mutations[types.RECEIVE_REVERT_DISMISSAL_SUCCESS](state, { securityFinding: {
    vulnerability, vulnerability: {
    data: { stateTransitions: { nodes: [detectedTransition] },
    securityFindingRevertToDetected: {
    securityFinding: {
    vulnerability: {
    stateTransitions: { nodes: [detectedTransition] },
    },
    }, },
    }, },
    }, },
    }); },
    });
    it('should set state and state_transitions on the passed vulnerability', () => {
    expect(vulnerability.state).toEqual(detectedTransition.toState.toLowerCase());
    expect(vulnerability.state_transitions).toEqual([
    convertObjectPropsToSnakeCase(detectedTransition),
    ]);
    });
    it('should set isDismissingVulnerability to false', () => {
    expect(state.isDismissingVulnerability).toBe(false);
    });
    it('should set isDismissed on the modal vulnerability to be false', () => {
    expect(state.modal.vulnerability.isDismissed).toBe(false);
    }); });
    }); });
    describe('deprecateVulnerabilitiesFeedback feature flag disabled', () => { it('should set state and state_transitions on the passed vulnerability', () => {
    beforeEach(() => { expect(vulnerability.state).toEqual(detectedTransition.toState.toLowerCase());
    gon.features = { deprecateVulnerabilitiesFeedback: false }; expect(vulnerability.state_transitions).toEqual([
    mutations[types.RECEIVE_REVERT_DISMISSAL_SUCCESS](state, { vulnerability }); convertObjectPropsToSnakeCase(detectedTransition),
    }); ]);
    });
    it('should set the dismissal feedback on the passed vulnerability', () => {
    expect(vulnerability.dismissal_feedback).toBeNull();
    });
    it('should set isDismissingVulnerability to false', () => { it('should set isDismissingVulnerability to false', () => {
    expect(state.isDismissingVulnerability).toBe(false); expect(state.isDismissingVulnerability).toBe(false);
    }); });
    it('should set isDismissed on the modal vulnerability to be false', () => { it('should set isDismissed on the modal vulnerability to be false', () => {
    expect(state.modal.vulnerability.isDismissed).toBe(false); expect(state.modal.vulnerability.isDismissed).toBe(false);
    });
    }); });
    }); });
    ......
    ...@@ -84,7 +84,6 @@ describe('MR Widget Security Reports', () => { ...@@ -84,7 +84,6 @@ describe('MR Widget Security Reports', () => {
    mountFn = shallowMountExtended, mountFn = shallowMountExtended,
    findingHandler = [findingQuery, findingQueryMockData()], findingHandler = [findingQuery, findingQueryMockData()],
    additionalHandlers = [], additionalHandlers = [],
    deprecateVulnerabilitiesFeedback = true,
    } = {}) => { } = {}) => {
    wrapper = mountFn(MRSecurityWidget, { wrapper = mountFn(MRSecurityWidget, {
    apolloProvider: createMockApollo([findingHandler, ...additionalHandlers]), apolloProvider: createMockApollo([findingHandler, ...additionalHandlers]),
    ...@@ -117,9 +116,6 @@ describe('MR Widget Security Reports', () => { ...@@ -117,9 +116,6 @@ describe('MR Widget Security Reports', () => {
    apiFuzzingHelp, apiFuzzingHelp,
    }, },
    }, },
    provide: {
    glFeatures: { deprecateVulnerabilitiesFeedback },
    },
    stubs: { stubs: {
    MrWidgetRow, MrWidgetRow,
    }, },
    ...@@ -133,7 +129,6 @@ describe('MR Widget Security Reports', () => { ...@@ -133,7 +129,6 @@ describe('MR Widget Security Reports', () => {
    mockDataProps, mockDataProps,
    mrProps = {}, mrProps = {},
    additionalHandlers, additionalHandlers,
    deprecateVulnerabilitiesFeedback,
    }) => { }) => {
    mockDataFn(mockDataProps); mockDataFn(mockDataProps);
    createComponent({ createComponent({
    ...@@ -142,7 +137,6 @@ describe('MR Widget Security Reports', () => { ...@@ -142,7 +137,6 @@ describe('MR Widget Security Reports', () => {
    propsData: { propsData: {
    mr: mrProps, mr: mrProps,
    }, },
    deprecateVulnerabilitiesFeedback,
    }); });
    await waitForPromises(); await waitForPromises();
    ...@@ -500,14 +494,12 @@ describe('MR Widget Security Reports', () => { ...@@ -500,14 +494,12 @@ describe('MR Widget Security Reports', () => {
    mockDataProps = {}, mockDataProps = {},
    mrProps, mrProps,
    additionalHandlers, additionalHandlers,
    deprecateVulnerabilitiesFeedback,
    } = {}) => { } = {}) => {
    await createComponentAndExpandWidget({ await createComponentAndExpandWidget({
    mockDataFn: mockWithData, mockDataFn: mockWithData,
    mockDataProps, mockDataProps,
    mrProps, mrProps,
    additionalHandlers, additionalHandlers,
    deprecateVulnerabilitiesFeedback,
    }); });
    // Click on the vulnerability name // Click on the vulnerability name
    ...@@ -579,52 +571,6 @@ describe('MR Widget Security Reports', () => { ...@@ -579,52 +571,6 @@ describe('MR Widget Security Reports', () => {
    }); });
    }); });
    it('renders the modal when the finding is clicked - deprecateVulnerabilitiesFeedback feature flag disabled', async () => {
    await createComponentExpandWidgetAndOpenModal({ deprecateVulnerabilitiesFeedback: false });
    const modal = findModal();
    expect(modal.props('canCreateIssue')).toBe(false);
    expect(modal.props('isDismissingVulnerability')).toBe(false);
    expect(modal.props('isLoadingAdditionalInfo')).toBe(true);
    await waitForPromises();
    expect(modal.props('isLoadingAdditionalInfo')).toBe(false);
    const { dismissedBy, dismissedAt, stateComment, mergeRequest, issueLinks } = findingMockData;
    const { issue } = issueLinks.nodes[0];
    expect(modal.props('modal')).toMatchObject({
    title: 'Password leak',
    error: null,
    isShowingDeleteButtons: false,
    vulnerability: {
    uuid: '0',
    severity: 'critical',
    name: 'Password leak',
    dismissal_feedback: {
    author: dismissedBy,
    created_at: dismissedAt,
    comment_details: { comment: stateComment },
    },
    merge_request_feedback: {
    author: mergeRequest.author,
    merge_request_path: mergeRequest.webUrl,
    created_at: mergeRequest.createdAt,
    merge_request_iid: mergeRequest.iid,
    },
    issue_feedback: {
    author: issue.author,
    created_at: issue.createdAt,
    issue_url: issue.webUrl,
    issue_iid: issue.iid,
    link_type: 'created',
    },
    },
    });
    });
    it('downloads a patch when the downloadPatch event is emitted', async () => { it('downloads a patch when the downloadPatch event is emitted', async () => {
    await createComponentExpandWidgetAndOpenModal({ await createComponentExpandWidgetAndOpenModal({
    mockDataProps: { mockDataProps: {
    ...@@ -669,35 +615,6 @@ describe('MR Widget Security Reports', () => { ...@@ -669,35 +615,6 @@ describe('MR Widget Security Reports', () => {
    expect(spy).toHaveBeenCalledWith(mergeRequestPath); expect(spy).toHaveBeenCalledWith(mergeRequestPath);
    }); });
    it('handles merge request creation - success - deprecateVulnerabilitiesFeedback feature flag disabled', async () => {
    const mergeRequestPath = '/merge/request/1';
    mockAxios.onPost(createVulnerabilityFeedbackMergeRequestPath).replyOnce(HTTP_STATUS_OK, {
    merge_request_path: mergeRequestPath,
    });
    await createComponentExpandWidgetAndOpenModal({
    deprecateVulnerabilitiesFeedback: false,
    mrProps: {
    createVulnerabilityFeedbackDismissalPath,
    },
    });
    const spy = jest.spyOn(urlUtils, 'visitUrl');
    expect(findModal().props('isCreatingMergeRequest')).toBe(false);
    findModal().vm.$emit('createMergeRequest');
    await nextTick();
    expect(findModal().props('isCreatingMergeRequest')).toBe(true);
    await waitForPromises();
    expect(spy).toHaveBeenCalledWith(mergeRequestPath);
    });
    it('handles merge request creation - error', async () => { it('handles merge request creation - error', async () => {
    mockAxios mockAxios
    .onPost(createVulnerabilityFeedbackMergeRequestPath) .onPost(createVulnerabilityFeedbackMergeRequestPath)
    ...@@ -760,27 +677,6 @@ describe('MR Widget Security Reports', () => { ...@@ -760,27 +677,6 @@ describe('MR Widget Security Reports', () => {
    expect(spy).toHaveBeenCalledWith('/my/issue/url'); expect(spy).toHaveBeenCalledWith('/my/issue/url');
    }); });
    it('handles issue creation - success - deprecateVulnerabilitiesFeedback feature flag disabled', async () => {
    await createComponentExpandWidgetAndOpenModal({
    deprecateVulnerabilitiesFeedback: false,
    mrProps: {
    createVulnerabilityFeedbackIssuePath,
    },
    });
    mockAxios.onPost(createVulnerabilityFeedbackIssuePath).replyOnce(HTTP_STATUS_OK, {
    issue_url: '/my/issue/url',
    });
    const spy = jest.spyOn(urlUtils, 'visitUrl');
    findModal().vm.$emit('createNewIssue');
    await waitForPromises();
    expect(spy).toHaveBeenCalledWith('/my/issue/url');
    });
    it('handles issue creation - error', async () => { it('handles issue creation - error', async () => {
    mockAxios.onPost(createVulnerabilityFeedbackIssuePath).replyOnce(HTTP_STATUS_BAD_REQUEST); mockAxios.onPost(createVulnerabilityFeedbackIssuePath).replyOnce(HTTP_STATUS_BAD_REQUEST);
    ...@@ -846,155 +742,147 @@ describe('MR Widget Security Reports', () => { ...@@ -846,155 +742,147 @@ describe('MR Widget Security Reports', () => {
    }); });
    }); });
    describe.each([true, false])( describe('dismissal comment', () => {
    'dismissal comment - deprecateVulnerabilities feature flag %s', let mockDataProps;
    (deprecateVulnerabilitiesFeedback) => {
    let mockDataProps; beforeEach(() => {
    mockDataProps = {
    beforeEach(() => { state: 'dismissed',
    mockDataProps = { state_transitions: [
    state: 'dismissed', {
    state_transitions: [
    {
    author: {},
    to_state: 'DISMISSED',
    },
    ],
    dismissal_feedback: {
    author: {}, author: {},
    project_id: 20, to_state: 'DISMISSED',
    id: 15,
    }, },
    }; ],
    dismissal_feedback: {
    author: {},
    project_id: 20,
    id: 15,
    },
    };
    });
    it.each`
    event | booleanValue
    ${'openDismissalCommentBox'} | ${true}
    ${'closeDismissalCommentBox'} | ${false}
    ${'editVulnerabilityDismissalComment'} | ${true}
    `('handles opening dismissal comment for event $event', async ({ event, booleanValue }) => {
    await createComponentExpandWidgetAndOpenModal({
    mockDataProps,
    }); });
    it.each` expect(findModal().props('modal').isCommentingOnDismissal).toBeUndefined();
    event | booleanValue
    ${'openDismissalCommentBox'} | ${true}
    ${'closeDismissalCommentBox'} | ${false}
    ${'editVulnerabilityDismissalComment'} | ${true}
    `('handles opening dismissal comment for event $event', async ({ event, booleanValue }) => {
    await createComponentExpandWidgetAndOpenModal({
    mockDataProps,
    deprecateVulnerabilitiesFeedback,
    });
    expect(findModal().props('modal').isCommentingOnDismissal).toBeUndefined(); findModal().vm.$emit(event);
    findModal().vm.$emit(event); await waitForPromises();
    await waitForPromises(); expect(findModal().props('modal').isCommentingOnDismissal).toBe(booleanValue);
    });
    expect(findModal().props('modal').isCommentingOnDismissal).toBe(booleanValue); it('adds the dismissal comment - success', async () => {
    await createComponentExpandWidgetAndOpenModal({
    mockDataProps,
    additionalHandlers: [[dismissFindingMutation, DISMISSAL_RESPONSE]],
    }); });
    it('adds the dismissal comment - success', async () => { findModal().vm.$emit('addDismissalComment', 'Edited comment');
    await createComponentExpandWidgetAndOpenModal({
    mockDataProps,
    additionalHandlers: [[dismissFindingMutation, DISMISSAL_RESPONSE]],
    });
    findModal().vm.$emit('addDismissalComment', 'Edited comment'); await waitForPromises();
    await waitForPromises(); expect(toast).toHaveBeenCalledWith("Comment added to 'Password leak'");
    expect(emitSpy).toHaveBeenCalledWith(BV_HIDE_MODAL, 'modal-mrwidget-security-issue');
    });
    expect(toast).toHaveBeenCalledWith("Comment added to 'Password leak'"); it('edits the dismissal comment - success', async () => {
    expect(emitSpy).toHaveBeenCalledWith(BV_HIDE_MODAL, 'modal-mrwidget-security-issue'); await createComponentExpandWidgetAndOpenModal({
    mockDataProps,
    additionalHandlers: [[dismissFindingMutation, DISMISSAL_RESPONSE]],
    }); });
    it('edits the dismissal comment - success', async () => { await waitForPromises();
    await createComponentExpandWidgetAndOpenModal({
    mockDataProps,
    deprecateVulnerabilitiesFeedback,
    additionalHandlers: [[dismissFindingMutation, DISMISSAL_RESPONSE]],
    });
    await waitForPromises(); findModal().vm.$emit('addDismissalComment', 'Edited comment');
    findModal().vm.$emit('addDismissalComment', 'Edited comment'); await waitForPromises();
    await waitForPromises(); expect(toast).toHaveBeenCalledWith("Comment edited on 'Password leak'");
    expect(emitSpy).toHaveBeenCalledWith(BV_HIDE_MODAL, 'modal-mrwidget-security-issue');
    });
    expect(toast).toHaveBeenCalledWith("Comment edited on 'Password leak'"); it('adds the dismissal comment - error', async () => {
    expect(emitSpy).toHaveBeenCalledWith(BV_HIDE_MODAL, 'modal-mrwidget-security-issue'); await createComponentExpandWidgetAndOpenModal({
    mockDataProps,
    additionalHandlers: [[dismissFindingMutation, jest.fn().mockRejectedValue()]],
    }); });
    it('adds the dismissal comment - error', async () => { findModal().vm.$emit('addDismissalComment', 'Edited comment');
    await createComponentExpandWidgetAndOpenModal({
    mockDataProps,
    deprecateVulnerabilitiesFeedback,
    additionalHandlers: [[dismissFindingMutation, jest.fn().mockRejectedValue()]],
    });
    findModal().vm.$emit('addDismissalComment', 'Edited comment'); await waitForPromises();
    await waitForPromises(); expect(toast).not.toHaveBeenCalled();
    expect(findModal().props('modal').error).toBe('There was an error adding the comment.');
    });
    expect(toast).not.toHaveBeenCalled(); it('deletes the dismissal comment - success', async () => {
    expect(findModal().props('modal').error).toBe('There was an error adding the comment.'); mockDataProps.dismissal_feedback.comment_details = {
    comment: 'Existing comment',
    comment_author: { id: 15 },
    };
    await createComponentExpandWidgetAndOpenModal({
    mockDataProps,
    additionalHandlers: [[dismissFindingMutation, DISMISSAL_RESPONSE]],
    }); });
    it('deletes the dismissal comment - success', async () => { expect(findModal().props('modal').isShowingDeleteButtons).toBe(false);
    mockDataProps.dismissal_feedback.comment_details = {
    comment: 'Existing comment',
    comment_author: { id: 15 },
    };
    await createComponentExpandWidgetAndOpenModal({ // This displays the `Delete` button
    mockDataProps, findModal().vm.$emit('showDismissalDeleteButtons');
    deprecateVulnerabilitiesFeedback, await nextTick();
    additionalHandlers: [[dismissFindingMutation, DISMISSAL_RESPONSE]],
    });
    expect(findModal().props('modal').isShowingDeleteButtons).toBe(false); expect(findModal().props('modal').isShowingDeleteButtons).toBe(true);
    // This displays the `Delete` button // This triggers the actual delete call
    findModal().vm.$emit('showDismissalDeleteButtons'); findModal().vm.$emit('deleteDismissalComment');
    await nextTick(); await nextTick();
    expect(findModal().props('modal').isShowingDeleteButtons).toBe(true); await waitForPromises();
    // This triggers the actual delete call expect(toast).toHaveBeenCalledWith("Comment deleted on 'Password leak'");
    findModal().vm.$emit('deleteDismissalComment'); expect(emitSpy).toHaveBeenCalledWith(BV_HIDE_MODAL, 'modal-mrwidget-security-issue');
    await nextTick(); });
    await waitForPromises(); it('deletes the dismissal comment - error', async () => {
    mockDataProps.dismissal_feedback.comment_details = {
    comment: 'Existing comment',
    comment_author: { id: 15 },
    };
    expect(toast).toHaveBeenCalledWith("Comment deleted on 'Password leak'"); await createComponentExpandWidgetAndOpenModal({
    expect(emitSpy).toHaveBeenCalledWith(BV_HIDE_MODAL, 'modal-mrwidget-security-issue'); mockDataProps,
    additionalHandlers: [[dismissFindingMutation, jest.fn().mockRejectedValue()]],
    }); });
    it('deletes the dismissal comment - error', async () => { expect(findModal().props('modal').isShowingDeleteButtons).toBe(false);
    mockDataProps.dismissal_feedback.comment_details = {
    comment: 'Existing comment',
    comment_author: { id: 15 },
    };
    await createComponentExpandWidgetAndOpenModal({
    mockDataProps,
    deprecateVulnerabilitiesFeedback,
    additionalHandlers: [[dismissFindingMutation, jest.fn().mockRejectedValue()]],
    });
    expect(findModal().props('modal').isShowingDeleteButtons).toBe(false);
    // This displays the `Delete` button // This displays the `Delete` button
    findModal().vm.$emit('showDismissalDeleteButtons'); findModal().vm.$emit('showDismissalDeleteButtons');
    await nextTick(); await nextTick();
    expect(findModal().props('modal').isShowingDeleteButtons).toBe(true); expect(findModal().props('modal').isShowingDeleteButtons).toBe(true);
    // This triggers the actual delete call // This triggers the actual delete call
    findModal().vm.$emit('deleteDismissalComment'); findModal().vm.$emit('deleteDismissalComment');
    await nextTick(); await nextTick();
    await waitForPromises(); await waitForPromises();
    expect(toast).not.toHaveBeenCalled(); expect(toast).not.toHaveBeenCalled();
    expect(findModal().props('modal').error).toBe('There was an error deleting the comment.'); expect(findModal().props('modal').error).toBe('There was an error deleting the comment.');
    }); });
    }, });
    );
    describe('undo dismissing finding', () => { describe('undo dismissing finding', () => {
    let mockDataProps; let mockDataProps;
    ......
    ...@@ -21,11 +21,7 @@ describe('Security Reports modal', () => { ...@@ -21,11 +21,7 @@ describe('Security Reports modal', () => {
    let wrapper; let wrapper;
    let modal; let modal;
    const mountComponent = ( const mountComponent = (propsData, mountFn = shallowMount) => {
    propsData,
    mountFn = shallowMount,
    { deprecateVulnerabilitiesFeedback = true } = {},
    ) => {
    wrapper = mountFn(Modal, { wrapper = mountFn(Modal, {
    attrs: { attrs: {
    static: true, static: true,
    ...@@ -37,7 +33,6 @@ describe('Security Reports modal', () => { ...@@ -37,7 +33,6 @@ describe('Security Reports modal', () => {
    isCreatingMergeRequest: false, isCreatingMergeRequest: false,
    ...propsData, ...propsData,
    }, },
    provide: { glFeatures: { deprecateVulnerabilitiesFeedback } },
    stubs: { GlModal }, stubs: { GlModal },
    }); });
    modal = wrapper.findComponent(GlModal); modal = wrapper.findComponent(GlModal);
    ...@@ -100,14 +95,6 @@ describe('Security Reports modal', () => { ...@@ -100,14 +95,6 @@ describe('Security Reports modal', () => {
    created_at: transition.created_at, created_at: transition.created_at,
    }); });
    }); });
    it('renders dismissal note - deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    const feedback = {};
    propsData.modal.vulnerability.dismissalFeedback = feedback;
    mountComponent(propsData, shallowMount, { deprecateVulnerabilitiesFeedback: false });
    expect(findDismissalNote().props('feedback')).toBe(feedback);
    });
    }); });
    describe('with about to be dismissed finding', () => { describe('with about to be dismissed finding', () => {
    ...@@ -130,14 +117,6 @@ describe('Security Reports modal', () => { ...@@ -130,14 +117,6 @@ describe('Security Reports modal', () => {
    created_at: transition.created_at, created_at: transition.created_at,
    }); });
    }); });
    it('renders dismissal note - deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    const feedback = {};
    propsData.modal.vulnerability.dismissalFeedback = feedback;
    mountComponent(propsData, shallowMount, { deprecateVulnerabilitiesFeedback: false });
    expect(findDismissalNote().props('feedback')).toBe(feedback);
    });
    }); });
    describe('with not dismissed issue', () => { describe('with not dismissed issue', () => {
    ...@@ -176,15 +155,6 @@ describe('Security Reports modal', () => { ...@@ -176,15 +155,6 @@ describe('Security Reports modal', () => {
    expect(findModalFooter().props('canCreateMergeRequest')).toBe(false); expect(findModalFooter().props('canCreateMergeRequest')).toBe(false);
    }); });
    it(`can't create merge request when there is an existing merge request - deprecateVulnerabilitiesFeedback feature flag off`, () => {
    modalData.vulnerability.merge_request_feedback = {};
    mountComponent({ modal: modalData }, shallowMount, {
    deprecateVulnerabilitiesFeedback: false,
    });
    expect(findModalFooter().props('canCreateMergeRequest')).toBe(false);
    });
    }); });
    describe('data', () => { describe('data', () => {
    ...@@ -275,37 +245,6 @@ describe('Security Reports modal', () => { ...@@ -275,37 +245,6 @@ describe('Security Reports modal', () => {
    }); });
    }); });
    describe('issue note - deprecateVulnerabilitiesFeedback feature flag disabled', () => {
    const modalData = createState().modal;
    modalData.vulnerability.project = {};
    it('shows issue note with expected props', () => {
    modalData.vulnerability.issue_feedback = { issue_iid: 1, issue_url: 'url' };
    mountComponent({ modal: modalData }, shallowMount, {
    deprecateVulnerabilitiesFeedback: false,
    });
    expect(findIssueNote().props()).toMatchObject({
    feedback: modalData.vulnerability.issue_feedback,
    project: modalData.vulnerability.project,
    });
    });
    it.each`
    issue | isShown
    ${null} | ${false}
    ${{}} | ${false}
    ${{ issue_iid: 1, issue_url: 'url' }} | ${true}
    `('shows issue note? $isShown when issue is $issue', ({ issue, isShown }) => {
    modalData.vulnerability.issue_feedback = issue;
    mountComponent({ modal: modalData }, shallowMount, {
    deprecateVulnerabilitiesFeedback: false,
    });
    expect(findIssueNote().exists()).toBe(isShown);
    });
    });
    describe('merge request note', () => { describe('merge request note', () => {
    const mergeRequest = { merge_request_path: 'path' }; const mergeRequest = { merge_request_path: 'path' };
    ...@@ -324,24 +263,6 @@ describe('Security Reports modal', () => { ...@@ -324,24 +263,6 @@ describe('Security Reports modal', () => {
    expect(wrapper.findComponent(MergeRequestNote).exists()).toBe(isShown); expect(wrapper.findComponent(MergeRequestNote).exists()).toBe(isShown);
    }, },
    ); );
    it.each`
    mergeRequestFeedback | isShown
    ${mergeRequest} | ${true}
    ${{}} | ${false}
    ${null} | ${false}
    `(
    'shows the merge request note? $isShown when mergeRequestFeedback is $mergeRequestFeedback, deprecateVulnerabilitiesFeedback feature flag disabled',
    ({ mergeRequestFeedback, isShown }) => {
    const modalData = createState().modal;
    modalData.vulnerability.merge_request_feedback = mergeRequestFeedback;
    mountComponent({ modal: modalData }, shallowMount, {
    deprecateVulnerabilitiesFeedback: false,
    });
    expect(wrapper.findComponent(MergeRequestNote).exists()).toBe(isShown);
    },
    );
    }); });
    describe('with a resolved issue', () => { describe('with a resolved issue', () => {
    ...@@ -483,14 +404,5 @@ describe('Security Reports modal', () => { ...@@ -483,14 +404,5 @@ describe('Security Reports modal', () => {
    expect(wrapper.emitted('addDismissalComment')[0][0]).toBe(comment); expect(wrapper.emitted('addDismissalComment')[0][0]).toBe(comment);
    expect(findDismissalCommentBoxToggle().props('errorMessage')).toBe(''); expect(findDismissalCommentBoxToggle().props('errorMessage')).toBe('');
    }); });
    it('adds the dismissal comment if the finding is already dismissed - deprecateVulnerabilitiesFeedback feature flag disabled', async () => {
    propsData.modal.vulnerability.dismissal_feedback = {};
    mountComponent(propsData, shallowMount, { deprecateVulnerabilitiesFeedback: false });
    await addCommentAndSubmit(comment);
    expect(wrapper.emitted('addDismissalComment')[0][0]).toBe(comment);
    expect(findDismissalCommentBoxToggle().props('errorMessage')).toBe('');
    });
    }); });
    }); });
    ...@@ -37,6 +37,7 @@ describe('Vulnerability Footer', () => { ...@@ -37,6 +37,7 @@ describe('Vulnerability Footer', () => {
    canModifyRelatedIssues: true, canModifyRelatedIssues: true,
    relatedIssuesHelpPath: 'help/path', relatedIssuesHelpPath: 'help/path',
    pipeline: {}, pipeline: {},
    mergeRequestLinks: [],
    }; };
    let discussion1; let discussion1;
    ...@@ -273,11 +274,11 @@ describe('Vulnerability Footer', () => { ...@@ -273,11 +274,11 @@ describe('Vulnerability Footer', () => {
    it('shows merge request note when a merge request exists for the vulnerability', () => { it('shows merge request note when a merge request exists for the vulnerability', () => {
    // The object itself does not matter, we just want to make sure it's passed to the issue note. // The object itself does not matter, we just want to make sure it's passed to the issue note.
    const mergeRequestFeedback = {}; const mergeRequestLinks = [{}];
    createWrapper({ properties: { mergeRequestFeedback } }); createWrapper({ properties: { mergeRequestLinks } });
    expect(findMergeRequestNote().exists()).toBe(true); expect(findMergeRequestNote().exists()).toBe(true);
    expect(findMergeRequestNote().props('feedback')).toBe(mergeRequestFeedback); expect(findMergeRequestNote().props('feedback')).toBe(mergeRequestLinks.at(-1));
    }); });
    }); });
    ......
    ...@@ -97,11 +97,7 @@ describe('Vulnerability Header', () => { ...@@ -97,11 +97,7 @@ describe('Vulnerability Header', () => {
    dropdown.vm.$emit('change', { action }); dropdown.vm.$emit('change', { action });
    }; };
    const createWrapper = ({ const createWrapper = ({ vulnerability = {}, apolloProvider }) => {
    vulnerability = {},
    apolloProvider,
    deprecateVulnerabilitiesFeedback = true,
    }) => {
    wrapper = shallowMount(Header, { wrapper = shallowMount(Header, {
    apolloProvider, apolloProvider,
    propsData: { propsData: {
    ...@@ -110,9 +106,6 @@ describe('Vulnerability Header', () => { ...@@ -110,9 +106,6 @@ describe('Vulnerability Header', () => {
    ...vulnerability, ...vulnerability,
    }, },
    }, },
    provide: {
    glFeatures: { deprecateVulnerabilitiesFeedback },
    },
    }); });
    }; };
    ...@@ -238,69 +231,65 @@ describe('Vulnerability Header', () => { ...@@ -238,69 +231,65 @@ describe('Vulnerability Header', () => {
    expect(findGlButton().exists()).toBe(false); expect(findGlButton().exists()).toBe(false);
    }); });
    describe.each([true, false])( describe('create merge request', () => {
    'create merge request - deprecateVulnerabilitiesFeedback feature flag %s', beforeEach(() => {
    (deprecateVulnerabilitiesFeedback) => { createWrapper({
    beforeEach(() => { vulnerability: {
    createWrapper({ ...getVulnerability({
    deprecateVulnerabilitiesFeedback, shouldShowMergeRequestButton: true,
    vulnerability: { shouldShowDownloadPatchButton: false,
    ...getVulnerability({ }),
    shouldShowMergeRequestButton: true, },
    shouldShowDownloadPatchButton: false,
    }),
    },
    });
    }); });
    });
    it('only renders the create merge request button', () => { it('only renders the create merge request button', () => {
    expect(findGlButton().exists()).toBe(true); expect(findGlButton().exists()).toBe(true);
    expect(findGlButton().text()).toBe('Resolve with merge request'); expect(findGlButton().text()).toBe('Resolve with merge request');
    }); });
    it('emits createMergeRequest when create merge request button is clicked', async () => { it('emits createMergeRequest when create merge request button is clicked', async () => {
    const mergeRequestPath = '/group/project/merge_request/123'; const mergeRequestPath = '/group/project/merge_request/123';
    const spy = jest.spyOn(urlUtility, 'redirectTo'); const spy = jest.spyOn(urlUtility, 'redirectTo');
    mockAxios.onPost(defaultVulnerability.createMrUrl).reply(HTTP_STATUS_OK, { mockAxios.onPost(defaultVulnerability.createMrUrl).reply(HTTP_STATUS_OK, {
    merge_request_path: mergeRequestPath, merge_request_path: mergeRequestPath,
    merge_request_links: [{ merge_request_path: mergeRequestPath }], merge_request_links: [{ merge_request_path: mergeRequestPath }],
    }); });
    findGlButton().vm.$emit('click'); findGlButton().vm.$emit('click');
    await waitForPromises(); await waitForPromises();
    expect(spy).toHaveBeenCalledWith(mergeRequestPath); expect(spy).toHaveBeenCalledWith(mergeRequestPath);
    expect(mockAxios.history.post).toHaveLength(1); expect(mockAxios.history.post).toHaveLength(1);
    expect(JSON.parse(mockAxios.history.post[0].data)).toMatchObject({ expect(JSON.parse(mockAxios.history.post[0].data)).toMatchObject({
    vulnerability_feedback: { vulnerability_feedback: {
    feedback_type: FEEDBACK_TYPES.MERGE_REQUEST, feedback_type: FEEDBACK_TYPES.MERGE_REQUEST,
    category: defaultVulnerability.reportType,
    project_fingerprint: defaultVulnerability.projectFingerprint,
    finding_uuid: defaultVulnerability.uuid,
    vulnerability_data: {
    ...convertObjectPropsToSnakeCase(
    getVulnerability({ shouldShowMergeRequestButton: true }),
    ),
    category: defaultVulnerability.reportType, category: defaultVulnerability.reportType,
    project_fingerprint: defaultVulnerability.projectFingerprint, state: 'resolved',
    finding_uuid: defaultVulnerability.uuid,
    vulnerability_data: {
    ...convertObjectPropsToSnakeCase(
    getVulnerability({ shouldShowMergeRequestButton: true }),
    ),
    category: defaultVulnerability.reportType,
    state: 'resolved',
    },
    }, },
    }); },
    }); });
    });
    it('shows an error message when merge request creation fails', () => { it('shows an error message when merge request creation fails', () => {
    mockAxios mockAxios
    .onPost(defaultVulnerability.create_mr_url) .onPost(defaultVulnerability.create_mr_url)
    .reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); .reply(HTTP_STATUS_INTERNAL_SERVER_ERROR);
    findGlButton().vm.$emit('click'); findGlButton().vm.$emit('click');
    return waitForPromises().then(() => { return waitForPromises().then(() => {
    expect(mockAxios.history.post).toHaveLength(1); expect(mockAxios.history.post).toHaveLength(1);
    expect(createAlert).toHaveBeenCalledWith({ expect(createAlert).toHaveBeenCalledWith({
    message: 'There was an error creating the merge request. Please try again.', message: 'There was an error creating the merge request. Please try again.',
    });
    }); });
    }); });
    }, });
    ); });
    describe('can download patch', () => { describe('can download patch', () => {
    beforeEach(() => { beforeEach(() => {
    ......
    ...@@ -14,4 +14,5 @@ export const mockVulnerability = { ...@@ -14,4 +14,5 @@ export const mockVulnerability = {
    full_path: '/project_full_path', full_path: '/project_full_path',
    }, },
    identifiers: [], identifiers: [],
    mergeRequestLinks: [],
    }; };
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Finish editing this message first!
    Please register or to comment