katello 3.9.1 → 3.10.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of katello might be problematic. Click here for more details.

Files changed (229) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/hosts/host_and_hostgroup_edit.js +28 -12
  3. data/app/controllers/katello/api/rhsm/candlepin_dynflow_proxy_controller.rb +12 -3
  4. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +4 -13
  5. data/app/controllers/katello/api/v2/content_credentials_controller.rb +1 -1
  6. data/app/controllers/katello/api/v2/content_view_filter_rules_controller.rb +1 -1
  7. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +6 -4
  8. data/app/controllers/katello/api/v2/content_views_controller.rb +8 -3
  9. data/app/controllers/katello/api/v2/gpg_keys_controller.rb +2 -1
  10. data/app/controllers/katello/api/v2/host_module_streams_controller.rb +39 -0
  11. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +20 -11
  12. data/app/controllers/katello/api/v2/module_streams_controller.rb +2 -1
  13. data/app/controllers/katello/api/v2/repository_sets_controller.rb +17 -8
  14. data/app/controllers/katello/application_controller.rb +0 -2
  15. data/app/controllers/katello/concerns/hosts_controller_extensions.rb +5 -2
  16. data/app/lib/actions/candlepin/consumer/attach_subscription.rb +0 -2
  17. data/app/lib/actions/candlepin/consumer/remove_subscription.rb +0 -2
  18. data/app/lib/actions/katello/capsule_content/create_repos.rb +1 -25
  19. data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
  20. data/app/lib/actions/katello/content_view/promote.rb +2 -5
  21. data/app/lib/actions/katello/content_view/promote_to_environment.rb +2 -5
  22. data/app/lib/actions/katello/content_view/publish.rb +1 -4
  23. data/app/lib/actions/katello/content_view_puppet_environment/create.rb +6 -10
  24. data/app/lib/actions/katello/content_view_version/export.rb +0 -2
  25. data/app/lib/actions/katello/content_view_version/incremental_update.rb +19 -1
  26. data/app/lib/actions/katello/environment/publish_repositories.rb +2 -1
  27. data/app/lib/actions/katello/gpg_key/update.rb +17 -0
  28. data/app/lib/actions/katello/host/attach_subscriptions.rb +0 -2
  29. data/app/lib/actions/katello/host/erratum/install.rb +6 -0
  30. data/app/lib/actions/katello/host/generate_applicability.rb +0 -2
  31. data/app/lib/actions/katello/host/hypervisors_update.rb +11 -6
  32. data/app/lib/actions/katello/host/package/install.rb +6 -0
  33. data/app/lib/actions/katello/host/package/remove.rb +6 -0
  34. data/app/lib/actions/katello/host/package/update.rb +7 -1
  35. data/app/lib/actions/katello/host/package_group/install.rb +6 -0
  36. data/app/lib/actions/katello/host/package_group/remove.rb +6 -0
  37. data/app/lib/actions/katello/host/recalculate_errata_status.rb +0 -2
  38. data/app/lib/actions/katello/host/remove_subscriptions.rb +0 -2
  39. data/app/lib/actions/katello/host/update.rb +1 -0
  40. data/app/lib/actions/katello/host/update_content_overrides.rb +0 -2
  41. data/app/lib/actions/katello/host/upload_package_profile.rb +13 -12
  42. data/app/lib/actions/katello/host/upload_profiles.rb +70 -0
  43. data/app/lib/actions/katello/product/reindex_subscriptions.rb +0 -2
  44. data/app/lib/actions/katello/product/repositories_certs_reset.rb +4 -4
  45. data/app/lib/actions/katello/product/repositories_gpg_reset.rb +2 -2
  46. data/app/lib/actions/katello/repository/check_matching_content.rb +18 -6
  47. data/app/lib/actions/katello/repository/clone_deb_content.rb +1 -1
  48. data/app/lib/actions/katello/repository/clone_to_environment.rb +3 -5
  49. data/app/lib/actions/katello/repository/clone_to_version.rb +2 -3
  50. data/app/lib/actions/katello/repository/clone_yum_content.rb +1 -2
  51. data/app/lib/actions/katello/repository/clone_yum_metadata.rb +2 -2
  52. data/app/lib/actions/katello/repository/create.rb +1 -31
  53. data/app/lib/actions/katello/repository/destroy.rb +1 -2
  54. data/app/lib/actions/katello/repository/export.rb +0 -2
  55. data/app/lib/actions/katello/repository/fetch_pxe_files.rb +0 -2
  56. data/app/lib/actions/katello/repository/filtered_index_content.rb +0 -2
  57. data/app/lib/actions/katello/repository/finish_upload.rb +0 -2
  58. data/app/lib/actions/katello/repository/import_upload.rb +0 -2
  59. data/app/lib/actions/katello/repository/index_content.rb +0 -1
  60. data/app/lib/actions/katello/repository/index_package_groups.rb +0 -2
  61. data/app/lib/actions/katello/repository/instance_update.rb +21 -0
  62. data/app/lib/actions/katello/repository/remove_content.rb +0 -2
  63. data/app/lib/actions/katello/repository/sync.rb +0 -1
  64. data/app/lib/actions/katello/repository/update.rb +0 -2
  65. data/app/lib/actions/katello/upstream_subscriptions/bind_entitlement.rb +0 -2
  66. data/app/lib/actions/katello/upstream_subscriptions/bind_entitlements.rb +0 -2
  67. data/app/lib/actions/katello/upstream_subscriptions/remove_entitlement.rb +0 -1
  68. data/app/lib/actions/katello/upstream_subscriptions/remove_entitlements.rb +0 -2
  69. data/app/lib/actions/katello/upstream_subscriptions/update_entitlement.rb +0 -1
  70. data/app/lib/actions/katello/upstream_subscriptions/update_entitlements.rb +0 -2
  71. data/app/lib/actions/pulp/abstract.rb +13 -14
  72. data/app/lib/actions/pulp/repository/create.rb +13 -211
  73. data/app/lib/actions/pulp/repository/create_in_plan.rb +4 -18
  74. data/app/lib/actions/pulp/repository/refresh.rb +7 -70
  75. data/app/lib/actions/pulp/repository/sync.rb +1 -2
  76. data/app/lib/katello/capsule_content.rb +3 -3
  77. data/app/lib/katello/resources/candlepin/consumer.rb +1 -1
  78. data/app/lib/katello/resources/candlepin/product.rb +1 -1
  79. data/app/lib/katello/validators/hostgroup_kickstart_repository_validator.rb +1 -1
  80. data/app/models/katello/available_module_stream.rb +11 -0
  81. data/app/models/katello/concerns/content_facet_host_extensions.rb +1 -0
  82. data/app/models/katello/concerns/host_managed_extensions.rb +56 -0
  83. data/app/models/katello/concerns/hostgroup_extensions.rb +17 -0
  84. data/app/models/katello/concerns/redhat_extensions.rb +20 -6
  85. data/app/models/katello/concerns/search_by_repository_name.rb +0 -1
  86. data/app/models/katello/concerns/smart_proxy_extensions.rb +26 -12
  87. data/app/models/katello/content_facet_applicable_module_stream.rb +7 -0
  88. data/app/models/katello/content_view_puppet_environment.rb +14 -35
  89. data/app/models/katello/erratum.rb +54 -24
  90. data/app/models/katello/erratum_package.rb +6 -0
  91. data/app/models/katello/glue/pulp/repo.rb +5 -228
  92. data/app/models/katello/gpg_key.rb +1 -0
  93. data/app/models/katello/host/content_facet.rb +38 -83
  94. data/app/models/katello/host_available_module_stream.rb +47 -0
  95. data/app/models/katello/module_stream.rb +18 -0
  96. data/app/models/katello/module_stream_erratum_package.rb +6 -0
  97. data/app/models/katello/product.rb +0 -2
  98. data/app/models/katello/product_content.rb +1 -0
  99. data/app/models/katello/repository.rb +15 -6
  100. data/app/models/katello/root_repository.rb +1 -1
  101. data/app/models/katello/rpm.rb +5 -17
  102. data/app/services/katello/applicable_content_helper.rb +111 -0
  103. data/app/services/katello/managed_content_medium_provider.rb +7 -0
  104. data/app/services/katello/pulp/consumer.rb +13 -7
  105. data/app/services/katello/pulp/repository.rb +157 -4
  106. data/app/services/katello/pulp/repository/deb.rb +47 -0
  107. data/app/services/katello/pulp/repository/docker.rb +43 -0
  108. data/app/services/katello/pulp/repository/file.rb +31 -0
  109. data/app/services/katello/pulp/repository/ostree.rb +40 -0
  110. data/app/services/katello/pulp/repository/puppet.rb +43 -0
  111. data/app/services/katello/pulp/repository/yum.rb +61 -0
  112. data/app/services/katello/repository_type.rb +1 -1
  113. data/app/views/katello/api/v2/content_facet/base.json.rabl +1 -0
  114. data/app/views/katello/api/v2/content_view_versions/base.json.rabl +0 -1
  115. data/app/views/katello/api/v2/errata/_counts.json.rabl +0 -1
  116. data/app/views/katello/api/v2/errata/show.json.rabl +9 -3
  117. data/app/views/katello/api/v2/host_collections/delta_activation_keys.rabl +0 -1
  118. data/app/views/katello/api/v2/host_module_streams/base.json.rabl +8 -0
  119. data/app/views/katello/api/v2/host_module_streams/index.json.rabl +7 -0
  120. data/app/views/katello/api/v2/packages/backend.json.rabl +0 -1
  121. data/app/views/katello/api/v2/repositories/show.json.rabl +6 -6
  122. data/app/views/katello/layouts/react.html.erb +2 -2
  123. data/app/views/overrides/activation_keys/_host_synced_content_select.html.erb +0 -1
  124. data/config/routes/api/rhsm.rb +1 -0
  125. data/config/routes/overrides.rb +4 -0
  126. data/db/migrate/20181008201422_add_modules_to_errata_packages.rb +29 -0
  127. data/db/migrate/20181017181806_available_module_streams.rb +34 -0
  128. data/db/migrate/20181027014323_add_applicable_modules.rb +24 -0
  129. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/common/module-stream-actions.service.js +2 -1
  130. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/details/views/content-credential-info.html +1 -1
  131. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/new/views/new-content-credential.html +1 -0
  132. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-host-bulk-module-streams-modal.html +2 -2
  133. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-errata-modal.html +37 -22
  134. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.controller.js +4 -1
  135. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-module-streams.controller.js +27 -7
  136. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-module-streams.html +29 -0
  137. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/errata-details.html +15 -1
  138. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +1 -1
  139. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/content-view-promotion.controller.js +0 -1
  140. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/content-view-publish.controller.js +1 -2
  141. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/content-view-versions.controller.js +3 -1
  142. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/histories/content-view-history.controller.js +1 -1
  143. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-promotion.html +0 -15
  144. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-publish.html +0 -14
  145. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/erratum.controller.js +19 -0
  146. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/views/erratum-info.html +0 -12
  147. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/views/erratum-packages.html +36 -0
  148. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/views/erratum.html +7 -0
  149. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/errata.routes.js +9 -0
  150. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/hosts/host-module-streams.factory.js +18 -0
  151. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +4 -2
  152. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +2 -2
  153. data/engines/bastion_katello/app/assets/stylesheets/bastion_katello/bastion_katello.scss +13 -0
  154. data/lib/katello/permissions/host_permissions.rb +3 -0
  155. data/lib/katello/repository_types/deb.rb +3 -1
  156. data/lib/katello/repository_types/docker.rb +3 -1
  157. data/lib/katello/repository_types/file.rb +1 -0
  158. data/lib/katello/repository_types/ostree.rb +3 -1
  159. data/lib/katello/repository_types/puppet.rb +3 -1
  160. data/lib/katello/repository_types/yum.rb +3 -1
  161. data/lib/katello/tasks/delete_orphaned_content.rake +1 -1
  162. data/lib/katello/tasks/reset.rake +1 -0
  163. data/lib/katello/tasks/test.rake +14 -0
  164. data/lib/katello/tasks/unify_hosts.rake +2 -0
  165. data/lib/katello/tasks/virt_who_report.rake +2 -1
  166. data/lib/katello/version.rb +1 -1
  167. data/locale/Makefile +52 -17
  168. data/locale/update-i18n +22 -0
  169. data/package.json +11 -1
  170. data/webpack/__mocks__/foremanReact/components/common/EmptyState.js +8 -0
  171. data/webpack/move_to_foreman/components/common/table/components/Table.js +2 -1
  172. data/webpack/move_to_pf/react-bootstrap-select/index.js +4 -2
  173. data/webpack/move_to_pf/test-utils/testHelpers.js +9 -0
  174. data/webpack/redux/OrganizationProducts/OrganizationProductsActions.js +24 -0
  175. data/webpack/redux/OrganizationProducts/OrganizationProductsConstants.js +5 -0
  176. data/webpack/redux/OrganizationProducts/OrganizationProductsReducer.js +38 -0
  177. data/webpack/redux/OrganizationProducts/OrganizationProductsSelectors.js +7 -0
  178. data/webpack/redux/OrganizationProducts/__tests__/OrganizationProductsActions.test.js +47 -0
  179. data/webpack/redux/OrganizationProducts/__tests__/OrganizationProductsReducer.test.js +33 -0
  180. data/webpack/redux/OrganizationProducts/__tests__/OrganizationProductsSelectors.test.js +19 -0
  181. data/webpack/redux/OrganizationProducts/__tests__/__snapshots__/OrganizationProductsActions.test.js.snap +49 -0
  182. data/webpack/redux/OrganizationProducts/__tests__/__snapshots__/OrganizationProductsReducer.test.js.snap +36 -0
  183. data/webpack/redux/OrganizationProducts/__tests__/__snapshots__/OrganizationProductsSelectors.test.js.snap +9 -0
  184. data/webpack/redux/OrganizationProducts/index.js +13 -0
  185. data/webpack/redux/actions/RedHatRepositories/enabled.js +7 -1
  186. data/webpack/redux/actions/RedHatRepositories/helpers.js +4 -0
  187. data/webpack/redux/actions/RedHatRepositories/sets.js +2 -0
  188. data/webpack/redux/reducers/RedHatRepositories/enabled.fixtures.js +8 -2
  189. data/webpack/redux/reducers/RedHatRepositories/enabled.js +1 -1
  190. data/webpack/redux/reducers/RedHatRepositories/sets.fixtures.js +12 -3
  191. data/webpack/redux/reducers/index.js +2 -0
  192. data/webpack/scenes/RedHatRepositories/components/SearchBar.js +68 -33
  193. data/webpack/scenes/RedHatRepositories/index.js +13 -2
  194. data/webpack/scenes/RedHatRepositories/index.scss +26 -0
  195. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +1 -1
  196. data/webpack/scenes/Subscriptions/Manifest/__tests__/__snapshots__/ManageManifestModal.test.js.snap +1 -1
  197. data/webpack/scenes/Subscriptions/SubscriptionActions.js +18 -2
  198. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +8 -0
  199. data/webpack/scenes/Subscriptions/SubscriptionHelpers.js +15 -0
  200. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +22 -14
  201. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +39 -90
  202. data/webpack/scenes/Subscriptions/SubscriptionsSelectors.js +14 -0
  203. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +1 -3
  204. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +0 -1
  205. data/webpack/scenes/Subscriptions/__tests__/SubscriptionHelpers.test.js +84 -0
  206. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsActions.test.js +26 -1
  207. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +5 -0
  208. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsReducer.test.js +177 -75
  209. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsSelectors.test.js +29 -0
  210. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionHelpers.test.js.snap +31 -0
  211. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsActions.test.js.snap +32 -0
  212. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +18 -96
  213. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsReducer.test.js.snap +511 -0
  214. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsSelectors.test.js.snap +26 -0
  215. data/webpack/scenes/Subscriptions/__tests__/subscriptions.fixtures.js +6 -1
  216. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +3 -21
  217. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.js +113 -0
  218. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.test.js +47 -0
  219. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/__snapshots__/SubscriptionsToolbar.test.js.snap +504 -0
  220. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/index.js +1 -0
  221. data/webpack/scenes/Subscriptions/index.js +15 -4
  222. metadata +59 -14
  223. data/app/lib/actions/pulp/repository/associate_distributor.rb +0 -20
  224. data/app/lib/actions/pulp/repository/associate_importer.rb +0 -23
  225. data/app/lib/actions/pulp/repository/delete_distributor.rb +0 -18
  226. data/app/lib/actions/pulp/repository/refresh_distributor.rb +0 -19
  227. data/app/lib/actions/pulp/repository/update_importer.rb +0 -33
  228. data/app/lib/katello/bulk_actions.rb +0 -63
  229. data/webpack/move_to_foreman/components/common/EmptyState/index.js +0 -68
data/package.json CHANGED
@@ -11,7 +11,8 @@
11
11
  "build": "npm run format && npm run lint",
12
12
  "lint": "eslint webpack/",
13
13
  "lint:fix": "eslint --fix webpack/",
14
- "lint:test": "npm run lint && npm test"
14
+ "lint:test": "npm run lint && npm test",
15
+ "coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js"
15
16
  },
16
17
  "repository": {
17
18
  "type": "git",
@@ -33,6 +34,7 @@
33
34
  "babel-preset-react": "^6.24.1",
34
35
  "enzyme": "^3.4.0",
35
36
  "enzyme-adapter-react-16": "^1.4.0",
37
+ "coveralls": "^3.0.0",
36
38
  "enzyme-to-json": "^3.1.2",
37
39
  "eslint": "^4.19.1",
38
40
  "eslint-config-airbnb": "^16.0.0",
@@ -74,6 +76,14 @@
74
76
  "seamless-immutable": "^7.1.2"
75
77
  },
76
78
  "jest": {
79
+ "collectCoverage": true,
80
+ "collectCoverageFrom": [
81
+ "webpack/**/*.js",
82
+ "!webpack/**/bundle*"
83
+ ],
84
+ "coverageReporters": [
85
+ "lcov"
86
+ ],
77
87
  "testURL": "http://localhost/",
78
88
  "setupFiles": [
79
89
  "raf/polyfill",
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+
3
+ const EmptyState = props => (
4
+ <div>
5
+ {`EmptyState: ${JSON.stringify(props)}`}
6
+ </div>
7
+ );
8
+ export default EmptyState;
@@ -2,7 +2,8 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { Table as PfTable } from 'patternfly-react';
4
4
  import { noop } from 'foremanReact/common/helpers';
5
- import EmptyState from '../../EmptyState';
5
+ import EmptyState from 'foremanReact/components/common/EmptyState';
6
+
6
7
  import PaginationRow from '../../../../../components/PaginationRow/index';
7
8
 
8
9
  import TableBody from './TableBody';
@@ -53,12 +53,12 @@ class BootstrapSelect extends React.Component {
53
53
  render() {
54
54
  // TODO: these classes are required because foreman assumes that all selects should use select2 and jquery multiselect
55
55
  // TODO: see also http://projects.theforeman.org/issues/21952
56
- const { noneSelectedText, defaultValue, defaultValues, value, ...props} = this.props;
56
+ const { noneSelectedText, defaultValue, defaultValues, value, maxItemsCountForFullLabel, ...props} = this.props;
57
57
  const initialValue = defaultValues || defaultValue || value;
58
58
 
59
59
  return <FormControl {...props}
60
60
  data-none-selected-text={noneSelectedText}
61
- data-selected-text-format="count>3"
61
+ data-selected-text-format={`count>${maxItemsCountForFullLabel}`}
62
62
  data-count-selected-text={__('{0} items selected')}
63
63
  defaultValue={initialValue}
64
64
  componentClass="select"
@@ -71,10 +71,12 @@ BootstrapSelect.propTypes = {
71
71
  noneSelectedText: PropTypes.string,
72
72
  defaultValue: PropTypes.string,
73
73
  defaultValues: PropTypes.arrayOf(PropTypes.string),
74
+ maxItemsCountForFullLabel: PropTypes.number,
74
75
  };
75
76
 
76
77
  BootstrapSelect.defaultProps = {
77
78
  noneSelectedText: __('Nothing selected'),
79
+ maxItemsCountForFullLabel: 3,
78
80
  defaultValue: null,
79
81
  defaultValues: null,
80
82
  };
@@ -81,3 +81,12 @@ export const testReducerSnapshotWithFixtures = (reducer, fixtures) => {
81
81
  Object.entries(fixtures).forEach(([description, action]) =>
82
82
  it(description, () => expect(reduce(action)).toMatchSnapshot()));
83
83
  };
84
+
85
+ /**
86
+ * Test selectors with fixtures and snapshots
87
+ * @param {Object} fixtures key=fixture description,
88
+ * value=selector runner function
89
+ */
90
+ export const testSelectorsSnapshotWithFixtures = fixtures =>
91
+ Object.entries(fixtures).forEach(([description, selectorRunner]) =>
92
+ it(description, () => expect(selectorRunner()).toMatchSnapshot()));
@@ -0,0 +1,24 @@
1
+ import api, { orgId as getOrgId } from '../../services/api';
2
+
3
+ import {
4
+ ORGANIZATION_PRODUCTS_REQUEST,
5
+ ORGANIZATION_PRODUCTS_SUCCESS,
6
+ ORGANIZATION_PRODUCTS_FAILURE,
7
+ } from './OrganizationProductsConstants';
8
+ import { apiError } from '../../move_to_foreman/common/helpers';
9
+
10
+ export const loadOrganizationProducts = (params = {}, orgId = getOrgId()) => (dispatch) => {
11
+ dispatch({ type: ORGANIZATION_PRODUCTS_REQUEST });
12
+
13
+ return api
14
+ .get(`/organizations/${orgId}/products/`, {}, params)
15
+ .then(({ data }) => {
16
+ dispatch({
17
+ type: ORGANIZATION_PRODUCTS_SUCCESS,
18
+ payload: { orgId, ...data },
19
+ });
20
+ })
21
+ .catch(result => dispatch(apiError(ORGANIZATION_PRODUCTS_FAILURE, result)));
22
+ };
23
+
24
+ export default loadOrganizationProducts;
@@ -0,0 +1,5 @@
1
+ export const ORGANIZATION_PRODUCTS_KEY = 'organizationProducts';
2
+
3
+ export const ORGANIZATION_PRODUCTS_REQUEST = 'ORGANIZATION_PRODUCTS_REQUEST';
4
+ export const ORGANIZATION_PRODUCTS_SUCCESS = 'ORGANIZATION_PRODUCTS_SUCCESS';
5
+ export const ORGANIZATION_PRODUCTS_FAILURE = 'ORGANIZATION_PRODUCTS_FAILURE';
@@ -0,0 +1,38 @@
1
+ import Immutable from 'seamless-immutable';
2
+
3
+ import {
4
+ ORGANIZATION_PRODUCTS_REQUEST,
5
+ ORGANIZATION_PRODUCTS_SUCCESS,
6
+ ORGANIZATION_PRODUCTS_FAILURE,
7
+ } from './OrganizationProductsConstants';
8
+
9
+ const initialState = Immutable({
10
+ loading: false,
11
+ error: null,
12
+ results: [],
13
+ });
14
+
15
+ export default (state = initialState, action) => {
16
+ const { type, payload } = action;
17
+
18
+ switch (type) {
19
+ case ORGANIZATION_PRODUCTS_REQUEST:
20
+ return state.set('loading', true);
21
+
22
+ case ORGANIZATION_PRODUCTS_SUCCESS:
23
+ return state.merge({
24
+ ...payload,
25
+ loading: false,
26
+ });
27
+
28
+ case ORGANIZATION_PRODUCTS_FAILURE:
29
+ return state.merge({
30
+ error: payload,
31
+ loading: false,
32
+ results: [],
33
+ });
34
+
35
+ default:
36
+ return state;
37
+ }
38
+ };
@@ -0,0 +1,7 @@
1
+ import { ORGANIZATION_PRODUCTS_KEY } from './OrganizationProductsConstants';
2
+
3
+ export const selectOrganizationProductsState = state =>
4
+ state.katello[ORGANIZATION_PRODUCTS_KEY];
5
+
6
+ export const selectOrganizationProducts = state =>
7
+ selectOrganizationProductsState(state).results;
@@ -0,0 +1,47 @@
1
+ import { testActionSnapshotWithFixtures } from '../../../move_to_pf/test-utils/testHelpers';
2
+ import api, { orgId } from '../../../services/api';
3
+ import { apiError } from '../../../move_to_foreman/common/helpers';
4
+
5
+ import { loadOrganizationProducts } from '../OrganizationProductsActions';
6
+
7
+ const params = {
8
+ search: 'some-search',
9
+ };
10
+
11
+ jest.mock('../../../services/api');
12
+ jest.mock('../../../move_to_foreman/common/helpers');
13
+
14
+ const fixtures = {
15
+ 'should load organization products and success': {
16
+ action: () => loadOrganizationProducts(params),
17
+ test: () => {
18
+ expect(api.get.mock.calls).toMatchSnapshot();
19
+ expect(apiError).not.toHaveBeenCalled();
20
+ },
21
+ },
22
+ 'should load organization products and fail': () => (dispatch) => {
23
+ api.get.mockImplementation(async () => {
24
+ throw new Error('some-error');
25
+ });
26
+
27
+ return loadOrganizationProducts(params)(dispatch);
28
+ },
29
+ };
30
+
31
+ describe('OrganizationProducts actions', () => {
32
+ beforeEach(() => {
33
+ orgId.mockImplementation(() => 'some-org-id');
34
+ api.get.mockImplementation(async () => ({
35
+ data: {
36
+ results: [{ id: 'some-id' }],
37
+ },
38
+ }));
39
+ });
40
+ afterEach(() => {
41
+ jest.resetAllMocks();
42
+ jest.restoreAllMocks();
43
+ jest.resetModules();
44
+ });
45
+
46
+ testActionSnapshotWithFixtures(fixtures);
47
+ });
@@ -0,0 +1,33 @@
1
+ import { testReducerSnapshotWithFixtures } from '../../../move_to_pf/test-utils/testHelpers';
2
+
3
+ import {
4
+ ORGANIZATION_PRODUCTS_REQUEST,
5
+ ORGANIZATION_PRODUCTS_SUCCESS,
6
+ ORGANIZATION_PRODUCTS_FAILURE,
7
+ } from '../OrganizationProductsConstants';
8
+ import reducer from '../OrganizationProductsReducer';
9
+
10
+ const fixtures = {
11
+ 'should return the initial state': {},
12
+ 'should handle ORGANIZATION_PRODUCTS_REQUEST': {
13
+ action: {
14
+ type: ORGANIZATION_PRODUCTS_REQUEST,
15
+ },
16
+ },
17
+ 'should handle ORGANIZATION_PRODUCTS_SUCCESS': {
18
+ action: {
19
+ type: ORGANIZATION_PRODUCTS_SUCCESS,
20
+ payload: {
21
+ results: ['some', 'results'],
22
+ },
23
+ },
24
+ },
25
+ 'should handle ORGANIZATION_PRODUCTS_FAILURE': {
26
+ action: {
27
+ type: ORGANIZATION_PRODUCTS_FAILURE,
28
+ payload: new Error('some error'),
29
+ },
30
+ },
31
+ };
32
+
33
+ describe('OrganizationProducts reducer', () => testReducerSnapshotWithFixtures(reducer, fixtures));
@@ -0,0 +1,19 @@
1
+ import { testSelectorsSnapshotWithFixtures } from '../../../move_to_pf/test-utils/testHelpers';
2
+
3
+ import { ORGANIZATION_PRODUCTS_KEY } from '../OrganizationProductsConstants';
4
+ import { selectOrganizationProductsState, selectOrganizationProducts } from '../OrganizationProductsSelectors';
5
+
6
+ const stateFixture = {
7
+ katello: {
8
+ [ORGANIZATION_PRODUCTS_KEY]: {
9
+ results: 'some-results',
10
+ },
11
+ },
12
+ };
13
+
14
+ const fixtures = {
15
+ 'should select the organization products state': () => selectOrganizationProductsState(stateFixture),
16
+ 'should select the organization products': () => selectOrganizationProducts(stateFixture),
17
+ };
18
+
19
+ describe('OrganizationProducts selectors', () => testSelectorsSnapshotWithFixtures(fixtures));
@@ -0,0 +1,49 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`OrganizationProducts actions should load organization products and fail 1`] = `
4
+ Array [
5
+ Array [
6
+ Object {
7
+ "type": "ORGANIZATION_PRODUCTS_REQUEST",
8
+ },
9
+ ],
10
+ Array [
11
+ undefined,
12
+ ],
13
+ ]
14
+ `;
15
+
16
+ exports[`OrganizationProducts actions should load organization products and success 1`] = `
17
+ Array [
18
+ Array [
19
+ Object {
20
+ "type": "ORGANIZATION_PRODUCTS_REQUEST",
21
+ },
22
+ ],
23
+ Array [
24
+ Object {
25
+ "payload": Object {
26
+ "orgId": "some-org-id",
27
+ "results": Array [
28
+ Object {
29
+ "id": "some-id",
30
+ },
31
+ ],
32
+ },
33
+ "type": "ORGANIZATION_PRODUCTS_SUCCESS",
34
+ },
35
+ ],
36
+ ]
37
+ `;
38
+
39
+ exports[`OrganizationProducts actions should load organization products and success 2`] = `
40
+ Array [
41
+ Array [
42
+ "/organizations/some-org-id/products/",
43
+ Object {},
44
+ Object {
45
+ "search": "some-search",
46
+ },
47
+ ],
48
+ ]
49
+ `;
@@ -0,0 +1,36 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`OrganizationProducts reducer should handle ORGANIZATION_PRODUCTS_FAILURE 1`] = `
4
+ Object {
5
+ "error": [Error: some error],
6
+ "loading": false,
7
+ "results": Array [],
8
+ }
9
+ `;
10
+
11
+ exports[`OrganizationProducts reducer should handle ORGANIZATION_PRODUCTS_REQUEST 1`] = `
12
+ Object {
13
+ "error": null,
14
+ "loading": true,
15
+ "results": Array [],
16
+ }
17
+ `;
18
+
19
+ exports[`OrganizationProducts reducer should handle ORGANIZATION_PRODUCTS_SUCCESS 1`] = `
20
+ Object {
21
+ "error": null,
22
+ "loading": false,
23
+ "results": Array [
24
+ "some",
25
+ "results",
26
+ ],
27
+ }
28
+ `;
29
+
30
+ exports[`OrganizationProducts reducer should return the initial state 1`] = `
31
+ Object {
32
+ "error": null,
33
+ "loading": false,
34
+ "results": Array [],
35
+ }
36
+ `;
@@ -0,0 +1,9 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`OrganizationProducts selectors should select the organization products 1`] = `"some-results"`;
4
+
5
+ exports[`OrganizationProducts selectors should select the organization products state 1`] = `
6
+ Object {
7
+ "results": "some-results",
8
+ }
9
+ `;
@@ -0,0 +1,13 @@
1
+ import { ORGANIZATION_PRODUCTS_KEY } from './OrganizationProductsConstants';
2
+ import reducer from './OrganizationProductsReducer';
3
+ import * as organizationProductsActions from './OrganizationProductsActions';
4
+ import * as organizationProductsSelectors from './OrganizationProductsSelectors';
5
+
6
+ // export actions
7
+ export const actions = { ...organizationProductsActions };
8
+
9
+ // export selectors
10
+ export const selectors = { ...organizationProductsSelectors };
11
+
12
+ // export reducers
13
+ export const reducers = { [ORGANIZATION_PRODUCTS_KEY]: reducer };
@@ -1,5 +1,10 @@
1
1
  import api, { orgId } from '../../../services/api';
2
- import { normalizeRepositorySets, repoTypeFilterToSearchQuery, joinSearchQueries } from './helpers';
2
+ import {
3
+ normalizeRepositorySets,
4
+ repoTypeFilterToSearchQuery,
5
+ productsIdsToSearchQuery,
6
+ joinSearchQueries,
7
+ } from './helpers';
3
8
  import { apiError, apiSuccess } from '../../../move_to_foreman/common/helpers.js';
4
9
 
5
10
  import {
@@ -23,6 +28,7 @@ export const createEnabledRepoParams = (extendedParams = {}) => {
23
28
  const search = joinSearchQueries([
24
29
  'redhat = true',
25
30
  repoTypeFilterToSearchQuery(searchParams.filters || []),
31
+ productsIdsToSearchQuery(searchParams.products || []),
26
32
  searchParams.query,
27
33
  ]);
28
34
 
@@ -53,6 +53,10 @@ export const repoTypeFilterToSearchQuery = filters => filters
53
53
  .map(f => `(${maptToSearchQuery(f)})`)
54
54
  .join(' or ');
55
55
 
56
+ export const productsIdsToSearchQuery = productIds => productIds
57
+ .map(id => `(product_id = "${id}")`)
58
+ .join(' or ');
59
+
56
60
  export const joinSearchQueries = parts => parts
57
61
  .filter(v => (v && v !== ''))
58
62
  .map(v => `(${v})`)
@@ -2,6 +2,7 @@ import api, { orgId } from '../../../services/api';
2
2
  import {
3
3
  normalizeRepositorySets,
4
4
  repoTypeFilterToSearchQuery,
5
+ productsIdsToSearchQuery,
5
6
  joinSearchQueries,
6
7
  recommendedRepositorySetsQuery,
7
8
  } from './helpers';
@@ -23,6 +24,7 @@ export const loadRepositorySets = (extendedParams = {}) => (dispatch, getState)
23
24
  const searchParams = extendedParams.search || {};
24
25
  const search = joinSearchQueries([
25
26
  repoTypeFilterToSearchQuery(searchParams.filters || []),
27
+ productsIdsToSearchQuery(searchParams.products || []),
26
28
  searchParams.query,
27
29
  recommended ? recommendedRepositorySetsQuery : '',
28
30
  ]);