Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-05-25 00:09:08 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-05-25 00:09:08 +0300
commite09f6bdfd191f0cf8e54f0bc272e4e0635990ed9 (patch)
tree0791fa74b2321e5f815458e35615cfbfacbe231b /spec
parent8015f09545c35b833f4955fc2e0b8f1a3214cbcb (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/frontend/security_configuration/components/app_spec.js187
-rw-r--r--spec/frontend/security_configuration/mock_data.js9
-rw-r--r--spec/frontend/vue_mr_widget/components/extensions/index_spec.js2
-rw-r--r--spec/models/project_spec.rb8
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb65
5 files changed, 199 insertions, 72 deletions
diff --git a/spec/frontend/security_configuration/components/app_spec.js b/spec/frontend/security_configuration/components/app_spec.js
index 161f1a405d1..d7d46d0d415 100644
--- a/spec/frontend/security_configuration/components/app_spec.js
+++ b/spec/frontend/security_configuration/components/app_spec.js
@@ -2,6 +2,7 @@ import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { GlTab, GlTabs, GlLink } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
import stubChildren from 'helpers/stub_children';
@@ -19,14 +20,22 @@ import {
LICENSE_COMPLIANCE_DESCRIPTION,
LICENSE_COMPLIANCE_HELP_PATH,
AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY,
+ LICENSE_ULTIMATE,
+ LICENSE_PREMIUM,
+ LICENSE_FREE,
} from '~/security_configuration/components/constants';
import FeatureCard from '~/security_configuration/components/feature_card.vue';
import TrainingProviderList from '~/security_configuration/components/training_provider_list.vue';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import currentLicenseQuery from '~/security_configuration/graphql/current_license.query.graphql';
+import waitForPromises from 'helpers/wait_for_promises';
+
import UpgradeBanner from '~/security_configuration/components/upgrade_banner.vue';
import {
REPORT_TYPE_LICENSE_COMPLIANCE,
REPORT_TYPE_SAST,
} from '~/vue_shared/security_reports/constants';
+import { getCurrentLicensePlanResponse } from '../mock_data';
const upgradePath = '/upgrade';
const autoDevopsHelpPagePath = '/autoDevopsHelpPagePath';
@@ -41,40 +50,31 @@ Vue.use(VueApollo);
describe('App component', () => {
let wrapper;
let userCalloutDismissSpy;
+ let mockApollo;
- const securityFeaturesMock = [
- {
- name: SAST_NAME,
- shortName: SAST_SHORT_NAME,
- description: SAST_DESCRIPTION,
- helpPath: SAST_HELP_PATH,
- configurationHelpPath: SAST_CONFIG_HELP_PATH,
- type: REPORT_TYPE_SAST,
- available: true,
- },
- ];
-
- const complianceFeaturesMock = [
- {
- name: LICENSE_COMPLIANCE_NAME,
- description: LICENSE_COMPLIANCE_DESCRIPTION,
- helpPath: LICENSE_COMPLIANCE_HELP_PATH,
- type: REPORT_TYPE_LICENSE_COMPLIANCE,
- configurationHelpPath: LICENSE_COMPLIANCE_HELP_PATH,
- },
- ];
-
- const createComponent = ({ shouldShowCallout = true, ...propsData } = {}) => {
+ const createComponent = ({
+ shouldShowCallout = true,
+ licenseQueryResponse = LICENSE_ULTIMATE,
+ ...propsData
+ }) => {
userCalloutDismissSpy = jest.fn();
+ mockApollo = createMockApollo([
+ [
+ currentLicenseQuery,
+ jest
+ .fn()
+ .mockResolvedValue(
+ licenseQueryResponse instanceof Error
+ ? licenseQueryResponse
+ : getCurrentLicensePlanResponse(licenseQueryResponse),
+ ),
+ ],
+ ]);
+
wrapper = extendedWrapper(
mount(SecurityConfigurationApp, {
- propsData: {
- augmentedSecurityFeatures: securityFeaturesMock,
- augmentedComplianceFeatures: complianceFeaturesMock,
- securityTrainingEnabled: true,
- ...propsData,
- },
+ propsData,
provide: {
upgradePath,
autoDevopsHelpPagePath,
@@ -82,6 +82,7 @@ describe('App component', () => {
projectFullPath,
vulnerabilityTrainingDocsPath,
},
+ apolloProvider: mockApollo,
stubs: {
...stubChildren(SecurityConfigurationApp),
GlLink: false,
@@ -132,13 +133,40 @@ describe('App component', () => {
const findAutoDevopsEnabledAlert = () => wrapper.findComponent(AutoDevopsEnabledAlert);
const findVulnerabilityManagementTab = () => wrapper.findByTestId('vulnerability-management-tab');
+ const securityFeaturesMock = [
+ {
+ name: SAST_NAME,
+ shortName: SAST_SHORT_NAME,
+ description: SAST_DESCRIPTION,
+ helpPath: SAST_HELP_PATH,
+ configurationHelpPath: SAST_CONFIG_HELP_PATH,
+ type: REPORT_TYPE_SAST,
+ available: true,
+ },
+ ];
+
+ const complianceFeaturesMock = [
+ {
+ name: LICENSE_COMPLIANCE_NAME,
+ description: LICENSE_COMPLIANCE_DESCRIPTION,
+ helpPath: LICENSE_COMPLIANCE_HELP_PATH,
+ type: REPORT_TYPE_LICENSE_COMPLIANCE,
+ configurationHelpPath: LICENSE_COMPLIANCE_HELP_PATH,
+ },
+ ];
+
afterEach(() => {
wrapper.destroy();
+ mockApollo = null;
});
describe('basic structure', () => {
- beforeEach(() => {
- createComponent();
+ beforeEach(async () => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ });
+ await waitForPromises();
});
it('renders main-heading with correct text', () => {
@@ -198,7 +226,10 @@ describe('App component', () => {
describe('Manage via MR Error Alert', () => {
beforeEach(() => {
- createComponent();
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ });
});
describe('on initial load', () => {
@@ -234,6 +265,8 @@ describe('App component', () => {
describe('given the right props', () => {
beforeEach(() => {
createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
autoDevopsEnabled: false,
gitlabCiPresent: false,
canEnableAutoDevops: true,
@@ -255,7 +288,10 @@ describe('App component', () => {
describe('given the wrong props', () => {
beforeEach(() => {
- createComponent();
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ });
});
it('should not show AutoDevopsAlert', () => {
expect(findAutoDevopsAlert().exists()).toBe(false);
@@ -279,7 +315,11 @@ describe('App component', () => {
);
}
- createComponent({ autoDevopsEnabled });
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ autoDevopsEnabled,
+ });
});
it(shouldRender ? 'renders' : 'does not render', () => {
@@ -305,7 +345,12 @@ describe('App component', () => {
);
}
- createComponent({ autoDevopsEnabled: true });
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ autoDevopsEnabled: true,
+ });
+
findAutoDevopsEnabledAlert().vm.$emit('dismiss');
});
@@ -330,6 +375,7 @@ describe('App component', () => {
describe('given at least one unavailable feature', () => {
beforeEach(() => {
createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
augmentedComplianceFeatures: complianceFeaturesMock.map(makeAvailable(false)),
});
});
@@ -350,6 +396,7 @@ describe('App component', () => {
describe('given at least one unavailable feature, but banner is already dismissed', () => {
beforeEach(() => {
createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
augmentedComplianceFeatures: complianceFeaturesMock.map(makeAvailable(false)),
shouldShowCallout: false,
});
@@ -376,7 +423,11 @@ describe('App component', () => {
describe('when given latestPipelinePath props', () => {
beforeEach(() => {
- createComponent({ latestPipelinePath: 'test/path' });
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ latestPipelinePath: 'test/path',
+ });
});
it('should show latest pipeline info on the security tab with correct link when latestPipelinePath is defined', () => {
@@ -401,6 +452,8 @@ describe('App component', () => {
describe('given gitlabCiPresent & gitlabCiHistoryPath props', () => {
beforeEach(() => {
createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
gitlabCiPresent: true,
gitlabCiHistoryPath,
});
@@ -415,36 +468,48 @@ describe('App component', () => {
});
});
- describe('Vulnerability management tab', () => {
- it('does not show tab if security training is disabled', () => {
- createComponent({ securityTrainingEnabled: false });
-
- expect(findVulnerabilityManagementTab().exists()).toBe(false);
- });
-
- describe('security training enabled', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('shows the tab if security training is enabled', () => {
- expect(findVulnerabilityManagementTab().exists()).toBe(true);
+ describe('Vulnerability management', () => {
+ beforeEach(async () => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
});
+ await waitForPromises();
+ });
- it('renders TrainingProviderList component', () => {
- expect(findTrainingProviderList().exists()).toBe(true);
- });
+ it('renders TrainingProviderList component', () => {
+ expect(findTrainingProviderList().exists()).toBe(true);
+ });
- it('renders security training description', () => {
- expect(findVulnerabilityManagementTab().text()).toContain(i18n.securityTrainingDescription);
- });
+ it('renders security training description', () => {
+ expect(findVulnerabilityManagementTab().text()).toContain(i18n.securityTrainingDescription);
+ });
- it('renders link to help docs', () => {
- const trainingLink = findVulnerabilityManagementTab().findComponent(GlLink);
+ it('renders link to help docs', () => {
+ const trainingLink = findVulnerabilityManagementTab().findComponent(GlLink);
- expect(trainingLink.text()).toBe('Learn more about vulnerability training');
- expect(trainingLink.attributes('href')).toBe(vulnerabilityTrainingDocsPath);
- });
+ expect(trainingLink.text()).toBe('Learn more about vulnerability training');
+ expect(trainingLink.attributes('href')).toBe(vulnerabilityTrainingDocsPath);
});
+
+ it.each`
+ licenseQueryResponse | display
+ ${LICENSE_ULTIMATE} | ${true}
+ ${LICENSE_PREMIUM} | ${false}
+ ${LICENSE_FREE} | ${false}
+ ${null} | ${true}
+ ${new Error()} | ${true}
+ `(
+ 'displays $display for license $licenseQueryResponse',
+ async ({ licenseQueryResponse, display }) => {
+ createComponent({
+ licenseQueryResponse,
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ });
+ await waitForPromises();
+ expect(findVulnerabilityManagementTab().exists()).toBe(display);
+ },
+ );
});
});
diff --git a/spec/frontend/security_configuration/mock_data.js b/spec/frontend/security_configuration/mock_data.js
index 18a480bf082..94a36472a1d 100644
--- a/spec/frontend/security_configuration/mock_data.js
+++ b/spec/frontend/security_configuration/mock_data.js
@@ -111,3 +111,12 @@ export const tempProviderLogos = {
svg: `<svg>${[testProviderName[1]]}</svg>`,
},
};
+
+export const getCurrentLicensePlanResponse = (plan) => ({
+ data: {
+ currentLicense: {
+ id: 'gid://gitlab/License/1',
+ plan,
+ },
+ },
+});
diff --git a/spec/frontend/vue_mr_widget/components/extensions/index_spec.js b/spec/frontend/vue_mr_widget/components/extensions/index_spec.js
index 63df63a9b00..dc25596655a 100644
--- a/spec/frontend/vue_mr_widget/components/extensions/index_spec.js
+++ b/spec/frontend/vue_mr_widget/components/extensions/index_spec.js
@@ -21,8 +21,8 @@ describe('MR widget extension registering', () => {
expect.objectContaining({
extends: ExtensionBase,
name: 'Test',
- props: ['helloWorld'],
computed: {
+ helloWorld: expect.any(Function),
test: expect.any(Function),
},
methods: {
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 5cbdba70815..5e4ffeb8455 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -8323,14 +8323,6 @@ RSpec.describe Project, factory_default: :keep do
end
end
- describe '#security_training_available?' do
- subject { build(:project) }
-
- it 'returns false' do
- expect(subject.security_training_available?).to eq false
- end
- end
-
private
def finish_job(export_job)
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index b67fd928e00..d928c1fb64a 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -122,7 +122,7 @@ RSpec.describe QuickActions::InterpretService do
inprogress # populate the label
_, updates, _ = service.execute(content, issuable)
- expect(updates).to eq(add_label_ids: [bug.id, inprogress.id])
+ expect(updates).to match(add_label_ids: contain_exactly(bug.id, inprogress.id))
end
it 'returns the label message' do
@@ -130,7 +130,10 @@ RSpec.describe QuickActions::InterpretService do
inprogress # populate the label
_, _, message = service.execute(content, issuable)
- expect(message).to eq("Added #{bug.to_reference(format: :name)} #{inprogress.to_reference(format: :name)} labels.")
+ # Compare message without making assumptions about ordering.
+ expect(message).to match %r{Added ~".*" ~".*" labels.}
+ expect(message).to include(bug.to_reference(format: :name))
+ expect(message).to include(inprogress.to_reference(format: :name))
end
end
@@ -1196,6 +1199,64 @@ RSpec.describe QuickActions::InterpretService do
let(:issuable) { merge_request }
end
+ context 'with a colon label' do
+ let(:bug) { create(:label, project: project, title: 'Category:Bug') }
+ let(:inprogress) { create(:label, project: project, title: 'status:in:progress') }
+
+ context 'when quoted' do
+ let(:content) { %(/label ~"#{inprogress.title}" ~"#{bug.title}" ~unknown) }
+
+ it_behaves_like 'label command' do
+ let(:issuable) { merge_request }
+ end
+
+ it_behaves_like 'label command' do
+ let(:issuable) { issue }
+ end
+ end
+
+ context 'when unquoted' do
+ let(:content) { %(/label ~#{inprogress.title} ~#{bug.title} ~unknown) }
+
+ it_behaves_like 'label command' do
+ let(:issuable) { merge_request }
+ end
+
+ it_behaves_like 'label command' do
+ let(:issuable) { issue }
+ end
+ end
+ end
+
+ context 'with a scoped label' do
+ let(:bug) { create(:label, :scoped, project: project) }
+ let(:inprogress) { create(:label, project: project, title: 'three::part::label') }
+
+ context 'when quoted' do
+ let(:content) { %(/label ~"#{inprogress.title}" ~"#{bug.title}" ~unknown) }
+
+ it_behaves_like 'label command' do
+ let(:issuable) { merge_request }
+ end
+
+ it_behaves_like 'label command' do
+ let(:issuable) { issue }
+ end
+ end
+
+ context 'when unquoted' do
+ let(:content) { %(/label ~#{inprogress.title} ~#{bug.title} ~unknown) }
+
+ it_behaves_like 'label command' do
+ let(:issuable) { merge_request }
+ end
+
+ it_behaves_like 'label command' do
+ let(:issuable) { issue }
+ end
+ end
+ end
+
it_behaves_like 'multiple label command' do
let(:content) { %(/label ~"#{inprogress.title}" \n/label ~#{bug.title}) }
let(:issuable) { issue }