katello 4.8.0.rc2 → 4.8.1

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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/v2/simple_content_access_controller.rb +3 -1
  3. data/app/lib/actions/katello/content_view/publish.rb +2 -9
  4. data/app/lib/actions/katello/organization/simple_content_access/enable.rb +10 -0
  5. data/app/lib/actions/katello/organization/simple_content_access/prepare_content_overrides.rb +36 -0
  6. data/app/lib/actions/katello/organization/simple_content_access/toggle.rb +12 -2
  7. data/app/lib/katello/util/content_overrides_migrator.rb +98 -0
  8. data/app/models/katello/content_view.rb +10 -6
  9. data/app/models/katello/host/content_facet.rb +10 -3
  10. data/db/migrate/20220110223754_update_disconnected_settings.rb +8 -4
  11. data/db/migrate/20230119003859_ensure_repo_username_password_nil_not_blank.rb +1 -1
  12. data/lib/katello/plugin.rb +0 -12
  13. data/lib/katello/version.rb +1 -1
  14. data/locale/bn/LC_MESSAGES/katello.mo +0 -0
  15. data/locale/cs/LC_MESSAGES/katello.mo +0 -0
  16. data/locale/de/LC_MESSAGES/katello.mo +0 -0
  17. data/locale/en/LC_MESSAGES/katello.mo +0 -0
  18. data/locale/es/LC_MESSAGES/katello.mo +0 -0
  19. data/locale/fr/LC_MESSAGES/katello.mo +0 -0
  20. data/locale/gu/LC_MESSAGES/katello.mo +0 -0
  21. data/locale/hi/LC_MESSAGES/katello.mo +0 -0
  22. data/locale/it/LC_MESSAGES/katello.mo +0 -0
  23. data/locale/ja/LC_MESSAGES/katello.mo +0 -0
  24. data/locale/ka/LC_MESSAGES/katello.mo +0 -0
  25. data/locale/kn/LC_MESSAGES/katello.mo +0 -0
  26. data/locale/ko/LC_MESSAGES/katello.mo +0 -0
  27. data/locale/mr/LC_MESSAGES/katello.mo +0 -0
  28. data/locale/or/LC_MESSAGES/katello.mo +0 -0
  29. data/locale/pa/LC_MESSAGES/katello.mo +0 -0
  30. data/locale/pt/LC_MESSAGES/katello.mo +0 -0
  31. data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
  32. data/locale/ru/LC_MESSAGES/katello.mo +0 -0
  33. data/locale/ta/LC_MESSAGES/katello.mo +0 -0
  34. data/locale/te/LC_MESSAGES/katello.mo +0 -0
  35. data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
  36. data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
  37. data/webpack/components/Content/{ContentPage.js → GenericContentPage.js} +7 -4
  38. data/webpack/components/Content/__tests__/ContentTable.test.js +1 -1
  39. data/webpack/components/Content/__tests__/GenericContentPage.test.js +35 -0
  40. data/webpack/components/Search/SearchText.js +70 -0
  41. data/webpack/components/Table/EmptyStateMessage.js +2 -2
  42. data/webpack/components/Table/TableWrapper.js +4 -0
  43. data/webpack/components/extensions/HostDetails/HostDetailsConstants.js +0 -1
  44. data/webpack/components/extensions/HostDetails/HostDetailsSelectors.js +0 -6
  45. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsTab.js +2 -2
  46. data/webpack/components/extensions/HostDetails/Tabs/__tests__/moduleStreamsTab.test.js +76 -0
  47. data/webpack/components/extensions/SearchBar/SearchBarConstants.js +3 -0
  48. data/webpack/components/extensions/SearchBar/SearchBarHooks.js +50 -0
  49. data/webpack/components/extensions/SearchBar/SearchBarReducer.js +14 -0
  50. data/webpack/components/extensions/SearchBar/SearchBarSelectors.js +5 -0
  51. data/webpack/redux/reducers/index.js +2 -2
  52. data/webpack/scenes/AlternateContentSources/Create/__tests__/acsCreate.test.js +1 -13
  53. data/webpack/scenes/AlternateContentSources/MainTable/ACSTable.js +1 -0
  54. data/webpack/scenes/Content/{ContentPage.js → GenericContentPage.js} +2 -2
  55. data/webpack/scenes/Content/__tests__/contentTable.test.js +2 -2
  56. data/webpack/scenes/Content/index.js +2 -2
  57. data/webpack/scenes/ContentViews/Details/Filters/Rules/ContainerTag/AddEditContainerTagRuleModal.js +14 -17
  58. data/webpack/scenes/ContentViews/Details/Filters/Rules/Package/AddEditPackageRuleModal.js +24 -28
  59. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVContainerImageFilterContent.test.js +11 -18
  60. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVRpmFilterContent.test.js +10 -23
  61. data/webpack/scenes/ContentViews/Details/Filters/__tests__/ContentViewPackageGroupFilter.test.js +0 -2
  62. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.test.js +1 -7
  63. data/webpack/scenes/ContentViews/expansions/__tests__/contentViewComponentsModal.test.js +0 -2
  64. data/webpack/scenes/ModuleStreams/ModuleStreamsPage.js +2 -2
  65. data/webpack/scenes/ModuleStreams/__tests__/ModuleStreamPage.test.js +2 -2
  66. data/webpack/scenes/ModuleStreams/__tests__/__snapshots__/ModuleStreamPage.test.js.snap +1 -1
  67. data/webpack/scenes/Settings/SettingsConstants.js +2 -3
  68. data/webpack/scenes/Settings/SettingsReducer.js +2 -16
  69. data/webpack/scenes/Settings/SettingsSelectors.js +2 -2
  70. data/webpack/test-utils/react-testing-lib-wrapper.js +0 -6
  71. metadata +45 -26
  72. data/webpack/components/Content/__tests__/ContentPage.test.js +0 -32
  73. data/webpack/components/Content/__tests__/__snapshots__/ContentPage.test.js.snap +0 -89
  74. data/webpack/components/Search/Search.js +0 -156
  75. data/webpack/components/Search/__tests__/search.test.js +0 -104
  76. data/webpack/components/Search/helpers.js +0 -6
  77. data/webpack/components/Search/index.js +0 -15
  78. data/webpack/components/TypeAhead/TypeAhead.js +0 -157
  79. data/webpack/components/TypeAhead/TypeAhead.scss +0 -7
  80. data/webpack/components/TypeAhead/helpers/commonPropTypes.js +0 -35
  81. data/webpack/components/TypeAhead/helpers/helpers.js +0 -32
  82. data/webpack/components/TypeAhead/index.js +0 -3
  83. data/webpack/components/TypeAhead/pf3Search/TypeAheadInput.js +0 -44
  84. data/webpack/components/TypeAhead/pf3Search/TypeAheadItems.js +0 -56
  85. data/webpack/components/TypeAhead/pf3Search/TypeAheadSearch.js +0 -53
  86. data/webpack/components/TypeAhead/pf4Search/TypeAheadInput.js +0 -66
  87. data/webpack/components/TypeAhead/pf4Search/TypeAheadInput.scss +0 -12
  88. data/webpack/components/TypeAhead/pf4Search/TypeAheadItems.js +0 -59
  89. data/webpack/components/TypeAhead/pf4Search/TypeAheadSearch.js +0 -81
@@ -93,6 +93,82 @@ test('Can handle no Module streams being present', async (done) => {
93
93
  act(done);
94
94
  });
95
95
 
96
+ test('When there are no search results, can display an empty state with a clear search link that works', async (done) => {
97
+ // Setup autocomplete with mockForemanAutoComplete since we aren't adding /katello
98
+ const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
99
+ const noResults = {
100
+ total: 0,
101
+ subtotal: 0,
102
+ page: 1,
103
+ search: 'bad search',
104
+ per_page: 20,
105
+ results: [],
106
+ };
107
+
108
+ const initialScope = nockInstance
109
+ .get(hostModuleStreams)
110
+ .query(true)
111
+ .times(1)
112
+ .reply(200, mockModuleStreams);
113
+
114
+ const badSearchScope = nockInstance
115
+ .get(hostModuleStreams)
116
+ .query({
117
+ sort_by: 'name',
118
+ sort_order: 'asc',
119
+ per_page: '20',
120
+ page: '1',
121
+ search: 'bad search',
122
+ })
123
+ .reply(200, noResults);
124
+
125
+ const badAutoCompleteScope =
126
+ mockForemanAutocomplete(
127
+ nockInstance,
128
+ autocompleteUrl,
129
+ true,
130
+ [],
131
+ 2, // times
132
+ );
133
+
134
+ const scopeWithoutSearch = nockInstance
135
+ .get(hostModuleStreams)
136
+ .query(true)
137
+ .reply(200, mockModuleStreams);
138
+
139
+ const { queryByText, getByRole } = renderWithRedux(<ModuleStreamsTab />, renderOptions());
140
+
141
+
142
+ await patientlyWaitFor(() => expect(queryByText(firstModuleStreams.name)).toBeInTheDocument());
143
+
144
+ const searchInput = getByRole('textbox', { name: 'Search input' });
145
+ // Foreman SearchAutocomplete doesn't run onSearchChange unless the element is focused!
146
+ searchInput.focus();
147
+
148
+ fireEvent.change(searchInput, { target: { value: 'bad search' } });
149
+ expect(searchInput.value).toBe('bad search');
150
+ const searchButton = getByRole('button', { name: 'Search' });
151
+ expect(searchButton).not.toHaveAttribute('aria-disabled', true);
152
+ fireEvent.click(searchButton);
153
+
154
+ await patientlyWaitFor(() => expect(queryByText('Your search returned no matching Module streams.')).toBeInTheDocument());
155
+ // Now click the clear search link and assert that the search is cleared and the results are back
156
+ const clearSearchLink = getByRole('button', { name: 'Clear search' });
157
+ fireEvent.click(clearSearchLink);
158
+
159
+ await patientlyWaitFor(() => {
160
+ expect(queryByText(firstModuleStreams.name)).toBeInTheDocument();
161
+ expect(getByRole('textbox', { name: 'Search input' }).value).toBe('');
162
+ expect(queryByText('Clear search')).not.toBeInTheDocument();
163
+ });
164
+
165
+ assertNockRequest(initialScope);
166
+ assertNockRequest(badAutoCompleteScope);
167
+ assertNockRequest(badSearchScope);
168
+ assertNockRequest(scopeWithoutSearch);
169
+ assertNockRequest(autocompleteScope, done);
170
+ });
171
+
96
172
  test('Can filter results based on status', async (done) => {
97
173
  const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
98
174
  const scope = nockInstance
@@ -0,0 +1,3 @@
1
+ export const SET_CLEAR_SEARCH = 'SET_CLEAR_SEARCH';
2
+
3
+ export default SET_CLEAR_SEARCH;
@@ -0,0 +1,50 @@
1
+ import { useEffect, useCallback, useRef } from 'react';
2
+ import { useDispatch, useSelector } from 'react-redux';
3
+ import { selectSearchBarClearSearch } from './SearchBarSelectors';
4
+
5
+ export const useClearSearch = ({
6
+ updateSearchQuery,
7
+ }) => {
8
+ const dispatch = useDispatch();
9
+ // We keep the clearSearch function in Redux to avoid prop drilling and make EmptyStateMessage
10
+ // more reusable both with and without TableWrapper.
11
+ const existingClearSearch = useSelector(selectSearchBarClearSearch);
12
+ // In Katello we don't have access to Foreman <SearchBar /> component's internal state,
13
+ // so we don't have an easy way to clear the search input. We can use a counter to
14
+ // pass as a key prop to the <SearchBar /> component, which will force it to reset
15
+ // its internal state when clearSearch is called.
16
+ const counter = useRef(0);
17
+
18
+ const clearSearch = useCallback(() => {
19
+ counter.current += 1; // reset the text input
20
+ if (typeof updateSearchQuery !== 'function') {
21
+ // eslint-disable-next-line no-console
22
+ console.error('You must pass the updateSearchQuery function to useClearSearch');
23
+ return;
24
+ }
25
+ updateSearchQuery(''); // make a new API call with blank search query
26
+ }, [updateSearchQuery]);
27
+
28
+ useEffect(() => {
29
+ if (typeof existingClearSearch !== 'function') {
30
+ dispatch({
31
+ type: 'SET_CLEAR_SEARCH',
32
+ payload: clearSearch,
33
+ });
34
+ }
35
+ }, [dispatch, existingClearSearch, clearSearch]);
36
+
37
+ // eslint-disable-next-line arrow-body-style
38
+ useEffect(() => {
39
+ return function cleanupClearSearch() {
40
+ dispatch({
41
+ type: 'SET_CLEAR_SEARCH',
42
+ payload: {},
43
+ });
44
+ };
45
+ }, [dispatch]);
46
+
47
+ return `search-bar-${counter.current}`;
48
+ };
49
+
50
+ export default useClearSearch;
@@ -0,0 +1,14 @@
1
+ import Immutable from 'seamless-immutable';
2
+
3
+ import { SET_CLEAR_SEARCH } from './SearchBarConstants';
4
+
5
+ const initialState = Immutable({ clearSearch: undefined });
6
+
7
+ export default (state = initialState, action) => {
8
+ switch (action.type) {
9
+ case SET_CLEAR_SEARCH:
10
+ return state.set('clearSearch', action.payload);
11
+ default:
12
+ return state;
13
+ }
14
+ };
@@ -0,0 +1,5 @@
1
+ export const selectSearchBarState = state =>
2
+ state.katello.searchBar;
3
+
4
+ export const selectSearchBarClearSearch = state =>
5
+ selectSearchBarState(state)?.clearSearch;
@@ -4,7 +4,6 @@ import redHatRepositories from './RedHatRepositories';
4
4
  import { subscriptions } from '../../scenes/Subscriptions';
5
5
  import { upstreamSubscriptions } from '../../scenes/Subscriptions/UpstreamSubscriptions';
6
6
  import { manifestHistory } from '../../scenes/Subscriptions/Manifest';
7
- import settings from '../../scenes/Settings';
8
7
  import { subscriptionDetails } from '../../scenes/Subscriptions/Details';
9
8
  import { setOrganization } from '../../components/SelectOrg/SetOrganization';
10
9
  import { moduleStreams } from '../../scenes/ModuleStreams';
@@ -13,6 +12,7 @@ import { moduleStreamDetails } from '../../scenes/ModuleStreams/Details';
13
12
  import { reducers as systemStatuses } from '../../components/extensions/about';
14
13
  import { contentViewDetails } from '../../scenes/ContentViews/Details';
15
14
  import hostDetails from '../../components/extensions/HostDetails/HostDetailsReducer';
15
+ import searchBar from '../../components/extensions/SearchBar/SearchBarReducer';
16
16
 
17
17
  export default combineReducers({
18
18
  organization,
@@ -20,13 +20,13 @@ export default combineReducers({
20
20
  subscriptions,
21
21
  upstreamSubscriptions,
22
22
  manifestHistory,
23
- settings,
24
23
  subscriptionDetails,
25
24
  setOrganization,
26
25
  moduleStreams,
27
26
  moduleStreamDetails,
28
27
  contentViewDetails,
29
28
  hostDetails,
29
+ searchBar,
30
30
  ...organizationProductsReducers,
31
31
  ...systemStatuses,
32
32
  });
@@ -3,7 +3,7 @@ import * as reactRedux from 'react-redux';
3
3
  import { Route } from 'react-router-dom';
4
4
  import { act, fireEvent, patientlyWaitFor, renderWithRedux } from 'react-testing-lib-wrapper';
5
5
  import api, { foremanApi } from '../../../../services/api';
6
- import { assertNockRequest, mockAutocomplete, mockSetting, nockInstance } from '../../../../test-utils/nockWrapper';
6
+ import { assertNockRequest, mockAutocomplete, nockInstance } from '../../../../test-utils/nockWrapper';
7
7
  import ACSTable from '../../MainTable/ACSTable';
8
8
  import contentCredentialResult from './contentCredentials.fixtures';
9
9
  import smartProxyResult from './smartProxy.fixtures';
@@ -70,18 +70,6 @@ const renderOptions = {
70
70
  },
71
71
  };
72
72
 
73
- let searchDelayScope;
74
- let autoSearchScope;
75
- beforeEach(() => {
76
- searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
77
- autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
78
- });
79
-
80
- afterEach(() => {
81
- assertNockRequest(searchDelayScope);
82
- assertNockRequest(autoSearchScope);
83
- });
84
-
85
73
  test('Can show add ACS button if can_create is true', async (done) => {
86
74
  const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
87
75
  const scope = nockInstance
@@ -107,6 +107,7 @@ const ACSTable = () => {
107
107
  const onBulkDelete = (ids) => {
108
108
  setDeleting(true);
109
109
  dispatch(bulkDeleteACS({ ids }, () => {
110
+ setDeleting(false);
110
111
  if (acsId && ids.has(Number(acsId))) {
111
112
  push('/alternate_content_sources');
112
113
  } else {
@@ -12,7 +12,7 @@ import { getContentTypes } from './ContentActions';
12
12
  import Loading from '../../components/Loading';
13
13
  import EmptyStateMessage from '../../components/Table/EmptyStateMessage';
14
14
 
15
- const ContentPage = () => {
15
+ const GenericContentPage = () => {
16
16
  const dispatch = useDispatch();
17
17
  const contentTypesResponse = useSelector(selectContentTypes);
18
18
  const contentTypesStatus = useSelector(selectContentTypesStatus);
@@ -86,4 +86,4 @@ const ContentPage = () => {
86
86
  );
87
87
  };
88
88
 
89
- export default ContentPage;
89
+ export default GenericContentPage;
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { renderWithRedux, patientlyWaitFor } from 'react-testing-lib-wrapper';
3
3
  import { nockInstance, assertNockRequest, mockAutocomplete } from '../../../test-utils/nockWrapper';
4
4
  import api from '../../../services/api';
5
- import ContentPage from '../ContentPage';
5
+ import GenericContentPage from '../GenericContentPage';
6
6
  import ansibleCollectionsResponse from './ansibleCollections.fixtures';
7
7
  import contentTypesResponse from './contentTypes.fixtures.json';
8
8
  import pythonPackagesResponse from './pythonPackages.fixtures.json';
@@ -29,7 +29,7 @@ test('Can call API for Python Packages and show table on page load', async (done
29
29
  .reply(200, contentTypesResponse);
30
30
 
31
31
  const { queryByText, getAllByText } =
32
- renderWithRedux(<ContentPage />);
32
+ renderWithRedux(<GenericContentPage />);
33
33
 
34
34
  expect(queryByText(firstPackage.name)).toBeNull();
35
35
  await patientlyWaitFor(() => {
@@ -1,4 +1,4 @@
1
1
  import { withRouter } from 'react-router-dom';
2
- import ContentPage from './ContentPage';
2
+ import GenericContentPage from './GenericContentPage';
3
3
 
4
- export default withRouter(ContentPage);
4
+ export default withRouter(GenericContentPage);
@@ -5,7 +5,7 @@ import { translate as __ } from 'foremanReact/common/I18n';
5
5
  import { Modal, ModalVariant, Form, FormGroup, ActionGroup, Button } from '@patternfly/react-core';
6
6
  import { addCVFilterRule, editCVFilterRule, getCVFilterRules } from '../../../ContentViewDetailActions';
7
7
  import { orgId } from '../../../../../../services/api';
8
- import Search from '../../../../../../components/Search/Search';
8
+ import SearchText from '../../../../../../components/Search/SearchText';
9
9
 
10
10
  const AddEditContainerTagRuleModal = ({
11
11
  onClose, filterId, selectedFilterRuleData, repositoryIds,
@@ -16,7 +16,7 @@ const AddEditContainerTagRuleModal = ({
16
16
  const [saving, setSaving] = useState(false);
17
17
  const isEditing = name && id;
18
18
 
19
- const autoCompleteEndpoint = '/docker_tags/auto_complete_name';
19
+ const autoCompleteEndpoint = '/katello/api/v2/docker_tags/auto_complete_name';
20
20
 
21
21
  const onSubmit = () => {
22
22
  setSaving(true);
@@ -36,13 +36,10 @@ const AddEditContainerTagRuleModal = ({
36
36
  onClose();
37
37
  };
38
38
 
39
- const getAutoCompleteParams = term => ({
40
- endpoint: autoCompleteEndpoint,
41
- params: {
42
- organization_id: orgId(),
43
- term,
44
- repoids: repositoryIds,
45
- },
39
+ const searchDataProp = term => ({
40
+ organization_id: orgId(),
41
+ term,
42
+ repoids: repositoryIds,
46
43
  });
47
44
 
48
45
  return (
@@ -59,14 +56,14 @@ const AddEditContainerTagRuleModal = ({
59
56
  }}
60
57
  >
61
58
  <FormGroup label={__('Tag name')} isRequired fieldId="tag_name">
62
- <Search
63
- patternfly4
64
- initialInputValue={tagName}
65
- onSearch={() => {}}
66
- getAutoCompleteParams={getAutoCompleteParams}
67
- foremanApiAutoComplete={false}
68
- isTextInput
69
- setTextInputValue={setTagName}
59
+ <SearchText
60
+ data={{
61
+ autocomplete: {
62
+ url: autoCompleteEndpoint,
63
+ apiParams: tag => searchDataProp(tag),
64
+ },
65
+ }}
66
+ onSearchChange={setTagName}
70
67
  />
71
68
  </FormGroup>
72
69
  <ActionGroup>
@@ -13,7 +13,7 @@ import {
13
13
  selectCreateFilterRuleStatus,
14
14
  } from '../../../ContentViewDetailSelectors';
15
15
  import { orgId } from '../../../../../../services/api';
16
- import Search from '../../../../../../components/Search/Search';
16
+ import SearchText from '../../../../../../components/Search/SearchText';
17
17
 
18
18
  const AddEditPackageRuleModal = ({
19
19
  filterId, onClose, selectedFilterRuleData, repositoryIds,
@@ -27,8 +27,8 @@ const AddEditPackageRuleModal = ({
27
27
  max_version: editingMaxVersion,
28
28
  } = selectedFilterRuleData || {};
29
29
 
30
- const architectureAutoCompleteEndpoint = '/packages/auto_complete_arch';
31
- const nameAutoCompleteEndpoint = '/packages/auto_complete_name';
30
+ const architectureAutoCompleteEndpoint = '/katello/api/v2/packages/auto_complete_arch';
31
+ const nameAutoCompleteEndpoint = '/katello/api/v2/packages/auto_complete_name';
32
32
 
33
33
  const isEditing = !!selectedFilterRuleData;
34
34
 
@@ -118,14 +118,11 @@ const AddEditPackageRuleModal = ({
118
118
  }
119
119
  }, [status, setSaving]);
120
120
 
121
- const getAutoCompleteParams = (term, autoCompleteEndpoint) => ({
122
- endpoint: autoCompleteEndpoint,
123
- params: {
124
- organization_id: orgId(),
125
- term,
126
- repoids: repositoryIds,
127
- non_modular: true,
128
- },
121
+ const searchDataProp = term => ({
122
+ organization_id: orgId(),
123
+ term,
124
+ repoids: repositoryIds,
125
+ non_modular: true,
129
126
  });
130
127
 
131
128
  return (
@@ -142,26 +139,25 @@ const AddEditPackageRuleModal = ({
142
139
  }}
143
140
  >
144
141
  <FormGroup label={__('RPM name')} isRequired fieldId="name">
145
- <Search
146
- patternfly4
147
- initialInputValue={name}
148
- onSearch={() => {}}
149
- getAutoCompleteParams={term => getAutoCompleteParams(term, nameAutoCompleteEndpoint)}
150
- foremanApiAutoComplete={false}
151
- isTextInput
152
- setTextInputValue={setName}
142
+ <SearchText
143
+ data={{
144
+ autocomplete: {
145
+ url: nameAutoCompleteEndpoint,
146
+ apiParams: input => searchDataProp(input),
147
+ },
148
+ }}
149
+ onSearchChange={setName}
153
150
  />
154
151
  </FormGroup>
155
152
  <FormGroup label={__('Architecture')} fieldId="architecture">
156
- <Search
157
- patternfly4
158
- initialInputValue={architecture}
159
- onSearch={() => {}}
160
- getAutoCompleteParams={term =>
161
- getAutoCompleteParams(term, architectureAutoCompleteEndpoint)}
162
- foremanApiAutoComplete={false}
163
- isTextInput
164
- setTextInputValue={setArchitecture}
153
+ <SearchText
154
+ data={{
155
+ autocomplete: {
156
+ url: architectureAutoCompleteEndpoint,
157
+ apiParams: arch => searchDataProp(arch),
158
+ },
159
+ }}
160
+ onSearchChange={setArchitecture}
165
161
  />
166
162
  </FormGroup>
167
163
  <FormGroup label={__('Version')} fieldId="version_comparator">
@@ -7,7 +7,6 @@ import {
7
7
  nockInstance,
8
8
  assertNockRequest,
9
9
  mockAutocomplete,
10
- mockSetting,
11
10
  } from '../../../../../test-utils/nockWrapper';
12
11
  import api from '../../../../../services/api';
13
12
  import CVContainerImageFilterContent from '../CVContainerImageFilterContent';
@@ -140,8 +139,6 @@ test('Can add filter rules', async (done) => {
140
139
  2,
141
140
  );
142
141
  const autocompleteNameScope = mockAutocomplete(nockInstance, autocompleteNameUrl, true, [], 2);
143
- const searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
144
- const autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
145
142
 
146
143
  const cvFiltersScope = nockInstance
147
144
  .get(cvFilterRulesPath)
@@ -158,7 +155,7 @@ test('Can add filter rules', async (done) => {
158
155
  .query(true)
159
156
  .reply(200, { ...cvFilterFixtures, results: [...cvFilterFixtures.results, addedRule] });
160
157
 
161
- const { queryByText, getByLabelText } =
158
+ const { queryByText, getByLabelText, getAllByLabelText } =
162
159
  renderWithRedux(
163
160
  withCVRoute(<CVContainerImageFilterContent filterId={195} details={details} />),
164
161
  renderOptions,
@@ -177,7 +174,9 @@ test('Can add filter rules', async (done) => {
177
174
  expect(getByLabelText('add_edit_filter_rule')).toHaveAttribute('aria-disabled', 'true');
178
175
  });
179
176
 
180
- fireEvent.change(getByLabelText('text input for search'), { target: { value: 'new-rule' } });
177
+ const searchInput = getAllByLabelText('Search input')[1];
178
+ searchInput.focus();
179
+ fireEvent.change(searchInput, { target: { value: 'new-rule' } });
181
180
  fireEvent.submit(getByLabelText('add_edit_filter_rule'));
182
181
 
183
182
  await patientlyWaitFor(() => {
@@ -185,8 +184,6 @@ test('Can add filter rules', async (done) => {
185
184
  });
186
185
 
187
186
  assertNockRequest(autocompleteScope);
188
- assertNockRequest(searchDelayScope);
189
- assertNockRequest(autoSearchScope);
190
187
  assertNockRequest(cvFiltersScope);
191
188
  assertNockRequest(cvFilterAddScope);
192
189
  assertNockRequest(autocompleteNameScope);
@@ -205,8 +202,6 @@ test('Can edit filter rules', async (done) => {
205
202
  2,
206
203
  );
207
204
  const autocompleteNameScope = mockAutocomplete(nockInstance, autocompleteNameUrl, true, [], 2);
208
- const searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
209
- const autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
210
205
 
211
206
  const cvFiltersScope = nockInstance
212
207
  .get(cvFilterRulesPath)
@@ -231,7 +226,9 @@ test('Can edit filter rules', async (done) => {
231
226
  }),
232
227
  });
233
228
 
234
- const { queryByText, getAllByLabelText, getByLabelText } =
229
+ const {
230
+ queryByText, getAllByLabelText, getByLabelText,
231
+ } =
235
232
  renderWithRedux(
236
233
  withCVRoute(<CVContainerImageFilterContent filterId={195} details={details} />),
237
234
  renderOptions,
@@ -258,7 +255,9 @@ test('Can edit filter rules', async (done) => {
258
255
  expect(getByLabelText('add_edit_filter_rule')).toHaveAttribute('aria-disabled', 'false');
259
256
  });
260
257
 
261
- fireEvent.change(getByLabelText('text input for search'), { target: { value: 'changed-name' } });
258
+ const searchInput = getAllByLabelText('Search input')[1];
259
+ searchInput.focus();
260
+ fireEvent.change(searchInput, { target: { value: 'changed-name' } });
262
261
  fireEvent.submit(getByLabelText('add_edit_filter_rule'));
263
262
 
264
263
  await patientlyWaitFor(() => {
@@ -266,8 +265,6 @@ test('Can edit filter rules', async (done) => {
266
265
  });
267
266
 
268
267
  assertNockRequest(autocompleteScope);
269
- assertNockRequest(searchDelayScope);
270
- assertNockRequest(autoSearchScope);
271
268
  assertNockRequest(cvFiltersScope);
272
269
  assertNockRequest(cvFilterAddScope);
273
270
  assertNockRequest(autocompleteNameScope);
@@ -284,8 +281,6 @@ test('Shows call-to-action when there are no filter rules', async (done) => {
284
281
  2,
285
282
  );
286
283
  const autocompleteNameScope = mockAutocomplete(nockInstance, autocompleteNameUrl, true, [], 2);
287
- const searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
288
- const autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
289
284
  const cvFiltersScope = nockInstance
290
285
  .get(cvFilterRulesPath)
291
286
  .times(2)
@@ -302,13 +297,11 @@ test('Shows call-to-action when there are no filter rules', async (done) => {
302
297
  await patientlyWaitFor(() => expect(queryByLabelText('add_filter_rule_empty_state')).toBeInTheDocument());
303
298
  fireEvent.click(queryByLabelText('add_filter_rule_empty_state'));
304
299
  await patientlyWaitFor(() => {
305
- expect(getAllByLabelText('text input for search')[0]).toBeInTheDocument();
300
+ expect(getAllByLabelText('Search input')[0]).toBeInTheDocument();
306
301
  });
307
302
 
308
303
  assertNockRequest(autocompleteScope);
309
304
  assertNockRequest(autocompleteNameScope);
310
- assertNockRequest(searchDelayScope);
311
- assertNockRequest(autoSearchScope);
312
305
  assertNockRequest(cvFiltersScope, done);
313
306
  act(done);
314
307
  });
@@ -8,7 +8,6 @@ import {
8
8
  nockInstance,
9
9
  assertNockRequest,
10
10
  mockAutocomplete,
11
- mockSetting,
12
11
  } from '../../../../../test-utils/nockWrapper';
13
12
  import api from '../../../../../services/api';
14
13
  import cvFilterDetails from './cvPackageFilterDetail.fixtures.json';
@@ -163,8 +162,6 @@ test('Can add package rules to filter in a self-closing modal', async (done) =>
163
162
  nockInstance, autocompleteArchUrl, true,
164
163
  undefined, 2,
165
164
  );
166
- const searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0, 3);
167
- const autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing', undefined, 3);
168
165
 
169
166
  const cvFiltersScope = nockInstance
170
167
  .get(cvFiltersPath)
@@ -214,20 +211,22 @@ test('Can add package rules to filter in a self-closing modal', async (done) =>
214
211
  });
215
212
  getByLabelText('add_rpm_rule').click();
216
213
  await patientlyWaitFor(() => {
217
- expect(getAllByLabelText('text input for search')[0]).toBeInTheDocument();
218
- expect(getAllByLabelText('text input for search')[1]).toBeInTheDocument();
214
+ expect(getAllByLabelText('Search input')[0]).toBeInTheDocument();
215
+ expect(getAllByLabelText('Search input')[1]).toBeInTheDocument();
219
216
  expect(getByLabelText('add_package_filter_rule')).toBeInTheDocument();
220
217
  });
221
- fireEvent.change(getAllByLabelText('text input for search')[0], { target: { value: 'elephant' } });
222
- fireEvent.change(getAllByLabelText('text input for search')[1], { target: { value: 'noarch' } });
218
+ const nameSearchInput = getAllByLabelText('Search input')[1];
219
+ const archSearchInput = getAllByLabelText('Search input')[2];
220
+ nameSearchInput.focus();
221
+ fireEvent.change(nameSearchInput, { target: { value: 'elephant' } });
222
+ archSearchInput.focus();
223
+ fireEvent.change(archSearchInput, { target: { value: 'noarch' } });
223
224
  fireEvent.submit(getByLabelText('add_package_filter_rule'));
224
225
 
225
226
  await patientlyWaitFor(() => {
226
227
  expect(queryByText('Add rule')).not.toBeInTheDocument();
227
228
  });
228
229
  assertNockRequest(autocompleteScope);
229
- assertNockRequest(searchDelayScope);
230
- assertNockRequest(autoSearchScope);
231
230
  assertNockRequest(autocompleteNameScope);
232
231
  assertNockRequest(autocompleteArchScope);
233
232
  assertNockRequest(cvFiltersScope);
@@ -241,8 +240,6 @@ test('Can add package rules to filter in a self-closing modal', async (done) =>
241
240
  test('Remove rpm filter rule in a self-closing modal', async (done) => {
242
241
  const { name: cvFilterName } = cvFilterDetails;
243
242
  const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
244
- const searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
245
- const autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
246
243
 
247
244
  const cvFiltersScope = nockInstance
248
245
  .get(cvFiltersPath)
@@ -289,8 +286,6 @@ test('Remove rpm filter rule in a self-closing modal', async (done) => {
289
286
  });
290
287
 
291
288
  assertNockRequest(autocompleteScope);
292
- assertNockRequest(searchDelayScope);
293
- assertNockRequest(autoSearchScope);
294
289
  assertNockRequest(cvFiltersScope);
295
290
  assertNockRequest(cvFilterDetailsScope);
296
291
  assertNockRequest(cvPackageFilterRulesScope);
@@ -310,8 +305,6 @@ test('Edit rpm filter rule in a self-closing modal', async (done) => {
310
305
  nockInstance, autocompleteArchUrl, true,
311
306
  undefined, 2,
312
307
  );
313
- const searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0, 3);
314
- const autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing', undefined, 3);
315
308
  const cvFiltersScope = nockInstance
316
309
  .get(cvFiltersPath)
317
310
  .times(2)
@@ -366,8 +359,6 @@ test('Edit rpm filter rule in a self-closing modal', async (done) => {
366
359
  });
367
360
 
368
361
  assertNockRequest(autocompleteScope);
369
- assertNockRequest(searchDelayScope);
370
- assertNockRequest(autoSearchScope);
371
362
  assertNockRequest(autocompleteNameScope);
372
363
  assertNockRequest(autocompleteArchScope);
373
364
  assertNockRequest(cvFiltersScope);
@@ -381,8 +372,6 @@ test('Shows call-to-action when there are no RPM filters', async (done) => {
381
372
  const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
382
373
  const autocompleteNameScope = mockAutocomplete(nockInstance, autocompleteNameUrl);
383
374
  const autocompleteArchScope = mockAutocomplete(nockInstance, autocompleteArchUrl);
384
- const searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0, 3);
385
- const autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing', undefined, 3);
386
375
  const cvFilterDetailScope = nockInstance
387
376
  .get(cvFilterDetailsPath)
388
377
  .query(true)
@@ -397,7 +386,7 @@ test('Shows call-to-action when there are no RPM filters', async (done) => {
397
386
  .query(true)
398
387
  .reply(200, emptyCVPackageFilterRules);
399
388
  const {
400
- queryByLabelText, getAllByLabelText, queryByText,
389
+ queryByLabelText, queryByText, getAllByLabelText,
401
390
  } =
402
391
  renderWithRedux(withCVRoute(<ContentViewFilterDetails
403
392
  cvId={1}
@@ -408,7 +397,7 @@ test('Shows call-to-action when there are no RPM filters', async (done) => {
408
397
  fireEvent.click(queryByLabelText('add_rpm_rule_empty_state'));
409
398
 
410
399
  await patientlyWaitFor(() => {
411
- expect(getAllByLabelText('text input for search')[0]).toBeInTheDocument();
400
+ expect(getAllByLabelText('Search input')[0]).toBeInTheDocument();
412
401
  expect(queryByText('Cancel')).toBeInTheDocument();
413
402
  });
414
403
  fireEvent.click(queryByText('Cancel'));
@@ -418,8 +407,6 @@ test('Shows call-to-action when there are no RPM filters', async (done) => {
418
407
  assertNockRequest(autocompleteNameScope);
419
408
  assertNockRequest(autocompleteArchScope);
420
409
  assertNockRequest(autocompleteScope);
421
- assertNockRequest(searchDelayScope);
422
- assertNockRequest(autoSearchScope);
423
410
  assertNockRequest(cvFiltersScope);
424
411
  assertNockRequest(cvFilterDetailScope);
425
412
  assertNockRequest(cvPackageFilterRulesScope);
@@ -46,8 +46,6 @@ const renderOptions = {
46
46
 
47
47
  const withCVRoute = component => <Route path="/content_views/:id([0-9]+)#/filters/:filterId([0-9]+)">{component}</Route>;
48
48
 
49
- jest.mock('../../../../../components/Search', () => () => 'mocked!');
50
-
51
49
  test('Can enable and disable add filter button', async (done) => {
52
50
  const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl, autocompleteQuery);
53
51
  const { name: cvFilterName } = cvFilterDetails;