Commit d20c33e2 authored by Alexander Turinske's avatar Alexander Turinske

Add tests for unsupported yaml

- fromYaml tests
- removeUnnecessaryDashes tests
- policy drawer tests
- policy editor tests
- policy preview tests
parent 46091fe6
...@@ -174,7 +174,7 @@ const hasUnsupportedAttribute = (manifest) => { ...@@ -174,7 +174,7 @@ const hasUnsupportedAttribute = (manifest) => {
* @param {String} manifest the policy from the API request * @param {String} manifest the policy from the API request
* @returns {String} the policy without the initial dashes or the initial string * @returns {String} the policy without the initial dashes or the initial string
*/ */
export const removeInitialDashes = (manifest) => { export const removeUnnecessaryDashes = (manifest) => {
return manifest.replace('---\n', ''); return manifest.replace('---\n', '');
}; };
......
<script> <script>
import { GlFormTextarea } from '@gitlab/ui'; import { GlFormTextarea } from '@gitlab/ui';
import fromYaml, { removeInitialDashes } from './lib/from_yaml'; import fromYaml, { removeUnnecessaryDashes } from './lib/from_yaml';
import humanizeNetworkPolicy from './lib/humanize'; import humanizeNetworkPolicy from './lib/humanize';
import toYaml from './lib/to_yaml'; import toYaml from './lib/to_yaml';
import PolicyPreview from './policy_preview.vue'; import PolicyPreview from './policy_preview.vue';
...@@ -28,7 +28,7 @@ export default { ...@@ -28,7 +28,7 @@ export default {
return this.policy ? humanizeNetworkPolicy(this.policy) : this.policy; return this.policy ? humanizeNetworkPolicy(this.policy) : this.policy;
}, },
policyYaml() { policyYaml() {
return removeInitialDashes(this.value); return removeUnnecessaryDashes(this.value);
}, },
}, },
methods: { methods: {
......
...@@ -25,7 +25,7 @@ import { ...@@ -25,7 +25,7 @@ import {
PARSING_ERROR_MESSAGE, PARSING_ERROR_MESSAGE,
} from './constants'; } from './constants';
import DimDisableContainer from './dim_disable_container.vue'; import DimDisableContainer from './dim_disable_container.vue';
import fromYaml, { removeInitialDashes } from './lib/from_yaml'; import fromYaml, { removeUnnecessaryDashes } from './lib/from_yaml';
import humanizeNetworkPolicy from './lib/humanize'; import humanizeNetworkPolicy from './lib/humanize';
import { buildRule } from './lib/rules'; import { buildRule } from './lib/rules';
import toYaml from './lib/to_yaml'; import toYaml from './lib/to_yaml';
...@@ -90,9 +90,13 @@ export default { ...@@ -90,9 +90,13 @@ export default {
}; };
policy.labels = { [ProjectIdLabel]: this.projectId }; policy.labels = { [ProjectIdLabel]: this.projectId };
const yamlEditorValue = this.existingPolicy
? removeUnnecessaryDashes(this.existingPolicy.manifest)
: '';
return { return {
editorMode: EditorModeRule, editorMode: EditorModeRule,
yamlEditorValue: removeInitialDashes(this.existingPolicy?.manifest) || '', yamlEditorValue,
yamlEditorError: policy.error ? true : null, yamlEditorError: policy.error ? true : null,
policy, policy,
}; };
...@@ -245,7 +249,7 @@ export default { ...@@ -245,7 +249,7 @@ export default {
</gl-form-group> </gl-form-group>
</div> </div>
<div class="col-sm-6 col-md-6 col-lg-5 col-xl-4"> <div class="col-sm-6 col-md-6 col-lg-5 col-xl-4">
<gl-form-group :disabled="hasParsingError"> <gl-form-group :disabled="hasParsingError" data-testid="policy-name">
<gl-form-group <gl-form-group
:disabled="hasParsingError" :disabled="hasParsingError"
:label="s__('NetworkPolicies|Name')" :label="s__('NetworkPolicies|Name')"
...@@ -258,7 +262,7 @@ export default { ...@@ -258,7 +262,7 @@ export default {
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-10 col-lg-8 col-xl-6"> <div class="col-sm-12 col-md-10 col-lg-8 col-xl-6">
<gl-form-group :disabled="hasParsingError"> <gl-form-group :disabled="hasParsingError" data-testid="policy-description">
<gl-form-group :label="s__('NetworkPolicies|Description')" label-for="policyDescription"> <gl-form-group :label="s__('NetworkPolicies|Description')" label-for="policyDescription">
<gl-form-textarea id="policyDescription" v-model="policy.description" /> <gl-form-textarea id="policyDescription" v-model="policy.description" />
</gl-form-group> </gl-form-group>
...@@ -270,7 +274,7 @@ export default { ...@@ -270,7 +274,7 @@ export default {
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-auto"> <div class="col-md-auto">
<gl-form-group :disabled="hasParsingError"> <gl-form-group :disabled="hasParsingError" data-testid="policy-enable">
<gl-toggle v-model="policy.isEnabled" :label="$options.i18n.toggleLabel" /> <gl-toggle v-model="policy.isEnabled" :label="$options.i18n.toggleLabel" />
</gl-form-group> </gl-form-group>
</div> </div>
......
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PolicyDrawer component renders policy preview tabs 1`] = ` exports[`PolicyDrawer component supported YAML renders policy preview tabs 1`] = `
<div> <div>
<h4> <h4>
Policy description Policy description
...@@ -46,3 +46,29 @@ spec: ...@@ -46,3 +46,29 @@ spec:
/> />
</div> </div>
`; `;
exports[`PolicyDrawer component unsupported YAML renders policy preview tabs 1`] = `
<div>
<h4>
Policy description
</h4>
<h5
class="gl-mt-6"
>
Policy type
</h5>
<p>
Network Policy
</p>
<!---->
<policy-preview-stub
class="gl-mt-4"
initialtab="0"
policyyaml="unsupportedPrimaryKey: test"
/>
</div>
`;
...@@ -52,16 +52,18 @@ exports[`PolicyEditorApp component renders the policy editor layout 1`] = ` ...@@ -52,16 +52,18 @@ exports[`PolicyEditorApp component renders the policy editor layout 1`] = `
<div <div
class="col-sm-6 col-md-4 col-lg-3 col-xl-2" class="col-sm-6 col-md-4 col-lg-3 col-xl-2"
> >
<gl-form-group-stub <gl-form-group-stub>
label="Policy type" <gl-form-group-stub
label-for="policyType" label="Policy type"
> label-for="policyType"
<gl-form-select-stub >
disabled="" <gl-form-select-stub
id="policyType" disabled=""
options="[object Object]" id="policyType"
value="networkPolicy" options="[object Object]"
/> value="networkPolicy"
/>
</gl-form-group-stub>
</gl-form-group-stub> </gl-form-group-stub>
</div> </div>
...@@ -69,13 +71,17 @@ exports[`PolicyEditorApp component renders the policy editor layout 1`] = ` ...@@ -69,13 +71,17 @@ exports[`PolicyEditorApp component renders the policy editor layout 1`] = `
class="col-sm-6 col-md-6 col-lg-5 col-xl-4" class="col-sm-6 col-md-6 col-lg-5 col-xl-4"
> >
<gl-form-group-stub <gl-form-group-stub
label="Name" data-testid="policy-name"
label-for="policyName"
> >
<gl-form-input-stub <gl-form-group-stub
id="policyName" label="Name"
value="" label-for="policyName"
/> >
<gl-form-input-stub
id="policyName"
value=""
/>
</gl-form-group-stub>
</gl-form-group-stub> </gl-form-group-stub>
</div> </div>
</div> </div>
...@@ -87,14 +93,18 @@ exports[`PolicyEditorApp component renders the policy editor layout 1`] = ` ...@@ -87,14 +93,18 @@ exports[`PolicyEditorApp component renders the policy editor layout 1`] = `
class="col-sm-12 col-md-10 col-lg-8 col-xl-6" class="col-sm-12 col-md-10 col-lg-8 col-xl-6"
> >
<gl-form-group-stub <gl-form-group-stub
label="Description" data-testid="policy-description"
label-for="policyDescription"
> >
<gl-form-textarea-stub <gl-form-group-stub
id="policyDescription" label="Description"
noresize="true" label-for="policyDescription"
value="" >
/> <gl-form-textarea-stub
id="policyDescription"
noresize="true"
value=""
/>
</gl-form-group-stub>
</gl-form-group-stub> </gl-form-group-stub>
</div> </div>
</div> </div>
...@@ -111,7 +121,9 @@ exports[`PolicyEditorApp component renders the policy editor layout 1`] = ` ...@@ -111,7 +121,9 @@ exports[`PolicyEditorApp component renders the policy editor layout 1`] = `
<div <div
class="col-md-auto" class="col-md-auto"
> >
<gl-form-group-stub> <gl-form-group-stub
data-testid="policy-enable"
>
<gl-toggle-stub <gl-toggle-stub
label="Policy status" label="Policy status"
labelposition="top" labelposition="top"
......
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PolicyPreview component renders policy preview tabs 1`] = ` exports[`PolicyPreview component with policy description renders policy preview tabs 1`] = `
<gl-tabs-stub <gl-tabs-stub
contentclass="gl-pt-0" contentclass="gl-pt-0"
theme="indigo" theme="indigo"
......
...@@ -11,7 +11,9 @@ import { ...@@ -11,7 +11,9 @@ import {
RuleTypeFQDN, RuleTypeFQDN,
EntityTypes, EntityTypes,
} from 'ee/threat_monitoring/components/policy_editor/constants'; } from 'ee/threat_monitoring/components/policy_editor/constants';
import fromYaml from 'ee/threat_monitoring/components/policy_editor/lib/from_yaml'; import fromYaml, {
removeUnnecessaryDashes,
} from 'ee/threat_monitoring/components/policy_editor/lib/from_yaml';
import { buildRule } from 'ee/threat_monitoring/components/policy_editor/lib/rules'; import { buildRule } from 'ee/threat_monitoring/components/policy_editor/lib/rules';
import toYaml from 'ee/threat_monitoring/components/policy_editor/lib/to_yaml'; import toYaml from 'ee/threat_monitoring/components/policy_editor/lib/to_yaml';
...@@ -310,4 +312,36 @@ spec: ...@@ -310,4 +312,36 @@ spec:
}); });
}); });
}); });
describe('unsupported attributes', () => {
const unsupportedYaml = [
'unsupportedPrimaryKey: test',
'apiVersion: 1\nunsupportedPrimaryKey: test',
'unsupportedPrimaryKey: test\nkind: test',
'metadata:\n unsupportedMetaKey: test',
'spec:\n unsupportedSpecKey: test',
'spec:\n ingress:\n - unsupportedRuleKey: test',
'spec:\n engress:\n - toPorts:\n - unsupportedToPortKey: test',
'spec:\n ingress:\n - toPorts:\n - ports:\n - port: 80\n unsupportedPortKey: test',
];
it.each(unsupportedYaml)(
'returns the unsupported attributes object for YAML with unsupported attributes',
(manifest) => {
expect(fromYaml(manifest)).toStrictEqual({ error: true });
},
);
});
});
describe('removeUnnecessaryDashes', () => {
it.each`
input | output
${'---\none'} | ${'one'}
${'two'} | ${'two'}
${'--\nthree'} | ${'--\nthree'}
${'four---\n'} | ${'four'}
`('returns $output when used on $input', ({ input, output }) => {
expect(removeUnnecessaryDashes(input)).toBe(output);
});
}); });
...@@ -3,6 +3,7 @@ import { shallowMount } from '@vue/test-utils'; ...@@ -3,6 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import fromYaml from 'ee/threat_monitoring/components/policy_editor/lib/from_yaml'; import fromYaml from 'ee/threat_monitoring/components/policy_editor/lib/from_yaml';
import toYaml from 'ee/threat_monitoring/components/policy_editor/lib/to_yaml'; import toYaml from 'ee/threat_monitoring/components/policy_editor/lib/to_yaml';
import PolicyDrawer from 'ee/threat_monitoring/components/policy_editor/policy_drawer.vue'; import PolicyDrawer from 'ee/threat_monitoring/components/policy_editor/policy_drawer.vue';
import PolicyPreview from 'ee/threat_monitoring/components/policy_editor/policy_preview.vue';
describe('PolicyDrawer component', () => { describe('PolicyDrawer component', () => {
let wrapper; let wrapper;
...@@ -12,6 +13,10 @@ describe('PolicyDrawer component', () => { ...@@ -12,6 +13,10 @@ describe('PolicyDrawer component', () => {
endpointLabels: '', endpointLabels: '',
rules: [], rules: [],
}; };
const unsupportedYaml = 'unsupportedPrimaryKey: test';
const findPolicyPreview = () => wrapper.findComponent(PolicyPreview);
const findTextForm = () => wrapper.findComponent(GlFormTextarea);
const factory = ({ propsData } = {}) => { const factory = ({ propsData } = {}) => {
wrapper = shallowMount(PolicyDrawer, { wrapper = shallowMount(PolicyDrawer, {
...@@ -21,27 +26,62 @@ describe('PolicyDrawer component', () => { ...@@ -21,27 +26,62 @@ describe('PolicyDrawer component', () => {
}); });
}; };
beforeEach(() => {
factory({
propsData: {
value: toYaml(policy),
},
});
});
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
}); });
it('renders policy preview tabs', () => { describe('supported YAML', () => {
expect(wrapper.find('div').element).toMatchSnapshot(); beforeEach(() => {
factory({ propsData: { value: toYaml(policy) } });
});
it('renders policy preview tabs', () => {
expect(wrapper.find('div').element).toMatchSnapshot();
});
it('does render the policy description', () => {
expect(findTextForm().exists()).toBe(true);
expect(findTextForm().props()).toMatchObject({ value: 'test description' });
});
it('does render the policy preview', () => {
expect(findPolicyPreview().exists()).toBe(true);
expect(findPolicyPreview().props()).toStrictEqual({
initialTab: 1,
policyDescription: 'Deny all traffic',
policyYaml: toYaml(policy),
});
});
it('emits input event on description change', () => {
wrapper.find(GlFormTextarea).vm.$emit('input', 'new description');
expect(wrapper.emitted().input.length).toEqual(1);
const updatedPolicy = fromYaml(wrapper.emitted().input[0][0]);
expect(updatedPolicy.description).toEqual('new description');
});
}); });
it('emits input event on description change', () => { describe('unsupported YAML', () => {
wrapper.find(GlFormTextarea).vm.$emit('input', 'new description'); beforeEach(() => {
factory({ propsData: { value: unsupportedYaml } });
});
expect(wrapper.emitted().input.length).toEqual(1); it('renders policy preview tabs', () => {
const updatedPolicy = fromYaml(wrapper.emitted().input[0][0]); expect(wrapper.find('div').element).toMatchSnapshot();
expect(updatedPolicy.description).toEqual('new description'); });
it('does not render the policy description', () => {
expect(findTextForm().exists()).toBe(false);
});
it('does render the policy preview', () => {
expect(findPolicyPreview().exists()).toBe(true);
expect(findPolicyPreview().props()).toStrictEqual({
initialTab: 0,
policyDescription: null,
policyYaml: unsupportedYaml,
});
});
}); });
}); });
...@@ -15,6 +15,7 @@ import PolicyEditorApp from 'ee/threat_monitoring/components/policy_editor/polic ...@@ -15,6 +15,7 @@ import PolicyEditorApp from 'ee/threat_monitoring/components/policy_editor/polic
import PolicyPreview from 'ee/threat_monitoring/components/policy_editor/policy_preview.vue'; import PolicyPreview from 'ee/threat_monitoring/components/policy_editor/policy_preview.vue';
import PolicyRuleBuilder from 'ee/threat_monitoring/components/policy_editor/policy_rule_builder.vue'; import PolicyRuleBuilder from 'ee/threat_monitoring/components/policy_editor/policy_rule_builder.vue';
import createStore from 'ee/threat_monitoring/store'; import createStore from 'ee/threat_monitoring/store';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { redirectTo } from '~/lib/utils/url_utility'; import { redirectTo } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility'); jest.mock('~/lib/utils/url_utility');
...@@ -53,33 +54,38 @@ spec: ...@@ -53,33 +54,38 @@ spec:
jest.spyOn(store, 'dispatch').mockImplementation(() => Promise.resolve()); jest.spyOn(store, 'dispatch').mockImplementation(() => Promise.resolve());
wrapper = shallowMount(PolicyEditorApp, { wrapper = extendedWrapper(
propsData: { shallowMount(PolicyEditorApp, {
threatMonitoringPath: '/threat-monitoring', propsData: {
projectId: '21', threatMonitoringPath: '/threat-monitoring',
...propsData, projectId: '21',
}, ...propsData,
provide: { },
glFeatures: { threatMonitoringAlerts: false }, provide: {
...provide, glFeatures: { threatMonitoringAlerts: false },
}, ...provide,
store, },
data, store,
stubs: { NetworkPolicyEditor: true }, data,
}); stubs: { NetworkPolicyEditor: true },
}),
);
}; };
const findRuleEditor = () => wrapper.find('[data-testid="rule-editor"]'); const findRuleEditor = () => wrapper.findByTestId('rule-editor');
const findYamlEditor = () => wrapper.find('[data-testid="yaml-editor"]'); const findYamlEditor = () => wrapper.findByTestId('yaml-editor');
const findPreview = () => wrapper.find(PolicyPreview); const findPreview = () => wrapper.find(PolicyPreview);
const findAddRuleButton = () => wrapper.find('[data-testid="add-rule"]'); const findAddRuleButton = () => wrapper.findByTestId('add-rule');
const findYAMLParsingAlert = () => wrapper.find('[data-testid="parsing-alert"]'); const findYAMLParsingAlert = () => wrapper.findByTestId('parsing-alert');
const findNetworkPolicyEditor = () => wrapper.find('[data-testid="network-policy-editor"]'); const findNetworkPolicyEditor = () => wrapper.findByTestId('network-policy-editor');
const findPolicyAlertPicker = () => wrapper.find(PolicyAlertPicker); const findPolicyAlertPicker = () => wrapper.find(PolicyAlertPicker);
const findPolicyName = () => wrapper.find("[id='policyName']"); const findPolicyDescriptionContainer = () => wrapper.findByTestId('policy-description');
const findSavePolicy = () => wrapper.find("[data-testid='save-policy']"); const findPolicyEnableContainer = () => wrapper.findByTestId('policy-enable');
const findDeletePolicy = () => wrapper.find("[data-testid='delete-policy']"); const findPolicyNameContainer = () => wrapper.findByTestId('policy-name');
const findEditorModeToggle = () => wrapper.find("[data-testid='editor-mode']"); const findPolicyName = () => findPolicyNameContainer().find("[id='policyName']");
const findSavePolicy = () => wrapper.findByTestId('save-policy');
const findDeletePolicy = () => wrapper.findByTestId('delete-policy');
const findEditorModeToggle = () => wrapper.findByTestId('editor-mode');
const modifyPolicyAlert = async ({ isAlertEnabled }) => { const modifyPolicyAlert = async ({ isAlertEnabled }) => {
const policyAlertPicker = findPolicyAlertPicker(); const policyAlertPicker = findPolicyAlertPicker();
...@@ -213,7 +219,7 @@ spec: ...@@ -213,7 +219,7 @@ spec:
beforeEach(() => { beforeEach(() => {
initialValue = findPreview().props('policyDescription'); initialValue = findPreview().props('policyDescription');
wrapper.find("[data-testid='add-rule']").vm.$emit('click'); wrapper.findByTestId('add-rule').vm.$emit('click');
}); });
it('updates policy description preview', () => { it('updates policy description preview', () => {
...@@ -273,20 +279,32 @@ spec: ...@@ -273,20 +279,32 @@ spec:
}); });
}); });
it('disables policy name field', () => {
expect(findPolicyNameContainer().attributes().disabled).toBe('true');
});
it('disables policy description field', () => {
expect(findPolicyDescriptionContainer().attributes().disabled).toBe('true');
});
it('disables policy enable/disable toggle', () => {
expect(findPolicyEnableContainer().attributes().disabled).toBe('true');
});
it('renders parsing error alert', () => { it('renders parsing error alert', () => {
expect(findYAMLParsingAlert().exists()).toBe(true); expect(findYAMLParsingAlert().exists()).toBe(true);
}); });
it('disables rule builder', () => { it('disables rule builder', () => {
expect(wrapper.find("[data-testid='rule-builder-container']").props().disabled).toBe(true); expect(wrapper.findByTestId('rule-builder-container').props().disabled).toBe(true);
}); });
it('disables action picker', () => { it('disables action picker', () => {
expect(wrapper.find("[data-testid='policy-action-container']").props().disabled).toBe(true); expect(wrapper.findByTestId('policy-action-container').props().disabled).toBe(true);
}); });
it('disables policy preview', () => { it('disables policy preview', () => {
expect(wrapper.find("[data-testid='policy-preview-container']").props().disabled).toBe(true); expect(wrapper.findByTestId('policy-preview-container').props().disabled).toBe(true);
}); });
it('does not update yaml editor value on switch to yaml editor', async () => { it('does not update yaml editor value on switch to yaml editor', async () => {
......
import { GlTabs } from '@gitlab/ui'; import { GlAlert, GlTabs } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import PolicyPreview from 'ee/threat_monitoring/components/policy_editor/policy_preview.vue'; import PolicyPreview from 'ee/threat_monitoring/components/policy_editor/policy_preview.vue';
describe('PolicyPreview component', () => { describe('PolicyPreview component', () => {
let wrapper; let wrapper;
const findAlert = () => wrapper.findComponent(GlAlert);
const findTabs = () => wrapper.findComponent(GlTabs);
const factory = ({ propsData } = {}) => { const factory = ({ propsData } = {}) => {
wrapper = shallowMount(PolicyPreview, { wrapper = shallowMount(PolicyPreview, {
propsData: { propsData: {
...@@ -13,36 +16,57 @@ describe('PolicyPreview component', () => { ...@@ -13,36 +16,57 @@ describe('PolicyPreview component', () => {
}); });
}; };
beforeEach(() => {
factory({
propsData: {
policyYaml: 'foo',
policyDescription: '<strong>bar</strong><br><div>test</div><script></script>',
},
});
});
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
}); });
it('renders policy preview tabs', () => { describe('with policy description', () => {
expect(wrapper.find(GlTabs).element).toMatchSnapshot(); beforeEach(() => {
factory({
propsData: {
policyYaml: 'foo',
policyDescription: '<strong>bar</strong><br><div>test</div><script></script>',
},
});
});
it('renders policy preview tabs', () => {
expect(findTabs().element).toMatchSnapshot();
});
it('renders the first tab', () => {
expect(findTabs().attributes().value).toEqual('0');
});
it('does not render the unsupported attributes alert', () => {
expect(findAlert().exists()).toBe(false);
});
describe('initial tab', () => {
it('selects initial tab', () => {
factory({
propsData: {
policyYaml: 'foo',
policyDescription: 'bar',
initialTab: 1,
},
});
expect(findTabs().attributes().value).toEqual('1');
});
});
}); });
describe('with initialTab', () => { describe('without policy description', () => {
beforeEach(() => { beforeEach(() => {
factory({ factory({
propsData: { propsData: {
policyYaml: 'foo', policyYaml: 'foo',
policyDescription: 'bar',
initialTab: 1,
}, },
}); });
}); });
it('selects initial tab', () => { it('does render the unsupported attributes alert', () => {
expect(wrapper.find(GlTabs).attributes().value).toEqual('1'); expect(findAlert().exists()).toBe(true);
}); });
}); });
}); });
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