foreman_ansible 9.0.1 → 10.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/foreman_ansible/ansible_hostgroups_helper.rb +1 -1
  3. data/lib/foreman_ansible/register.rb +1 -1
  4. data/lib/foreman_ansible/version.rb +1 -1
  5. data/package.json +0 -1
  6. data/test/integration/hostgroup_js_test.rb +30 -0
  7. data/webpack/components/AnsibleHostDetail/AnsibleHostDetail.js +1 -0
  8. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverridesTable.js +10 -4
  9. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableAction.js +3 -0
  10. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/EditableValueHelper.js +5 -1
  11. data/webpack/components/AnsibleHostDetail/components/JobsTab/NewRecurringJobModal.js +3 -0
  12. data/webpack/components/AnsibleHostDetail/components/JobsTab/PreviousJobsTable.js +10 -4
  13. data/webpack/components/AnsibleHostDetail/components/JobsTab/RecurringJobsTable.js +3 -3
  14. data/webpack/components/AnsibleHostDetail/components/JobsTab/index.js +5 -1
  15. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/AllRolesTable.js +10 -4
  16. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/index.js +1 -0
  17. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesForm.js +2 -1
  18. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/index.js +7 -1
  19. data/webpack/components/AnsibleHostDetail/components/RolesTab/RolesTable.js +14 -5
  20. data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/EditRoles.test.js +2 -1
  21. data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/RolesTab.test.js +3 -1
  22. data/webpack/components/AnsibleHostDetail/components/RolesTab/index.js +27 -2
  23. data/webpack/components/AnsibleHostDetail/components/SecondaryTabRoutes.js +1 -1
  24. data/webpack/testHelper.js +12 -3
  25. metadata +20 -56
  26. data/lib/foreman_ansible/register.rb.orig +0 -257
  27. data/locale/ca/foreman_ansible.edit.po +0 -1162
  28. data/locale/ca/foreman_ansible.po.time_stamp +0 -0
  29. data/locale/cs_CZ/foreman_ansible.edit.po +0 -1207
  30. data/locale/cs_CZ/foreman_ansible.po.time_stamp +0 -0
  31. data/locale/de/foreman_ansible.edit.po +0 -1148
  32. data/locale/de/foreman_ansible.po.time_stamp +0 -0
  33. data/locale/en/foreman_ansible.edit.po +0 -1146
  34. data/locale/en/foreman_ansible.po.time_stamp +0 -0
  35. data/locale/en_GB/foreman_ansible.edit.po +0 -1155
  36. data/locale/en_GB/foreman_ansible.po.time_stamp +0 -0
  37. data/locale/es/foreman_ansible.edit.po +0 -1148
  38. data/locale/es/foreman_ansible.po.time_stamp +0 -0
  39. data/locale/fr/foreman_ansible.edit.po +0 -1148
  40. data/locale/fr/foreman_ansible.po.time_stamp +0 -0
  41. data/locale/gl/foreman_ansible.edit.po +0 -1156
  42. data/locale/gl/foreman_ansible.po.time_stamp +0 -0
  43. data/locale/it/foreman_ansible.edit.po +0 -1148
  44. data/locale/it/foreman_ansible.po.time_stamp +0 -0
  45. data/locale/ja/foreman_ansible.edit.po +0 -1148
  46. data/locale/ja/foreman_ansible.po.time_stamp +0 -0
  47. data/locale/ko/foreman_ansible.edit.po +0 -1148
  48. data/locale/ko/foreman_ansible.po.time_stamp +0 -0
  49. data/locale/nl_NL/foreman_ansible.edit.po +0 -1168
  50. data/locale/nl_NL/foreman_ansible.po.time_stamp +0 -0
  51. data/locale/pl/foreman_ansible.edit.po +0 -1180
  52. data/locale/pl/foreman_ansible.po.time_stamp +0 -0
  53. data/locale/pt_BR/foreman_ansible.edit.po +0 -1148
  54. data/locale/pt_BR/foreman_ansible.po.time_stamp +0 -0
  55. data/locale/ru/foreman_ansible.edit.po +0 -1149
  56. data/locale/ru/foreman_ansible.po.time_stamp +0 -0
  57. data/locale/sv_SE/foreman_ansible.edit.po +0 -1180
  58. data/locale/sv_SE/foreman_ansible.po.time_stamp +0 -0
  59. data/locale/zh_CN/foreman_ansible.edit.po +0 -1148
  60. data/locale/zh_CN/foreman_ansible.po.time_stamp +0 -0
  61. data/locale/zh_TW/foreman_ansible.edit.po +0 -1148
  62. data/locale/zh_TW/foreman_ansible.po.time_stamp +0 -0
  63. data/webpack/components/AnsibleHostDetail/components/JobsTab/PreviousJobsTable.js.orig +0 -151
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf08e369d1c4b9a445123a9fab3a02b1da8c3bfe9261b7027693959d90e1e1a3
4
- data.tar.gz: 13ac8e3cb9b88bf5167a2fdeb9e95409ad9a93c6f4dce12f0500cc5c5bd787a9
3
+ metadata.gz: 3141b6325f66438c16c630fc728eb9bb7f381ade6987491cbc62fa98d911e83b
4
+ data.tar.gz: 68f84c9a0251af1aa1a284c5ae509008d24c9d68802097b50aa700f407d5cabb
5
5
  SHA512:
6
- metadata.gz: 8c515c517add1b91f020c63a50b6b58eaafdacfe08d52d39286ae79efd034cb8ca0ffc8ef4aa8aa2f5be9e5dcc6a797910dd9b32f444e61e525077c8239e3e56
7
- data.tar.gz: 18fac58f8a1d119af822b6be9f28ce33b626b0951791d5c3ca201d6e2475f2399c52d21ba92b19335f267a183306e568cbc384910942f1d7d0de9d1d74a88ef2
6
+ metadata.gz: d62e5e435516a8cef1dc345663d735a767b0b2150ac2c0938fd278e1466d7d1c15428cad48b9313d86902ac10acc00bb34fdadc2337456ed5bf52acb1aaad94e
7
+ data.tar.gz: 881639c08f95a3cf8771bbf20d74d3410b2caef5e25c4f000e414faf7d4292f365ed4a22ec8edebc3c357d89efd10f8b3ae41bfbb7eeca4e9ea894867c020b0f
@@ -4,7 +4,7 @@ module ForemanAnsible
4
4
  module AnsibleHostgroupsHelper
5
5
  def ansible_hostgroups_actions(hostgroup)
6
6
  play_roles = if hostgroup.all_ansible_roles.empty?
7
- { action: (link_to _('Run all Ansible roles'), 'javascript:void(0);', disabled: true, title: 'No Roles assigned'), priority: 31 }
7
+ { action: { content: (link_to _('Run all Ansible roles'), 'javascript:void(0);', disabled: true, title: 'No roles assigned', class: 'disabled'), options: { class: 'disabled' } }, priority: 31 }
8
8
  else
9
9
  { action: display_link_if_authorized(_('Run all Ansible roles'), hash_for_play_roles_hostgroup_path(id: hostgroup), 'data-no-turbolink': true, title: _('Run all Ansible roles on hosts belonging to this host group')), priority: 31 }
10
10
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Foreman::Plugin.register :foreman_ansible do
4
- requires_foreman '>= 3.4'
4
+ requires_foreman '>= 3.5'
5
5
 
6
6
  settings do
7
7
  category :ansible, N_('Ansible') do
@@ -4,5 +4,5 @@
4
4
  # This way other parts of Foreman can just call ForemanAnsible::VERSION
5
5
  # and detect what version the plugin is running.
6
6
  module ForemanAnsible
7
- VERSION = '9.0.1'
7
+ VERSION = '10.0.0'
8
8
  end
data/package.json CHANGED
@@ -21,7 +21,6 @@
21
21
  "@theforeman/stories": "^10.0",
22
22
  "@theforeman/test": "^10.0",
23
23
  "@theforeman/vendor-dev": "^10.0",
24
- "@testing-library/user-event": "^13.2.1",
25
24
  "babel-eslint": "^10.0.3",
26
25
  "eslint": "^6.7.2",
27
26
  "prettier": "^1.13.5"
@@ -0,0 +1,30 @@
1
+ require_relative '../test_plugin_helper'
2
+ require 'integration_test_helper'
3
+
4
+ class HostgroupJsTest < IntegrationTestWithJavascript
5
+ let(:hostgroup) { FactoryBot.create(:hostgroup, :name => 'HostgroupWithoutRoles') }
6
+ let(:hostgroup_with_roles) { FactoryBot.create(:hostgroup, :with_ansible_roles, :name => 'HostgroupWithRoles') }
7
+
8
+ setup do
9
+ FactoryBot.create(:host, :hostgroup_id => hostgroup.id)
10
+ FactoryBot.create(:host, :hostgroup_id => hostgroup_with_roles.id)
11
+ end
12
+
13
+ test 'hostgroup without roles should have disabled link' do
14
+ visit hostgroups_path(search: hostgroup.name)
15
+
16
+ first_row = page.find('table > tbody > tr:nth-child(1)')
17
+ first_row.find('td:nth-child(4) > div > a').click
18
+
19
+ assert_includes first(:link, 'Run all Ansible roles')[:class], 'disabled'
20
+ end
21
+
22
+ test 'hostgroup with roles should have clickable link' do
23
+ visit hostgroups_path(search: hostgroup_with_roles.name)
24
+
25
+ first_row = page.find('table > tbody > tr:nth-child(1)')
26
+ first_row.find('td:nth-child(4) > div > a').click
27
+
28
+ assert_not first(:link, 'Run all Ansible roles')[:class].include?('disabled')
29
+ end
30
+ end
@@ -22,6 +22,7 @@ const AnsibleHostDetail = ({
22
22
  <>
23
23
  <Tabs
24
24
  className="ansible-host-details-tabs"
25
+ ouiaId="ansible-host-details-tabs"
25
26
  onSelect={(evt, subTab) => hashHistory.push(subTab)}
26
27
  activeKey={pathname?.split('/')[2]}
27
28
  isSecondary
@@ -148,12 +148,17 @@ const AnsibleVariableOverridesTable = ({
148
148
  <React.Fragment>
149
149
  <Flex direction={{ default: 'column' }}>
150
150
  <FlexItem align={{ default: 'alignRight' }}>
151
- <Pagination updateParamsByUrl itemCount={totalCount} variant="top" />
151
+ <Pagination
152
+ ouiaId="pagination-top"
153
+ updateParamsByUrl
154
+ itemCount={totalCount}
155
+ variant="top"
156
+ />
152
157
  </FlexItem>
153
158
  <FlexItem>
154
- <TableComposable variant="compact">
159
+ <TableComposable ouiaId="table-composable-compact" variant="compact">
155
160
  <Thead>
156
- <Tr>
161
+ <Tr ouiaId="row-header">
157
162
  {columns.map(col => (
158
163
  <Th key={col}>{col}</Th>
159
164
  ))}
@@ -162,7 +167,7 @@ const AnsibleVariableOverridesTable = ({
162
167
  </Thead>
163
168
  <Tbody>
164
169
  {variables.map((variable, idx) => (
165
- <Tr key={idx}>
170
+ <Tr key={idx} ouiaId={`row-${idx}`}>
166
171
  <Td>
167
172
  <a href={variable.path}>{variable.key}</a>
168
173
  </Td>
@@ -202,6 +207,7 @@ const AnsibleVariableOverridesTable = ({
202
207
  </FlexItem>
203
208
  <FlexItem align={{ default: 'alignRight' }}>
204
209
  <Pagination
210
+ ouiaId="pagination-bottom"
205
211
  updateParamsByUrl
206
212
  itemCount={totalCount}
207
213
  variant="bottom"
@@ -111,6 +111,7 @@ const EditableAction = ({
111
111
  onClick={onClose}
112
112
  isDisabled={state.working}
113
113
  aria-label="Cancel editing override button"
114
+ ouiaId="cancel-editing-override-button"
114
115
  >
115
116
  <TimesIcon />
116
117
  </Button>
@@ -119,6 +120,7 @@ const EditableAction = ({
119
120
  onClick={onSubmit}
120
121
  isDisabled={state.working || hasError(state)}
121
122
  aria-label="Submit editing override button"
123
+ ouiaId="submit-editing-override-button"
122
124
  >
123
125
  <CheckIcon />
124
126
  </Button>
@@ -136,6 +138,7 @@ const EditableAction = ({
136
138
  onClick={onOpen}
137
139
  variant="plain"
138
140
  aria-label="Edit override button"
141
+ ouiaId="edit-override-button"
139
142
  >
140
143
  <PencilAltIcon />
141
144
  </Button>
@@ -23,7 +23,11 @@ const withFormGroup = Component => componentProps => {
23
23
  export const SelectField = componentProps => {
24
24
  const { selectItems, ...rest } = componentProps;
25
25
  return (
26
- <FormSelect className="without_select2" {...rest}>
26
+ <FormSelect
27
+ className="without_select2"
28
+ ouiaId="without-form-select"
29
+ {...rest}
30
+ >
27
31
  {selectItems.map(item => (
28
32
  <FormSelectOption key={item.id} value={item.value} label={item.name} />
29
33
  ))}
@@ -57,6 +57,7 @@ const NewRecurringJobModal = props => {
57
57
  const actions = [
58
58
  <Button
59
59
  aria-label="submit creating job"
60
+ ouiaId="submit-creating-job"
60
61
  key="confirm"
61
62
  variant="primary"
62
63
  onClick={formProps.handleSubmit}
@@ -66,6 +67,7 @@ const NewRecurringJobModal = props => {
66
67
  </Button>,
67
68
  <Button
68
69
  aria-label="cancel creating job"
70
+ ouiaId="cancel-creating-job"
69
71
  key="cancel"
70
72
  variant="link"
71
73
  onClick={onClose}
@@ -83,6 +85,7 @@ const NewRecurringJobModal = props => {
83
85
  <Modal
84
86
  variant={ModalVariant.large}
85
87
  title="Create New Recurring Ansible Run"
88
+ ouiaId="modal-recurring-ansible-run"
86
89
  isOpen={props.isOpen}
87
90
  className="foreman-modal modal-high"
88
91
  showClose={false}
@@ -32,12 +32,17 @@ const PreviousJobsTable = ({ history, totalCount, jobs, pagination }) => {
32
32
  <h3>{__('Previously executed jobs')}</h3>
33
33
  <Flex direction={{ default: 'column' }} className="pf-u-pt-md">
34
34
  <FlexItem align={{ default: 'alignRight' }}>
35
- <Pagination updateParamsByUrl itemCount={totalCount} variant="top" />
35
+ <Pagination
36
+ ouiaId="pagination-top"
37
+ updateParamsByUrl
38
+ itemCount={totalCount}
39
+ variant="top"
40
+ />
36
41
  </FlexItem>
37
42
  <FlexItem>
38
- <TableComposable variant="compact">
43
+ <TableComposable ouiaId="table-composable-compact" variant="compact">
39
44
  <Thead>
40
- <Tr>
45
+ <Tr ouiaId="row-header">
41
46
  {columns.map(col => (
42
47
  <Th key={col}>{col}</Th>
43
48
  ))}
@@ -45,7 +50,7 @@ const PreviousJobsTable = ({ history, totalCount, jobs, pagination }) => {
45
50
  </Thead>
46
51
  <Tbody>
47
52
  {jobs.map(job => (
48
- <Tr key={job.id}>
53
+ <Tr key={job.id} ouiaId={`row-${job.id}`}>
49
54
  <Td>
50
55
  <a
51
56
  onClick={() =>
@@ -72,6 +77,7 @@ const PreviousJobsTable = ({ history, totalCount, jobs, pagination }) => {
72
77
  </FlexItem>
73
78
  <FlexItem align={{ default: 'alignRight' }}>
74
79
  <Pagination
80
+ ouiaId="pagination-bottom"
75
81
  updateParamsByUrl
76
82
  itemCount={totalCount}
77
83
  variant="bottom"
@@ -60,9 +60,9 @@ const RecurringJobsTable = ({
60
60
  return (
61
61
  <React.Fragment>
62
62
  <h3>{__('Scheduled recurring jobs')}</h3>
63
- <TableComposable variant="compact">
63
+ <TableComposable ouiaId="table-composable-compact" variant="compact">
64
64
  <Thead>
65
- <Tr>
65
+ <Tr ouiaId="row-header">
66
66
  {columns.map(col => (
67
67
  <Th key={col}>{col}</Th>
68
68
  ))}
@@ -71,7 +71,7 @@ const RecurringJobsTable = ({
71
71
  </Thead>
72
72
  <Tbody>
73
73
  {jobs.map(job => (
74
- <Tr key={job.id}>
74
+ <Tr key={job.id} ouiaId={`row-${job.id}`}>
75
75
  <Td>
76
76
  <a
77
77
  onClick={() =>
@@ -33,7 +33,11 @@ const JobsTab = ({ resourceName, resourceId, hostGroupId, history }) => {
33
33
  ];
34
34
 
35
35
  const scheduleBtn = (
36
- <Button aria-label="schedule recurring job" onClick={toggleModal}>
36
+ <Button
37
+ aria-label="schedule recurring job"
38
+ ouiaId="schedule-recurring-job"
39
+ onClick={toggleModal}
40
+ >
37
41
  {__('Schedule recurring job')}
38
42
  </Button>
39
43
  );
@@ -21,11 +21,16 @@ const AllRolesTable = ({ allAnsibleRoles, totalCount }) => {
21
21
  <React.Fragment>
22
22
  <Flex direction={{ default: 'column' }} className="pf-u-pt-md">
23
23
  <FlexItem align={{ default: 'alignRight' }}>
24
- <Pagination updateParamsByUrl itemCount={totalCount} variant="top" />
24
+ <Pagination
25
+ ouiaId="pagination-top"
26
+ updateParamsByUrl
27
+ itemCount={totalCount}
28
+ variant="top"
29
+ />
25
30
  </FlexItem>
26
- <TableComposable variant="compact">
31
+ <TableComposable ouiaId="table-composable-compact" variant="compact">
27
32
  <Thead>
28
- <Tr>
33
+ <Tr ouiaId="row-header">
29
34
  <Th />
30
35
  {columns.map(col => (
31
36
  <Th key={`${col}-all`}>{col}</Th>
@@ -34,7 +39,7 @@ const AllRolesTable = ({ allAnsibleRoles, totalCount }) => {
34
39
  </Thead>
35
40
  <Tbody>
36
41
  {allAnsibleRoles.map(role => (
37
- <Tr key={`${role.id}-all`} id={role.id}>
42
+ <Tr key={`${role.id}-all`} id={role.id} ouiaId={`row-${role.id}`}>
38
43
  <Td />
39
44
  <Td>{role.name}</Td>
40
45
  <Td>
@@ -58,6 +63,7 @@ const AllRolesTable = ({ allAnsibleRoles, totalCount }) => {
58
63
  </TableComposable>
59
64
  <FlexItem align={{ default: 'alignRight' }}>
60
65
  <Pagination
66
+ ouiaId="pagination-bottom"
61
67
  updateParamsByUrl
62
68
  itemCount={totalCount}
63
69
  variant="bottom"
@@ -15,6 +15,7 @@ import {
15
15
 
16
16
  const AllRolesModal = ({ hostGlobalId, onClose, history }) => {
17
17
  const baseModalProps = {
18
+ ouiaId: 'modal-ansible-roles',
18
19
  variant: ModalVariant.large,
19
20
  isOpen: true,
20
21
  onClose,
@@ -54,6 +54,7 @@ const EditRolesForm = props => {
54
54
  onClick={() => callMutation({ variables })}
55
55
  isDisabled={loading || didNotModifyOptions()}
56
56
  aria-label="submit ansible roles"
57
+ ouiaId="submit-ansible-roles-button"
57
58
  >
58
59
  {__('Confirm')}
59
60
  </Button>,
@@ -65,7 +66,7 @@ const EditRolesForm = props => {
65
66
  }
66
67
 
67
68
  return (
68
- <Modal {...baseModalProps} actions={formActions}>
69
+ <Modal ouiaId="modal-edit-roles" {...baseModalProps} actions={formActions}>
69
70
  <DualList
70
71
  availableOptions={availableOptions}
71
72
  chosenOptions={chosenOptions}
@@ -20,6 +20,7 @@ const EditRolesModal = ({
20
20
  canEditHost,
21
21
  }) => {
22
22
  const baseModalProps = {
23
+ ouiaId: 'edit-ansible-roles-modal',
23
24
  width: '50%',
24
25
  isOpen,
25
26
  className: 'foreman-modal',
@@ -32,7 +33,12 @@ const EditRolesModal = ({
32
33
  };
33
34
 
34
35
  const actions = [
35
- <Button variant="link" onClick={event => closeModal()} key="close">
36
+ <Button
37
+ ouiaId="close-button"
38
+ variant="link"
39
+ onClick={event => closeModal()}
40
+ key="close"
41
+ >
36
42
  {__('Close')}
37
43
  </Button>,
38
44
  ];
@@ -32,7 +32,10 @@ const RolesTable = ({
32
32
  const editBtn = canEditHost ? (
33
33
  <FlexItem>
34
34
  <Link to="/Ansible/roles/edit">
35
- <Button aria-label="edit ansible roles">
35
+ <Button
36
+ aria-label="edit ansible roles"
37
+ ouiaId="edit-ansible-roles-button"
38
+ >
36
39
  {__('Edit Ansible roles')}
37
40
  </Button>
38
41
  </Link>
@@ -53,14 +56,19 @@ const RolesTable = ({
53
56
  <Flex>
54
57
  <FlexItem>{editBtn}</FlexItem>
55
58
  <FlexItem align={{ default: 'alignRight' }}>
56
- <Pagination updateParamsByUrl itemCount={totalCount} variant="top" />
59
+ <Pagination
60
+ ouiaId="pagination-top"
61
+ updateParamsByUrl
62
+ itemCount={totalCount}
63
+ variant="top"
64
+ />
57
65
  </FlexItem>
58
66
  </Flex>
59
67
  <Flex direction={{ default: 'column' }}>
60
68
  <FlexItem>
61
- <TableComposable variant="compact">
69
+ <TableComposable variant="compact" ouiaId="table-composable-compact">
62
70
  <Thead>
63
- <Tr>
71
+ <Tr ouiaId="row-header">
64
72
  {columns.map(col => (
65
73
  <Th key={col}>{col}</Th>
66
74
  ))}
@@ -68,7 +76,7 @@ const RolesTable = ({
68
76
  </Thead>
69
77
  <Tbody>
70
78
  {ansibleRoles.map(role => (
71
- <Tr key={role.id}>
79
+ <Tr key={role.id} ouiaId={`row-${role.id}`}>
72
80
  <Td>
73
81
  <a href={role.path}>{role.name}</a>
74
82
  </Td>
@@ -88,6 +96,7 @@ const RolesTable = ({
88
96
  </FlexItem>
89
97
  <FlexItem align={{ default: 'alignRight' }}>
90
98
  <Pagination
99
+ ouiaId="pagination-bottom"
91
100
  updateParamsByUrl
92
101
  itemCount={totalCount}
93
102
  variant="bottom"
@@ -21,7 +21,8 @@ import {
21
21
  assignRolesErrorMock,
22
22
  } from './RolesTab.fixtures';
23
23
 
24
- const TestComponent = withReactRouter(withRedux(withMockedProvider(RolesTab)));
24
+ jest.mock('axios');
25
+ const TestComponent = withRedux(withReactRouter(withMockedProvider(RolesTab)));
25
26
 
26
27
  describe('assigning Ansible roles', () => {
27
28
  it('should assign Ansible roles', async () => {
@@ -6,6 +6,7 @@ import {
6
6
  tick,
7
7
  withMockedProvider,
8
8
  withReactRouter,
9
+ withRedux,
9
10
  } from '../../../../../testHelper';
10
11
 
11
12
  import {
@@ -18,7 +19,8 @@ import {
18
19
 
19
20
  import RolesTab from '../';
20
21
 
21
- const TestComponent = withReactRouter(withMockedProvider(RolesTab));
22
+ jest.mock('axios');
23
+ const TestComponent = withRedux(withReactRouter(withMockedProvider(RolesTab)));
22
24
 
23
25
  describe('RolesTab', () => {
24
26
  it('should load Ansible Roles as admin', async () => {
@@ -2,7 +2,10 @@ import React, { useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { useQuery } from '@apollo/client';
4
4
  import { Button } from '@patternfly/react-core';
5
+ import { Link, Route } from 'react-router-dom';
5
6
  import { translate as __ } from 'foremanReact/common/I18n';
7
+ import { foremanUrl } from 'foremanReact/common/helpers';
8
+ import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
6
9
 
7
10
  import ansibleRolesQuery from '../../../../graphql/queries/hostAnsibleRoles.gql';
8
11
  import { encodeId } from '../../../../globalIdHelper';
@@ -12,6 +15,7 @@ import {
12
15
  useCurrentPagination,
13
16
  } from '../../../../helpers/pageParamsHelper';
14
17
  import EditRolesModal from './EditRolesModal';
18
+ import AllRolesModal from './AllRolesModal';
15
19
 
16
20
  const RolesTab = ({ hostId, history, canEditHost }) => {
17
21
  const hostGlobalId = encodeId('Host', hostId);
@@ -32,10 +36,30 @@ const RolesTab = ({ hostId, history, canEditHost }) => {
32
36
  <Button
33
37
  onClick={() => setAssignModal(true)}
34
38
  aria-label="edit ansible roles"
39
+ ouiaId="edit-ansible-roles-button"
35
40
  >
36
- {__('Assign Ansible roles')}
41
+ {__('Assign roles directly to the host')}
37
42
  </Button>
38
43
  ) : null;
44
+
45
+ const url = hostId && foremanUrl(`/api/v2/hosts/${hostId}/ansible_roles`);
46
+ const { response: allAnsibleRoles } = useAPI('get', url, {
47
+ key: 'ANSIBLE_ROLES',
48
+ });
49
+ const emptyStateDescription = allAnsibleRoles.length > 0 && (
50
+ <>
51
+ <Route path="/Ansible/roles/all">
52
+ <AllRolesModal
53
+ onClose={() => history.push('/Ansible/roles')}
54
+ isOpen
55
+ hostGlobalId={hostGlobalId}
56
+ history={history}
57
+ />
58
+ </Route>
59
+ <Link to="/Ansible/roles/all">{__('View inherited roles')}</Link>
60
+ </>
61
+ );
62
+
39
63
  return (
40
64
  <>
41
65
  <RolesTable
@@ -46,8 +70,9 @@ const RolesTab = ({ hostId, history, canEditHost }) => {
46
70
  history={history}
47
71
  hostGlobalId={hostGlobalId}
48
72
  emptyStateProps={{
49
- header: __('No Ansible roles assigned'),
73
+ header: __('No roles assigned directly to the host'),
50
74
  action: editBtn,
75
+ description: emptyStateDescription,
51
76
  }}
52
77
  pagination={pagination}
53
78
  canEditHost={canEditHost}
@@ -12,7 +12,7 @@ import { ANSIBLE_KEY } from '../constants';
12
12
  import { route } from '../helpers';
13
13
 
14
14
  const SecondaryTabRoutes = ({ response, router, history }) => (
15
- <Switch>
15
+ <Switch ouiaId="switch">
16
16
  <Route exact path={`/${ANSIBLE_KEY}`}>
17
17
  <Redirect to={route('roles')} />
18
18
  </Route>
@@ -1,15 +1,24 @@
1
1
  import React from 'react';
2
2
  import { Provider } from 'react-redux';
3
+ import thunk from 'redux-thunk';
4
+ import { applyMiddleware, createStore, compose, combineReducers } from 'redux';
3
5
  import { MockedProvider } from '@apollo/react-testing';
4
6
  import { Router, MemoryRouter } from 'react-router-dom';
5
7
  import { createMemoryHistory } from 'history';
6
8
 
7
- import store from 'foremanReact/redux';
8
- import ConfirmModal from 'foremanReact/components/ConfirmModal';
9
+ import { reducers as apiReducer, APIMiddleware } from 'foremanReact/redux/API';
10
+ import ConfirmModal, {
11
+ reducers as confirmModalReducers,
12
+ } from 'foremanReact/components/ConfirmModal';
9
13
  import { getForemanContext } from 'foremanReact/Root/Context/ForemanContext';
10
14
 
15
+ const reducers = combineReducers({ ...apiReducer, ...confirmModalReducers });
16
+
17
+ export const generateStore = () =>
18
+ createStore(reducers, compose(applyMiddleware(thunk, APIMiddleware)));
19
+
11
20
  export const withRedux = Component => props => (
12
- <Provider store={store}>
21
+ <Provider store={generateStore()}>
13
22
  <Component {...props} />
14
23
  <ConfirmModal />
15
24
  </Provider>