foreman_remote_execution 13.0.0 → 13.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc +4 -1
  3. data/.github/workflows/release.yml +4 -2
  4. data/app/lib/actions/remote_execution/run_host_job.rb +0 -14
  5. data/app/models/concerns/foreman_remote_execution/host_extensions.rb +8 -0
  6. data/app/models/job_invocation_composer.rb +4 -3
  7. data/app/views/api/v2/job_invocations/base.json.rabl +5 -3
  8. data/app/views/templates/script/convert2rhel_analyze.erb +1 -12
  9. data/app/views/templates/script/package_action.erb +11 -1
  10. data/app/views/templates/script/puppet_run_once.erb +3 -3
  11. data/lib/foreman_remote_execution/version.rb +1 -1
  12. data/package.json +6 -6
  13. data/test/unit/job_invocation_composer_test.rb +31 -3
  14. data/webpack/JobInvocationDetail/JobInvocationConstants.js +10 -0
  15. data/webpack/JobInvocationDetail/JobInvocationDetail.scss +38 -0
  16. data/webpack/JobInvocationDetail/JobInvocationOverview.js +13 -25
  17. data/webpack/JobInvocationDetail/JobInvocationSystemStatusChart.js +153 -0
  18. data/webpack/JobInvocationDetail/index.js +48 -10
  19. data/webpack/JobWizard/Footer.js +5 -1
  20. data/webpack/JobWizard/JobWizardPageRerun.js +3 -0
  21. data/webpack/JobWizard/StartsBeforeErrorAlert.js +1 -0
  22. data/webpack/JobWizard/index.js +1 -0
  23. data/webpack/JobWizard/steps/AdvancedFields/DescriptionField.js +8 -1
  24. data/webpack/JobWizard/steps/AdvancedFields/Fields.js +7 -0
  25. data/webpack/JobWizard/steps/CategoryAndTemplate/CategoryAndTemplate.js +16 -3
  26. data/webpack/JobWizard/steps/HostsAndInputs/HostPreviewModal.js +5 -1
  27. data/webpack/JobWizard/steps/HostsAndInputs/SelectedChips.js +8 -1
  28. data/webpack/JobWizard/steps/HostsAndInputs/index.js +7 -2
  29. data/webpack/JobWizard/steps/ReviewDetails/index.js +4 -0
  30. data/webpack/JobWizard/steps/Schedule/PurposeField.js +1 -0
  31. data/webpack/JobWizard/steps/Schedule/QueryType.js +2 -0
  32. data/webpack/JobWizard/steps/Schedule/RepeatCron.js +1 -0
  33. data/webpack/JobWizard/steps/Schedule/RepeatHour.js +2 -0
  34. data/webpack/JobWizard/steps/Schedule/RepeatMonth.js +1 -0
  35. data/webpack/JobWizard/steps/Schedule/RepeatWeek.js +1 -0
  36. data/webpack/JobWizard/steps/Schedule/ScheduleFuture.js +2 -0
  37. data/webpack/JobWizard/steps/Schedule/ScheduleRecurring.js +6 -0
  38. data/webpack/JobWizard/steps/Schedule/ScheduleType.js +3 -0
  39. data/webpack/JobWizard/steps/form/FormHelpers.js +1 -0
  40. data/webpack/JobWizard/steps/form/GroupedSelectField.js +1 -0
  41. data/webpack/JobWizard/steps/form/NumberInput.js +1 -0
  42. data/webpack/JobWizard/steps/form/ResourceSelect.js +1 -0
  43. data/webpack/JobWizard/steps/form/SearchSelect.js +1 -0
  44. data/webpack/JobWizard/steps/form/SelectField.js +1 -0
  45. data/webpack/JobWizard/steps/form/WizardTitle.js +6 -1
  46. data/webpack/__mocks__/foremanReact/routes/Hosts/constants.js +1 -0
  47. data/webpack/react_app/components/FeaturesDropdown/index.js +1 -0
  48. data/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js +3 -0
  49. data/webpack/react_app/components/RecentJobsCard/RecentJobsTable.js +2 -1
  50. data/webpack/react_app/components/RegistrationExtension/RexInterface.js +1 -0
  51. data/webpack/react_app/components/RegistrationExtension/RexPull.js +1 -0
  52. data/webpack/react_app/components/RegistrationExtension/__tests__/__snapshots__/RexInterface.test.js.snap +1 -0
  53. metadata +9 -6
@@ -48,6 +48,7 @@ const JobWizardPageRerun = ({
48
48
  searchable={false}
49
49
  toolbarButtons={
50
50
  <Button
51
+ ouiaId="job-wizard-rerun-old-form-button"
51
52
  variant="link"
52
53
  component="a"
53
54
  href={`/old/job_invocations/${id}/rerun${search}`}
@@ -71,6 +72,7 @@ const JobWizardPageRerun = ({
71
72
  <React.Fragment>
72
73
  {jobOrganization?.id !== currentOrganization?.id && (
73
74
  <Alert
75
+ ouiaId="job-wizard-alert-organization"
74
76
  isInline
75
77
  className="job-wizard-alert"
76
78
  variant="warning"
@@ -85,6 +87,7 @@ const JobWizardPageRerun = ({
85
87
  )}
86
88
  {jobLocation?.id !== currentLocation?.id && (
87
89
  <Alert
90
+ ouiaId="job-wizard-alert-location"
88
91
  isInline
89
92
  className="job-wizard-alert"
90
93
  variant="warning"
@@ -5,6 +5,7 @@ import { translate as __ } from 'foremanReact/common/I18n';
5
5
  export const StartsBeforeErrorAlert = () => (
6
6
  <>
7
7
  <Alert
8
+ ouiaId="starts-before-error-alert"
8
9
  variant="danger"
9
10
  title={__("'Starts before' date must in the future")}
10
11
  >
@@ -59,6 +59,7 @@ const JobWizardPage = ({ location: { search } }) => {
59
59
  searchable={false}
60
60
  toolbarButtons={
61
61
  <Button
62
+ ouiaId="legacy-form"
62
63
  variant="link"
63
64
  component="a"
64
65
  href={`/old/job_invocations/new${search}`}
@@ -56,7 +56,12 @@ export const DescriptionField = ({
56
56
  }
57
57
  fieldId="description"
58
58
  helperText={
59
- <Button variant="link" isInline onClick={togglePreview}>
59
+ <Button
60
+ ouiaId="description-preview-button"
61
+ variant="link"
62
+ isInline
63
+ onClick={togglePreview}
64
+ >
60
65
  {isPreview
61
66
  ? __('Edit job description template')
62
67
  : __('Preview job description')}
@@ -68,6 +73,7 @@ export const DescriptionField = ({
68
73
  <div>
69
74
  {/* div wrapper so the tooltip will be shown in chrome */}
70
75
  <TextInput
76
+ ouiaId="description-preview"
71
77
  aria-label="description preview"
72
78
  id="description-preview"
73
79
  value={generatedDesc}
@@ -77,6 +83,7 @@ export const DescriptionField = ({
77
83
  </Tooltip>
78
84
  ) : (
79
85
  <TextInput
86
+ ouiaId="description-edit"
80
87
  aria-label="description edit"
81
88
  type="text"
82
89
  autoComplete="description"
@@ -19,6 +19,7 @@ export const EffectiveUserField = ({ value, setValue, defaultValue }) => (
19
19
  labelInfo={<ResetDefault setValue={setValue} defaultValue={defaultValue} />}
20
20
  >
21
21
  <TextInput
22
+ ouiaId="effective-user"
22
23
  aria-label="effective user"
23
24
  autoComplete="effective-user"
24
25
  id="effective-user"
@@ -86,6 +87,7 @@ export const PasswordField = ({ value, setValue }) => (
86
87
  fieldId="job-password"
87
88
  >
88
89
  <TextInput
90
+ ouiaId="job-password"
89
91
  aria-label="job password"
90
92
  autoComplete="new-password" // to prevent firefox from autofilling the user password
91
93
  id="job-password"
@@ -109,6 +111,7 @@ export const KeyPassphraseField = ({ value, setValue }) => (
109
111
  fieldId="key-passphrase"
110
112
  >
111
113
  <TextInput
114
+ ouiaId="key-passphrase"
112
115
  aria-label="key passphrase"
113
116
  autoComplete="key-passphrase"
114
117
  id="key-passphrase"
@@ -132,6 +135,7 @@ export const EffectiveUserPasswordField = ({ value, setValue }) => (
132
135
  fieldId="effective-user-password"
133
136
  >
134
137
  <TextInput
138
+ ouiaId="effective-user-password"
135
139
  aria-label="effective userpassword"
136
140
  autoComplete="effective-user-password"
137
141
  id="effective-user-password"
@@ -186,6 +190,7 @@ export const ExecutionOrderingField = ({ isRandomizedOrdering, setValue }) => (
186
190
  isInline
187
191
  >
188
192
  <Radio
193
+ ouiaId="execution-order-alphabetical"
189
194
  aria-label="execution order alphabetical"
190
195
  isChecked={!isRandomizedOrdering}
191
196
  name="execution-order"
@@ -194,6 +199,7 @@ export const ExecutionOrderingField = ({ isRandomizedOrdering, setValue }) => (
194
199
  label={__('Alphabetical')}
195
200
  />
196
201
  <Radio
202
+ ouiaId="execution-order-randomized"
197
203
  aria-label="execution order randomized"
198
204
  isChecked={isRandomizedOrdering}
199
205
  name="execution-order"
@@ -216,6 +222,7 @@ export const SSHUserField = ({ value, setValue, defaultValue }) => (
216
222
  labelInfo={<ResetDefault setValue={setValue} defaultValue={defaultValue} />}
217
223
  >
218
224
  <TextInput
225
+ ouiaId="ssh-user"
219
226
  aria-label="ssh user"
220
227
  autoComplete="ssh-user"
221
228
  id="ssh-user"
@@ -71,7 +71,12 @@ export const CategoryAndTemplate = ({
71
71
  return (
72
72
  <>
73
73
  <WizardTitle title={WIZARD_TITLES.categoryAndTemplate} />
74
- <Text component={TextVariants.p}>{__('All fields are required.')}</Text>
74
+ <Text
75
+ ouiaId="category-and-template-required-fields"
76
+ component={TextVariants.p}
77
+ >
78
+ {__('All fields are required.')}
79
+ </Text>
75
80
  <Form>
76
81
  <SelectField
77
82
  label={__('Job category')}
@@ -95,7 +100,11 @@ export const CategoryAndTemplate = ({
95
100
  placeholderText={allTemplatesError ? __('Not available') : ''}
96
101
  />
97
102
  {!isEmpty(missingPermissions) && (
98
- <Alert variant="warning" title={__('Access denied')}>
103
+ <Alert
104
+ ouiaId="category-and-template-access-denied"
105
+ variant="warning"
106
+ title={__('Access denied')}
107
+ >
99
108
  <span>
100
109
  {__(
101
110
  `Missing the required permissions: ${missingPermissions.join(
@@ -106,7 +115,11 @@ export const CategoryAndTemplate = ({
106
115
  </Alert>
107
116
  )}
108
117
  {isError && (
109
- <Alert variant="danger" title={__('Errors:')}>
118
+ <Alert
119
+ variant="danger"
120
+ title={__('Errors:')}
121
+ ouiaId="category-and-template-errors"
122
+ >
110
123
  {categoryError && isEmpty(missingPermissions) && (
111
124
  <span>
112
125
  {__('Categories list failed with:')} {categoryError}
@@ -5,6 +5,7 @@ import URI from 'urijs';
5
5
  import { List, ListItem, Modal, Button } from '@patternfly/react-core';
6
6
  import { translate as __, sprintf } from 'foremanReact/common/I18n';
7
7
  import { foremanUrl } from 'foremanReact/common/helpers';
8
+ import { HOSTS_PATH } from 'foremanReact/routes/Hosts/constants';
8
9
  import { selectHosts, selectHostCount } from '../../JobWizardSelectors';
9
10
  import { HOSTS_TO_PREVIEW_AMOUNT } from '../../JobWizardConstants';
10
11
 
@@ -15,6 +16,7 @@ export const HostPreviewModal = ({ isOpen, setIsOpen, searchQuery }) => {
15
16
 
16
17
  return (
17
18
  <Modal
19
+ ouiaId="host-preview-modal"
18
20
  title={__('Preview Hosts')}
19
21
  isOpen={isOpen}
20
22
  onClose={() => setIsOpen(false)}
@@ -24,8 +26,9 @@ export const HostPreviewModal = ({ isOpen, setIsOpen, searchQuery }) => {
24
26
  {hosts.map(host => (
25
27
  <ListItem key={host.name}>
26
28
  <Button
29
+ ouiaId={`host-preview-${host}`}
27
30
  component="a"
28
- href={foremanUrl(`/hosts/${host.name}`)}
31
+ href={foremanUrl(`${HOSTS_PATH}/${host.name}`)}
29
32
  variant="link"
30
33
  target="_blank"
31
34
  rel="noreferrer"
@@ -38,6 +41,7 @@ export const HostPreviewModal = ({ isOpen, setIsOpen, searchQuery }) => {
38
41
  {hostsCount > HOSTS_TO_PREVIEW_AMOUNT && (
39
42
  <ListItem>
40
43
  <Button
44
+ ouiaId="host-preview-more"
41
45
  component="a"
42
46
  href={url.addSearch({ search: searchQuery })}
43
47
  variant="link"
@@ -14,6 +14,7 @@ const SelectedChip = ({ selected, setSelected, categoryName, setLabel }) => {
14
14
  return (
15
15
  <>
16
16
  <ChipGroup
17
+ ouiaId="hosts-chip-group"
17
18
  className="hosts-chip-group"
18
19
  categoryName={categoryName}
19
20
  isClosable
@@ -26,6 +27,7 @@ const SelectedChip = ({ selected, setSelected, categoryName, setLabel }) => {
26
27
  >
27
28
  {selected.map((result, index) => (
28
29
  <Chip
30
+ ouiaId={`${categoryName}-${result.id}`}
29
31
  key={index}
30
32
  id={`${categoryName}-${result.id}`}
31
33
  onClick={() => deleteItem(result.id)}
@@ -93,7 +95,12 @@ export const SelectedChips = ({
93
95
  setLabel={setLabel}
94
96
  />
95
97
  {showClear && (
96
- <Button variant="link" className="clear-chips" onClick={clearAll}>
98
+ <Button
99
+ ouiaId="clear-chips"
100
+ variant="link"
101
+ className="clear-chips"
102
+ onClick={clearAll}
103
+ >
97
104
  {__('Clear all filters')}
98
105
  </Button>
99
106
  )}
@@ -229,9 +229,10 @@ const HostsAndInputs = ({
229
229
  clearSearch={clearSearch}
230
230
  setLabel={setLabel}
231
231
  />
232
- <Text>
232
+ <Text ouiaId="host-preview-label">
233
233
  {__('Apply to')}{' '}
234
234
  <Button
235
+ ouiaId="host-preview-open-button"
235
236
  variant="link"
236
237
  isInline
237
238
  onClick={() => setHostPreviewOpen(true)}
@@ -247,7 +248,11 @@ const HostsAndInputs = ({
247
248
  setValue={setTemplateValues}
248
249
  />
249
250
  {!isEmpty(missingPermissions) && (
250
- <Alert variant="warning" title={__('Access denied')}>
251
+ <Alert
252
+ ouiaId="host-access-denied"
253
+ variant="warning"
254
+ title={__('Access denied')}
255
+ >
251
256
  <span>
252
257
  {__(
253
258
  `Missing the required permissions: ${missingPermissions.join(
@@ -46,6 +46,7 @@ const ReviewDetails = ({
46
46
  // eslint-disable-next-line react/prop-types
47
47
  const StepButton = ({ stepName, children }) => (
48
48
  <Button
49
+ ouiaId={`step-button-${stepName}`}
49
50
  variant="link"
50
51
  isInline
51
52
  onClick={() => {
@@ -91,6 +92,7 @@ const ReviewDetails = ({
91
92
  <div>
92
93
  {hostsCount} {__('hosts')}{' '}
93
94
  <Button
95
+ ouiaId="view-host-names"
94
96
  variant="link"
95
97
  isInline
96
98
  onClick={() => setHostPreviewOpen(true)}
@@ -140,6 +142,7 @@ const ReviewDetails = ({
140
142
  ),
141
143
  value: isAdvancedShown ? (
142
144
  <Button
145
+ ouiaId="hide-advanced-fields"
143
146
  variant="link"
144
147
  isInline
145
148
  onClick={() => {
@@ -150,6 +153,7 @@ const ReviewDetails = ({
150
153
  </Button>
151
154
  ) : (
152
155
  <Button
156
+ ouiaId="show-advanced-fields"
153
157
  variant="link"
154
158
  isInline
155
159
  onClick={() => {
@@ -14,6 +14,7 @@ export const PurposeField = ({ purpose, setPurpose }) => (
14
14
  )}
15
15
  >
16
16
  <TextInput
17
+ ouiaId="purpose"
17
18
  aria-label="purpose"
18
19
  type="text"
19
20
  value={purpose}
@@ -15,6 +15,7 @@ export const QueryType = ({ isTypeStatic, setIsTypeStatic }) => (
15
15
  )}
16
16
  >
17
17
  <Radio
18
+ ouiaId="query-type-static"
18
19
  isChecked={isTypeStatic}
19
20
  name="query-type"
20
21
  onChange={() => setIsTypeStatic(true)}
@@ -25,6 +26,7 @@ export const QueryType = ({ isTypeStatic, setIsTypeStatic }) => (
25
26
  </FormGroup>
26
27
  <FormGroup fieldId="query-type-dynamic">
27
28
  <Radio
29
+ ouiaId="query-type-dynamic"
28
30
  isChecked={!isTypeStatic}
29
31
  name="query-type"
30
32
  onChange={() => setIsTypeStatic(false)}
@@ -65,6 +65,7 @@ export const RepeatCron = ({ repeatData, setRepeatData, setValid }) => {
65
65
  isRequired
66
66
  >
67
67
  <TextInput
68
+ ouiaId="cronline"
68
69
  isRequired
69
70
  validated={cronline ? ValidatedOptions.noval : ValidatedOptions.error}
70
71
  aria-label="cronline"
@@ -34,6 +34,7 @@ export const RepeatHour = ({ repeatData, setRepeatData }) => {
34
34
  isRequired
35
35
  >
36
36
  <Select
37
+ ouiaId="repeat-on-hourly"
37
38
  id="repeat-on-hourly"
38
39
  variant={SelectVariant.typeahead}
39
40
  typeAheadAriaLabel="repeat-at-minute-typeahead"
@@ -75,6 +76,7 @@ export const RepeatHour = ({ repeatData, setRepeatData }) => {
75
76
  </Select>
76
77
  {isAlertOpen && (
77
78
  <Alert
79
+ ouiaId="repeat-on-hourly-alert"
78
80
  variant="danger"
79
81
  isInline
80
82
  title={__('Minute can only be a number between 0-59')}
@@ -19,6 +19,7 @@ export const RepeatMonth = ({ repeatData, setRepeatData, setValid }) => {
19
19
  <>
20
20
  <FormGroup label={__('Days')} isRequired>
21
21
  <TextInput
22
+ ouiaId="repeat-on-monthly-days"
22
23
  isRequired
23
24
  validated={days ? ValidatedOptions.noval : ValidatedOptions.error}
24
25
  aria-label="days"
@@ -44,6 +44,7 @@ export const RepeatWeek = ({ repeatData, setRepeatData, setValid }) => {
44
44
  <div id="repeat-on-weekly">
45
45
  {days.map((day, index) => (
46
46
  <Checkbox
47
+ ouiaId={`repeat-on-day-${index}`}
47
48
  aria-label={`${day} checkbox`}
48
49
  key={index}
49
50
  isChecked={daysOfWeek?.[index]}
@@ -61,6 +61,7 @@ export const ScheduleFuture = ({
61
61
  }
62
62
  />
63
63
  <Button
64
+ ouiaId="clear-datetime-start-button"
64
65
  variant="link"
65
66
  isInline
66
67
  className="clear-datetime-button"
@@ -101,6 +102,7 @@ export const ScheduleFuture = ({
101
102
  variant="link"
102
103
  isInline
103
104
  className="clear-datetime-button"
105
+ ouiaId="clear-datetime-end-button"
104
106
  onClick={() =>
105
107
  setScheduleValue(current => ({
106
108
  ...current,
@@ -89,6 +89,7 @@ export const ScheduleRecurring = ({
89
89
  <div className="pf-c-form">
90
90
  <FormGroup fieldId="schedule-starts-now">
91
91
  <Radio
92
+ ouiaId="schedule-start-now"
92
93
  isChecked={!isFuture}
93
94
  onChange={() =>
94
95
  setScheduleValue(current => ({
@@ -105,6 +106,7 @@ export const ScheduleRecurring = ({
105
106
  </FormGroup>
106
107
  <FormGroup fieldId="start-at-date">
107
108
  <Radio
109
+ ouiaId="schedule-start-at-date"
108
110
  isChecked={isFuture}
109
111
  onChange={() =>
110
112
  setScheduleValue(current => ({
@@ -161,6 +163,7 @@ export const ScheduleRecurring = ({
161
163
  <div className="pf-c-form">
162
164
  <FormGroup fieldId="schedule-ends-never">
163
165
  <Radio
166
+ ouiaId="schedule-never-ends"
164
167
  isChecked={isNeverEnds}
165
168
  onChange={() =>
166
169
  setScheduleValue(current => ({
@@ -184,6 +187,7 @@ export const ScheduleRecurring = ({
184
187
  helperTextInvalidIcon={<ExclamationCircleIcon />}
185
188
  >
186
189
  <Radio
190
+ ouiaId="schedule-ends-on-date"
187
191
  isChecked={!!ends}
188
192
  onChange={() =>
189
193
  setScheduleValue(current => ({
@@ -216,6 +220,7 @@ export const ScheduleRecurring = ({
216
220
  </FormGroup>
217
221
  <FormGroup fieldId="ends-after">
218
222
  <Radio
223
+ ouiaId="schedule-ends-after"
219
224
  isChecked={repeatAmount === 0 || !!repeatAmount}
220
225
  onChange={() =>
221
226
  setScheduleValue(current => ({
@@ -239,6 +244,7 @@ export const ScheduleRecurring = ({
239
244
  className="schedule-radio-repeat-text"
240
245
  >
241
246
  <TextInput
247
+ ouiaId="repeat-amount"
242
248
  id="repeat-amount"
243
249
  value={repeatAmount || ''}
244
250
  type="number"
@@ -24,6 +24,7 @@ export const ScheduleType = ({
24
24
  label={__('Select the type of execution')}
25
25
  >
26
26
  <Radio
27
+ ouiaId="schedule-type-now"
27
28
  isChecked={scheduleType === SCHEDULE_TYPES.NOW}
28
29
  name="schedule-type-now"
29
30
  id="schedule-type-now"
@@ -43,6 +44,7 @@ export const ScheduleType = ({
43
44
  </FormGroup>
44
45
  <FormGroup fieldId="schedule-type-future">
45
46
  <Radio
47
+ ouiaId="schedule-type-future"
46
48
  isChecked={scheduleType === SCHEDULE_TYPES.FUTURE}
47
49
  onChange={() => {
48
50
  setScheduleValue(current => ({
@@ -61,6 +63,7 @@ export const ScheduleType = ({
61
63
  </FormGroup>
62
64
  <FormGroup fieldId="schedule-type-recurring">
63
65
  <Radio
66
+ ouiaId="schedule-type-recurring"
64
67
  isChecked={scheduleType === SCHEDULE_TYPES.RECURRING}
65
68
  onChange={() => {
66
69
  setScheduleValue(current => ({
@@ -27,6 +27,7 @@ export const isValidDate = d => d instanceof Date && !Number.isNaN(d);
27
27
  export const ResetDefault = ({ setValue, defaultValue }) =>
28
28
  defaultValue && (
29
29
  <Button
30
+ ouiaId="reset-default"
30
31
  className="reset-default"
31
32
  component="a"
32
33
  variant="link"
@@ -59,6 +59,7 @@ export const GroupedSelectField = ({
59
59
  return (
60
60
  <FormGroup label={label} fieldId={fieldId}>
61
61
  <Select
62
+ ouiaId={fieldId}
62
63
  isGrouped
63
64
  variant={SelectVariant.typeahead}
64
65
  onToggle={setIsOpen}
@@ -14,6 +14,7 @@ export const NumberInput = ({ formProps, inputProps }) => {
14
14
  validated={validated}
15
15
  >
16
16
  <TextInput
17
+ ouiaId={name}
17
18
  aria-label={name}
18
19
  type="text"
19
20
  {...inputProps}
@@ -78,6 +78,7 @@ export const ResourceSelect = ({
78
78
  };
79
79
  return (
80
80
  <Select
81
+ ouiaId={name}
81
82
  toggleAriaLabel={`${name} toggle`}
82
83
  chipGroupComponent={<></>}
83
84
  variant={SelectVariant.typeahead}
@@ -76,6 +76,7 @@ export const SearchSelect = ({
76
76
  };
77
77
  return (
78
78
  <Select
79
+ ouiaId={name}
79
80
  toggleAriaLabel={`${name} toggle`}
80
81
  chipGroupComponent={<></>}
81
82
  variant={variant}
@@ -37,6 +37,7 @@ export const SelectField = ({
37
37
  isRequired={isRequired}
38
38
  >
39
39
  <Select
40
+ ouiaId={fieldId}
40
41
  selections={value}
41
42
  onSelect={onSelect}
42
43
  onToggle={setIsOpen}
@@ -3,7 +3,12 @@ import PropTypes from 'prop-types';
3
3
  import { Title } from '@patternfly/react-core';
4
4
 
5
5
  export const WizardTitle = ({ title, ...props }) => (
6
- <Title headingLevel="h2" className="wizard-title" {...props}>
6
+ <Title
7
+ ouiaId="wizard-title"
8
+ headingLevel="h2"
9
+ className="wizard-title"
10
+ {...props}
11
+ >
7
12
  {title}
8
13
  </Title>
9
14
  );
@@ -0,0 +1 @@
1
+ export const HOSTS_PATH = '/new/hosts';
@@ -53,6 +53,7 @@ const FeaturesDropdown = ({
53
53
  ?.filter(feature => feature.host_action_button)
54
54
  ?.map(({ name, label, id, description }) => (
55
55
  <DropdownItem
56
+ ouiaId={`schedule-a-job-dropdown-item-${id}`}
56
57
  onClick={() => dispatch(runFeature(hostId, label, name, hostSearch))}
57
58
  key={id}
58
59
  description={description}
@@ -64,18 +64,21 @@ const RecentJobsCard = ({ hostDetails: { name, id } }) => {
64
64
  onSelect={handleTabClick}
65
65
  >
66
66
  <Tab
67
+ ouiaId="finished-tab"
67
68
  eventKey={FINISHED_TAB}
68
69
  title={<TabTitleText>{__('Finished')}</TabTitleText>}
69
70
  >
70
71
  <RecentJobsTable hostId={id} status="failed+or+status%3D+succeeded" />
71
72
  </Tab>
72
73
  <Tab
74
+ ouiaId="running-tab"
73
75
  eventKey={RUNNING_TAB}
74
76
  title={<TabTitleText>{__('Running')}</TabTitleText>}
75
77
  >
76
78
  <RecentJobsTable hostId={id} status="running" />
77
79
  </Tab>
78
80
  <Tab
81
+ ouiaId="scheduled-tab"
79
82
  eventKey={SCHEDULED_TAB}
80
83
  title={<TabTitleText>{__('Scheduled')}</TabTitleText>}
81
84
  >
@@ -42,6 +42,7 @@ const RecentJobsTable = ({ status, hostId }) => {
42
42
  >
43
43
  {!!jobs?.length && (
44
44
  <TableComposable
45
+ ouiaId="recent-jobs-table"
45
46
  aria-label="recent-jobs-table"
46
47
  variant="compact"
47
48
  borders="compactBorderless"
@@ -55,7 +56,7 @@ const RecentJobsTable = ({ status, hostId }) => {
55
56
  start_at: startAt,
56
57
  description,
57
58
  }) => (
58
- <Tr key={id}>
59
+ <Tr ouiaId="recent-jobs-table-row" key={id}>
59
60
  <Td modifier="truncate" key={`name-${id}`}>
60
61
  <a href={foremanUrl(`/job_invocations/${id}`)}>
61
62
  {description}
@@ -29,6 +29,7 @@ const RexInterface = ({ isLoading, onChange }) => (
29
29
  }
30
30
  >
31
31
  <TextInput
32
+ ouiaId="reg_rex_interface_input"
32
33
  type="text"
33
34
  onBlur={e => onChange({ remoteExecutionInterface: e.target.value })}
34
35
  id="reg_rex_interface_input"
@@ -36,6 +36,7 @@ const RexPull = ({ isLoading, onChange, pluginValues, configParams }) => (
36
36
  fieldId="registration_setup_remote_execution_pull"
37
37
  >
38
38
  <FormSelect
39
+ ouiaId="registration_setup_remote_execution_pull"
39
40
  value={pluginValues.setupRemoteExecutionPull}
40
41
  onChange={setupRemoteExecutionPull =>
41
42
  onChange({ setupRemoteExecutionPull })
@@ -29,6 +29,7 @@ exports[`RexInterface renders 1`] = `
29
29
  id="reg_rex_interface_input"
30
30
  isDisabled={false}
31
31
  onBlur={[Function]}
32
+ ouiaId="reg_rex_interface_input"
32
33
  type="text"
33
34
  />
34
35
  </FormGroup>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_remote_execution
3
3
  version: !ruby/object:Gem::Version
4
- version: 13.0.0
4
+ version: 13.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Remote Execution team
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-12 00:00:00.000000000 Z
11
+ date: 2024-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface
@@ -436,8 +436,10 @@ files:
436
436
  - test/unit/template_invocation_input_value_test.rb
437
437
  - webpack/JobInvocationDetail/JobInvocationActions.js
438
438
  - webpack/JobInvocationDetail/JobInvocationConstants.js
439
+ - webpack/JobInvocationDetail/JobInvocationDetail.scss
439
440
  - webpack/JobInvocationDetail/JobInvocationOverview.js
440
441
  - webpack/JobInvocationDetail/JobInvocationSelectors.js
442
+ - webpack/JobInvocationDetail/JobInvocationSystemStatusChart.js
441
443
  - webpack/JobInvocationDetail/index.js
442
444
  - webpack/JobWizard/Footer.js
443
445
  - webpack/JobWizard/JobWizard.js
@@ -518,6 +520,7 @@ files:
518
520
  - webpack/__mocks__/foremanReact/redux/API/APISelectors.js
519
521
  - webpack/__mocks__/foremanReact/redux/API/index.js
520
522
  - webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware/IntervalSelectors.js
523
+ - webpack/__mocks__/foremanReact/routes/Hosts/constants.js
521
524
  - webpack/__mocks__/foremanReact/routes/RouterSelector.js
522
525
  - webpack/__mocks__/foremanReact/routes/common/PageLayout/PageLayout.js
523
526
  - webpack/global_index.js
@@ -576,7 +579,7 @@ homepage: https://github.com/theforeman/foreman_remote_execution
576
579
  licenses:
577
580
  - GPL-3.0
578
581
  metadata: {}
579
- post_install_message:
582
+ post_install_message:
580
583
  rdoc_options: []
581
584
  require_paths:
582
585
  - lib
@@ -594,8 +597,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
594
597
  - !ruby/object:Gem::Version
595
598
  version: '0'
596
599
  requirements: []
597
- rubygems_version: 3.3.26
598
- signing_key:
600
+ rubygems_version: 3.3.27
601
+ signing_key:
599
602
  specification_version: 4
600
603
  summary: A plugin bringing remote execution to the Foreman, completing the config
601
604
  management functionality with remote management functionality.