foreman_openscap 8.0.2 → 9.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -1
  3. data/app/services/foreman_openscap/client_config/ansible.rb +1 -10
  4. data/config/initializers/inflections.rb +0 -2
  5. data/config/routes.rb +0 -15
  6. data/db/migrate/20240313111822_drop_oval.rb +17 -0
  7. data/lib/foreman_openscap/engine.rb +2 -56
  8. data/lib/foreman_openscap/version.rb +1 -1
  9. data/test/factories/compliance_host_factory.rb +0 -12
  10. data/test/test_plugin_helper.rb +0 -2
  11. data/webpack/global_index.js +0 -4
  12. metadata +7 -168
  13. data/app/controllers/api/v2/compliance/oval_contents_controller.rb +0 -72
  14. data/app/controllers/api/v2/compliance/oval_policies_controller.rb +0 -111
  15. data/app/controllers/api/v2/compliance/oval_reports_controller.rb +0 -47
  16. data/app/controllers/concerns/foreman/controller/parameters/oval_content.rb +0 -22
  17. data/app/controllers/concerns/foreman/controller/parameters/oval_policy.rb +0 -22
  18. data/app/graphql/mutations/oval_contents/delete.rb +0 -9
  19. data/app/graphql/mutations/oval_policies/create.rb +0 -33
  20. data/app/graphql/mutations/oval_policies/delete.rb +0 -9
  21. data/app/graphql/mutations/oval_policies/update.rb +0 -15
  22. data/app/graphql/types/cve.rb +0 -17
  23. data/app/graphql/types/oval_check.rb +0 -11
  24. data/app/graphql/types/oval_content.rb +0 -19
  25. data/app/graphql/types/oval_policy.rb +0 -24
  26. data/app/models/concerns/foreman_openscap/oval_facet_host_extensions.rb +0 -38
  27. data/app/models/concerns/foreman_openscap/oval_facet_hostgroup_extensions.rb +0 -31
  28. data/app/models/foreman_openscap/cve.rb +0 -23
  29. data/app/models/foreman_openscap/host/oval_facet.rb +0 -14
  30. data/app/models/foreman_openscap/host_cve.rb +0 -7
  31. data/app/models/foreman_openscap/hostgroup/oval_facet.rb +0 -14
  32. data/app/models/foreman_openscap/hostgroup_oval_facet_oval_policy.rb +0 -6
  33. data/app/models/foreman_openscap/oval_content.rb +0 -28
  34. data/app/models/foreman_openscap/oval_facet_oval_policy.rb +0 -6
  35. data/app/models/foreman_openscap/oval_policy.rb +0 -54
  36. data/app/models/foreman_openscap/oval_status.rb +0 -45
  37. data/app/services/foreman_openscap/oval/check_collection.rb +0 -45
  38. data/app/services/foreman_openscap/oval/configure.rb +0 -83
  39. data/app/services/foreman_openscap/oval/cves.rb +0 -41
  40. data/app/services/foreman_openscap/oval/setup.rb +0 -93
  41. data/app/services/foreman_openscap/oval/setup_check.rb +0 -58
  42. data/app/services/foreman_openscap/oval/sync_oval_contents.rb +0 -42
  43. data/app/views/api/v2/compliance/oval_contents/base.json.rabl +0 -6
  44. data/app/views/api/v2/compliance/oval_contents/create.json.rabl +0 -3
  45. data/app/views/api/v2/compliance/oval_contents/destroy.json.rabl +0 -3
  46. data/app/views/api/v2/compliance/oval_contents/index.json.rabl +0 -3
  47. data/app/views/api/v2/compliance/oval_contents/show.json.rabl +0 -3
  48. data/app/views/api/v2/compliance/oval_contents/sync.json.rabl +0 -3
  49. data/app/views/api/v2/compliance/oval_contents/sync_result.json.rabl +0 -11
  50. data/app/views/api/v2/compliance/oval_contents/update.json.rabl +0 -3
  51. data/app/views/api/v2/compliance/oval_policies/create.json.rabl +0 -3
  52. data/app/views/api/v2/compliance/oval_policies/index.json.rabl +0 -3
  53. data/app/views/api/v2/compliance/oval_policies/main.json.rabl +0 -15
  54. data/app/views/api/v2/compliance/oval_policies/show.json.rabl +0 -3
  55. data/app/views/job_templates/run_oval_scans.erb +0 -24
  56. data/locale/cs_CZ/foreman_openscap.edit.po +0 -1863
  57. data/locale/cs_CZ/foreman_openscap.po.time_stamp +0 -0
  58. data/locale/de/foreman_openscap.edit.po +0 -1873
  59. data/locale/de/foreman_openscap.po.time_stamp +0 -0
  60. data/locale/en/foreman_openscap.edit.po +0 -1863
  61. data/locale/en/foreman_openscap.po.time_stamp +0 -0
  62. data/locale/en_GB/foreman_openscap.edit.po +0 -1863
  63. data/locale/en_GB/foreman_openscap.po.time_stamp +0 -0
  64. data/locale/es/foreman_openscap.edit.po +0 -1868
  65. data/locale/es/foreman_openscap.po.time_stamp +0 -0
  66. data/locale/fr/foreman_openscap.edit.po +0 -1874
  67. data/locale/fr/foreman_openscap.po.time_stamp +0 -0
  68. data/locale/gl/foreman_openscap.edit.po +0 -1863
  69. data/locale/gl/foreman_openscap.po.time_stamp +0 -0
  70. data/locale/it/foreman_openscap.edit.po +0 -1865
  71. data/locale/it/foreman_openscap.po.time_stamp +0 -0
  72. data/locale/ja/foreman_openscap.edit.po +0 -1869
  73. data/locale/ja/foreman_openscap.po.time_stamp +0 -0
  74. data/locale/ka/foreman_openscap.edit.po +0 -1863
  75. data/locale/ka/foreman_openscap.po.time_stamp +0 -0
  76. data/locale/ko/foreman_openscap.edit.po +0 -1863
  77. data/locale/ko/foreman_openscap.po.time_stamp +0 -0
  78. data/locale/pt_BR/foreman_openscap.edit.po +0 -1873
  79. data/locale/pt_BR/foreman_openscap.po.time_stamp +0 -0
  80. data/locale/ru/foreman_openscap.edit.po +0 -1867
  81. data/locale/ru/foreman_openscap.po.time_stamp +0 -0
  82. data/locale/sv_SE/foreman_openscap.edit.po +0 -1863
  83. data/locale/sv_SE/foreman_openscap.po.time_stamp +0 -0
  84. data/locale/zh_CN/foreman_openscap.edit.po +0 -1868
  85. data/locale/zh_CN/foreman_openscap.po.time_stamp +0 -0
  86. data/locale/zh_TW/foreman_openscap.edit.po +0 -1864
  87. data/locale/zh_TW/foreman_openscap.po.time_stamp +0 -0
  88. data/test/factories/oval_content_factory.rb +0 -7
  89. data/test/factories/oval_policy_factory.rb +0 -9
  90. data/test/fixtures/cve_fixtures.rb +0 -104
  91. data/test/functional/api/v2/compliance/oval_contents_controller_test.rb +0 -39
  92. data/test/functional/api/v2/compliance/oval_policies_controller_test.rb +0 -141
  93. data/test/functional/api/v2/compliance/oval_reports_controller_test.rb +0 -32
  94. data/test/graphql/mutations/oval_policies/delete_mutation_test.rb +0 -63
  95. data/test/graphql/queries/oval_content_query_test.rb +0 -29
  96. data/test/graphql/queries/oval_contents_query_test.rb +0 -35
  97. data/test/graphql/queries/oval_policies_query_test.rb +0 -35
  98. data/test/unit/oval_host_test.rb +0 -45
  99. data/test/unit/oval_policy_test.rb +0 -133
  100. data/test/unit/oval_status_test.rb +0 -47
  101. data/test/unit/services/oval/cves_test.rb +0 -81
  102. data/test/unit/services/oval/setup_check_test.rb +0 -37
  103. data/test/unit/services/oval/setup_test.rb +0 -87
  104. data/webpack/graphql/mutations/createOvalPolicy.gql +0 -22
  105. data/webpack/graphql/mutations/deleteOvalContent.gql +0 -9
  106. data/webpack/graphql/mutations/deleteOvalPolicy.gql +0 -9
  107. data/webpack/graphql/mutations/updateOvalPolicy.gql +0 -14
  108. data/webpack/graphql/queries/currentUserAttributes.gql +0 -11
  109. data/webpack/graphql/queries/cves.gql +0 -23
  110. data/webpack/graphql/queries/hostgroups.gql +0 -14
  111. data/webpack/graphql/queries/ovalContent.gql +0 -8
  112. data/webpack/graphql/queries/ovalContents.gql +0 -19
  113. data/webpack/graphql/queries/ovalPolicies.gql +0 -20
  114. data/webpack/graphql/queries/ovalPolicy.gql +0 -29
  115. data/webpack/helpers/pathsHelper.js +0 -29
  116. data/webpack/routes/OvalContents/OvalContentsIndex/OvalContentsIndex.js +0 -71
  117. data/webpack/routes/OvalContents/OvalContentsIndex/OvalContentsTable.js +0 -83
  118. data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsDestroy.fixtures.js +0 -105
  119. data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsDestroy.test.js +0 -124
  120. data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.fixtures.js +0 -127
  121. data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.test.js +0 -89
  122. data/webpack/routes/OvalContents/OvalContentsIndex/index.js +0 -13
  123. data/webpack/routes/OvalContents/OvalContentsNew/OvalContentsNew.js +0 -138
  124. data/webpack/routes/OvalContents/OvalContentsNew/OvalContentsNew.scss +0 -3
  125. data/webpack/routes/OvalContents/OvalContentsNew/OvalContentsNewHelper.js +0 -73
  126. data/webpack/routes/OvalContents/OvalContentsNew/__tests__/OvalContentsNew.test.js +0 -104
  127. data/webpack/routes/OvalContents/OvalContentsNew/index.js +0 -13
  128. data/webpack/routes/OvalContents/OvalContentsShow/OvalContentsShow.js +0 -62
  129. data/webpack/routes/OvalContents/OvalContentsShow/OvalContentsShow.test.js +0 -45
  130. data/webpack/routes/OvalContents/OvalContentsShow/OvalContentsShowHelper.js +0 -0
  131. data/webpack/routes/OvalContents/OvalContentsShow/index.js +0 -35
  132. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesIndex.js +0 -62
  133. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesTable.js +0 -74
  134. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesDestroy.fixtures.js +0 -101
  135. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesDestroy.test.js +0 -117
  136. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.fixtures.js +0 -111
  137. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.test.js +0 -81
  138. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/index.js +0 -13
  139. data/webpack/routes/OvalPolicies/OvalPoliciesNew/HostgroupSelect.js +0 -135
  140. data/webpack/routes/OvalPolicies/OvalPoliciesNew/NewOvalPolicyForm.js +0 -119
  141. data/webpack/routes/OvalPolicies/OvalPoliciesNew/NewOvalPolicyFormHelpers.js +0 -107
  142. data/webpack/routes/OvalPolicies/OvalPoliciesNew/OvalPoliciesNew.js +0 -32
  143. data/webpack/routes/OvalPolicies/OvalPoliciesNew/__tests__/OvalPoliciesNew.fixtures.js +0 -147
  144. data/webpack/routes/OvalPolicies/OvalPoliciesNew/__tests__/OvalPoliciesNew.test.js +0 -172
  145. data/webpack/routes/OvalPolicies/OvalPoliciesNew/index.js +0 -11
  146. data/webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTab.js +0 -49
  147. data/webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTable.js +0 -63
  148. data/webpack/routes/OvalPolicies/OvalPoliciesShow/DetailsTab.js +0 -87
  149. data/webpack/routes/OvalPolicies/OvalPoliciesShow/HostgroupsTab.js +0 -49
  150. data/webpack/routes/OvalPolicies/OvalPoliciesShow/HostgroupsTable.js +0 -38
  151. data/webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShow.js +0 -82
  152. data/webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShowHelper.js +0 -117
  153. data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesEdit.fixtures.js +0 -48
  154. data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesEdit.test.js +0 -202
  155. data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.fixtures.js +0 -124
  156. data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.test.js +0 -172
  157. data/webpack/routes/OvalPolicies/OvalPoliciesShow/index.js +0 -39
  158. data/webpack/routes/routes.js +0 -49
@@ -1,117 +0,0 @@
1
- import { translate as __, sprintf } from 'foremanReact/common/I18n';
2
- import { decodeModelId } from '../../../helpers/globalIdHelper';
3
- import { addSearch } from '../../../helpers/pageParamsHelper';
4
- import { newJobPath } from '../../../helpers/pathsHelper';
5
-
6
- export const policySchedule = policy => {
7
- switch (policy.period) {
8
- case 'weekly':
9
- return sprintf(__('Weekly, on %s'), policy.weekday);
10
- case 'monthly':
11
- return sprintf(__('Monthly, day of month: %s'), policy.dayOfMonth);
12
- case 'custom':
13
- return sprintf(__('Custom cron: %s'), policy.cronLine);
14
- default:
15
- return __('Unknown schedule');
16
- }
17
- };
18
-
19
- const targetingScopedSearchQuery = policy => {
20
- const hgIds = policy.hostgroups.nodes.reduce((memo, hg) => {
21
- const ids = [decodeModelId(hg)].concat(
22
- hg.descendants.nodes.map(decodeModelId)
23
- );
24
- return ids.reduce(
25
- (acc, id) => (acc.includes(id) ? acc : [...acc, id]),
26
- memo
27
- );
28
- }, []);
29
-
30
- if (hgIds.length === 0) {
31
- return '';
32
- }
33
-
34
- return `hostgroup_id ^ (${hgIds.join(' ')})`;
35
- };
36
-
37
- export const newJobFormPath = (policy, policyId) =>
38
- addSearch(newJobPath, {
39
- feature: 'foreman_openscap_run_oval_scans',
40
- host_ids: targetingScopedSearchQuery(policy),
41
- 'inputs[oval_policies]': policyId,
42
- });
43
-
44
- const policyToAttrs = (policy, attrs) =>
45
- Object.entries(policy).reduce((memo, [key, value]) => {
46
- if (attrs.includes(key)) {
47
- memo[key] = value;
48
- }
49
- return memo;
50
- }, {});
51
-
52
- const onUpdateSuccess = (
53
- closeEditable,
54
- stopSubmitting,
55
- showToast,
56
- attr,
57
- onValidationError
58
- ) => result => {
59
- const { errors } = result.data.updateOvalPolicy;
60
- if (Array.isArray(errors) && errors.length > 0) {
61
- stopSubmitting();
62
- if (
63
- errors.length === 1 &&
64
- errors[0].path.join(' ') === `attributes ${attr}`
65
- ) {
66
- onValidationError(errors[0].message);
67
- } else {
68
- showToast({
69
- type: 'error',
70
- message: formatError(joinErrors(errors)),
71
- });
72
- }
73
- } else {
74
- closeEditable();
75
- showToast({
76
- type: 'success',
77
- message: __('OVAL policy was successfully updated.'),
78
- });
79
- }
80
- };
81
-
82
- const formatError = error =>
83
- sprintf(
84
- __('There was a following error when updating OVAL policy: %s'),
85
- error
86
- );
87
-
88
- const joinErrors = errors => errors.map(err => err.message).join(', ');
89
-
90
- const onUpdateError = (showToast, stopSubmitting) => error => {
91
- stopSubmitting();
92
- showToast({ type: 'error', message: formatError(error.message) });
93
- };
94
-
95
- export const onAttrUpdate = (attr, policy, callMutation, showToast) => (
96
- newValue,
97
- closeEditable,
98
- stopSubmitting,
99
- onValidationError
100
- ) => {
101
- const vars = policyToAttrs(policy, ['id', 'name', 'description', 'cronLine']);
102
- vars[attr] = newValue;
103
- return (
104
- callMutation({ variables: vars })
105
- // eslint-disable-next-line promise/prefer-await-to-then
106
- .then(
107
- onUpdateSuccess(
108
- closeEditable,
109
- stopSubmitting,
110
- showToast,
111
- attr,
112
- onValidationError
113
- )
114
- )
115
- .catch(onUpdateError(showToast, stopSubmitting))
116
- );
117
- };
@@ -1,48 +0,0 @@
1
- import { mockFactory } from '../../../../testHelper';
2
- import updateOvalPolicyMutation from '../../../../graphql/mutations/updateOvalPolicy.gql';
3
- import { ovalPolicy } from './OvalPoliciesShow.fixtures';
4
-
5
- const updateOvalPolicyMockFactory = mockFactory(
6
- 'updateOvalPolicy',
7
- updateOvalPolicyMutation
8
- );
9
-
10
- export const updatedName = 'updated policy name';
11
-
12
- const variables = {
13
- id: ovalPolicy.id,
14
- name: updatedName,
15
- cronLine: ovalPolicy.cronLine,
16
- description: ovalPolicy.description,
17
- };
18
- const responsePolicy = {
19
- ovalPolicy: {
20
- __typename: 'ForemanOpenscap::OvalPolicy',
21
- id: ovalPolicy.id,
22
- name: updatedName,
23
- description: ovalPolicy.description,
24
- cronLine: ovalPolicy.cronLine,
25
- },
26
- errors: [],
27
- };
28
-
29
- export const policyUpdateMock = updateOvalPolicyMockFactory(
30
- variables,
31
- responsePolicy
32
- );
33
-
34
- export const policyUpdateErrorMock = updateOvalPolicyMockFactory(
35
- variables,
36
- responsePolicy,
37
- { errors: [{ message: 'This is an unexpected failure.' }] }
38
- );
39
-
40
- export const policyUpdateValidationMock = updateOvalPolicyMockFactory(
41
- variables,
42
- {
43
- ovalPolicy,
44
- errors: [
45
- { path: ['attributes', 'name'], message: 'has already been taken' },
46
- ],
47
- }
48
- );
@@ -1,202 +0,0 @@
1
- import React from 'react';
2
-
3
- import { render, screen, waitFor } from '@testing-library/react';
4
- import '@testing-library/jest-dom';
5
- import userEvent from '@testing-library/user-event';
6
-
7
- import OvalPoliciesShow from '../';
8
- import {
9
- historyMock,
10
- ovalPolicyId,
11
- policyDetailMock,
12
- policyEditPermissionsMock,
13
- ovalPolicy,
14
- } from './OvalPoliciesShow.fixtures';
15
- import {
16
- policyUpdateMock,
17
- policyUpdateErrorMock,
18
- policyUpdateValidationMock,
19
- updatedName,
20
- } from './OvalPoliciesEdit.fixtures';
21
- import { ovalPoliciesShowPath } from '../../../../helpers/pathsHelper';
22
-
23
- import {
24
- withMockedProvider,
25
- tick,
26
- withRouter,
27
- withRedux,
28
- } from '../../../../testHelper';
29
-
30
- import * as toasts from '../../../../helpers/toastHelper';
31
-
32
- const TestComponent = withRouter(
33
- withRedux(withMockedProvider(OvalPoliciesShow))
34
- );
35
-
36
- describe('OvalPoliciesShow', () => {
37
- it('should open and close inline edit for name', async () => {
38
- render(
39
- <TestComponent
40
- history={historyMock}
41
- match={{
42
- params: { id: ovalPolicyId, tab: 'details' },
43
- path: ovalPoliciesShowPath,
44
- }}
45
- mocks={policyDetailMock}
46
- />
47
- );
48
- await waitFor(tick);
49
- userEvent.click(screen.getByRole('button', { name: 'edit name' }));
50
- userEvent.clear(screen.getByLabelText(/name text input/));
51
- userEvent.type(screen.getByLabelText(/name text input/), 'foo');
52
- expect(screen.getByLabelText(/name text input/)).toHaveAttribute(
53
- 'value',
54
- 'foo'
55
- );
56
- userEvent.click(
57
- screen.getByRole('button', { name: 'cancel editing name' })
58
- );
59
- expect(screen.queryByText('foo')).not.toBeInTheDocument();
60
- });
61
- it('should update policy name', async () => {
62
- const showToast = jest.fn();
63
- jest.spyOn(toasts, 'showToast').mockImplementation(() => showToast);
64
-
65
- const { container } = render(
66
- <TestComponent
67
- history={historyMock}
68
- match={{
69
- params: { id: ovalPolicyId, tab: 'details' },
70
- path: ovalPoliciesShowPath,
71
- }}
72
- mocks={policyDetailMock.concat(policyUpdateMock)}
73
- />
74
- );
75
- await waitFor(tick);
76
- const editBtn = screen.getByRole('button', { name: 'edit name' });
77
- expect(editBtn).toBeInTheDocument();
78
- expect(
79
- screen.queryByRole('button', { name: 'submit name' })
80
- ).not.toBeInTheDocument();
81
-
82
- userEvent.click(editBtn);
83
- expect(
84
- screen.queryByRole('button', { name: 'edit name' })
85
- ).not.toBeInTheDocument();
86
- const inputField = screen.getByLabelText(/name text input/);
87
- const submitBtn = screen.getByRole('button', { name: 'submit name' });
88
- const cancelBtn = screen.getByRole('button', {
89
- name: 'cancel editing name',
90
- });
91
-
92
- userEvent.clear(inputField);
93
- userEvent.type(inputField, updatedName);
94
- userEvent.click(submitBtn);
95
- expect(inputField).toBeDisabled();
96
- expect(submitBtn).toBeDisabled();
97
- expect(cancelBtn).toBeDisabled();
98
- const spinner = container.querySelector('#edit-name-spinner');
99
- expect(spinner).toBeInTheDocument();
100
- await waitFor(tick);
101
- expect(showToast).toHaveBeenCalledWith({
102
- type: 'success',
103
- message: 'OVAL policy was successfully updated.',
104
- });
105
-
106
- expect(inputField).not.toBeInTheDocument();
107
- expect(editBtn).toBeInTheDocument();
108
- expect(cancelBtn).not.toBeInTheDocument();
109
- expect(
110
- screen.queryByRole('button', { name: 'submit name' })
111
- ).not.toBeInTheDocument();
112
- await waitFor(tick);
113
- expect(screen.getAllByText(updatedName).pop()).toBeInTheDocument();
114
- });
115
- it('should show unexpected errors', async () => {
116
- const showToast = jest.fn();
117
- jest.spyOn(toasts, 'showToast').mockImplementation(() => showToast);
118
-
119
- render(
120
- <TestComponent
121
- history={historyMock}
122
- match={{
123
- params: { id: ovalPolicyId, tab: 'details' },
124
- path: ovalPoliciesShowPath,
125
- }}
126
- mocks={policyDetailMock.concat(policyUpdateErrorMock)}
127
- />
128
- );
129
- await waitFor(tick);
130
- const editBtn = screen.getByRole('button', { name: 'edit name' });
131
- userEvent.click(editBtn);
132
- const inputField = screen.getByLabelText(/name text input/);
133
- userEvent.clear(inputField);
134
- userEvent.type(inputField, updatedName);
135
- userEvent.click(screen.getByRole('button', { name: 'submit name' }));
136
- await waitFor(tick);
137
- expect(showToast).toHaveBeenCalledWith({
138
- type: 'error',
139
- message:
140
- 'There was a following error when updating OVAL policy: This is an unexpected failure.',
141
- });
142
- expect(inputField).toBeInTheDocument();
143
- expect(inputField).not.toBeDisabled();
144
- expect(screen.getByText(ovalPolicy.name)).toBeInTheDocument();
145
- });
146
- it('should show validation errors', async () => {
147
- const showToast = jest.fn();
148
- jest.spyOn(toasts, 'showToast').mockImplementation(() => showToast);
149
-
150
- const { container } = render(
151
- <TestComponent
152
- history={historyMock}
153
- match={{
154
- params: { id: ovalPolicyId, tab: 'details' },
155
- path: ovalPoliciesShowPath,
156
- }}
157
- mocks={policyDetailMock.concat(policyUpdateValidationMock)}
158
- />
159
- );
160
- await waitFor(tick);
161
- const editBtn = screen.getByRole('button', { name: 'edit name' });
162
- userEvent.click(editBtn);
163
- const inputField = screen.getByLabelText(/name text input/);
164
- userEvent.clear(inputField);
165
- userEvent.type(inputField, updatedName);
166
- userEvent.click(screen.getByRole('button', { name: 'submit name' }));
167
- await waitFor(tick);
168
- expect(inputField).toBeInTheDocument();
169
- expect(inputField).not.toBeDisabled();
170
- expect(
171
- container.querySelector('#edit-name-spinner')
172
- ).not.toBeInTheDocument();
173
- expect(screen.getByText(ovalPolicy.name)).toBeInTheDocument();
174
- expect(screen.getByText('has already been taken')).toBeInTheDocument();
175
- userEvent.click(
176
- screen.getByRole('button', { name: 'cancel editing name' })
177
- );
178
- userEvent.click(editBtn);
179
- expect(
180
- screen.queryByText('has already been taken')
181
- ).not.toBeInTheDocument();
182
- });
183
- it('should not show edit btns when user is not allowed to edit', async () => {
184
- render(
185
- <TestComponent
186
- history={historyMock}
187
- match={{
188
- params: { id: ovalPolicyId, tab: 'details' },
189
- path: ovalPoliciesShowPath,
190
- }}
191
- mocks={policyEditPermissionsMock}
192
- />
193
- );
194
- await waitFor(tick);
195
- expect(
196
- screen.queryByRole('button', { name: 'edit name' })
197
- ).not.toBeInTheDocument();
198
- expect(
199
- screen.queryByRole('button', { name: 'edit description' })
200
- ).not.toBeInTheDocument();
201
- });
202
- });
@@ -1,124 +0,0 @@
1
- import { mockFactory, admin, intruder, viewer } from '../../../../testHelper';
2
- import ovalPolicyQuery from '../../../../graphql/queries/ovalPolicy.gql';
3
- import cvesQuery from '../../../../graphql/queries/cves.gql';
4
- import hostgroupsQuery from '../../../../graphql/queries/hostgroups.gql';
5
-
6
- const policyDetailMockFactory = mockFactory('ovalPolicy', ovalPolicyQuery);
7
- const cvesMockFactory = mockFactory('cves', cvesQuery);
8
- const hostgroupsMockFactory = mockFactory('hostgroups', hostgroupsQuery);
9
-
10
- export const ovalPolicy = {
11
- __typename: 'ForemanOpenscap::OvalPolicy',
12
- id: 'MDE6Rm9yZW1hbk9wZW5zY2FwOjpPdmFsUG9saWN5LTM=',
13
- name: 'Third policy',
14
- period: 'weekly',
15
- cronLine: null,
16
- weekday: 'tuesday',
17
- dayOfMonth: null,
18
- description: 'A very strict policy',
19
- meta: {
20
- canEdit: true,
21
- },
22
- hostgroups: {
23
- nodes: [
24
- {
25
- id: 'MDE6SG9zdGdyb3VwLTQ=',
26
- name: 'oval hg',
27
- descendants: {
28
- nodes: [
29
- { id: 'MDE6SG9zdGdyb3VwLTEw' },
30
- { id: 'MDE6SG9zdGdyb3VwLTEy' },
31
- { id: 'MDE6SG9zdGdyb3VwLTEx' },
32
- ],
33
- },
34
- },
35
- ],
36
- },
37
- };
38
-
39
- const noEditPolicy = { ...ovalPolicy, meta: { canEdit: false } };
40
-
41
- const cvesResult = {
42
- totalCount: 1,
43
- nodes: [
44
- {
45
- id: 'MDE6Rm9yZW1hbk9wZW5zY2FwOjpDdmUtMjY3',
46
- refId: 'CVE-2020-14365',
47
- refUrl: 'https://access.redhat.com/security/cve/CVE-2020-14365',
48
- definitionId: 'oval:com.redhat.rhsa:def:20203601',
49
- hasErrata: true,
50
- hosts: {
51
- nodes: [
52
- {
53
- id: 'MDE6SG9zdC0z',
54
- name: 'centos-random.example.com',
55
- },
56
- ],
57
- },
58
- },
59
- ],
60
- };
61
-
62
- const hostgroupsResult = {
63
- totalCount: 2,
64
- nodes: [
65
- {
66
- id: 'MDE6SG9zdGdyb3VwLTQ=',
67
- name: 'first hostgroup',
68
- },
69
- {
70
- id: 'MDE6SG9zdGdyb3VwLTEy',
71
- name: 'second hostgroup',
72
- },
73
- ],
74
- };
75
-
76
- export const ovalPolicyId = 3;
77
-
78
- export const pushMock = jest.fn();
79
-
80
- export const historyMock = {
81
- location: {
82
- search: '',
83
- },
84
- push: pushMock,
85
- };
86
-
87
- export const historyWithSearch = {
88
- location: {
89
- search: '?page=1&perPage=5',
90
- },
91
- };
92
-
93
- export const policyDetailMock = policyDetailMockFactory(
94
- { id: ovalPolicy.id },
95
- ovalPolicy,
96
- { currentUser: admin }
97
- );
98
-
99
- export const policyUnauthorizedMock = policyDetailMockFactory(
100
- { id: ovalPolicy.id },
101
- ovalPolicy,
102
- { currentUser: intruder }
103
- );
104
-
105
- export const policyCvesMock = cvesMockFactory(
106
- { search: `oval_policy_id = ${ovalPolicyId}`, first: 5, last: 5 },
107
- cvesResult,
108
- { currentUser: admin }
109
- );
110
- export const policyHostgroupsMock = hostgroupsMockFactory(
111
- { search: `oval_policy_id = ${ovalPolicyId}`, first: 5, last: 5 },
112
- hostgroupsResult,
113
- { currentUser: admin }
114
- );
115
- export const policyHostgroupsDeniedMock = hostgroupsMockFactory(
116
- { search: `oval_policy_id = ${ovalPolicyId}`, first: 5, last: 5 },
117
- { totalCount: 0, nodes: [] },
118
- { currentUser: intruder }
119
- );
120
- export const policyEditPermissionsMock = policyDetailMockFactory(
121
- { id: ovalPolicy.id },
122
- noEditPolicy,
123
- { currentUser: viewer }
124
- );
@@ -1,172 +0,0 @@
1
- import React from 'react';
2
- import { Router } from 'react-router-dom';
3
- import { render, screen, waitFor } from '@testing-library/react';
4
- import { within } from '@testing-library/dom';
5
- import '@testing-library/jest-dom';
6
- import userEvent from '@testing-library/user-event';
7
- import { createMemoryHistory } from 'history';
8
-
9
- import OvalPoliciesShow from '../index';
10
- import {
11
- ovalPoliciesShowPath,
12
- resolvePath,
13
- } from '../../../../helpers/pathsHelper';
14
-
15
- import {
16
- withRedux,
17
- withMockedProvider,
18
- tick,
19
- withRouter,
20
- } from '../../../../testHelper';
21
- import {
22
- policyDetailMock,
23
- historyMock,
24
- historyWithSearch,
25
- pushMock,
26
- policyCvesMock,
27
- policyHostgroupsMock,
28
- policyHostgroupsDeniedMock,
29
- ovalPolicyId,
30
- policyUnauthorizedMock,
31
- } from './OvalPoliciesShow.fixtures';
32
-
33
- const TestComponent = withRedux(
34
- withRouter(withMockedProvider(OvalPoliciesShow))
35
- );
36
-
37
- describe('OvalPoliciesShow', () => {
38
- it('should load details by default and handle tab change', async () => {
39
- const { container } = render(
40
- <TestComponent
41
- history={historyMock}
42
- match={{ params: { id: ovalPolicyId }, path: ovalPoliciesShowPath }}
43
- mocks={policyDetailMock}
44
- />
45
- );
46
- expect(screen.getByText('Loading')).toBeInTheDocument();
47
- await waitFor(tick);
48
- expect(screen.queryByText('Loading')).not.toBeInTheDocument();
49
- expect(screen.getAllByText('Third policy').pop()).toBeInTheDocument();
50
- expect(screen.getByText('Weekly, on tuesday')).toBeInTheDocument();
51
- expect(screen.getByText('A very strict policy')).toBeInTheDocument();
52
- const activeTabHeader = container.querySelector(
53
- '.pf-c-tabs__item.pf-m-current'
54
- );
55
- expect(within(activeTabHeader).getByText('Details')).toBeInTheDocument();
56
- userEvent.click(screen.getByRole('tab', { name: 'CVEs' }));
57
- expect(pushMock).toHaveBeenCalledWith(
58
- resolvePath(ovalPoliciesShowPath, {
59
- ':id': ovalPolicyId,
60
- ':tab?': 'cves',
61
- })
62
- );
63
- });
64
- it('should load details tab when specified in URL', async () => {
65
- render(
66
- <TestComponent
67
- history={historyMock}
68
- match={{
69
- params: { id: ovalPolicyId, tab: 'details' },
70
- path: ovalPoliciesShowPath,
71
- }}
72
- mocks={policyDetailMock}
73
- />
74
- );
75
- expect(screen.getByText('Loading')).toBeInTheDocument();
76
- await waitFor(tick);
77
- expect(screen.queryByText('Loading')).not.toBeInTheDocument();
78
- expect(screen.getByText('Weekly, on tuesday')).toBeInTheDocument();
79
- });
80
- it('should not load the page when user does not have permissions', async () => {
81
- render(
82
- <TestComponent
83
- history={historyMock}
84
- match={{ params: { id: ovalPolicyId }, path: ovalPoliciesShowPath }}
85
- mocks={policyUnauthorizedMock}
86
- />
87
- );
88
- await waitFor(tick);
89
- expect(screen.queryByText('Loading')).not.toBeInTheDocument();
90
- expect(
91
- screen.getByText(
92
- 'You are not authorized to view the page. Request the following permissions from administrator: view_oval_policies.'
93
- )
94
- ).toBeInTheDocument();
95
- });
96
- it('should load CVEs tab when specified in URL', async () => {
97
- const mocks = policyDetailMock.concat(policyCvesMock);
98
- render(
99
- <TestComponent
100
- history={historyWithSearch}
101
- match={{
102
- params: { id: ovalPolicyId, tab: 'cves' },
103
- path: ovalPoliciesShowPath,
104
- }}
105
- mocks={mocks}
106
- />
107
- );
108
- expect(screen.getByText('Loading')).toBeInTheDocument();
109
- await waitFor(tick);
110
- await waitFor(tick);
111
- expect(screen.queryByText('Loading')).not.toBeInTheDocument();
112
- expect(screen.getByText('CVE-2020-14365')).toBeInTheDocument();
113
- });
114
- it('should have button for scanning all hostgroups', async () => {
115
- const btnText = 'Scan All Hostgroups';
116
-
117
- const WithProvider = withRedux(withMockedProvider(OvalPoliciesShow));
118
- const history = createMemoryHistory();
119
- history.push = jest.fn();
120
-
121
- render(
122
- <Router history={history}>
123
- <WithProvider
124
- history={history}
125
- match={{ params: { id: ovalPolicyId }, path: ovalPoliciesShowPath }}
126
- mocks={policyDetailMock}
127
- />
128
- </Router>
129
- );
130
- await waitFor(tick);
131
- expect(screen.queryByText('Loading')).not.toBeInTheDocument();
132
- expect(screen.getByText(btnText)).toBeInTheDocument();
133
- userEvent.click(screen.getByRole('button', { name: btnText }));
134
- expect(history.push).toHaveBeenCalledWith(
135
- '/job_invocations/new?feature=foreman_openscap_run_oval_scans&host_ids=hostgroup_id+%5E+%284+10+12+11%29&inputs%5Boval_policies%5D=3'
136
- );
137
- });
138
- it('should load hostgroups tab when specified in URL', async () => {
139
- const mocks = policyDetailMock.concat(policyHostgroupsMock);
140
- render(
141
- <TestComponent
142
- history={historyWithSearch}
143
- match={{
144
- params: { id: ovalPolicyId, tab: 'hostgroups' },
145
- path: ovalPoliciesShowPath,
146
- }}
147
- mocks={mocks}
148
- />
149
- );
150
- expect(screen.getByText('Loading')).toBeInTheDocument();
151
- await waitFor(tick);
152
- await waitFor(tick);
153
- expect(screen.queryByText('Loading')).not.toBeInTheDocument();
154
- expect(screen.getByText('first hostgroup')).toBeInTheDocument();
155
- });
156
- it('should not show hostgroups for a user without permissions', async () => {
157
- const mocks = policyDetailMock.concat(policyHostgroupsDeniedMock);
158
- render(
159
- <TestComponent
160
- history={historyWithSearch}
161
- match={{
162
- params: { id: ovalPolicyId, tab: 'hostgroups' },
163
- path: ovalPoliciesShowPath,
164
- }}
165
- mocks={mocks}
166
- />
167
- );
168
- await waitFor(tick);
169
- await waitFor(tick);
170
- expect(screen.getByText('Permission denied')).toBeInTheDocument();
171
- });
172
- });
@@ -1,39 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { useQuery } from '@apollo/client';
4
- import { useDispatch } from 'react-redux';
5
-
6
- import { translate as __ } from 'foremanReact/common/I18n';
7
- import { showToast } from '../../../helpers/toastHelper';
8
-
9
- import OvalPoliciesShow from './OvalPoliciesShow';
10
- import { encodeId } from '../../../helpers/globalIdHelper';
11
-
12
- import ovalPolicy from '../../../graphql/queries/ovalPolicy.gql';
13
-
14
- const WrappedOvalPoliciesShow = props => {
15
- const id = encodeId('ForemanOpenscap::OvalPolicy', props.match.params.id);
16
-
17
- const useFetchFn = componentProps =>
18
- useQuery(ovalPolicy, { variables: { id } });
19
-
20
- const renameData = data => ({ policy: data.ovalPolicy });
21
-
22
- return (
23
- <OvalPoliciesShow
24
- {...props}
25
- fetchFn={useFetchFn}
26
- renameData={renameData}
27
- resultPath="ovalPolicy"
28
- emptyStateTitle={__('No OVAL Policy found')}
29
- permissions={['view_oval_policies']}
30
- showToast={showToast(useDispatch())}
31
- />
32
- );
33
- };
34
-
35
- WrappedOvalPoliciesShow.propTypes = {
36
- match: PropTypes.object.isRequired,
37
- };
38
-
39
- export default WrappedOvalPoliciesShow;