Commit bf3a07c9 authored by Thong Kuah's avatar Thong Kuah

Revert "Merge branch 'license-compliance-policy-tab' into 'master'"

This reverts merge request !22465
parent 843ca90c
import Vue from 'vue'; import Vue from 'vue';
import LicenseManagement from 'ee/vue_shared/license_management/license_management.vue'; import Dashboard from 'ee/vue_shared/license_management/license_management.vue';
import createStore from 'ee/vue_shared/license_management/store/index';
import ProtectedEnvironmentCreate from 'ee/protected_environments/protected_environment_create'; import ProtectedEnvironmentCreate from 'ee/protected_environments/protected_environment_create';
import ProtectedEnvironmentEditList from 'ee/protected_environments/protected_environment_edit_list'; import ProtectedEnvironmentEditList from 'ee/protected_environments/protected_environment_edit_list';
import showToast from '~/vue_shared/plugins/global_toast'; import showToast from '~/vue_shared/plugins/global_toast';
...@@ -11,14 +10,11 @@ document.addEventListener('DOMContentLoaded', () => { ...@@ -11,14 +10,11 @@ document.addEventListener('DOMContentLoaded', () => {
const toasts = document.querySelectorAll('.js-toast-message'); const toasts = document.querySelectorAll('.js-toast-message');
if (el && el.dataset && el.dataset.apiUrl) { if (el && el.dataset && el.dataset.apiUrl) {
const store = createStore();
store.dispatch('licenseManagement/setIsAdmin', Boolean(el.dataset.apiUrl));
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new Vue({ new Vue({
el, el,
store,
render(createElement) { render(createElement) {
return createElement(LicenseManagement, { return createElement(Dashboard, {
props: { props: {
...el.dataset, ...el.dataset,
}, },
......
<script> <script>
import { mapActions, mapState, mapGetters } from 'vuex'; import { mapActions, mapState, mapGetters } from 'vuex';
import { GlEmptyState, GlLoadingIcon, GlLink, GlIcon, GlTab, GlTabs, GlBadge } from '@gitlab/ui'; import { GlEmptyState, GlLoadingIcon, GlLink, GlIcon } from '@gitlab/ui';
import { LICENSE_LIST } from '../store/constants'; import { LICENSE_LIST } from '../store/constants';
import { LICENSE_MANAGEMENT } from 'ee/vue_shared/license_management/store/constants';
import PaginatedLicensesTable from './paginated_licenses_table.vue'; import PaginatedLicensesTable from './paginated_licenses_table.vue';
import PipelineInfo from './pipeline_info.vue'; import PipelineInfo from './pipeline_info.vue';
import LicenseManagement from 'ee/vue_shared/license_management/license_management.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default { export default {
name: 'ProjectLicensesApp', name: 'ProjectLicensesApp',
...@@ -17,12 +14,7 @@ export default { ...@@ -17,12 +14,7 @@ export default {
PaginatedLicensesTable, PaginatedLicensesTable,
PipelineInfo, PipelineInfo,
GlIcon, GlIcon,
GlTab,
GlTabs,
GlBadge,
LicenseManagement,
}, },
mixins: [glFeatureFlagsMixin()],
props: { props: {
emptyStateSvgPath: { emptyStateSvgPath: {
type: String, type: String,
...@@ -32,35 +24,13 @@ export default { ...@@ -32,35 +24,13 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
readLicensePoliciesEndpoint: {
type: String,
required: true,
},
},
data() {
return {
tabIndex: 0,
};
}, },
computed: { computed: {
...mapState(LICENSE_LIST, ['initialized', 'licenses', 'reportInfo', 'listTypes']), ...mapState(LICENSE_LIST, ['initialized', 'reportInfo']),
...mapState(LICENSE_MANAGEMENT, ['managedLicenses']),
...mapGetters(LICENSE_LIST, ['isJobSetUp', 'isJobFailed']), ...mapGetters(LICENSE_LIST, ['isJobSetUp', 'isJobFailed']),
hasEmptyState() { hasEmptyState() {
return Boolean(!this.isJobSetUp || this.isJobFailed); return Boolean(!this.isJobSetUp || this.isJobFailed);
}, },
hasLicensePolicyList() {
return Boolean(this.glFeatures.licensePolicyList);
},
licenseCount() {
return this.licenses.length;
},
policyCount() {
return this.managedLicenses.length;
},
isDetectedProjectTab() {
return this.tabIndex === 0;
},
}, },
created() { created() {
this.fetchLicenses(); this.fetchLicenses();
...@@ -95,38 +65,7 @@ export default { ...@@ -95,38 +65,7 @@ export default {
</gl-link> </gl-link>
</h2> </h2>
<pipeline-info <pipeline-info :path="reportInfo.jobPath" :timestamp="reportInfo.generatedAt" />
v-if="isDetectedProjectTab" <paginated-licenses-table class="mt-3" />
:path="reportInfo.jobPath"
:timestamp="reportInfo.generatedAt"
/>
<template v-else>{{ s__('Licenses|Specified policies in this project') }}</template>
<!-- TODO: Remove feature flag -->
<template v-if="hasLicensePolicyList">
<gl-tabs v-model="tabIndex" content-class="pt-0">
<gl-tab>
<template #title>
{{ s__('Licenses|Detected in Project') }}
<gl-badge pill>{{ licenseCount }}</gl-badge>
</template>
<paginated-licenses-table />
</gl-tab>
<gl-tab>
<template #title>
{{ s__('Licenses|Policies') }}
<gl-badge pill>{{ policyCount }}</gl-badge>
</template>
<license-management :api-url="readLicensePoliciesEndpoint" />
</gl-tab>
</gl-tabs>
</template>
<template v-else>
<paginated-licenses-table class="mt-3" />
</template>
</div> </div>
</template> </template>
...@@ -5,16 +5,9 @@ import { LICENSE_LIST } from './store/constants'; ...@@ -5,16 +5,9 @@ import { LICENSE_LIST } from './store/constants';
export default () => { export default () => {
const el = document.querySelector('#js-licenses-app'); const el = document.querySelector('#js-licenses-app');
const { const { endpoint, emptyStateSvgPath, documentationPath } = el.dataset;
projectLicensesEndpoint,
emptyStateSvgPath,
documentationPath,
readLicensePoliciesEndpoint,
writeLicensePoliciesEndpoint,
} = el.dataset;
const store = createStore(); const store = createStore();
store.dispatch('licenseManagement/setIsAdmin', Boolean(writeLicensePoliciesEndpoint)); store.dispatch(`${LICENSE_LIST}/setLicensesEndpoint`, endpoint);
store.dispatch(`${LICENSE_LIST}/setLicensesEndpoint`, projectLicensesEndpoint);
return new Vue({ return new Vue({
el, el,
...@@ -27,7 +20,6 @@ export default () => { ...@@ -27,7 +20,6 @@ export default () => {
props: { props: {
emptyStateSvgPath, emptyStateSvgPath,
documentationPath, documentationPath,
readLicensePoliciesEndpoint,
}, },
}); });
}, },
......
...@@ -2,9 +2,7 @@ import Vue from 'vue'; ...@@ -2,9 +2,7 @@ import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import listModule from './modules/list'; import listModule from './modules/list';
import { licenseManagementModule } from 'ee/vue_shared/license_management/store/index';
import { LICENSE_LIST } from './constants'; import { LICENSE_LIST } from './constants';
import { LICENSE_MANAGEMENT } from 'ee/vue_shared/license_management/store/constants';
Vue.use(Vuex); Vue.use(Vuex);
...@@ -12,6 +10,5 @@ export default () => ...@@ -12,6 +10,5 @@ export default () =>
new Vuex.Store({ new Vuex.Store({
modules: { modules: {
[LICENSE_LIST]: listModule(), [LICENSE_LIST]: listModule(),
[LICENSE_MANAGEMENT]: licenseManagementModule(),
}, },
}); });
...@@ -12,8 +12,8 @@ export default { ...@@ -12,8 +12,8 @@ export default {
}, },
LICENSE_APPROVAL_STATUS, LICENSE_APPROVAL_STATUS,
approvalStatusOptions: [ approvalStatusOptions: [
{ value: LICENSE_APPROVAL_STATUS.APPROVED, label: s__('LicenseCompliance|Allow') }, { value: LICENSE_APPROVAL_STATUS.APPROVED, label: s__('LicenseCompliance|Approve') },
{ value: LICENSE_APPROVAL_STATUS.BLACKLISTED, label: s__('LicenseCompliance|Deny') }, { value: LICENSE_APPROVAL_STATUS.BLACKLISTED, label: s__('LicenseCompliance|Blacklist') },
], ],
props: { props: {
managedLicenses: { managedLicenses: {
......
<script>
import { mapActions } from 'vuex';
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { getIssueStatusFromLicenseStatus } from 'ee/vue_shared/license_management/store/utils';
import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
import { LICENSE_APPROVAL_STATUS } from '../constants';
import { LICENSE_MANAGEMENT } from 'ee/vue_shared/license_management/store/constants';
const visibleClass = 'visible';
const invisibleClass = 'invisible';
export default {
name: 'AdminLicenseManagementRow',
components: {
GlDropdown,
GlDropdownItem,
Icon,
IssueStatusIcon,
},
props: {
license: {
type: Object,
required: true,
validator: license =>
Boolean(license.name) &&
Object.values(LICENSE_APPROVAL_STATUS).includes(license.approvalStatus),
},
},
LICENSE_APPROVAL_STATUS,
[LICENSE_APPROVAL_STATUS.APPROVED]: s__('LicenseCompliance|Allowed'),
[LICENSE_APPROVAL_STATUS.BLACKLISTED]: s__('LicenseCompliance|Denied'),
computed: {
approveIconClass() {
return this.license.approvalStatus === LICENSE_APPROVAL_STATUS.APPROVED
? visibleClass
: invisibleClass;
},
blacklistIconClass() {
return this.license.approvalStatus === LICENSE_APPROVAL_STATUS.BLACKLISTED
? visibleClass
: invisibleClass;
},
status() {
return getIssueStatusFromLicenseStatus(this.license.approvalStatus);
},
dropdownText() {
return this.$options[this.license.approvalStatus];
},
},
methods: {
...mapActions(LICENSE_MANAGEMENT, ['setLicenseInModal', 'approveLicense', 'blacklistLicense']),
},
};
</script>
<template>
<div data-qa-selector="admin_license_compliance_row">
<issue-status-icon :status="status" class="float-left append-right-default" />
<span class="js-license-name" data-qa-selector="license_name_content">{{ license.name }}</span>
<div class="float-right">
<div class="d-flex">
<gl-dropdown
:text="dropdownText"
toggle-class="d-flex justify-content-between align-items-center"
right
>
<gl-dropdown-item @click="approveLicense(license)">
<icon :class="approveIconClass" name="mobile-issue-close" />
{{ $options[$options.LICENSE_APPROVAL_STATUS.APPROVED] }}
</gl-dropdown-item>
<gl-dropdown-item @click="blacklistLicense(license)">
<icon :class="blacklistIconClass" name="mobile-issue-close" />
{{ $options[$options.LICENSE_APPROVAL_STATUS.BLACKLISTED] }}
</gl-dropdown-item>
</gl-dropdown>
<button
class="btn btn-blank js-remove-button"
type="button"
data-toggle="modal"
data-target="#modal-license-delete-confirmation"
@click="setLicenseInModal(license)"
>
<icon name="remove" />
</button>
</div>
</div>
</div>
</template>
...@@ -4,13 +4,11 @@ import { mapActions, mapState } from 'vuex'; ...@@ -4,13 +4,11 @@ import { mapActions, mapState } from 'vuex';
import { s__, sprintf } from '~/locale'; import { s__, sprintf } from '~/locale';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue'; import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { LICENSE_MANAGEMENT } from 'ee/vue_shared/license_management/store/constants';
export default { export default {
name: 'LicenseDeleteConfirmationModal', name: 'LicenseDeleteConfirmationModal',
components: { GlModal: DeprecatedModal2 }, components: { GlModal: DeprecatedModal2 },
computed: { computed: {
...mapState(LICENSE_MANAGEMENT, ['currentLicenseInModal']), ...mapState(['currentLicenseInModal']),
confirmationText() { confirmationText() {
const name = `<strong>${_.escape(this.currentLicenseInModal.name)}</strong>`; const name = `<strong>${_.escape(this.currentLicenseInModal.name)}</strong>`;
...@@ -22,7 +20,7 @@ export default { ...@@ -22,7 +20,7 @@ export default {
}, },
}, },
methods: { methods: {
...mapActions(LICENSE_MANAGEMENT, ['resetLicenseInModal', 'deleteLicense']), ...mapActions(['resetLicenseInModal', 'deleteLicense']),
}, },
}; };
</script> </script>
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
import { mapActions } from 'vuex'; import { mapActions } from 'vuex';
import LicensePackages from './license_packages.vue'; import LicensePackages from './license_packages.vue';
import { LICENSE_MANAGEMENT } from 'ee/vue_shared/license_management/store/constants';
export default { export default {
name: 'LicenseIssueBody', name: 'LicenseIssueBody',
...@@ -13,7 +12,7 @@ export default { ...@@ -13,7 +12,7 @@ export default {
required: true, required: true,
}, },
}, },
methods: { ...mapActions(LICENSE_MANAGEMENT, ['setLicenseInModal']) }, methods: { ...mapActions(['setLicenseInModal']) },
}; };
</script> </script>
......
<script> <script>
import { import { mapActions } from 'vuex';
getIssueStatusFromLicenseStatus, import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
getStatusTranslationsFromLicenseStatus, import { getIssueStatusFromLicenseStatus } from 'ee/vue_shared/license_management/store/utils';
} from 'ee/vue_shared/license_management/store/utils'; import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import IssueStatusIcon from '~/reports/components/issue_status_icon.vue'; import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
import { LICENSE_APPROVAL_STATUS } from '../constants';
const visibleClass = 'visible';
const invisibleClass = 'invisible';
export default { export default {
name: 'LicenseManagementRow', name: 'LicenseManagementRow',
components: { components: {
GlDropdown,
GlDropdownItem,
Icon,
IssueStatusIcon, IssueStatusIcon,
}, },
props: { props: {
license: { license: {
type: Object, type: Object,
required: false, required: true,
default: null, validator: license =>
Boolean(license.name) &&
Object.values(LICENSE_APPROVAL_STATUS).includes(license.approvalStatus),
}, },
}, },
LICENSE_APPROVAL_STATUS,
[LICENSE_APPROVAL_STATUS.APPROVED]: s__('LicenseCompliance|Approved'),
[LICENSE_APPROVAL_STATUS.BLACKLISTED]: s__('LicenseCompliance|Blacklisted'),
computed: { computed: {
iconStatus() { approveIconClass() {
return this.license.approvalStatus === LICENSE_APPROVAL_STATUS.APPROVED
? visibleClass
: invisibleClass;
},
blacklistIconClass() {
return this.license.approvalStatus === LICENSE_APPROVAL_STATUS.BLACKLISTED
? visibleClass
: invisibleClass;
},
status() {
return getIssueStatusFromLicenseStatus(this.license.approvalStatus); return getIssueStatusFromLicenseStatus(this.license.approvalStatus);
}, },
textStatus() { dropdownText() {
return getStatusTranslationsFromLicenseStatus(this.license.approvalStatus); return this.$options[this.license.approvalStatus];
}, },
}, },
methods: {
...mapActions(['setLicenseInModal', 'approveLicense', 'blacklistLicense']),
},
}; };
</script> </script>
<template> <template>
<div class="gl-responsive-table-row flex-md-column align-items-md-stretch p-0"> <div data-qa-selector="license_compliance_row">
<div class="d-md-flex align-items-center js-license-row"> <issue-status-icon :status="status" class="float-left append-right-default" />
<!-- Name--> <span class="js-license-name" data-qa-selector="license_name_content">{{ license.name }}</span>
<div class="table-section section-30 section-wrap pr-md-3"> <div class="float-right">
<div class="table-mobile-header" role="rowheader"> <div class="d-flex">
{{ s__('Licenses|Name') }} <gl-dropdown
</div> :text="dropdownText"
<div class="table-mobile-content name"> toggle-class="d-flex justify-content-between align-items-center"
{{ license.name }} right
</div> >
</div> <gl-dropdown-item @click="approveLicense(license)">
<icon :class="approveIconClass" name="mobile-issue-close" />
<!-- Policy --> {{ $options[$options.LICENSE_APPROVAL_STATUS.APPROVED] }}
<div class="table-section section-70 section-wrap pr-md-3"> </gl-dropdown-item>
<div class="table-mobile-header" role="rowheader">{{ s__('Licenses|Policy') }}</div> <gl-dropdown-item @click="blacklistLicense(license)">
<div <icon :class="blacklistIconClass" name="mobile-issue-close" />
class="table-mobile-content text-capitalize d-flex align-items-center justify-content-end justify-content-md-start status" {{ $options[$options.LICENSE_APPROVAL_STATUS.BLACKLISTED] }}
</gl-dropdown-item>
</gl-dropdown>
<button
class="btn btn-blank js-remove-button"
type="button"
data-toggle="modal"
data-target="#modal-license-delete-confirmation"
@click="setLicenseInModal(license)"
> >
<issue-status-icon :status="iconStatus" /> <icon name="remove" />
{{ textStatus }} </button>
</div>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -5,18 +5,20 @@ import { s__ } from '~/locale'; ...@@ -5,18 +5,20 @@ import { s__ } from '~/locale';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue'; import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import LicensePackages from './license_packages.vue'; import LicensePackages from './license_packages.vue';
import { LICENSE_APPROVAL_STATUS } from '../constants'; import { LICENSE_APPROVAL_STATUS } from '../constants';
import { LICENSE_MANAGEMENT } from 'ee/vue_shared/license_management/store/constants';
export default { export default {
name: 'LicenseSetApprovalStatusModal', name: 'LicenseSetApprovalStatusModal',
components: { SafeLink, LicensePackages, GlModal: DeprecatedModal2 }, components: { SafeLink, LicensePackages, GlModal: DeprecatedModal2 },
computed: { computed: {
...mapState(LICENSE_MANAGEMENT, ['currentLicenseInModal', 'canManageLicenses']), ...mapState(['currentLicenseInModal', 'canManageLicenses']),
headerTitleText() { headerTitleText() {
if (!this.canManageLicenses) { if (!this.canManageLicenses) {
return s__('LicenseCompliance|License details'); return s__('LicenseCompliance|License details');
} }
return s__('LicenseCompliance|License review'); if (this.canApprove) {
return s__('LicenseCompliance|Approve license?');
}
return s__('LicenseCompliance|Blacklist license?');
}, },
canApprove() { canApprove() {
return ( return (
...@@ -34,11 +36,7 @@ export default { ...@@ -34,11 +36,7 @@ export default {
}, },
}, },
methods: { methods: {
...mapActions(LICENSE_MANAGEMENT, [ ...mapActions(['resetLicenseInModal', 'approveLicense', 'blacklistLicense']),
'resetLicenseInModal',
'approveLicense',
'blacklistLicense',
]),
}, },
}; };
</script> </script>
...@@ -99,7 +97,7 @@ export default { ...@@ -99,7 +97,7 @@ export default {
data-qa-selector="blacklist_license_button" data-qa-selector="blacklist_license_button"
@click="blacklistLicense(currentLicenseInModal)" @click="blacklistLicense(currentLicenseInModal)"
> >
{{ s__('LicenseCompliance|Deny') }} {{ s__('LicenseCompliance|Blacklist license') }}
</button> </button>
<button <button
v-if="canApprove" v-if="canApprove"
...@@ -109,7 +107,7 @@ export default { ...@@ -109,7 +107,7 @@ export default {
data-qa-selector="approve_license_button" data-qa-selector="approve_license_button"
@click="approveLicense(currentLicenseInModal)" @click="approveLicense(currentLicenseInModal)"
> >
{{ s__('LicenseCompliance|Allow') }} {{ s__('LicenseCompliance|Approve license') }}
</button> </button>
</template> </template>
</gl-modal> </gl-modal>
......
...@@ -3,19 +3,18 @@ import { mapState, mapActions } from 'vuex'; ...@@ -3,19 +3,18 @@ import { mapState, mapActions } from 'vuex';
import { GlButton, GlLoadingIcon } from '@gitlab/ui'; import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import AddLicenseForm from './components/add_license_form.vue'; import AddLicenseForm from './components/add_license_form.vue';
import AdminLicenseManagementRow from './components/admin_license_management_row.vue';
import LicenseManagementRow from './components/license_management_row.vue'; import LicenseManagementRow from './components/license_management_row.vue';
import DeleteConfirmationModal from './components/delete_confirmation_modal.vue'; import DeleteConfirmationModal from './components/delete_confirmation_modal.vue';
import PaginatedList from '~/vue_shared/components/paginated_list.vue'; import PaginatedList from '~/vue_shared/components/paginated_list.vue';
import createStore from './store/index';
import { LICENSE_MANAGEMENT } from 'ee/vue_shared/license_management/store/constants'; const store = createStore();
export default { export default {
name: 'LicenseManagement', name: 'LicenseManagement',
components: { components: {
AddLicenseForm, AddLicenseForm,
DeleteConfirmationModal, DeleteConfirmationModal,
AdminLicenseManagementRow,
LicenseManagementRow, LicenseManagementRow,
GlButton, GlButton,
GlLoadingIcon, GlLoadingIcon,
...@@ -28,16 +27,11 @@ export default { ...@@ -28,16 +27,11 @@ export default {
}, },
}, },
data() { data() {
return { return { formIsOpen: false };
formIsOpen: false,
tableHeaders: [
{ className: 'section-70', label: s__('Licenses|Policy') },
{ className: 'section-30', label: s__('Licenses|Name') },
],
};
}, },
store,
computed: { computed: {
...mapState(LICENSE_MANAGEMENT, ['managedLicenses', 'isLoadingManagedLicenses', 'isAdmin']), ...mapState(['managedLicenses', 'isLoadingManagedLicenses']),
}, },
mounted() { mounted() {
this.setAPISettings({ this.setAPISettings({
...@@ -46,11 +40,7 @@ export default { ...@@ -46,11 +40,7 @@ export default {
this.fetchManagedLicenses(); this.fetchManagedLicenses();
}, },
methods: { methods: {
...mapActions(LICENSE_MANAGEMENT, [ ...mapActions(['fetchManagedLicenses', 'setAPISettings', 'setLicenseApproval']),
'fetchManagedLicenses',
'setAPISettings',
'setLicenseApproval',
]),
openAddLicenseForm() { openAddLicenseForm() {
this.formIsOpen = true; this.formIsOpen = true;
}, },
...@@ -69,19 +59,17 @@ export default { ...@@ -69,19 +59,17 @@ export default {
<template> <template>
<gl-loading-icon v-if="isLoadingManagedLicenses" /> <gl-loading-icon v-if="isLoadingManagedLicenses" />
<div v-else class="license-management"> <div v-else class="license-management">
<delete-confirmation-modal v-if="isAdmin" /> <delete-confirmation-modal />
<paginated-list <paginated-list
:list="managedLicenses" :list="managedLicenses"
:empty-search-message="$options.emptySearchMessage" :empty-search-message="$options.emptySearchMessage"
:empty-message="$options.emptyMessage" :empty-message="$options.emptyMessage"
:filterable="isAdmin"
filter="name" filter="name"
data-qa-selector="license_compliance_list" data-qa-selector="license_compliance_list"
> >
<template #header> <template #header>
<gl-button <gl-button
v-if="isAdmin"
class="js-open-form order-1" class="js-open-form order-1"
:disabled="formIsOpen" :disabled="formIsOpen"
variant="success" variant="success"
...@@ -90,21 +78,9 @@ export default { ...@@ -90,21 +78,9 @@ export default {
> >
{{ s__('LicenseCompliance|Add a license') }} {{ s__('LicenseCompliance|Add a license') }}
</gl-button> </gl-button>
<template v-else>
<div
v-for="header in tableHeaders"
:key="header.label"
class="table-section"
:class="header.className"
role="rowheader"
>
{{ header.label }}
</div>
</template>
</template> </template>
<template v-if="isAdmin" #subheader> <template #subheader>
<div v-if="formIsOpen" class="prepend-top-default append-bottom-default"> <div v-if="formIsOpen" class="prepend-top-default append-bottom-default">
<add-license-form <add-license-form
:managed-licenses="managedLicenses" :managed-licenses="managedLicenses"
...@@ -115,8 +91,7 @@ export default { ...@@ -115,8 +91,7 @@ export default {
</template> </template>
<template #default="{ listItem }"> <template #default="{ listItem }">
<admin-license-management-row v-if="isAdmin" :license="listItem" /> <license-management-row :license="listItem" />
<license-management-row v-else :license="listItem" />
</template> </template>
</paginated-list> </paginated-list>
</div> </div>
......
...@@ -7,8 +7,6 @@ import { componentNames } from 'ee/reports/components/issue_body'; ...@@ -7,8 +7,6 @@ import { componentNames } from 'ee/reports/components/issue_body';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import ReportSection from '~/reports/components/report_section.vue'; import ReportSection from '~/reports/components/report_section.vue';
import { LICENSE_MANAGEMENT } from 'ee/vue_shared/license_management/store/constants';
import createStore from './store'; import createStore from './store';
const store = createStore(); const store = createStore();
...@@ -65,8 +63,8 @@ export default { ...@@ -65,8 +63,8 @@ export default {
}, },
}, },
computed: { computed: {
...mapState(LICENSE_MANAGEMENT, ['loadLicenseReportError']), ...mapState(['loadLicenseReportError']),
...mapGetters(LICENSE_MANAGEMENT, [ ...mapGetters([
'licenseReport', 'licenseReport',
'isLoading', 'isLoading',
'licenseSummaryText', 'licenseSummaryText',
...@@ -100,7 +98,7 @@ export default { ...@@ -100,7 +98,7 @@ export default {
this.fetchParsedLicenseReport(); this.fetchParsedLicenseReport();
}, },
methods: { methods: {
...mapActions(LICENSE_MANAGEMENT, ['setAPISettings', 'fetchParsedLicenseReport']), ...mapActions(['setAPISettings', 'fetchParsedLicenseReport']),
}, },
}; };
</script> </script>
......
...@@ -105,11 +105,6 @@ export const receiveSetLicenseApproval = ({ commit, dispatch, state }) => { ...@@ -105,11 +105,6 @@ export const receiveSetLicenseApproval = ({ commit, dispatch, state }) => {
export const receiveSetLicenseApprovalError = ({ commit }, error) => { export const receiveSetLicenseApprovalError = ({ commit }, error) => {
commit(types.RECEIVE_SET_LICENSE_APPROVAL_ERROR, error); commit(types.RECEIVE_SET_LICENSE_APPROVAL_ERROR, error);
}; };
export const setIsAdmin = ({ commit }, payload) => {
commit(types.SET_IS_ADMIN, payload);
};
export const setLicenseApproval = ({ dispatch, state }, payload) => { export const setLicenseApproval = ({ dispatch, state }, payload) => {
const { apiUrlManageLicenses } = state; const { apiUrlManageLicenses } = state;
const { license, newStatus } = payload; const { license, newStatus } = payload;
......
/* eslint-disable import/prefer-default-export */
export const LICENSE_MANAGEMENT = 'licenseManagement';
...@@ -7,17 +7,10 @@ import mutations from './mutations'; ...@@ -7,17 +7,10 @@ import mutations from './mutations';
Vue.use(Vuex); Vue.use(Vuex);
export const licenseManagementModule = () => ({
namespaced: true,
state: createState(),
actions,
getters,
mutations,
});
export default () => export default () =>
new Vuex.Store({ new Vuex.Store({
modules: { state: createState(),
licenseManagement: licenseManagementModule(), actions,
}, getters,
mutations,
}); });
...@@ -13,7 +13,6 @@ export const REQUEST_SET_LICENSE_APPROVAL = 'REQUEST_SET_LICENSE_APPROVAL'; ...@@ -13,7 +13,6 @@ export const REQUEST_SET_LICENSE_APPROVAL = 'REQUEST_SET_LICENSE_APPROVAL';
export const RESET_LICENSE_IN_MODAL = 'RESET_LICENSE_IN_MODAL'; export const RESET_LICENSE_IN_MODAL = 'RESET_LICENSE_IN_MODAL';
export const SET_API_SETTINGS = 'SET_API_SETTINGS'; export const SET_API_SETTINGS = 'SET_API_SETTINGS';
export const SET_LICENSE_IN_MODAL = 'SET_LICENSE_IN_MODAL'; export const SET_LICENSE_IN_MODAL = 'SET_LICENSE_IN_MODAL';
export const SET_IS_ADMIN = 'SET_IS_ADMIN';
// prevent babel-plugin-rewire from generating an invalid default during karma tests // prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {}; export default () => {};
...@@ -15,11 +15,7 @@ export default { ...@@ -15,11 +15,7 @@ export default {
[types.SET_API_SETTINGS](state, data) { [types.SET_API_SETTINGS](state, data) {
Object.assign(state, data); Object.assign(state, data);
}, },
[types.SET_IS_ADMIN](state, data) {
Object.assign(state, {
isAdmin: data,
});
},
[types.RECEIVE_MANAGED_LICENSES_SUCCESS](state, licenses = []) { [types.RECEIVE_MANAGED_LICENSES_SUCCESS](state, licenses = []) {
const managedLicenses = licenses.map(normalizeLicense).reverse(); const managedLicenses = licenses.map(normalizeLicense).reverse();
......
...@@ -3,7 +3,6 @@ export default () => ({ ...@@ -3,7 +3,6 @@ export default () => ({
licensesApiPath: null, licensesApiPath: null,
canManageLicenses: false, canManageLicenses: false,
currentLicenseInModal: null, currentLicenseInModal: null,
isAdmin: false,
isDeleting: false, isDeleting: false,
isLoadingLicenseReport: false, isLoadingLicenseReport: false,
isLoadingManagedLicenses: false, isLoadingManagedLicenses: false,
......
import { LICENSE_APPROVAL_STATUS } from 'ee/vue_shared/license_management/constants'; import { LICENSE_APPROVAL_STATUS } from 'ee/vue_shared/license_management/constants';
import { s__, n__, sprintf } from '~/locale'; import { n__, sprintf } from '~/locale';
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants'; import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants';
/** /**
...@@ -18,15 +18,6 @@ export const normalizeLicense = license => { ...@@ -18,15 +18,6 @@ export const normalizeLicense = license => {
}; };
}; };
export const getStatusTranslationsFromLicenseStatus = approvalStatus => {
if (approvalStatus === LICENSE_APPROVAL_STATUS.APPROVED) {
return s__('LicenseCompliance|Allowed');
} else if (approvalStatus === LICENSE_APPROVAL_STATUS.BLACKLISTED) {
return s__('LicenseCompliance|Denied');
}
return '';
};
export const getIssueStatusFromLicenseStatus = approvalStatus => { export const getIssueStatusFromLicenseStatus = approvalStatus => {
if (approvalStatus === LICENSE_APPROVAL_STATUS.APPROVED) { if (approvalStatus === LICENSE_APPROVAL_STATUS.APPROVED) {
return STATUS_SUCCESS; return STATUS_SUCCESS;
......
...@@ -4,9 +4,6 @@ module Projects ...@@ -4,9 +4,6 @@ module Projects
class LicensesController < Projects::ApplicationController class LicensesController < Projects::ApplicationController
before_action :authorize_read_licenses!, only: [:index] before_action :authorize_read_licenses!, only: [:index]
before_action :authorize_admin_software_license_policy!, only: [:create, :update] before_action :authorize_admin_software_license_policy!, only: [:create, :update]
before_action do
push_frontend_feature_flag(:license_policy_list)
end
def index def index
respond_to do |format| respond_to do |format|
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LicenseManagementRow allowed license renders the allowed status text with the status icon 1`] = `
<div
class="table-mobile-content text-capitalize d-flex align-items-center justify-content-end justify-content-md-start status"
>
<issue-status-icon-stub
status="success"
statusiconsize="24"
/>
Allowed
</div>
`;
exports[`LicenseManagementRow allowed license renders the license name 1`] = `
<div
class="table-mobile-content name"
>
MIT
</div>
`;
exports[`LicenseManagementRow denied license renders the denied status text with the status icon 1`] = `
<div
class="table-mobile-content text-capitalize d-flex align-items-center justify-content-end justify-content-md-start status"
>
<issue-status-icon-stub
status="failed"
statusiconsize="24"
/>
Denied
</div>
`;
exports[`LicenseManagementRow denied license renders the license name 1`] = `
<div
class="table-mobile-content name"
>
New BSD
</div>
`;
import { shallowMount } from '@vue/test-utils';
import LicenseManagementRow from 'ee/vue_shared/license_management/components/license_management_row.vue';
import { approvedLicense, blacklistedLicense } from 'ee_jest/license_management/mock_data';
let wrapper;
describe('LicenseManagementRow', () => {
afterEach(() => {
wrapper.destroy();
});
describe('allowed license', () => {
beforeEach(() => {
const props = { license: approvedLicense };
wrapper = shallowMount(LicenseManagementRow, {
propsData: {
...props,
},
});
});
it('renders the license name', () => {
expect(wrapper.find('.name').element).toMatchSnapshot();
});
it('renders the allowed status text with the status icon', () => {
expect(wrapper.find('.status').element).toMatchSnapshot();
});
});
describe('denied license', () => {
beforeEach(() => {
const props = { license: blacklistedLicense };
wrapper = shallowMount(LicenseManagementRow, {
propsData: {
...props,
},
});
});
it('renders the license name', () => {
expect(wrapper.find('.name').element).toMatchSnapshot();
});
it('renders the denied status text with the status icon', () => {
expect(wrapper.find('.status').element).toMatchSnapshot();
});
});
});
import { shallowMount } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlButton, GlLoadingIcon } from '@gitlab/ui'; import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import LicenseManagement from 'ee/vue_shared/license_management/license_management.vue'; import LicenseManagement from 'ee/vue_shared/license_management/license_management.vue';
import AdminLicenseManagementRow from 'ee/vue_shared/license_management/components/admin_license_management_row.vue';
import LicenseManagementRow from 'ee/vue_shared/license_management/components/license_management_row.vue';
import AddLicenseForm from 'ee/vue_shared/license_management/components/add_license_form.vue'; import AddLicenseForm from 'ee/vue_shared/license_management/components/add_license_form.vue';
import DeleteConfirmationModal from 'ee/vue_shared/license_management/components/delete_confirmation_modal.vue'; import DeleteConfirmationModal from 'ee/vue_shared/license_management/components/delete_confirmation_modal.vue';
import { TEST_HOST } from 'helpers/test_constants'; import { TEST_HOST } from 'helpers/test_constants';
import { approvedLicense, blacklistedLicense } from './mock_data'; import { approvedLicense, blacklistedLicense } from './mock_data';
Vue.use(Vuex); const localVue = createLocalVue();
localVue.use(Vuex);
let wrapper;
const apiUrl = `${TEST_HOST}/license_management`;
const managedLicenses = [approvedLicense, blacklistedLicense];
const PaginatedListMock = { const PaginatedListMock = {
name: 'PaginatedList', name: 'PaginatedList',
...@@ -31,174 +24,111 @@ const PaginatedListMock = { ...@@ -31,174 +24,111 @@ const PaginatedListMock = {
const noop = () => {}; const noop = () => {};
const createComponent = ({ state, props, actionMocks, isAdmin }) => { describe('LicenseManagement', () => {
const fakeStore = new Vuex.Store({ const apiUrl = `${TEST_HOST}/license_management`;
modules: { const managedLicenses = [approvedLicense, blacklistedLicense];
licenseManagement: { let wrapper;
namespaced: true,
state: { const createComponent = ({ state, props, actionMocks }) => {
managedLicenses, const fakeStore = new Vuex.Store({
isLoadingManagedLicenses: true, state: {
isAdmin, managedLicenses,
...state, isLoadingManagedLicenses: true,
}, ...state,
actions: {
fetchManagedLicenses: noop,
setAPISettings: noop,
setLicenseApproval: noop,
...actionMocks,
},
}, },
}, actions: {
}); fetchManagedLicenses: noop,
setAPISettings: noop,
setLicenseApproval: noop,
...actionMocks,
},
});
wrapper = shallowMount(LicenseManagement, { wrapper = shallowMount(LicenseManagement, {
propsData: { propsData: {
apiUrl, apiUrl,
...props, ...props,
}, },
stubs: { stubs: {
PaginatedList: PaginatedListMock, LicenseManagementRow: true,
}, PaginatedList: PaginatedListMock,
store: fakeStore, },
}); store: fakeStore,
}; });
};
describe('License Management', () => {
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
}); });
describe('common functionality', () => { it('when loading should render loading icon', () => {
describe.each` createComponent({ state: { isLoadingManagedLicenses: true } });
desc | isAdmin expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
${'when admin'} | ${true} });
${'when developer'} | ${false}
`('$desc', ({ isAdmin }) => {
it('when loading should render loading icon', () => {
createComponent({ state: { isLoadingManagedLicenses: true }, isAdmin });
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
describe('when not loading', () => { describe('when not loading', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ state: { isLoadingManagedLicenses: false }, isAdmin }); createComponent({ state: { isLoadingManagedLicenses: false } });
}); });
it('should render list of managed licenses', () => { it('should render the form if the form is open and disable the form button', () => {
expect(wrapper.find({ name: 'PaginatedList' }).props('list')).toBe(managedLicenses); wrapper.find(GlButton).vm.$emit('click');
});
});
it('should set api settings after mount and init API calls', () => { return wrapper.vm.$nextTick().then(() => {
const setAPISettingsMock = jest.fn(); expect(wrapper.find(AddLicenseForm).exists()).toBe(true);
const fetchManagedLicensesMock = jest.fn(); expect(wrapper.find(GlButton).attributes('disabled')).toBe('true');
createComponent({
state: { isLoadingManagedLicenses: false },
actionMocks: {
setAPISettings: setAPISettingsMock,
fetchManagedLicenses: fetchManagedLicensesMock,
},
isAdmin,
});
expect(setAPISettingsMock).toHaveBeenCalledWith(
expect.any(Object),
{
apiUrlManageLicenses: apiUrl,
},
undefined,
);
expect(fetchManagedLicensesMock).toHaveBeenCalledWith(
expect.any(Object),
undefined,
undefined,
);
}); });
}); });
});
describe('permission based functionality', () => { it('should not render the form if the form is closed and have active button', () => {
describe('when admin', () => { expect(wrapper.find(AddLicenseForm).exists()).toBe(false);
it('should invoke `setLicenseAprroval` action on `addLicense` event on form only', () => { expect(wrapper.find(GlButton).attributes('disabled')).not.toBe('true');
const setLicenseApprovalMock = jest.fn(); });
createComponent({
state: { isLoadingManagedLicenses: false },
actionMocks: { setLicenseApproval: setLicenseApprovalMock },
isAdmin: true,
});
wrapper.find(GlButton).vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
wrapper.find(AddLicenseForm).vm.$emit('addLicense');
expect(setLicenseApprovalMock).toHaveBeenCalled();
});
});
describe('when not loading', () => { it('should render delete confirmation modal', () => {
beforeEach(() => { expect(wrapper.find(DeleteConfirmationModal).exists()).toBe(true);
createComponent({ state: { isLoadingManagedLicenses: false }, isAdmin: true });
});
it('should render the form if the form is open and disable the form button', () => {
wrapper.find(GlButton).vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(AddLicenseForm).exists()).toBe(true);
expect(wrapper.find(GlButton).attributes('disabled')).toBe('true');
});
});
it('should not render the form if the form is closed and have active button', () => {
expect(wrapper.find(AddLicenseForm).exists()).toBe(false);
expect(wrapper.find(GlButton).attributes('disabled')).not.toBe('true');
});
it('should render delete confirmation modal', () => {
expect(wrapper.find(DeleteConfirmationModal).exists()).toBe(true);
});
it('renders the admin row', () => {
expect(wrapper.find(LicenseManagementRow).exists()).toBe(false);
expect(wrapper.find(AdminLicenseManagementRow).exists()).toBe(true);
});
});
}); });
describe('when developer', () => {
it('should not invoke `setLicenseAprroval` action or `addLicense` event on form', () => {
const setLicenseApprovalMock = jest.fn();
createComponent({
state: { isLoadingManagedLicenses: false },
actionMocks: { setLicenseApproval: setLicenseApprovalMock },
isAdmin: false,
});
expect(wrapper.find(GlButton).exists()).toBe(false);
expect(wrapper.find(AddLicenseForm).exists()).toBe(false);
expect(setLicenseApprovalMock).not.toHaveBeenCalled();
});
describe('when not loading', () => { it('should render list of managed licenses', () => {
beforeEach(() => { expect(wrapper.find({ name: 'PaginatedList' }).props('list')).toBe(managedLicenses);
createComponent({ state: { isLoadingManagedLicenses: false, isAdmin: false } }); });
}); });
it('should not render the form', () => { it('should invoke `setLicenseAprroval` action on `addLicense` event on form', () => {
expect(wrapper.find(AddLicenseForm).exists()).toBe(false); const setLicenseApprovalMock = jest.fn();
expect(wrapper.find(GlButton).exists()).toBe(false); createComponent({
}); state: { isLoadingManagedLicenses: false },
actionMocks: { setLicenseApproval: setLicenseApprovalMock },
});
wrapper.find(GlButton).vm.$emit('click');
it('should not render delete confirmation modal', () => { return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(DeleteConfirmationModal).exists()).toBe(false); wrapper.find(AddLicenseForm).vm.$emit('addLicense');
}); expect(setLicenseApprovalMock).toHaveBeenCalled();
});
});
it('renders the read only row', () => { it('should set api settings after mount and init API calls', () => {
expect(wrapper.find(LicenseManagementRow).exists()).toBe(true); const setAPISettingsMock = jest.fn();
expect(wrapper.find(AdminLicenseManagementRow).exists()).toBe(false); const fetchManagedLicensesMock = jest.fn();
});
}); createComponent({
state: { isLoadingManagedLicenses: false },
actionMocks: {
setAPISettings: setAPISettingsMock,
fetchManagedLicenses: fetchManagedLicensesMock,
},
}); });
expect(setAPISettingsMock).toHaveBeenCalledWith(
expect.any(Object),
{
apiUrlManageLicenses: apiUrl,
},
undefined,
);
expect(fetchManagedLicensesMock).toHaveBeenCalledWith(expect.any(Object), undefined, undefined);
}); });
}); });
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
import { GlEmptyState, GlLoadingIcon, GlTab, GlTabs } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants';
import { REPORT_STATUS } from 'ee/project_licenses/store/modules/list/constants';
import ProjectLicensesApp from 'ee/project_licenses/components/app.vue';
import PaginatedLicensesTable from 'ee/project_licenses/components/paginated_licenses_table.vue';
import PipelineInfo from 'ee/project_licenses/components/pipeline_info.vue';
import LicenseManagement from 'ee/vue_shared/license_management/license_management.vue';
import * as getters from 'ee/project_licenses/store/modules/list/getters';
import { approvedLicense, blacklistedLicense } from 'ee_jest/license_management/mock_data';
Vue.use(Vuex);
let wrapper;
const readLicensePoliciesEndpoint = `${TEST_HOST}/license_management`;
const managedLicenses = [approvedLicense, blacklistedLicense];
const licenses = [{}, {}];
const emptyStateSvgPath = '/';
const documentationPath = '/';
const noop = () => {};
const createComponent = ({ state, props, options }) => {
const fakeStore = new Vuex.Store({
modules: {
licenseManagement: {
namespaced: true,
state: {
managedLicenses,
},
},
licenseList: {
namespaced: true,
state: {
licenses,
reportInfo: {
jobPath: '/',
generatedAt: '',
},
...state,
},
actions: {
fetchLicenses: noop,
},
getters,
},
},
});
wrapper = shallowMount(ProjectLicensesApp, {
propsData: {
emptyStateSvgPath,
documentationPath,
readLicensePoliciesEndpoint,
...props,
},
...options,
store: fakeStore,
});
};
describe('Project Licenses', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('when loading', () => {
beforeEach(() => {
createComponent({
state: { initialized: false },
});
});
it('shows the loading component', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('does not show the empty state component', () => {
expect(wrapper.find(GlEmptyState).exists()).toBe(false);
});
it('does not show the list of detected in project licenses', () => {
expect(wrapper.find(PaginatedLicensesTable).exists()).toBe(false);
});
it('does not show the list of license policies', () => {
expect(wrapper.find(LicenseManagement).exists()).toBe(false);
});
it('does not render any tabs', () => {
expect(wrapper.find(GlTabs).exists()).toBe(false);
expect(wrapper.find(GlTab).exists()).toBe(false);
});
});
describe('when empty state', () => {
beforeEach(() => {
createComponent({
state: {
initialized: true,
reportInfo: {
jobPath: '/',
generatedAt: '',
status: REPORT_STATUS.jobNotSetUp,
},
},
});
});
it('shows the empty state component', () => {
expect(wrapper.find(GlEmptyState).exists()).toBe(true);
});
it('does not show the loading component', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
it('does not show the list of detected in project licenses', () => {
expect(wrapper.find(PaginatedLicensesTable).exists()).toBe(false);
});
it('does not show the list of license policies', () => {
expect(wrapper.find(LicenseManagement).exists()).toBe(false);
});
it('does not render any tabs', () => {
expect(wrapper.find(GlTabs).exists()).toBe(false);
expect(wrapper.find(GlTab).exists()).toBe(false);
});
});
describe('when licensePolicyList feature flag is enabled', () => {
beforeEach(() => {
createComponent({
state: {
initialized: true,
reportInfo: {
jobPath: '/',
generatedAt: '',
status: REPORT_STATUS.ok,
},
},
options: {
provide: {
glFeatures: { licensePolicyList: true },
},
},
});
});
it('renders a "Detected in project" tab and a "Policies" tab', () => {
expect(wrapper.find(GlTabs).exists()).toBe(true);
expect(wrapper.find(GlTab).exists()).toBe(true);
expect(wrapper.findAll(GlTab).length).toBe(2);
});
it('it renders the "Detected in project" table', () => {
expect(wrapper.find(PaginatedLicensesTable).exists()).toBe(true);
});
it('it renders the "Policies" table', () => {
expect(wrapper.find(LicenseManagement).exists()).toBe(true);
});
it('renders the pipeline info', () => {
expect(wrapper.find(PipelineInfo).exists()).toBe(true);
});
});
describe('when licensePolicyList feature flag is disabled', () => {
beforeEach(() => {
createComponent({
state: {
initialized: true,
reportInfo: {
jobPath: '/',
generatedAt: '',
status: REPORT_STATUS.ok,
},
},
options: {
provide: {
glFeatures: { licensePolicyList: false },
},
},
});
});
it('only renders the "Detected in project" table', () => {
expect(wrapper.find(PaginatedLicensesTable).exists()).toBe(true);
expect(wrapper.find(LicenseManagement).exists()).toBe(false);
});
it('renders no "Policies" table', () => {
expect(wrapper.find(GlTabs).exists()).toBe(false);
expect(wrapper.find(GlTab).exists()).toBe(false);
});
it('renders the pipeline info', () => {
expect(wrapper.find(PipelineInfo).exists()).toBe(true);
});
it('renders no tabs', () => {
expect(wrapper.find(GlTabs).exists()).toBe(false);
expect(wrapper.find(GlTab).exists()).toBe(false);
});
});
});
...@@ -98,9 +98,9 @@ describe('AddLicenseForm', () => { ...@@ -98,9 +98,9 @@ describe('AddLicenseForm', () => {
const radioButtonParents = vm.$el.querySelectorAll('.form-check'); const radioButtonParents = vm.$el.querySelectorAll('.form-check');
expect(radioButtonParents.length).toBe(2); expect(radioButtonParents.length).toBe(2);
expect(radioButtonParents[0].innerText.trim()).toBe('Allow'); expect(radioButtonParents[0].innerText.trim()).toBe('Approve');
expect(radioButtonParents[0].querySelector('.form-check-input')).not.toBeNull(); expect(radioButtonParents[0].querySelector('.form-check-input')).not.toBeNull();
expect(radioButtonParents[1].innerText.trim()).toBe('Deny'); expect(radioButtonParents[1].innerText.trim()).toBe('Blacklist');
expect(radioButtonParents[1].querySelector('.form-check-input')).not.toBeNull(); expect(radioButtonParents[1].querySelector('.form-check-input')).not.toBeNull();
}); });
......
...@@ -8,6 +8,7 @@ import { approvedLicense } from 'ee_spec/license_management/mock_data'; ...@@ -8,6 +8,7 @@ import { approvedLicense } from 'ee_spec/license_management/mock_data';
describe('DeleteConfirmationModal', () => { describe('DeleteConfirmationModal', () => {
const Component = Vue.extend(DeleteConfirmationModal); const Component = Vue.extend(DeleteConfirmationModal);
let vm; let vm;
let store; let store;
let actions; let actions;
...@@ -19,15 +20,10 @@ describe('DeleteConfirmationModal', () => { ...@@ -19,15 +20,10 @@ describe('DeleteConfirmationModal', () => {
}; };
store = new Vuex.Store({ store = new Vuex.Store({
modules: { state: {
licenseManagement: { currentLicenseInModal: approvedLicense,
namespaced: true,
state: {
currentLicenseInModal: approvedLicense,
},
actions,
},
}, },
actions,
}); });
vm = mountComponentWithStore(Component, { store }); vm = mountComponentWithStore(Component, { store });
...@@ -51,11 +47,9 @@ describe('DeleteConfirmationModal', () => { ...@@ -51,11 +47,9 @@ describe('DeleteConfirmationModal', () => {
store.replaceState({ store.replaceState({
...store.state, ...store.state,
licenseManagement: { currentLicenseInModal: {
currentLicenseInModal: { ...approvedLicense,
...approvedLicense, name,
name,
},
}, },
}); });
...@@ -95,7 +89,7 @@ describe('DeleteConfirmationModal', () => { ...@@ -95,7 +89,7 @@ describe('DeleteConfirmationModal', () => {
expect(actions.deleteLicense).toHaveBeenCalledWith( expect(actions.deleteLicense).toHaveBeenCalledWith(
jasmine.any(Object), jasmine.any(Object),
store.state.licenseManagement.currentLicenseInModal, store.state.currentLicenseInModal,
undefined, undefined,
); );
}); });
......
...@@ -25,11 +25,11 @@ describe('LicenseIssueBody', () => { ...@@ -25,11 +25,11 @@ describe('LicenseIssueBody', () => {
it('clicking the button triggers openModal with the current license', () => { it('clicking the button triggers openModal with the current license', () => {
const linkEl = vm.$el.querySelector('.license-item > .btn-link'); const linkEl = vm.$el.querySelector('.license-item > .btn-link');
expect(store.state.licenseManagement.currentLicenseInModal).toBe(null); expect(store.state.currentLicenseInModal).toBe(null);
linkEl.click(); linkEl.click();
expect(store.state.licenseManagement.currentLicenseInModal).toBe(issue); expect(store.state.currentLicenseInModal).toBe(issue);
}); });
}); });
......
import Vue from 'vue'; import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import AdminLicenseManagementRow from 'ee/vue_shared/license_management/components/admin_license_management_row.vue'; import LicenseManagementRow from 'ee/vue_shared/license_management/components/license_management_row.vue';
import { LICENSE_APPROVAL_STATUS } from 'ee/vue_shared/license_management/constants'; import { LICENSE_APPROVAL_STATUS } from 'ee/vue_shared/license_management/constants';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
...@@ -10,8 +10,8 @@ import { approvedLicense } from 'ee_spec/license_management/mock_data'; ...@@ -10,8 +10,8 @@ import { approvedLicense } from 'ee_spec/license_management/mock_data';
const visibleClass = 'visible'; const visibleClass = 'visible';
const invisibleClass = 'invisible'; const invisibleClass = 'invisible';
describe('AdminLicenseManagementRow', () => { describe('LicenseManagementRow', () => {
const Component = Vue.extend(AdminLicenseManagementRow); const Component = Vue.extend(LicenseManagementRow);
let vm; let vm;
let store; let store;
...@@ -28,13 +28,8 @@ describe('AdminLicenseManagementRow', () => { ...@@ -28,13 +28,8 @@ describe('AdminLicenseManagementRow', () => {
}; };
store = new Vuex.Store({ store = new Vuex.Store({
modules: { state: {},
licenseManagement: { actions,
namespaced: true,
state: {},
actions,
},
},
}); });
const props = { license: approvedLicense }; const props = { license: approvedLicense };
...@@ -53,8 +48,8 @@ describe('AdminLicenseManagementRow', () => { ...@@ -53,8 +48,8 @@ describe('AdminLicenseManagementRow', () => {
}); });
describe('computed', () => { describe('computed', () => {
it('dropdownText returns `Allowed`', () => { it('dropdownText returns `Approved`', () => {
expect(vm.dropdownText).toBe('Allowed'); expect(vm.dropdownText).toBe('Approved');
}); });
it('isApproved returns `true`', () => { it('isApproved returns `true`', () => {
...@@ -88,8 +83,8 @@ describe('AdminLicenseManagementRow', () => { ...@@ -88,8 +83,8 @@ describe('AdminLicenseManagementRow', () => {
}); });
describe('computed', () => { describe('computed', () => {
it('dropdownText returns `Denied`', () => { it('dropdownText returns `Blacklisted`', () => {
expect(vm.dropdownText).toBe('Denied'); expect(vm.dropdownText).toBe('Blacklisted');
}); });
it('isApproved returns `false`', () => { it('isApproved returns `false`', () => {
...@@ -169,7 +164,7 @@ describe('AdminLicenseManagementRow', () => { ...@@ -169,7 +164,7 @@ describe('AdminLicenseManagementRow', () => {
expect(dropdownEl.innerText.trim()).toBe(vm.dropdownText); expect(dropdownEl.innerText.trim()).toBe(vm.dropdownText);
}); });
it('renders the dropdown with `Allowed` and `Denied` options', () => { it('renders the dropdown with `Approved` and `Blacklisted` options', () => {
const dropdownEl = vm.$el.querySelector('.dropdown'); const dropdownEl = vm.$el.querySelector('.dropdown');
expect(dropdownEl).not.toBeNull(); expect(dropdownEl).not.toBeNull();
...@@ -177,12 +172,12 @@ describe('AdminLicenseManagementRow', () => { ...@@ -177,12 +172,12 @@ describe('AdminLicenseManagementRow', () => {
const firstOption = findNthDropdown(0); const firstOption = findNthDropdown(0);
expect(firstOption).not.toBeNull(); expect(firstOption).not.toBeNull();
expect(firstOption.innerText.trim()).toBe('Allowed'); expect(firstOption.innerText.trim()).toBe('Approved');
const secondOption = findNthDropdown(1); const secondOption = findNthDropdown(1);
expect(secondOption).not.toBeNull(); expect(secondOption).not.toBeNull();
expect(secondOption.innerText.trim()).toBe('Denied'); expect(secondOption.innerText.trim()).toBe('Blacklisted');
}); });
}); });
}); });
...@@ -22,16 +22,11 @@ describe('SetApprovalModal', () => { ...@@ -22,16 +22,11 @@ describe('SetApprovalModal', () => {
}; };
store = new Vuex.Store({ store = new Vuex.Store({
modules: { state: {
licenseManagement: { currentLicenseInModal: licenseReport[0],
namespaced: true, canManageLicenses: true,
state: {
currentLicenseInModal: licenseReport[0],
canManageLicenses: true,
},
actions,
},
}, },
actions,
}); });
vm = mountComponentWithStore(Component, { store }); vm = mountComponentWithStore(Component, { store });
...@@ -44,20 +39,18 @@ describe('SetApprovalModal', () => { ...@@ -44,20 +39,18 @@ describe('SetApprovalModal', () => {
describe('for approved license', () => { describe('for approved license', () => {
beforeEach(done => { beforeEach(done => {
store.replaceState({ store.replaceState({
licenseManagement: { currentLicenseInModal: {
currentLicenseInModal: { ...licenseReport[0],
...licenseReport[0], approvalStatus: LICENSE_APPROVAL_STATUS.APPROVED,
approvalStatus: LICENSE_APPROVAL_STATUS.APPROVED,
},
canManageLicenses: true,
}, },
canManageLicenses: true,
}); });
Vue.nextTick(done); Vue.nextTick(done);
}); });
describe('computed', () => { describe('computed', () => {
it('headerTitleText returns `License review', () => { it('headerTitleText returns `Blacklist license?`', () => {
expect(vm.headerTitleText).toBe('License review'); expect(vm.headerTitleText).toBe('Blacklist license?');
}); });
it('canApprove is false', () => { it('canApprove is false', () => {
...@@ -74,20 +67,20 @@ describe('SetApprovalModal', () => { ...@@ -74,20 +67,20 @@ describe('SetApprovalModal', () => {
const headerEl = vm.$el.querySelector('.modal-title'); const headerEl = vm.$el.querySelector('.modal-title');
expect(headerEl).not.toBeNull(); expect(headerEl).not.toBeNull();
expect(headerEl.innerText.trim()).toBe('License review'); expect(headerEl.innerText.trim()).toBe('Blacklist license?');
}); });
it('renders no Allow button in modal footer', () => { it('renders no Approve button in modal footer', () => {
const footerButton = vm.$el.querySelector('.js-modal-primary-action'); const footerButton = vm.$el.querySelector('.js-modal-primary-action');
expect(footerButton).toBeNull(); expect(footerButton).toBeNull();
}); });
it('renders Deny button in modal footer', () => { it('renders Blacklist button in modal footer', () => {
const footerButton = vm.$el.querySelector('.js-modal-secondary-action'); const footerButton = vm.$el.querySelector('.js-modal-secondary-action');
expect(footerButton).not.toBeNull(); expect(footerButton).not.toBeNull();
expect(footerButton.innerText.trim()).toBe('Deny'); expect(footerButton.innerText.trim()).toBe('Blacklist license');
}); });
}); });
}); });
...@@ -95,20 +88,18 @@ describe('SetApprovalModal', () => { ...@@ -95,20 +88,18 @@ describe('SetApprovalModal', () => {
describe('for unapproved license', () => { describe('for unapproved license', () => {
beforeEach(done => { beforeEach(done => {
store.replaceState({ store.replaceState({
licenseManagement: { currentLicenseInModal: {
currentLicenseInModal: { ...licenseReport[0],
...licenseReport[0], approvalStatus: undefined,
approvalStatus: undefined,
},
canManageLicenses: true,
}, },
canManageLicenses: true,
}); });
Vue.nextTick(done); Vue.nextTick(done);
}); });
describe('computed', () => { describe('computed', () => {
it('headerTitleText returns `License review`', () => { it('headerTitleText returns `Approve license?`', () => {
expect(vm.headerTitleText).toBe('License review'); expect(vm.headerTitleText).toBe('Approve license?');
}); });
it('canApprove is true', () => { it('canApprove is true', () => {
...@@ -125,21 +116,21 @@ describe('SetApprovalModal', () => { ...@@ -125,21 +116,21 @@ describe('SetApprovalModal', () => {
const headerEl = vm.$el.querySelector('.modal-title'); const headerEl = vm.$el.querySelector('.modal-title');
expect(headerEl).not.toBeNull(); expect(headerEl).not.toBeNull();
expect(headerEl.innerText.trim()).toBe('License review'); expect(headerEl.innerText.trim()).toBe('Approve license?');
}); });
it('renders Allow button in modal footer', () => { it('renders Approve button in modal footer', () => {
const footerButton = vm.$el.querySelector('.js-modal-primary-action'); const footerButton = vm.$el.querySelector('.js-modal-primary-action');
expect(footerButton).not.toBeNull(); expect(footerButton).not.toBeNull();
expect(footerButton.innerText.trim()).toBe('Allow'); expect(footerButton.innerText.trim()).toBe('Approve license');
}); });
it('renders Deny button in modal footer', () => { it('renders Blacklist button in modal footer', () => {
const footerButton = vm.$el.querySelector('.js-modal-secondary-action'); const footerButton = vm.$el.querySelector('.js-modal-secondary-action');
expect(footerButton).not.toBeNull(); expect(footerButton).not.toBeNull();
expect(footerButton.innerText.trim()).toBe('Deny'); expect(footerButton.innerText.trim()).toBe('Blacklist license');
}); });
}); });
}); });
...@@ -147,20 +138,18 @@ describe('SetApprovalModal', () => { ...@@ -147,20 +138,18 @@ describe('SetApprovalModal', () => {
describe('for blacklisted license', () => { describe('for blacklisted license', () => {
beforeEach(done => { beforeEach(done => {
store.replaceState({ store.replaceState({
licenseManagement: { currentLicenseInModal: {
currentLicenseInModal: { ...licenseReport[0],
...licenseReport[0], approvalStatus: LICENSE_APPROVAL_STATUS.BLACKLISTED,
approvalStatus: LICENSE_APPROVAL_STATUS.BLACKLISTED,
},
canManageLicenses: true,
}, },
canManageLicenses: true,
}); });
Vue.nextTick(done); Vue.nextTick(done);
}); });
describe('computed', () => { describe('computed', () => {
it('headerTitleText returns `License review`', () => { it('headerTitleText returns `Approve license?`', () => {
expect(vm.headerTitleText).toBe('License review'); expect(vm.headerTitleText).toBe('Approve license?');
}); });
it('canApprove is true', () => { it('canApprove is true', () => {
...@@ -177,17 +166,17 @@ describe('SetApprovalModal', () => { ...@@ -177,17 +166,17 @@ describe('SetApprovalModal', () => {
const headerEl = vm.$el.querySelector('.modal-title'); const headerEl = vm.$el.querySelector('.modal-title');
expect(headerEl).not.toBeNull(); expect(headerEl).not.toBeNull();
expect(headerEl.innerText.trim()).toBe('License review'); expect(headerEl.innerText.trim()).toBe('Approve license?');
}); });
it('renders Allow button in modal footer', () => { it('renders Approve button in modal footer', () => {
const footerButton = vm.$el.querySelector('.js-modal-primary-action'); const footerButton = vm.$el.querySelector('.js-modal-primary-action');
expect(footerButton).not.toBeNull(); expect(footerButton).not.toBeNull();
expect(footerButton.innerText.trim()).toBe('Allow'); expect(footerButton.innerText.trim()).toBe('Approve license');
}); });
it('renders no Deny button in modal footer', () => { it('renders no Blacklist button in modal footer', () => {
const footerButton = vm.$el.querySelector('.js-modal-secondary-action'); const footerButton = vm.$el.querySelector('.js-modal-secondary-action');
expect(footerButton).toBeNull(); expect(footerButton).toBeNull();
...@@ -198,13 +187,11 @@ describe('SetApprovalModal', () => { ...@@ -198,13 +187,11 @@ describe('SetApprovalModal', () => {
describe('for user without the rights to manage licenses', () => { describe('for user without the rights to manage licenses', () => {
beforeEach(done => { beforeEach(done => {
store.replaceState({ store.replaceState({
licenseManagement: { currentLicenseInModal: {
currentLicenseInModal: { ...licenseReport[0],
...licenseReport[0], approvalStatus: undefined,
approvalStatus: undefined,
},
canManageLicenses: false,
}, },
canManageLicenses: false,
}); });
Vue.nextTick(done); Vue.nextTick(done);
}); });
...@@ -297,7 +284,7 @@ describe('SetApprovalModal', () => { ...@@ -297,7 +284,7 @@ describe('SetApprovalModal', () => {
expect(actions.approveLicense).toHaveBeenCalledWith( expect(actions.approveLicense).toHaveBeenCalledWith(
jasmine.any(Object), jasmine.any(Object),
store.state.licenseManagement.currentLicenseInModal, store.state.currentLicenseInModal,
undefined, undefined,
); );
}); });
...@@ -310,7 +297,7 @@ describe('SetApprovalModal', () => { ...@@ -310,7 +297,7 @@ describe('SetApprovalModal', () => {
expect(actions.blacklistLicense).toHaveBeenCalledWith( expect(actions.blacklistLicense).toHaveBeenCalledWith(
jasmine.any(Object), jasmine.any(Object),
store.state.licenseManagement.currentLicenseInModal, store.state.currentLicenseInModal,
undefined, undefined,
); );
}); });
...@@ -322,12 +309,10 @@ describe('SetApprovalModal', () => { ...@@ -322,12 +309,10 @@ describe('SetApprovalModal', () => {
const badURL = 'javascript:alert("")'; const badURL = 'javascript:alert("")';
store.replaceState({ store.replaceState({
licenseManagement: { currentLicenseInModal: {
currentLicenseInModal: { ...licenseReport[0],
...licenseReport[0], url: badURL,
url: badURL, approvalStatus: LICENSE_APPROVAL_STATUS.APPROVED,
approvalStatus: LICENSE_APPROVAL_STATUS.APPROVED,
},
}, },
}); });
Vue.nextTick() Vue.nextTick()
......
...@@ -62,14 +62,9 @@ describe('License Report MR Widget', () => { ...@@ -62,14 +62,9 @@ describe('License Report MR Widget', () => {
actions = defaultActions, actions = defaultActions,
} = {}) => { } = {}) => {
const store = new Vuex.Store({ const store = new Vuex.Store({
modules: { state,
licenseManagement: { getters,
namespaced: true, actions,
state,
getters,
actions,
},
},
}); });
return mountComponentWithStore(Component, { props, store }); return mountComponentWithStore(Component, { props, store });
}; };
......
...@@ -59,20 +59,6 @@ describe('License store actions', () => { ...@@ -59,20 +59,6 @@ describe('License store actions', () => {
}); });
}); });
describe('setIsAdmin', () => {
it('commits SET_IS_ADMIN', done => {
testAction(
actions.setIsAdmin,
false,
state,
[{ type: mutationTypes.SET_IS_ADMIN, payload: false }],
[],
)
.then(done)
.catch(done.fail);
});
});
describe('resetLicenseInModal', () => { describe('resetLicenseInModal', () => {
it('commits RESET_LICENSE_IN_MODAL', done => { it('commits RESET_LICENSE_IN_MODAL', done => {
testAction( testAction(
......
import { import {
normalizeLicense, normalizeLicense,
getPackagesString, getPackagesString,
getStatusTranslationsFromLicenseStatus,
getIssueStatusFromLicenseStatus, getIssueStatusFromLicenseStatus,
convertToOldReportFormat, convertToOldReportFormat,
} from 'ee/vue_shared/license_management/store/utils'; } from 'ee/vue_shared/license_management/store/utils';
...@@ -46,24 +45,6 @@ describe('utils', () => { ...@@ -46,24 +45,6 @@ describe('utils', () => {
}); });
}); });
describe('getStatusTranslationsFromLicenseStatus', () => {
it('returns "Allowed" for allowed license status', () => {
expect(getStatusTranslationsFromLicenseStatus(LICENSE_APPROVAL_STATUS.APPROVED)).toBe(
'Allowed',
);
});
it('returns "Denied" status for denied license status', () => {
expect(getStatusTranslationsFromLicenseStatus(LICENSE_APPROVAL_STATUS.BLACKLISTED)).toBe(
'Denied',
);
});
it('returns "" for any other status', () => {
expect(getStatusTranslationsFromLicenseStatus()).toBe('');
});
});
describe('getIssueStatusFromLicenseStatus', () => { describe('getIssueStatusFromLicenseStatus', () => {
it('returns SUCCESS status for approved license status', () => { it('returns SUCCESS status for approved license status', () => {
expect(getIssueStatusFromLicenseStatus(LICENSE_APPROVAL_STATUS.APPROVED)).toBe( expect(getIssueStatusFromLicenseStatus(LICENSE_APPROVAL_STATUS.APPROVED)).toBe(
......
...@@ -11256,19 +11256,31 @@ msgstr "" ...@@ -11256,19 +11256,31 @@ msgstr ""
msgid "LicenseCompliance|Add licenses manually to approve or blacklist" msgid "LicenseCompliance|Add licenses manually to approve or blacklist"
msgstr "" msgstr ""
msgid "LicenseCompliance|Allow" msgid "LicenseCompliance|Approve"
msgstr "" msgstr ""
msgid "LicenseCompliance|Allowed" msgid "LicenseCompliance|Approve license"
msgstr "" msgstr ""
msgid "LicenseCompliance|Cancel" msgid "LicenseCompliance|Approve license?"
msgstr ""
msgid "LicenseCompliance|Approved"
msgstr ""
msgid "LicenseCompliance|Blacklist"
msgstr "" msgstr ""
msgid "LicenseCompliance|Denied" msgid "LicenseCompliance|Blacklist license"
msgstr "" msgstr ""
msgid "LicenseCompliance|Deny" msgid "LicenseCompliance|Blacklist license?"
msgstr ""
msgid "LicenseCompliance|Blacklisted"
msgstr ""
msgid "LicenseCompliance|Cancel"
msgstr "" msgstr ""
msgid "LicenseCompliance|Here you can approve or blacklist licenses for this project. Using %{ci} or %{license} will allow you to see if there are any unmanaged licenses and approve or blacklist them in merge request." msgid "LicenseCompliance|Here you can approve or blacklist licenses for this project. Using %{ci} or %{license} will allow you to see if there are any unmanaged licenses and approve or blacklist them in merge request."
...@@ -11312,9 +11324,6 @@ msgstr "" ...@@ -11312,9 +11324,6 @@ msgstr ""
msgid "LicenseCompliance|License name" msgid "LicenseCompliance|License name"
msgstr "" msgstr ""
msgid "LicenseCompliance|License review"
msgstr ""
msgid "LicenseCompliance|Packages" msgid "LicenseCompliance|Packages"
msgstr "" msgstr ""
...@@ -11360,9 +11369,6 @@ msgstr "" ...@@ -11360,9 +11369,6 @@ msgstr ""
msgid "Licenses|Components" msgid "Licenses|Components"
msgstr "" msgstr ""
msgid "Licenses|Detected in Project"
msgstr ""
msgid "Licenses|Displays licenses detected in the project, based on the %{linkStart}latest pipeline%{linkEnd} scan" msgid "Licenses|Displays licenses detected in the project, based on the %{linkStart}latest pipeline%{linkEnd} scan"
msgstr "" msgstr ""
...@@ -11378,15 +11384,6 @@ msgstr "" ...@@ -11378,15 +11384,6 @@ msgstr ""
msgid "Licenses|Name" msgid "Licenses|Name"
msgstr "" msgstr ""
msgid "Licenses|Policies"
msgstr ""
msgid "Licenses|Policy"
msgstr ""
msgid "Licenses|Specified policies in this project"
msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project." msgid "Licenses|The license list details information about the licenses used within your project."
msgstr "" msgstr ""
......
...@@ -20,8 +20,8 @@ module QA::EE ...@@ -20,8 +20,8 @@ module QA::EE
element :license_compliance_list element :license_compliance_list
end end
view 'ee/app/assets/javascripts/vue_shared/license_management/components/admin_license_management_row.vue' do view 'ee/app/assets/javascripts/vue_shared/license_management/components/license_management_row.vue' do
element :admin_license_compliance_row element :license_compliance_row
element :license_name_content element :license_name_content
end end
...@@ -30,13 +30,13 @@ module QA::EE ...@@ -30,13 +30,13 @@ module QA::EE
end end
def has_approved_license?(name) def has_approved_license?(name)
within_element(:admin_license_compliance_row, text: name) do within_element(:license_compliance_row, text: name) do
has_element?(:status_success_icon) has_element?(:status_success_icon)
end end
end end
def has_denied_license?(name) def has_denied_license?(name)
within_element(:admin_license_compliance_row, text: name) do within_element(:license_compliance_row, text: name) do
has_element?(:status_failed_icon) has_element?(:status_failed_icon)
end end
end end
......
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