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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-01-20 12:16:11 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-01-20 12:16:11 +0300
commitedaa33dee2ff2f7ea3fac488d41558eb5f86d68c (patch)
tree11f143effbfeba52329fb7afbd05e6e2a3790241 /spec/frontend/security_configuration
parentd8a5691316400a0f7ec4f83832698f1988eb27c1 (diff)
Add latest changes from gitlab-org/gitlab@14-7-stable-eev14.7.0-rc42
Diffstat (limited to 'spec/frontend/security_configuration')
-rw-r--r--spec/frontend/security_configuration/components/app_spec.js38
-rw-r--r--spec/frontend/security_configuration/components/training_provider_list_spec.js181
-rw-r--r--spec/frontend/security_configuration/mock_data.js25
3 files changed, 193 insertions, 51 deletions
diff --git a/spec/frontend/security_configuration/components/app_spec.js b/spec/frontend/security_configuration/components/app_spec.js
index 0a2b18caf25..cbdf7f53913 100644
--- a/spec/frontend/security_configuration/components/app_spec.js
+++ b/spec/frontend/security_configuration/components/app_spec.js
@@ -1,4 +1,4 @@
-import { GlTab } from '@gitlab/ui';
+import { GlTab, GlTabs } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
@@ -77,6 +77,7 @@ describe('App component', () => {
const findMainHeading = () => wrapper.find('h1');
const findTab = () => wrapper.findComponent(GlTab);
const findTabs = () => wrapper.findAllComponents(GlTab);
+ const findGlTabs = () => wrapper.findComponent(GlTabs);
const findByTestId = (id) => wrapper.findByTestId(id);
const findFeatureCards = () => wrapper.findAllComponents(FeatureCard);
const findTrainingProviderList = () => wrapper.findComponent(TrainingProviderList);
@@ -154,6 +155,14 @@ describe('App component', () => {
expect(findTab().exists()).toBe(true);
});
+ it('passes the `sync-active-tab-with-query-params` prop', () => {
+ expect(findGlTabs().props('syncActiveTabWithQueryParams')).toBe(true);
+ });
+
+ it('lazy loads each tab', () => {
+ expect(findGlTabs().attributes('lazy')).not.toBe(undefined);
+ });
+
it('renders correct amount of tabs', () => {
expect(findTabs()).toHaveLength(expectedTabs.length);
});
@@ -161,6 +170,10 @@ describe('App component', () => {
it.each(expectedTabs)('renders the %s tab', (tabName) => {
expect(findByTestId(`${tabName}-tab`).exists()).toBe(true);
});
+
+ it.each(expectedTabs)('has the %s query-param-value', (tabName) => {
+ expect(findByTestId(`${tabName}-tab`).props('queryParamValue')).toBe(tabName);
+ });
});
it('renders right amount of feature cards for given props with correct props', () => {
@@ -182,10 +195,6 @@ describe('App component', () => {
expect(findComplianceViewHistoryLink().exists()).toBe(false);
expect(findSecurityViewHistoryLink().exists()).toBe(false);
});
-
- it('renders TrainingProviderList component', () => {
- expect(findTrainingProviderList().exists()).toBe(true);
- });
});
describe('Manage via MR Error Alert', () => {
@@ -432,6 +441,25 @@ describe('App component', () => {
});
});
+ describe('Vulnerability management', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ });
+ });
+
+ it('renders TrainingProviderList component', () => {
+ expect(findTrainingProviderList().exists()).toBe(true);
+ });
+
+ it('renders security training description', () => {
+ const vulnerabilityManagementTab = wrapper.findByTestId('vulnerability-management-tab');
+
+ expect(vulnerabilityManagementTab.text()).toContain(i18n.securityTrainingDescription);
+ });
+ });
+
describe('when secureVulnerabilityTraining feature flag is disabled', () => {
beforeEach(() => {
createComponent({
diff --git a/spec/frontend/security_configuration/components/training_provider_list_spec.js b/spec/frontend/security_configuration/components/training_provider_list_spec.js
index 60cc36a634c..578248e696f 100644
--- a/spec/frontend/security_configuration/components/training_provider_list_spec.js
+++ b/spec/frontend/security_configuration/components/training_provider_list_spec.js
@@ -1,87 +1,192 @@
-import { GlLink, GlToggle, GlCard, GlSkeletonLoader } from '@gitlab/ui';
+import { GlAlert, GlLink, GlToggle, GlCard, GlSkeletonLoader } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import TrainingProviderList from '~/security_configuration/components/training_provider_list.vue';
+import configureSecurityTrainingProvidersMutation from '~/security_configuration/graphql/configure_security_training_providers.mutation.graphql';
import waitForPromises from 'helpers/wait_for_promises';
-import { securityTrainingProviders, mockResolvers } from '../mock_data';
+import {
+ securityTrainingProviders,
+ createMockResolvers,
+ testProjectPath,
+ textProviderIds,
+} from '../mock_data';
Vue.use(VueApollo);
describe('TrainingProviderList component', () => {
let wrapper;
- let mockApollo;
- let mockSecurityTrainingProvidersData;
+ let apolloProvider;
- const createComponent = () => {
- mockApollo = createMockApollo([], mockResolvers);
+ const createApolloProvider = ({ resolvers } = {}) => {
+ apolloProvider = createMockApollo([], createMockResolvers({ resolvers }));
+ };
+ const createComponent = () => {
wrapper = shallowMount(TrainingProviderList, {
- apolloProvider: mockApollo,
+ provide: {
+ projectPath: testProjectPath,
+ },
+ apolloProvider,
});
};
const waitForQueryToBeLoaded = () => waitForPromises();
+ const waitForMutationToBeLoaded = waitForQueryToBeLoaded;
const findCards = () => wrapper.findAllComponents(GlCard);
const findLinks = () => wrapper.findAllComponents(GlLink);
const findToggles = () => wrapper.findAllComponents(GlToggle);
+ const findFirstToggle = () => findToggles().at(0);
const findLoader = () => wrapper.findComponent(GlSkeletonLoader);
+ const findErrorAlert = () => wrapper.findComponent(GlAlert);
- beforeEach(() => {
- mockSecurityTrainingProvidersData = jest.fn();
- mockSecurityTrainingProvidersData.mockResolvedValue(securityTrainingProviders);
-
- createComponent();
- });
+ const toggleFirstProvider = () => findFirstToggle().vm.$emit('change');
afterEach(() => {
wrapper.destroy();
- mockApollo = null;
+ apolloProvider = null;
});
- describe('when loading', () => {
- it('shows the loader', () => {
- expect(findLoader().exists()).toBe(true);
+ describe('with a successful response', () => {
+ beforeEach(() => {
+ createApolloProvider();
+ createComponent();
});
- it('does not show the cards', () => {
- expect(findCards().exists()).toBe(false);
+ describe('when loading', () => {
+ it('shows the loader', () => {
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('does not show the cards', () => {
+ expect(findCards().exists()).toBe(false);
+ });
});
- });
- describe('basic structure', () => {
- beforeEach(async () => {
- await waitForQueryToBeLoaded();
+ describe('basic structure', () => {
+ beforeEach(async () => {
+ await waitForQueryToBeLoaded();
+ });
+
+ it('renders correct amount of cards', () => {
+ expect(findCards()).toHaveLength(securityTrainingProviders.length);
+ });
+
+ securityTrainingProviders.forEach(({ name, description, url, isEnabled }, index) => {
+ it(`shows the name for card ${index}`, () => {
+ expect(findCards().at(index).text()).toContain(name);
+ });
+
+ it(`shows the description for card ${index}`, () => {
+ expect(findCards().at(index).text()).toContain(description);
+ });
+
+ it(`shows the learn more link for card ${index}`, () => {
+ expect(findLinks().at(index).attributes()).toEqual({
+ target: '_blank',
+ href: url,
+ });
+ });
+
+ it(`shows the toggle with the correct value for card ${index}`, () => {
+ expect(findToggles().at(index).props('value')).toEqual(isEnabled);
+ });
+
+ it('does not show loader when query is populated', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+ });
});
- it('renders correct amount of cards', () => {
- expect(findCards()).toHaveLength(securityTrainingProviders.length);
+ describe('storing training provider settings', () => {
+ beforeEach(async () => {
+ jest.spyOn(apolloProvider.defaultClient, 'mutate');
+
+ await waitForMutationToBeLoaded();
+
+ toggleFirstProvider();
+ });
+
+ it.each`
+ loading | wait | desc
+ ${true} | ${false} | ${'enables loading of GlToggle when mutation is called'}
+ ${false} | ${true} | ${'disables loading of GlToggle when mutation is complete'}
+ `('$desc', async ({ loading, wait }) => {
+ if (wait) {
+ await waitForMutationToBeLoaded();
+ }
+ expect(findFirstToggle().props('isLoading')).toBe(loading);
+ });
+
+ it('calls mutation when toggle is changed', () => {
+ expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledWith(
+ expect.objectContaining({
+ mutation: configureSecurityTrainingProvidersMutation,
+ variables: { input: { enabledProviders: textProviderIds, fullPath: testProjectPath } },
+ }),
+ );
+ });
});
+ });
+
+ describe('with errors', () => {
+ const expectErrorAlertToExist = () => {
+ expect(findErrorAlert().props()).toMatchObject({
+ dismissible: false,
+ variant: 'danger',
+ });
+ };
+
+ describe('when fetching training providers', () => {
+ beforeEach(async () => {
+ createApolloProvider({
+ resolvers: {
+ Query: {
+ securityTrainingProviders: jest.fn().mockReturnValue(new Error()),
+ },
+ },
+ });
+ createComponent();
- securityTrainingProviders.forEach(({ name, description, url, isEnabled }, index) => {
- it(`shows the name for card ${index}`, () => {
- expect(findCards().at(index).text()).toContain(name);
+ await waitForQueryToBeLoaded();
});
- it(`shows the description for card ${index}`, () => {
- expect(findCards().at(index).text()).toContain(description);
+ it('shows an non-dismissible error alert', () => {
+ expectErrorAlertToExist();
});
- it(`shows the learn more link for card ${index}`, () => {
- expect(findLinks().at(index).attributes()).toEqual({
- target: '_blank',
- href: url,
+ it('shows an error description', () => {
+ expect(findErrorAlert().text()).toBe(TrainingProviderList.i18n.providerQueryErrorMessage);
+ });
+ });
+
+ describe('when storing training provider configurations', () => {
+ beforeEach(async () => {
+ createApolloProvider({
+ resolvers: {
+ Mutation: {
+ configureSecurityTrainingProviders: () => ({
+ errors: ['something went wrong!'],
+ securityTrainingProviders: [],
+ }),
+ },
+ },
});
+ createComponent();
+
+ await waitForQueryToBeLoaded();
+ toggleFirstProvider();
+ await waitForMutationToBeLoaded();
});
- it(`shows the toggle with the correct value for card ${index}`, () => {
- expect(findToggles().at(index).props('value')).toEqual(isEnabled);
+ it('shows an non-dismissible error alert', () => {
+ expectErrorAlertToExist();
});
- it('does not show loader when query is populated', () => {
- expect(findLoader().exists()).toBe(false);
+ it('shows an error description', () => {
+ expect(findErrorAlert().text()).toBe(TrainingProviderList.i18n.configMutationErrorMessage);
});
});
});
diff --git a/spec/frontend/security_configuration/mock_data.js b/spec/frontend/security_configuration/mock_data.js
index cdb859c3800..37ecce3886d 100644
--- a/spec/frontend/security_configuration/mock_data.js
+++ b/spec/frontend/security_configuration/mock_data.js
@@ -1,16 +1,20 @@
+export const testProjectPath = 'foo/bar';
+
+export const textProviderIds = [101, 102];
+
export const securityTrainingProviders = [
{
- id: 101,
- name: 'Kontra',
- description: 'Interactive developer security education.',
- url: 'https://application.security/',
+ id: textProviderIds[0],
+ name: 'Vendor Name 1',
+ description: 'Interactive developer security education',
+ url: 'https://www.example.org/security/training',
isEnabled: false,
},
{
- id: 102,
- name: 'SecureCodeWarrior',
+ id: textProviderIds[1],
+ name: 'Vendor Name 2',
description: 'Security training with guide and learning pathways.',
- url: 'https://www.securecodewarrior.com/',
+ url: 'https://www.vendornametwo.com/',
isEnabled: true,
},
];
@@ -21,10 +25,15 @@ export const securityTrainingProvidersResponse = {
},
};
-export const mockResolvers = {
+const defaultMockResolvers = {
Query: {
securityTrainingProviders() {
return securityTrainingProviders;
},
},
};
+
+export const createMockResolvers = ({ resolvers: customMockResolvers = {} } = {}) => ({
+ ...defaultMockResolvers,
+ ...customMockResolvers,
+});