Skip to content
Snippets Groups Projects
Commit daa15704 authored by Samantha Ming's avatar Samantha Ming
Browse files

Update TrainingProviderList to use Apollo

Refactor apollo query into TrainingProviderList component
and update specs accordingly.
parent 92f4b73c
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -4,7 +4,6 @@ import { __, s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
import securityTrainingProvidersQuery from '../graphql/security_training_providers.query.graphql';
import AutoDevOpsAlert from './auto_dev_ops_alert.vue';
import AutoDevOpsEnabledAlert from './auto_dev_ops_enabled_alert.vue';
import { AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY } from './constants';
Loading
Loading
@@ -88,7 +87,6 @@ export default {
return {
autoDevopsEnabledAlertDismissedProjects: [],
errorMessage: '',
securityTrainingProviders: [],
};
},
computed: {
Loading
Loading
@@ -110,11 +108,6 @@ export default {
);
},
},
apollo: {
securityTrainingProviders: {
query: securityTrainingProvidersQuery,
},
},
methods: {
dismissAutoDevopsEnabledAlert() {
const dismissedProjects = new Set(this.autoDevopsEnabledAlertDismissedProjects);
Loading
Loading
@@ -251,10 +244,7 @@ export default {
>
<section-layout :heading="$options.i18n.securityTraining">
<template #features>
<training-provider-list
:loading="$apollo.queries.securityTrainingProviders.loading"
:providers="securityTrainingProviders"
/>
<training-provider-list />
</template>
</section-layout>
</gl-tab>
Loading
Loading
<script>
import { GlCard, GlToggle, GlLink, GlSkeletonLoader } from '@gitlab/ui';
import securityTrainingProvidersQuery from '../graphql/security_training_providers.query.graphql';
 
export default {
components: {
Loading
Loading
@@ -8,15 +9,19 @@ export default {
GlLink,
GlSkeletonLoader,
},
props: {
providers: {
type: Array,
required: true,
apollo: {
securityTrainingProviders: {
query: securityTrainingProvidersQuery,
},
loading: {
type: Boolean,
required: false,
default: false,
},
data() {
return {
securityTrainingProviders: [],
};
},
computed: {
isLoading() {
return this.$apollo.queries.securityTrainingProviders.loading;
},
},
};
Loading
Loading
@@ -24,7 +29,7 @@ export default {
 
<template>
<div
v-if="loading"
v-if="isLoading"
class="gl-bg-white gl-py-6 gl-rounded-base gl-border-1 gl-border-solid gl-border-gray-100"
>
<gl-skeleton-loader :width="350" :height="44">
Loading
Loading
@@ -34,7 +39,11 @@ export default {
</gl-skeleton-loader>
</div>
<ul v-else class="gl-list-style-none gl-m-0 gl-p-0">
<li v-for="{ id, isEnabled, name, description, url } in providers" :key="id" class="gl-mb-6">
<li
v-for="{ id, isEnabled, name, description, url } in securityTrainingProviders"
:key="id"
class="gl-mb-6"
>
<gl-card>
<div class="gl-display-flex">
<gl-toggle :value="isEnabled" :label="__('Training mode')" label-position="hidden" />
Loading
Loading
import { GlTab } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { nextTick } from 'vue';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
import stubChildren from 'helpers/stub_children';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import SecurityConfigurationApp, { i18n } from '~/security_configuration/components/app.vue';
import AutoDevopsAlert from '~/security_configuration/components/auto_dev_ops_alert.vue';
import AutoDevopsEnabledAlert from '~/security_configuration/components/auto_dev_ops_enabled_alert.vue';
Loading
Loading
@@ -29,8 +27,6 @@ import {
REPORT_TYPE_LICENSE_COMPLIANCE,
REPORT_TYPE_SAST,
} from '~/vue_shared/security_reports/constants';
import waitForPromises from 'helpers/wait_for_promises';
import { securityTrainingProviders } from '../mock_data';
 
const upgradePath = '/upgrade';
const autoDevopsHelpPagePath = '/autoDevopsHelpPagePath';
Loading
Loading
@@ -39,21 +35,10 @@ const gitlabCiHistoryPath = 'test/historyPath';
const projectPath = 'namespace/project';
 
useLocalStorageSpy();
Vue.use(VueApollo);
 
describe('App component', () => {
let wrapper;
let userCalloutDismissSpy;
let mockApollo;
let mockSecurityTrainingProvidersData;
const mockResolvers = {
Query: {
securityTrainingProviders() {
return securityTrainingProviders;
},
},
};
 
const createComponent = ({
shouldShowCallout = true,
Loading
Loading
@@ -61,11 +46,9 @@ describe('App component', () => {
...propsData
}) => {
userCalloutDismissSpy = jest.fn();
mockApollo = createMockApollo([], mockResolvers);
 
wrapper = extendedWrapper(
mount(SecurityConfigurationApp, {
apolloProvider: mockApollo,
propsData,
provide: {
upgradePath,
Loading
Loading
@@ -148,14 +131,10 @@ describe('App component', () => {
 
afterEach(() => {
wrapper.destroy();
mockApollo = null;
});
 
describe('basic structure', () => {
beforeEach(() => {
mockSecurityTrainingProvidersData = jest.fn();
mockSecurityTrainingProvidersData.mockResolvedValue(securityTrainingProviders);
createComponent({
augmentedSecurityFeatures: securityFeaturesMock,
augmentedComplianceFeatures: complianceFeaturesMock,
Loading
Loading
@@ -204,9 +183,8 @@ describe('App component', () => {
expect(findSecurityViewHistoryLink().exists()).toBe(false);
});
 
it('renders training provider list with correct props', async () => {
await waitForPromises();
expect(findTrainingProviderList().props('providers')).toEqual(securityTrainingProviders);
it('renders TrainingProviderList component', () => {
expect(findTrainingProviderList().exists()).toBe(true);
});
});
 
Loading
Loading
import { 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 { securityTrainingProviders } from '../mock_data';
import waitForPromises from 'helpers/wait_for_promises';
import { securityTrainingProviders, mockResolvers } from '../mock_data';
 
const DEFAULT_PROPS = {
providers: securityTrainingProviders,
};
Vue.use(VueApollo);
 
describe('TrainingProviderList component', () => {
let wrapper;
let mockApollo;
let mockSecurityTrainingProvidersData;
const createComponent = () => {
mockApollo = createMockApollo([], mockResolvers);
 
const createComponent = (props = {}) => {
wrapper = shallowMount(TrainingProviderList, {
propsData: {
...DEFAULT_PROPS,
...props,
},
apolloProvider: mockApollo,
});
};
 
const waitForQueryToBeLoaded = () => waitForPromises();
const findCards = () => wrapper.findAllComponents(GlCard);
const findLinks = () => wrapper.findAllComponents(GlLink);
const findToggles = () => wrapper.findAllComponents(GlToggle);
const findLoader = () => wrapper.findComponent(GlSkeletonLoader);
 
beforeEach(() => {
mockSecurityTrainingProvidersData = jest.fn();
mockSecurityTrainingProvidersData.mockResolvedValue(securityTrainingProviders);
createComponent();
});
afterEach(() => {
wrapper.destroy();
mockApollo = null;
});
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(() => {
createComponent();
beforeEach(async () => {
await waitForQueryToBeLoaded();
});
 
it('renders correct amount of cards', () => {
expect(findCards()).toHaveLength(DEFAULT_PROPS.providers.length);
expect(findCards()).toHaveLength(securityTrainingProviders.length);
});
 
DEFAULT_PROPS.providers.forEach(({ name, description, url, isEnabled }, index) => {
securityTrainingProviders.forEach(({ name, description, url, isEnabled }, index) => {
it(`shows the name for card ${index}`, () => {
expect(findCards().at(index).text()).toContain(name);
});
Loading
Loading
@@ -56,25 +79,10 @@ describe('TrainingProviderList component', () => {
it(`shows the toggle with the correct value for card ${index}`, () => {
expect(findToggles().at(index).props('value')).toEqual(isEnabled);
});
});
});
describe('loading', () => {
beforeEach(() => {
createComponent({ loading: true });
});
 
it('shows the loader', () => {
expect(findLoader().exists()).toBe(true);
});
it('does not show the cards', () => {
expect(findCards().exists()).toBe(false);
});
it('does not show loader when not loading', () => {
createComponent({ loading: false });
expect(findLoader().exists()).toBe(false);
it('does not show loader when query is populated', () => {
expect(findLoader().exists()).toBe(false);
});
});
});
});
Loading
Loading
@@ -20,3 +20,11 @@ export const securityTrainingProvidersResponse = {
securityTrainingProviders,
},
};
export const mockResolvers = {
Query: {
securityTrainingProviders() {
return securityTrainingProviders;
},
},
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment