katello 4.4.1 → 4.5.0

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 (488) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/hosts/activation_key_edit.js +9 -2
  3. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +3 -0
  4. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +5 -1
  5. data/app/controllers/katello/api/v2/alternate_content_sources_bulk_actions_controller.rb +44 -0
  6. data/app/controllers/katello/api/v2/alternate_content_sources_controller.rb +121 -0
  7. data/app/controllers/katello/api/v2/content_export_incrementals_controller.rb +39 -3
  8. data/app/controllers/katello/api/v2/content_exports_controller.rb +19 -0
  9. data/app/controllers/katello/api/v2/content_imports_controller.rb +13 -16
  10. data/app/controllers/katello/api/v2/content_view_components_controller.rb +1 -1
  11. data/app/controllers/katello/api/v2/content_view_repositories_controller.rb +1 -1
  12. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +0 -12
  13. data/app/controllers/katello/api/v2/content_views_controller.rb +13 -0
  14. data/app/controllers/katello/api/v2/environments_controller.rb +1 -1
  15. data/app/controllers/katello/api/v2/host_module_streams_controller.rb +8 -2
  16. data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +25 -3
  17. data/app/controllers/katello/api/v2/organizations_controller.rb +4 -2
  18. data/app/controllers/katello/api/v2/repositories_bulk_actions_controller.rb +1 -1
  19. data/app/controllers/katello/api/v2/repositories_controller.rb +1 -1
  20. data/app/controllers/katello/api/v2/repository_sets_controller.rb +40 -7
  21. data/app/controllers/katello/api/v2/subscriptions_controller.rb +2 -2
  22. data/app/controllers/katello/concerns/api/v2/hosts_controller_extensions.rb +1 -1
  23. data/app/helpers/katello/concerns/smart_proxy_helper_extensions.rb +4 -0
  24. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +21 -3
  25. data/app/lib/actions/katello/alternate_content_source/create.rb +24 -0
  26. data/app/lib/actions/katello/alternate_content_source/destroy.rb +27 -0
  27. data/app/lib/actions/katello/alternate_content_source/refresh.rb +27 -0
  28. data/app/lib/actions/katello/alternate_content_source/update.rb +41 -0
  29. data/app/lib/actions/katello/cdn_configuration/update.rb +3 -3
  30. data/app/lib/actions/katello/content_view/destroy.rb +2 -1
  31. data/app/lib/actions/katello/content_view/incremental_updates.rb +7 -3
  32. data/app/lib/actions/katello/content_view/publish.rb +8 -10
  33. data/app/lib/actions/katello/content_view_version/auto_create_products.rb +4 -4
  34. data/app/lib/actions/katello/content_view_version/auto_create_redhat_repositories.rb +6 -4
  35. data/app/lib/actions/katello/content_view_version/auto_create_repositories.rb +6 -4
  36. data/app/lib/actions/katello/content_view_version/import.rb +25 -22
  37. data/app/lib/actions/katello/content_view_version/import_library.rb +0 -1
  38. data/app/lib/actions/katello/content_view_version/import_repository.rb +21 -0
  39. data/app/lib/actions/katello/content_view_version/incremental_update.rb +85 -93
  40. data/app/lib/actions/katello/content_view_version/reset_content_view_repositories_from_metadata.rb +2 -2
  41. data/app/lib/actions/katello/organization/manifest_refresh.rb +1 -1
  42. data/app/lib/actions/katello/product/content_create.rb +10 -8
  43. data/app/lib/actions/katello/repository/destroy.rb +36 -12
  44. data/app/lib/actions/katello/repository_set/disable_repository.rb +8 -3
  45. data/app/lib/actions/pulp3/alternate_content_source/create.rb +20 -0
  46. data/app/lib/actions/pulp3/alternate_content_source/create_remote.rb +20 -0
  47. data/app/lib/actions/pulp3/alternate_content_source/delete.rb +16 -0
  48. data/app/lib/actions/pulp3/alternate_content_source/delete_remote.rb +16 -0
  49. data/app/lib/actions/pulp3/alternate_content_source/refresh.rb +23 -0
  50. data/app/lib/actions/pulp3/alternate_content_source/update.rb +16 -0
  51. data/app/lib/actions/pulp3/alternate_content_source/update_remote.rb +17 -0
  52. data/app/lib/actions/pulp3/content_view_version/{import.rb → create_import.rb} +5 -5
  53. data/app/lib/actions/pulp3/content_view_version/create_importer.rb +4 -3
  54. data/app/lib/actions/pulp3/content_view_version/destroy_importer.rb +12 -1
  55. data/app/lib/actions/pulp3/orchestration/alternate_content_source/create.rb +16 -0
  56. data/app/lib/actions/pulp3/orchestration/alternate_content_source/delete.rb +23 -0
  57. data/app/lib/actions/pulp3/orchestration/alternate_content_source/refresh.rb +15 -0
  58. data/app/lib/actions/pulp3/orchestration/alternate_content_source/update.rb +16 -0
  59. data/app/lib/actions/pulp3/orchestration/content_view_version/copy_version_units_to_library.rb +1 -1
  60. data/app/lib/actions/pulp3/orchestration/content_view_version/export_repository.rb +51 -0
  61. data/app/lib/actions/pulp3/orchestration/content_view_version/import.rb +5 -2
  62. data/app/lib/actions/pulp3/repository/save_artifact.rb +1 -1
  63. data/app/lib/katello/api/v2/error_handling.rb +1 -0
  64. data/app/lib/katello/concerns/base_template_scope_extensions.rb +24 -11
  65. data/app/lib/katello/resources/cdn/katello_cdn.rb +3 -1
  66. data/app/lib/katello/util/errata.rb +2 -3
  67. data/app/lib/katello/validators/alternate_content_source_path_validator.rb +29 -0
  68. data/app/lib/katello/validators/content_default_http_proxy_setting_validator.rb +12 -0
  69. data/app/lib/katello/validators/content_view_environment_validator.rb +10 -5
  70. data/app/models/katello/alternate_content_source.rb +71 -0
  71. data/app/models/katello/authorization/alternate_content_source.rb +33 -0
  72. data/app/models/katello/authorization/repository.rb +5 -3
  73. data/app/models/katello/candlepin/repository_mapper.rb +13 -6
  74. data/app/models/katello/cdn_configuration.rb +15 -15
  75. data/app/models/katello/concerns/content_facet_host_extensions.rb +25 -0
  76. data/app/models/katello/concerns/host_managed_extensions.rb +7 -6
  77. data/app/models/katello/concerns/http_proxy_extensions.rb +14 -0
  78. data/app/models/katello/concerns/organization_extensions.rb +4 -2
  79. data/app/models/katello/concerns/setting_extensions.rb +14 -0
  80. data/app/models/katello/concerns/smart_proxy_extensions.rb +2 -1
  81. data/app/models/katello/content.rb +1 -0
  82. data/app/models/katello/content_credential.rb +6 -0
  83. data/app/models/katello/content_override.rb +7 -3
  84. data/app/models/katello/content_view.rb +33 -2
  85. data/app/models/katello/content_view_erratum_filter.rb +26 -12
  86. data/app/models/katello/content_view_filter.rb +4 -0
  87. data/app/models/katello/content_view_version.rb +12 -0
  88. data/app/models/katello/content_view_version_export_history.rb +3 -1
  89. data/app/models/katello/erratum.rb +9 -5
  90. data/app/models/katello/events/delete_latest_content_view_version.rb +40 -0
  91. data/app/models/katello/host/content_facet.rb +14 -0
  92. data/app/models/katello/host_available_module_stream.rb +12 -0
  93. data/app/models/katello/product_content.rb +1 -0
  94. data/app/models/katello/purpose_sla_status.rb +1 -1
  95. data/app/models/katello/purpose_status.rb +2 -2
  96. data/app/models/katello/repository.rb +7 -4
  97. data/app/models/katello/root_repository.rb +1 -1
  98. data/app/models/katello/smart_proxy_alternate_content_source.rb +8 -0
  99. data/app/models/katello/sync_plan.rb +1 -1
  100. data/app/presenters/katello/product_content_presenter.rb +15 -0
  101. data/app/services/katello/applicable_host_queue.rb +1 -1
  102. data/app/services/katello/product_content_finder.rb +12 -2
  103. data/app/services/katello/pulp3/alternate_content_source.rb +123 -0
  104. data/app/services/katello/pulp3/api/file.rb +8 -0
  105. data/app/services/katello/pulp3/api/yum.rb +8 -0
  106. data/app/services/katello/pulp3/content_view_version/export.rb +27 -5
  107. data/app/services/katello/pulp3/content_view_version/import.rb +104 -71
  108. data/app/services/katello/pulp3/content_view_version/import_export_common.rb +4 -4
  109. data/app/services/katello/pulp3/content_view_version/import_gpg_keys.rb +13 -11
  110. data/app/services/katello/pulp3/content_view_version/import_validator.rb +67 -72
  111. data/app/services/katello/pulp3/content_view_version/importable_products.rb +40 -24
  112. data/app/services/katello/pulp3/content_view_version/importable_repositories.rb +102 -38
  113. data/app/services/katello/pulp3/content_view_version/metadata_generator.rb +2 -2
  114. data/app/services/katello/pulp3/content_view_version/metadata_map.rb +117 -0
  115. data/app/services/katello/pulp3/pulp_content_unit.rb +6 -1
  116. data/app/services/katello/pulp3/repository/yum.rb +70 -12
  117. data/app/services/katello/pulp3/repository.rb +6 -62
  118. data/app/services/katello/pulp3/service_common.rb +66 -0
  119. data/app/services/katello/pulp3/smart_proxy_mirror_repository.rb +4 -1
  120. data/app/services/katello/ui_notifications/content_view/delete_latest_version_failure.rb +22 -0
  121. data/app/views/foreman/job_templates/change_content_source.erb +1 -1
  122. data/app/views/foreman/job_templates/install_errata.erb +5 -5
  123. data/app/views/foreman/job_templates/install_errata_by_search_query.erb +10 -8
  124. data/app/views/foreman/job_templates/install_group.erb +4 -4
  125. data/app/views/foreman/job_templates/install_package.erb +4 -4
  126. data/app/views/foreman/job_templates/install_packages_by_search_query.erb +3 -3
  127. data/app/views/foreman/job_templates/remove_group.erb +4 -4
  128. data/app/views/foreman/job_templates/remove_package.erb +4 -4
  129. data/app/views/foreman/job_templates/remove_packages_by_search_query.erb +3 -3
  130. data/app/views/foreman/job_templates/resolve_traces.erb +2 -2
  131. data/app/views/foreman/job_templates/restart_services.erb +3 -3
  132. data/app/views/foreman/job_templates/update_group.erb +4 -4
  133. data/app/views/foreman/job_templates/update_package.erb +4 -4
  134. data/app/views/foreman/job_templates/update_packages_by_search_query.erb +3 -3
  135. data/app/views/katello/api/v2/alternate_content_sources/base.json.rabl +24 -0
  136. data/app/views/katello/api/v2/alternate_content_sources/index.json.rabl +7 -0
  137. data/app/views/katello/api/v2/alternate_content_sources/show.json.rabl +3 -0
  138. data/app/views/katello/api/v2/capsule_content/sync_status.json.rabl +1 -1
  139. data/app/views/katello/api/v2/content_facet/show.json.rabl +12 -0
  140. data/app/views/katello/api/v2/content_view_version_export_histories/show.json.rabl +2 -3
  141. data/app/views/katello/api/v2/content_view_versions/base.json.rabl +1 -1
  142. data/app/views/katello/api/v2/content_views/base.json.rabl +1 -0
  143. data/app/views/katello/api/v2/environments/show.json.rabl +2 -0
  144. data/app/views/katello/api/v2/errata/_counts.json.rabl +2 -2
  145. data/app/views/katello/api/v2/host_module_streams/base.json.rabl +2 -2
  146. data/app/views/katello/api/v2/hosts/host_collections.json.rabl +1 -1
  147. data/app/views/katello/api/v2/organizations/show.json.rabl +7 -1
  148. data/app/views/katello/api/v2/repositories/show.json.rabl +2 -1
  149. data/app/views/katello/api/v2/repository_sets/show.json.rabl +4 -0
  150. data/app/views/katello/sync_management/_repo.html.erb +8 -29
  151. data/config/routes/api/v2.rb +19 -0
  152. data/db/migrate/20150930183738_migrate_content_hosts.rb +0 -399
  153. data/db/migrate/20171025163149_remove_use_pulp_oauth_setting.rb +1 -1
  154. data/db/migrate/20171114150937_cleanup_installed_packages.rb +1 -1
  155. data/db/migrate/20180402160223_clean_up_force_post_sync_action_setting.rb +1 -1
  156. data/db/migrate/20211129200124_remove_dependency_solving_algorithm_setting.rb +1 -1
  157. data/db/migrate/20211220185935_clean_duplicate_content_units.rb +1 -1
  158. data/db/migrate/20220110223754_update_disconnected_settings.rb +5 -5
  159. data/db/migrate/20220117151612_add_alternate_content_sources.rb +48 -0
  160. data/db/migrate/20220124191056_add_type_to_cdn_configuration.rb +9 -4
  161. data/db/migrate/20220209203251_add_generated_for_to_content_views.rb +13 -0
  162. data/db/migrate/20220209205137_expand_sync_timeout_settings.rb +7 -7
  163. data/db/migrate/20220228173251_remove_drpm_from_ignorable_content.rb +12 -0
  164. data/db/migrate/20220303160220_remove_duplicate_errata.rb +1 -1
  165. data/db/migrate/20220404190836_delete_old_setting_data.rb +9 -0
  166. data/db/migrate/20220405220616_update_cdn_configuration_type.rb +11 -0
  167. data/db/migrate/20220419193414_content_settings_to_dsl_category.rb +5 -0
  168. data/db/migrate/20220428203334_add_last_refreshed_to_katello_alternate_content_sources.rb +5 -0
  169. data/db/seeds.d/110-content-view-autopublish.rb +13 -0
  170. data/db/seeds.d/150-module_job_templates.rb +1 -1
  171. data/engines/bastion/README.md +1 -0
  172. data/engines/bastion/app/assets/javascripts/bastion/components/bst-modal.directive.js +1 -0
  173. data/engines/bastion/app/views/bastion/layouts/assets.html.erb +1 -0
  174. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/activation-keys.routes.js +1 -1
  175. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-details.controller.js +4 -2
  176. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/views/activation-key-details.html +1 -1
  177. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/capsule-content/capsule-content.controller.js +11 -6
  178. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-module-streams.controller.js +1 -0
  179. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-installed.controller.js +1 -0
  180. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages.controller.js +11 -3
  181. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-traces.controller.js +1 -0
  182. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-actions.html +1 -1
  183. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-packages-applicable.html +1 -1
  184. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.controller.js +8 -0
  185. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-details.controller.js +4 -2
  186. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +2 -2
  187. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/content.service.js +10 -0
  188. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/views/environment-deb-repositories.html +26 -0
  189. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/views/environment-debs.html +27 -0
  190. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/environments.controller.js +1 -0
  191. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/environments.routes.js +22 -0
  192. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/views/environments.html +13 -7
  193. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +63 -17
  194. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +7 -8
  195. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details.controller.js +10 -1
  196. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-details.html +21 -3
  197. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +8 -12
  198. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/new-repository.controller.js +7 -5
  199. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +2 -1
  200. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/discovery-create.controller.js +1 -1
  201. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/views/discovery-create.html +1 -1
  202. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/products.routes.js +1 -0
  203. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/views/content-access-mode-banner.html +6 -1
  204. data/lib/katello/engine.rb +1 -5
  205. data/lib/katello/permission_creator.rb +34 -4
  206. data/lib/katello/plugin.rb +377 -3
  207. data/lib/katello/tasks/refresh_alternate_content_sources.rake +15 -0
  208. data/lib/katello/tasks/reset.rake.bak +67 -0
  209. data/lib/katello/tasks/update_content_default_http_proxy.rake +2 -3
  210. data/lib/katello/version.rb +1 -1
  211. data/locale/action_names.rb +47 -41
  212. data/locale/bn/LC_MESSAGES/katello.mo +0 -0
  213. data/locale/bn/katello.po +820 -106
  214. data/locale/bn/katello.po.time_stamp +0 -0
  215. data/locale/cs/LC_MESSAGES/katello.mo +0 -0
  216. data/locale/cs/katello.po +818 -104
  217. data/locale/cs/katello.po.time_stamp +0 -0
  218. data/locale/de/LC_MESSAGES/katello.mo +0 -0
  219. data/locale/de/katello.po +893 -179
  220. data/locale/de/katello.po.time_stamp +0 -0
  221. data/locale/en/LC_MESSAGES/katello.mo +0 -0
  222. data/locale/en/katello.po +817 -103
  223. data/locale/en/katello.po.time_stamp +0 -0
  224. data/locale/es/LC_MESSAGES/katello.mo +0 -0
  225. data/locale/es/katello.po +882 -168
  226. data/locale/es/katello.po.time_stamp +0 -0
  227. data/locale/fr/LC_MESSAGES/katello.mo +0 -0
  228. data/locale/fr/katello.po +1219 -505
  229. data/locale/fr/katello.po.time_stamp +0 -0
  230. data/locale/gu/LC_MESSAGES/katello.mo +0 -0
  231. data/locale/gu/katello.po +826 -112
  232. data/locale/gu/katello.po.time_stamp +0 -0
  233. data/locale/hi/LC_MESSAGES/katello.mo +0 -0
  234. data/locale/hi/katello.po +826 -112
  235. data/locale/hi/katello.po.time_stamp +0 -0
  236. data/locale/it/LC_MESSAGES/katello.mo +0 -0
  237. data/locale/it/katello.po +863 -148
  238. data/locale/it/katello.po.time_stamp +0 -0
  239. data/locale/ja/LC_MESSAGES/katello.mo +0 -0
  240. data/locale/ja/katello.po +1216 -499
  241. data/locale/ja/katello.po.time_stamp +0 -0
  242. data/locale/katello.pot +3847 -2507
  243. data/locale/kn/LC_MESSAGES/katello.mo +0 -0
  244. data/locale/kn/katello.po +826 -112
  245. data/locale/kn/katello.po.time_stamp +0 -0
  246. data/locale/ko/LC_MESSAGES/katello.mo +0 -0
  247. data/locale/ko/katello.po +912 -198
  248. data/locale/ko/katello.po.time_stamp +0 -0
  249. data/locale/mr/LC_MESSAGES/katello.mo +0 -0
  250. data/locale/mr/katello.po +826 -112
  251. data/locale/mr/katello.po.time_stamp +0 -0
  252. data/locale/or/LC_MESSAGES/katello.mo +0 -0
  253. data/locale/or/katello.po +826 -112
  254. data/locale/or/katello.po.time_stamp +0 -0
  255. data/locale/pa/LC_MESSAGES/katello.mo +0 -0
  256. data/locale/pa/katello.po +826 -112
  257. data/locale/pa/katello.po.time_stamp +0 -0
  258. data/locale/pt/LC_MESSAGES/katello.mo +0 -0
  259. data/locale/pt/katello.po +817 -103
  260. data/locale/pt/katello.po.time_stamp +0 -0
  261. data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
  262. data/locale/pt_BR/katello.po +879 -165
  263. data/locale/pt_BR/katello.po.time_stamp +0 -0
  264. data/locale/ru/LC_MESSAGES/katello.mo +0 -0
  265. data/locale/ru/katello.po +927 -213
  266. data/locale/ru/katello.po.time_stamp +0 -0
  267. data/locale/ta/LC_MESSAGES/katello.mo +0 -0
  268. data/locale/ta/katello.po +820 -106
  269. data/locale/ta/katello.po.time_stamp +0 -0
  270. data/locale/te/LC_MESSAGES/katello.mo +0 -0
  271. data/locale/te/katello.po +826 -112
  272. data/locale/te/katello.po.time_stamp +0 -0
  273. data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
  274. data/locale/zh_CN/katello.po +1202 -486
  275. data/locale/zh_CN/katello.po.time_stamp +0 -0
  276. data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
  277. data/locale/zh_TW/katello.po +856 -142
  278. data/locale/zh_TW/katello.po.time_stamp +0 -0
  279. data/webpack/components/Bookmark/index.js +22 -14
  280. data/webpack/components/EditableTextInput/EditableTextInput.js +20 -5
  281. data/webpack/components/Errata/index.js +38 -8
  282. data/webpack/components/Packages/index.js +1 -4
  283. data/webpack/components/Search/Search.js +22 -3
  284. data/webpack/components/SelectAllCheckbox/index.js +1 -0
  285. data/webpack/components/SelectableDropdown/SelectableDropdown.js +4 -2
  286. data/webpack/components/Table/EmptyStateMessage.js +21 -7
  287. data/webpack/components/Table/MainTable.js +29 -4
  288. data/webpack/components/Table/MainTable.scss +5 -1
  289. data/webpack/components/Table/TableHooks.js +65 -20
  290. data/webpack/components/Table/TableWrapper.js +9 -3
  291. data/webpack/components/Table/components/SortableColumnHeaders.js +19 -0
  292. data/webpack/components/Table/components/TranslatedPlural.js +57 -0
  293. data/webpack/components/TypeAhead/TypeAhead.js +12 -0
  294. data/webpack/components/TypeAhead/pf4Search/TypeAheadInput.js +13 -11
  295. data/webpack/components/TypeAhead/pf4Search/TypeAheadSearch.js +7 -2
  296. data/webpack/components/extensions/HostDetails/ActionsBar/index.js +27 -0
  297. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/ChangeHostCVModal.js +250 -0
  298. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/ContentViewDetailsCard.js +232 -0
  299. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/HostContentViewActions.js +19 -0
  300. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/HostContentViewConstants.js +2 -0
  301. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/__tests__/changeHostCVModal.test.js +131 -0
  302. data/webpack/components/extensions/HostDetails/Cards/{__tests__ → ContentViewDetailsCard/__tests__}/contentViewDetailsCard.test.js +22 -0
  303. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/__tests__/contentViews.fixtures.json +443 -0
  304. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/__tests__/envPaths.fixtures.json +320 -0
  305. data/webpack/components/extensions/HostDetails/Cards/ErrataOverviewCard.js +57 -33
  306. data/webpack/components/extensions/HostDetails/Cards/ErrataOverviewCard.scss +3 -0
  307. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsActions.js +30 -0
  308. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsCard.js +206 -0
  309. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsConstants.js +7 -0
  310. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsModal.js +227 -0
  311. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/HostCollectionsSelectors.js +18 -0
  312. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/__tests__/availableHostCollections.fixtures.json +106 -0
  313. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/__tests__/hostCollectionsCard.test.js +118 -0
  314. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/__tests__/hostCollectionsModal.test.js +235 -0
  315. data/webpack/components/extensions/HostDetails/Cards/HostCollectionsCard/__tests__/removableHostCollections.fixtures.json +45 -0
  316. data/webpack/components/extensions/HostDetails/Cards/__tests__/errataOverviewCard.test.js +33 -8
  317. data/webpack/components/extensions/HostDetails/DetailsTabCards/InstalledProductsCard.js +44 -0
  318. data/webpack/components/extensions/HostDetails/DetailsTabCards/RecentCommunicationCardExtensions.js +37 -0
  319. data/webpack/components/extensions/HostDetails/DetailsTabCards/RegistrationCard.js +107 -0
  320. data/webpack/components/extensions/HostDetails/DetailsTabCards/SystemPropertiesCardExtensions.js +38 -0
  321. data/webpack/components/extensions/HostDetails/HostDetailsActions.js +11 -0
  322. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/SecondaryTabsRoutes.js +4 -0
  323. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/constants.js +2 -0
  324. data/webpack/components/extensions/HostDetails/Tabs/ContentTab/index.js +6 -1
  325. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/ErrataTab.js +176 -72
  326. data/webpack/components/extensions/HostDetails/Tabs/ErrataTab/HostErrataActions.js +1 -7
  327. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsActions.js +1 -3
  328. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsConstants.js +28 -0
  329. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsTab.js +522 -118
  330. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/HostPackagesActions.js +1 -7
  331. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackageInstallModal.js +6 -4
  332. data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackagesTab.js +164 -58
  333. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionActions.js +59 -49
  334. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionConstants.js +1 -0
  335. data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionHooks.js +85 -0
  336. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsActions.js +33 -54
  337. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsConstants.js +20 -0
  338. data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.js +298 -107
  339. data/webpack/components/extensions/HostDetails/Tabs/TracesTab/EnableTracerModal.js +14 -7
  340. data/webpack/components/extensions/HostDetails/Tabs/TracesTab/HostTracesActions.js +2 -1
  341. data/webpack/components/extensions/HostDetails/Tabs/TracesTab/TracesEnabler.js +104 -0
  342. data/webpack/components/extensions/HostDetails/Tabs/TracesTab/TracesTab.js +134 -57
  343. data/webpack/components/extensions/HostDetails/Tabs/__tests__/errataTab.test.js +37 -32
  344. data/webpack/components/extensions/HostDetails/Tabs/{ModuleStreamsTab/__tests__/modules.fixtures.json → __tests__/moduleStreams.fixtures.json} +6 -3
  345. data/webpack/components/extensions/HostDetails/Tabs/__tests__/moduleStreamsTab.test.js +261 -0
  346. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packageInstallModal.test.js +21 -15
  347. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +44 -1
  348. data/webpack/components/extensions/HostDetails/Tabs/__tests__/repositorySets.fixtures.json +4 -1
  349. data/webpack/components/extensions/HostDetails/Tabs/__tests__/repositorySetsTab.test.js +105 -6
  350. data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracesTab.test.js +25 -6
  351. data/webpack/components/extensions/HostDetails/Tabs/customizedRexUrlHelpers.js +6 -0
  352. data/webpack/components/extensions/HostDetails/hostDetailsHelpers.js +18 -0
  353. data/webpack/containers/Application/config.js +5 -0
  354. data/webpack/global_index.js +32 -9
  355. data/webpack/global_test_setup.js +13 -0
  356. data/webpack/redux/actions/RedHatRepositories/enabled.js +2 -1
  357. data/webpack/redux/actions/RedHatRepositories/helpers.js +13 -8
  358. data/webpack/scenes/AlternateContentSources/ACSActions.js +65 -0
  359. data/webpack/scenes/AlternateContentSources/ACSConstants.js +18 -0
  360. data/webpack/scenes/AlternateContentSources/ACSIndexPage.js +23 -0
  361. data/webpack/scenes/AlternateContentSources/ACSSelectors.js +24 -0
  362. data/webpack/scenes/AlternateContentSources/Create/ACSCreateContext.js +4 -0
  363. data/webpack/scenes/AlternateContentSources/Create/ACSCreateWizard.js +160 -0
  364. data/webpack/scenes/AlternateContentSources/Create/Steps/ACSCreateFinish.js +79 -0
  365. data/webpack/scenes/AlternateContentSources/Create/Steps/ACSCredentials.js +199 -0
  366. data/webpack/scenes/AlternateContentSources/Create/Steps/ACSReview.js +104 -0
  367. data/webpack/scenes/AlternateContentSources/Create/Steps/ACSSmartProxies.js +41 -0
  368. data/webpack/scenes/AlternateContentSources/Create/Steps/AcsUrlPaths.js +71 -0
  369. data/webpack/scenes/AlternateContentSources/Create/Steps/NameACS.js +57 -0
  370. data/webpack/scenes/AlternateContentSources/Create/Steps/SelectSource.js +77 -0
  371. data/webpack/scenes/AlternateContentSources/Create/__tests__/acsCreate.test.js +149 -0
  372. data/webpack/scenes/AlternateContentSources/Create/__tests__/acsCreateData.fixtures.json +3 -0
  373. data/webpack/scenes/AlternateContentSources/Create/__tests__/contentCredentials.fixtures.json +69 -0
  374. data/webpack/scenes/AlternateContentSources/Create/__tests__/smartProxy.fixtures.json +65 -0
  375. data/webpack/scenes/AlternateContentSources/MainTable/ACSTable.js +162 -0
  376. data/webpack/scenes/AlternateContentSources/MainTable/__tests__/acsIndex.fixtures.json +91 -0
  377. data/webpack/scenes/AlternateContentSources/MainTable/__tests__/acsTable.test.js +67 -0
  378. data/webpack/scenes/AlternateContentSources/index.js +4 -0
  379. data/webpack/scenes/Content/Details/ContentRepositories.js +1 -0
  380. data/webpack/scenes/Content/Table/ContentTable.js +1 -0
  381. data/webpack/scenes/ContentCredentials/ContentCredentialSelectors.js +4 -1
  382. data/webpack/scenes/ContentViews/ContentViewsActions.js +6 -2
  383. data/webpack/scenes/ContentViews/ContentViewsConstants.js +11 -3
  384. data/webpack/scenes/ContentViews/Copy/CopyContentViewForm.js +2 -1
  385. data/webpack/scenes/ContentViews/Create/ContentViewFormComponents.js +10 -1
  386. data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +2 -1
  387. data/webpack/scenes/ContentViews/Delete/ContentViewDeleteWizard.js +7 -5
  388. data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionFinish.js +29 -21
  389. data/webpack/scenes/ContentViews/Delete/__tests__/contentViewDelete.test.js +15 -8
  390. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewAddModal.js +2 -2
  391. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewBulkAddModal.js +2 -2
  392. data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +3 -1
  393. data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +34 -8
  394. data/webpack/scenes/ContentViews/Details/ContentViewDetailSelectors.js +33 -29
  395. data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +130 -79
  396. data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +16 -2
  397. data/webpack/scenes/ContentViews/Details/Filters/Add/CVFilterAddModal.js +2 -1
  398. data/webpack/scenes/ContentViews/Details/Filters/AffectedRepositories/AffectedRepositoryTable.js +2 -1
  399. data/webpack/scenes/ContentViews/Details/Filters/CVContainerImageFilterContent.js +6 -1
  400. data/webpack/scenes/ContentViews/Details/Filters/CVErrataDateFilterContent.js +41 -21
  401. data/webpack/scenes/ContentViews/Details/Filters/CVErrataIDFilterContent.js +38 -20
  402. data/webpack/scenes/ContentViews/Details/Filters/CVModuleStreamFilterContent.js +2 -0
  403. data/webpack/scenes/ContentViews/Details/Filters/CVPackageGroupFilterContent.js +8 -1
  404. data/webpack/scenes/ContentViews/Details/Filters/CVRpmFilterContent.js +9 -1
  405. data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilters.js +2 -1
  406. data/webpack/scenes/ContentViews/Details/Filters/MatchContentModal/CVRpmMatchContentModal.js +1 -0
  407. data/webpack/scenes/ContentViews/Details/Filters/Rules/ContainerTag/AddEditContainerTagRuleModal.js +27 -12
  408. data/webpack/scenes/ContentViews/Details/Filters/Rules/Package/AddEditPackageRuleModal.js +39 -17
  409. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVContainerImageFilterContent.test.js +27 -10
  410. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVRpmFilterContent.test.js +46 -23
  411. data/webpack/scenes/ContentViews/Details/Histories/ContentViewHistories.js +3 -2
  412. data/webpack/scenes/ContentViews/Details/Promote/ContentViewVersionPromote.js +5 -2
  413. data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +161 -108
  414. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewAddRemove.test.js +7 -7
  415. data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewRepoAdd.fixture.json +1 -0
  416. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/ActionSummary.js +58 -0
  417. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/BulkDeleteContextWrapper.js +45 -0
  418. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/BulkDeleteHelpers.js +30 -0
  419. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/BulkDeleteModal.js +56 -0
  420. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/ConfirmBulkDelete.js +126 -0
  421. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/FinishBulkDelete.js +61 -0
  422. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/ReassignActivationKeys.js +196 -0
  423. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/ReassignHosts.js +220 -0
  424. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/ReviewEnvironments.js +104 -0
  425. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/BulkDeleteModal.test.js +122 -0
  426. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/BulkDeleteVersions.fixtures.json +600 -0
  427. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/contentView.fixtures.json +1504 -0
  428. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/contentViewVersion.fixtures.json +936 -0
  429. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/environmentPaths.fixtures.json +261 -0
  430. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/__tests__/hosts.fixtures.json +163 -0
  431. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/bulkDeleteSteps.js +79 -0
  432. data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersions.js +192 -167
  433. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveCVVersionWizard.js +2 -5
  434. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVVersionDeleteFinish.js +38 -53
  435. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVVersionRemoveReview.js +1 -1
  436. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvVersionRemove.test.js +6 -12
  437. data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedActivationKeys.js +1 -0
  438. data/webpack/scenes/ContentViews/Details/Versions/Delete/affectedHosts.js +1 -0
  439. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailConfig.js +1 -0
  440. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetails.js +8 -20
  441. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsHeader.js +23 -13
  442. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionDetailsTable.js +3 -0
  443. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.fixtures.json +4 -4
  444. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.test.js +0 -3
  445. data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetailsEmpty.test.js +4 -4
  446. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.test.js +12 -14
  447. data/webpack/scenes/ContentViews/Details/__tests__/contentViewDetails.fixtures.json +1 -0
  448. data/webpack/scenes/ContentViews/Publish/CVPublishFinish.js +96 -117
  449. data/webpack/scenes/ContentViews/Publish/PublishContentViewWizard.js +13 -19
  450. data/webpack/scenes/ContentViews/Publish/__tests__/publishContentView.test.js +9 -20
  451. data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +165 -148
  452. data/webpack/scenes/ContentViews/Table/tableDataGenerator.js +2 -0
  453. data/webpack/scenes/ContentViews/components/ContentViewIcon.js +14 -3
  454. data/webpack/scenes/ContentViews/components/EnvironmentLabels.js +4 -3
  455. data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.js +10 -6
  456. data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.scss +6 -1
  457. data/webpack/scenes/ContentViews/components/TaskPresenter/TaskPresenter.js +40 -35
  458. data/webpack/scenes/ContentViews/expansions/RelatedCompositeContentViewsModal.js +1 -1
  459. data/webpack/scenes/ContentViews/expansions/RelatedContentViewComponentsModal.js +2 -2
  460. data/webpack/scenes/ContentViews/helpers.js +3 -0
  461. data/webpack/scenes/Hosts/ChangeContentSource/helpers.js +5 -0
  462. data/webpack/scenes/RedHatRepositories/RedHatRepositoriesPage.js +3 -3
  463. data/webpack/scenes/RedHatRepositories/components/EnabledRepository/EnabledRepository.js +2 -1
  464. data/webpack/scenes/RedHatRepositories/components/EnabledRepository/__tests__/EnabledRepository.test.js +2 -0
  465. data/webpack/scenes/RedHatRepositories/components/Search.js +4 -4
  466. data/webpack/scenes/SmartProxy/SmartProxyContentActions.js +9 -2
  467. data/webpack/scenes/SmartProxy/SmartProxyContentConstants.js +1 -1
  468. data/webpack/scenes/SmartProxy/SmartProxyContentSelectors.js +10 -1
  469. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnConfigurationConstants.js +3 -3
  470. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/CdnTypeForm.js +2 -0
  471. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/{AirGappedTypeForm.js → ExportSyncForm.js} +7 -6
  472. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/{UpstreamServerTypeForm.js → NetworkSyncForm.js} +15 -7
  473. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/__tests__/{AirGappedTypeForm.test.js → ExportSyncForm.test.js} +4 -4
  474. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/__tests__/{UpstreamServerTypeForm.test.js → NetworkSyncForm.test.js} +8 -8
  475. data/webpack/scenes/Subscriptions/Manifest/CdnConfigurationTab/index.js +11 -11
  476. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +1 -0
  477. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +8 -7
  478. data/webpack/scenes/Tasks/TaskActions.js +6 -0
  479. data/webpack/scenes/Tasks/TaskSelectors.js +11 -0
  480. data/webpack/scenes/Tasks/helpers.js +60 -5
  481. data/webpack/utils/helpers.js +2 -0
  482. metadata +183 -38
  483. data/app/models/setting/content.rb +0 -201
  484. data/db/seeds.d/107-enable_dynflow.rb +0 -8
  485. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard.js +0 -96
  486. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/__tests__/moduleStreamsTab.test.js +0 -108
  487. data/webpack/components/extensions/HostDetails/Tabs/TracesTab/EnableTracerEmptyState.js +0 -42
  488. data/webpack/scenes/ContentViews/Details/DetailsContainer.js +0 -36
@@ -0,0 +1,261 @@
1
+ import React from 'react';
2
+ import { act } from 'react-test-renderer';
3
+ import { renderWithRedux, patientlyWaitFor, within, fireEvent } from 'react-testing-lib-wrapper';
4
+ import { nockInstance, assertNockRequest, mockForemanAutocomplete, mockSetting } from '../../../../../test-utils/nockWrapper';
5
+ import { ModuleStreamsTab } from '../ModuleStreamsTab/ModuleStreamsTab.js';
6
+ import mockModuleStreams from './moduleStreams.fixtures.json';
7
+ import mockBookmarkData from './bookmarks.fixtures.json';
8
+ import { MODULE_STREAMS_KEY } from '../../../../../scenes/ModuleStreams/ModuleStreamsConstants';
9
+ import { foremanApi } from '../../../../../services/api';
10
+
11
+ jest.mock('../../hostDetailsHelpers', () => ({
12
+ ...jest.requireActual('../../hostDetailsHelpers'),
13
+ userPermissionsFromHostDetails: () => ({
14
+ create_job_invocations: true,
15
+ }),
16
+ }));
17
+
18
+ const moduleBookmarks = foremanApi.getApiUrl('/bookmarks?search=controller%3Dkatello_host_available_module_streams');
19
+
20
+ const contentFacetAttributes = {
21
+ id: 11,
22
+ uuid: 'e5761ea3-4117-4ecf-83d0-b694f99b389e',
23
+ content_view_default: false,
24
+ lifecycle_environment_library: false,
25
+ };
26
+
27
+ const renderOptions = (facetAttributes = contentFacetAttributes) => ({
28
+ apiNamespace: MODULE_STREAMS_KEY,
29
+ initialState: {
30
+ API: {
31
+ HOST_DETAILS: {
32
+ response: {
33
+ id: 1,
34
+ name: 'test-host',
35
+ content_facet_attributes: { ...facetAttributes },
36
+ },
37
+ status: 'RESOLVED',
38
+ },
39
+ },
40
+ },
41
+ });
42
+
43
+ const hostModuleStreams = foremanApi.getApiUrl('/hosts/1/module_streams');
44
+ const autocompleteUrl = '/hosts/1/module_streams/auto_complete_search';
45
+
46
+ let firstModuleStreams;
47
+ let searchDelayScope;
48
+ let autoSearchScope;
49
+ let bookmarkScope;
50
+
51
+ beforeEach(() => {
52
+ const { results } = mockModuleStreams;
53
+ [firstModuleStreams] = results;
54
+ bookmarkScope = nockInstance.get(moduleBookmarks).reply(200, mockBookmarkData);
55
+ searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
56
+ autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
57
+ });
58
+
59
+ afterEach(() => {
60
+ assertNockRequest(searchDelayScope);
61
+ assertNockRequest(autoSearchScope);
62
+ assertNockRequest(bookmarkScope);
63
+ });
64
+
65
+ beforeEach(() => {
66
+ const { results } = mockModuleStreams;
67
+ [firstModuleStreams] = results;
68
+ searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
69
+ autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
70
+ });
71
+
72
+ afterEach(() => {
73
+ assertNockRequest(searchDelayScope);
74
+ assertNockRequest(autoSearchScope);
75
+ });
76
+
77
+ test('Can call API for Module streams and show on screen on page load', async (done) => {
78
+ // Setup autocomplete with mockForemanAutoComplete since we aren't adding /katello
79
+ const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
80
+ const scope = nockInstance
81
+ .get(hostModuleStreams)
82
+ .query(true)
83
+ .reply(200, mockModuleStreams);
84
+
85
+ const { getAllByText } = renderWithRedux(<ModuleStreamsTab />, renderOptions());
86
+
87
+ // Assert that the Module streams are now showing on the screen, but wait for them to appear.
88
+ await patientlyWaitFor(() =>
89
+ expect(getAllByText(firstModuleStreams.name)[0]).toBeInTheDocument());
90
+ // Assert request was made and completed, see helper function
91
+ assertNockRequest(autocompleteScope);
92
+ assertNockRequest(scope, done); // Pass jest callback to confirm test is done
93
+ act(done);
94
+ });
95
+
96
+ test('Can handle no Module streams being present', async (done) => {
97
+ // Setup autocomplete with mockForemanAutoComplete since we aren't adding /katello
98
+ const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
99
+
100
+ const noResults = {
101
+ total: 0,
102
+ subtotal: 0,
103
+ page: 1,
104
+ per_page: 20,
105
+ results: [],
106
+ };
107
+
108
+ const scope = nockInstance
109
+ .get(hostModuleStreams)
110
+ .query(true)
111
+ .reply(200, noResults);
112
+
113
+ const { queryByText } = renderWithRedux(<ModuleStreamsTab />, renderOptions());
114
+
115
+ // Assert that there are not any Module streams showing on the screen.
116
+ await patientlyWaitFor(() => expect(queryByText('This host does not have any Module streams.')).toBeInTheDocument());
117
+ // Assert request was made and completed, see helper function
118
+ assertNockRequest(autocompleteScope);
119
+ assertNockRequest(scope, done); // Pass jest callback to confirm test is done
120
+ act(done);
121
+ });
122
+
123
+ test('Can filter results based on status', async (done) => {
124
+ const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
125
+ const scope = nockInstance
126
+ .get(hostModuleStreams)
127
+ .query(true)
128
+ .reply(200, mockModuleStreams);
129
+
130
+ const scope2 = nockInstance
131
+ .get(hostModuleStreams)
132
+ .query(true)
133
+ .reply(200, mockModuleStreams);
134
+
135
+ const {
136
+ queryByLabelText,
137
+ getByRole,
138
+ getAllByText,
139
+ } = renderWithRedux(<ModuleStreamsTab />, renderOptions());
140
+
141
+ // Assert that the Module streams are now showing on the screen, but wait for them to appear.
142
+ await patientlyWaitFor(() =>
143
+ expect(getAllByText(firstModuleStreams.name)[0]).toBeInTheDocument());
144
+ const typeContainer = queryByLabelText('select Status container', { ignore: 'th' });
145
+ const typeDropdown = within(typeContainer).queryByText('Status');
146
+ expect(typeDropdown).toBeInTheDocument();
147
+ fireEvent.click(typeDropdown);
148
+ const installed = getByRole('option', { name: 'select Installed' });
149
+ fireEvent.click(installed);
150
+ assertNockRequest(autocompleteScope);
151
+ assertNockRequest(scope);
152
+ assertNockRequest(scope2, done);
153
+ act(done);
154
+ });
155
+
156
+ test('Can filter results based on Installation status', async (done) => {
157
+ const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
158
+ const scope = nockInstance
159
+ .get(hostModuleStreams)
160
+ .query(true)
161
+ .reply(200, mockModuleStreams);
162
+
163
+ const scope2 = nockInstance
164
+ .get(hostModuleStreams)
165
+ .query(true)
166
+ .reply(200, mockModuleStreams);
167
+
168
+ const {
169
+ queryByLabelText,
170
+ getByRole,
171
+ getAllByText,
172
+ } = renderWithRedux(<ModuleStreamsTab />, renderOptions());
173
+
174
+ // Assert that the Module streams are now showing on the screen, but wait for them to appear.
175
+ await patientlyWaitFor(() =>
176
+ expect(getAllByText(firstModuleStreams.name)[0]).toBeInTheDocument());
177
+ const typeContainer = queryByLabelText('select Installation status container', { ignore: 'th' });
178
+ const typeDropdown = within(typeContainer).queryByText('Installation status');
179
+ expect(typeDropdown).toBeInTheDocument();
180
+ fireEvent.click(typeDropdown);
181
+ const installed = getByRole('option', { name: 'select Upgradable' });
182
+ fireEvent.click(installed);
183
+ assertNockRequest(autocompleteScope);
184
+ assertNockRequest(scope);
185
+ assertNockRequest(scope2, done);
186
+ act(done);
187
+ });
188
+
189
+ test('Can provide dropdown actions with redirects on Module Streams with customized Rex', async (done) => {
190
+ const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
191
+ const scope = nockInstance
192
+ .get(hostModuleStreams)
193
+ .query(true)
194
+ .reply(200, mockModuleStreams);
195
+
196
+ const {
197
+ queryByLabelText,
198
+ getByText,
199
+ getAllByText,
200
+ getByLabelText,
201
+ } = renderWithRedux(<ModuleStreamsTab />, renderOptions());
202
+
203
+ // Assert that the Module streams are now showing on the screen, but wait for them to appear.
204
+ await patientlyWaitFor(() =>
205
+ expect(getAllByText(firstModuleStreams.name)[0]).toBeInTheDocument());
206
+ expect(queryByLabelText('kebab-dropdown-3')).toBeInTheDocument();
207
+ fireEvent.click(queryByLabelText('kebab-dropdown-3'));
208
+ await patientlyWaitFor(() => expect(getByLabelText('customize-checkbox-3')).toBeInTheDocument());
209
+ fireEvent.click(getByLabelText('customize-checkbox-3'));
210
+ await patientlyWaitFor(() => expect(getByText('Enable')).toBeInTheDocument());
211
+ expect(getByText('Enable')).toHaveAttribute('href', '/job_invocations/new?feature=katello_module_stream_action&host_ids=name%20%5E%20(test-host)&inputs%5Baction%5D=enable&inputs%5Bmodule_spec%5D=walrus:2.4');
212
+ expect(getByText('Install')).toHaveAttribute('href', '/job_invocations/new?feature=katello_module_stream_action&host_ids=name%20%5E%20(test-host)&inputs%5Baction%5D=install&inputs%5Bmodule_spec%5D=walrus:2.4');
213
+ assertNockRequest(autocompleteScope);
214
+ assertNockRequest(scope, done);
215
+ act(done);
216
+ });
217
+
218
+ test('Can perform actions on Module Streams', async (done) => {
219
+ const jobInvocationURL = foremanApi.getApiUrl('/job_invocations');
220
+ const exampleRemoveAction = {
221
+ job_invocation:
222
+ {
223
+ feature: 'katello_module_stream_action',
224
+ inputs: {
225
+ action: 'remove',
226
+ module_spec: 'walrus:2.4',
227
+ },
228
+ search_query: 'name ^ (test-host)',
229
+ },
230
+ };
231
+ const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
232
+ const scope = nockInstance
233
+ .get(hostModuleStreams)
234
+ .query(true)
235
+ .reply(200, mockModuleStreams);
236
+
237
+ const jobScope = nockInstance
238
+ .post(jobInvocationURL, exampleRemoveAction)
239
+ .reply(200, { id: 'dummy_id', description: 'Remove action dummy response' });
240
+
241
+ const {
242
+ queryByLabelText,
243
+ getByText,
244
+ getAllByText,
245
+ getByLabelText,
246
+ } = renderWithRedux(<ModuleStreamsTab />, renderOptions());
247
+
248
+ // Assert that the Module streams are now showing on the screen, but wait for them to appear.
249
+ await patientlyWaitFor(() =>
250
+ expect(getAllByText(firstModuleStreams.name)[0]).toBeInTheDocument());
251
+ expect(queryByLabelText('kebab-dropdown-3')).toBeInTheDocument();
252
+ fireEvent.click(queryByLabelText('kebab-dropdown-3'));
253
+ await patientlyWaitFor(() => expect(getByText('Enable')).toBeInTheDocument());
254
+ fireEvent.click(getByText('Remove'));
255
+ expect(getByLabelText('confirm-module-action')).toBeInTheDocument();
256
+ fireEvent.click(getByLabelText('confirm-module-action'));
257
+ assertNockRequest(autocompleteScope);
258
+ assertNockRequest(scope);
259
+ assertNockRequest(jobScope, done);
260
+ act(done);
261
+ });
@@ -4,9 +4,17 @@ import { nockInstance, assertNockRequest, mockForemanAutocomplete, mockSetting }
4
4
  import katelloApi, { foremanApi } from '../../../../../services/api';
5
5
  import mockPackagesData from './yumInstallablePackages.fixtures.json';
6
6
  import PackageInstallModal from '../PackagesTab/PackageInstallModal';
7
- import { HOST_YUM_INSTALLABLE_PACKAGES_KEY, PACKAGE_SEARCH_QUERY } from '../PackagesTab/YumInstallablePackagesConstants';
7
+ import { HOST_YUM_INSTALLABLE_PACKAGES_KEY } from '../PackagesTab/YumInstallablePackagesConstants';
8
8
  import { REX_FEATURES } from '../RemoteExecutionConstants';
9
9
 
10
+ jest.mock('../../hostDetailsHelpers', () => ({
11
+ ...jest.requireActual('../../hostDetailsHelpers'),
12
+ userPermissionsFromHostDetails: () => ({
13
+ create_job_invocations: true,
14
+ edit_hosts: true,
15
+ }),
16
+ }));
17
+
10
18
  const contentFacetAttributes = {
11
19
  id: 11,
12
20
  uuid: 'e5761ea3-4117-4ecf-83d0-b694f99b389e',
@@ -32,7 +40,6 @@ const renderOptions = (facetAttributes = contentFacetAttributes) => ({
32
40
 
33
41
  const hostYumInstallablePackages = katelloApi.getApiUrl('/packages');
34
42
  const hostPackages = foremanApi.getApiUrl('/hosts/1/packages/install');
35
- const jobInvocations = foremanApi.getApiUrl('/job_invocations');
36
43
  const autocompleteUrl = '/hosts/1/packages/auto_complete_search';
37
44
  const fakeTask = { id: '21c0f9e4-b27b-49aa-8774-6be66126043b' };
38
45
 
@@ -77,6 +84,7 @@ test('Can call API for installable packages and show on screen on page load', as
77
84
  hostId={1}
78
85
  hostName="test-host"
79
86
  showKatelloAgent={false}
87
+ triggerPackageInstall={jest.fn()}
80
88
  />, renderOptions());
81
89
 
82
90
  // Assert that the packages are now showing on the screen, but wait for them to appear.
@@ -109,6 +117,7 @@ test('Can handle no installable packages being present', async (done) => {
109
117
  hostId={1}
110
118
  hostName="test-host"
111
119
  showKatelloAgent={false}
120
+ triggerPackageInstall={jest.fn()}
112
121
  />, renderOptions());
113
122
 
114
123
  // Assert that there are not any packages showing on the screen.
@@ -134,6 +143,7 @@ test('Does not show katello-agent option when disabled', async (done) => {
134
143
  hostId={1}
135
144
  hostName="test-host"
136
145
  showKatelloAgent={false}
146
+ triggerPackageInstall={jest.fn()}
137
147
  />, renderOptions());
138
148
 
139
149
  // Assert that the packages are now showing on the screen, but wait for them to appear.
@@ -172,6 +182,7 @@ test('Shows the katello-agent option when enabled', async (done) => {
172
182
  hostId={1}
173
183
  hostName="test-host"
174
184
  showKatelloAgent
185
+ triggerPackageInstall={jest.fn()}
175
186
  />, renderOptions());
176
187
 
177
188
  // Assert that the packages are now showing on the screen, but wait for them to appear.
@@ -209,6 +220,7 @@ test('Can install packages via katello-agent', async (done) => {
209
220
  hostId={1}
210
221
  hostName="test-host"
211
222
  showKatelloAgent
223
+ triggerPackageInstall={jest.fn()}
212
224
  />, renderOptions());
213
225
 
214
226
  await patientlyWaitFor(() => expect(getAllByText(firstPackages.name)[0]).toBeInTheDocument());
@@ -236,17 +248,7 @@ test('Can install a package via remote execution', async (done) => {
236
248
  .get(hostYumInstallablePackages)
237
249
  .query(defaultQuery)
238
250
  .reply(200, mockPackagesData);
239
- const installScope = nockInstance
240
- .post(jobInvocations, {
241
- job_invocation: {
242
- inputs: {
243
- [PACKAGE_SEARCH_QUERY]: `id ^ (${firstPackages.id},${secondPackages.id})`,
244
- },
245
- search_query: 'name ^ (test-host)',
246
- feature: REX_FEATURES.KATELLO_PACKAGE_INSTALL_BY_SEARCH,
247
- },
248
- })
249
- .reply(201);
251
+ const triggerPackageInstall = jest.fn();
250
252
 
251
253
  const {
252
254
  getAllByText, getByText, getByRole,
@@ -256,6 +258,7 @@ test('Can install a package via remote execution', async (done) => {
256
258
  hostId={1}
257
259
  hostName="test-host"
258
260
  showKatelloAgent
261
+ triggerPackageInstall={triggerPackageInstall}
259
262
  />, renderOptions());
260
263
 
261
264
  await patientlyWaitFor(() => expect(getAllByText(firstPackages.name)[0]).toBeInTheDocument());
@@ -271,9 +274,9 @@ test('Can install a package via remote execution', async (done) => {
271
274
  const rexOption = getByText('Install via remote execution');
272
275
  fireEvent.click(rexOption);
273
276
 
277
+ expect(triggerPackageInstall).toHaveBeenCalled();
274
278
  assertNockRequest(autocompleteScope);
275
- assertNockRequest(scope);
276
- assertNockRequest(installScope, done);
279
+ assertNockRequest(scope, done);
277
280
  });
278
281
 
279
282
  test('Can install a package via customized remote execution', async (done) => {
@@ -290,6 +293,7 @@ test('Can install a package via customized remote execution', async (done) => {
290
293
  closeModal={jest.fn()}
291
294
  hostId={1}
292
295
  hostName="test-host"
296
+ triggerPackageInstall={jest.fn()}
293
297
  />, renderOptions());
294
298
 
295
299
  await patientlyWaitFor(() => expect(getAllByText(firstPackages.name)[0]).toBeInTheDocument());
@@ -326,6 +330,7 @@ test('Uses package_install_by_search_query template when in select all mode', as
326
330
  closeModal={jest.fn()}
327
331
  hostId={1}
328
332
  hostName="test-host"
333
+ triggerPackageInstall={jest.fn()}
329
334
  />, renderOptions());
330
335
 
331
336
  await patientlyWaitFor(() => expect(getAllByText(firstPackages.name)[0]).toBeInTheDocument());
@@ -364,6 +369,7 @@ test('Disables the katello-agent option when in select all mode', async (done) =
364
369
  hostId={1}
365
370
  hostName="test-host"
366
371
  showKatelloAgent
372
+ triggerPackageInstall={jest.fn()}
367
373
  />, renderOptions());
368
374
 
369
375
  await patientlyWaitFor(() => expect(getAllByText(firstPackages.name)[0]).toBeInTheDocument());
@@ -6,6 +6,16 @@ import { HOST_PACKAGES_KEY, PACKAGES_SEARCH_QUERY } from '../PackagesTab/HostPac
6
6
  import { PackagesTab } from '../PackagesTab/PackagesTab.js';
7
7
  import mockPackagesData from './packages.fixtures.json';
8
8
  import { REX_FEATURES } from '../RemoteExecutionConstants';
9
+ import * as hooks from '../../../../Table/TableHooks';
10
+ import mockBookmarkData from './bookmarks.fixtures.json';
11
+
12
+ jest.mock('../../hostDetailsHelpers', () => ({
13
+ ...jest.requireActual('../../hostDetailsHelpers'),
14
+ userPermissionsFromHostDetails: () => ({
15
+ create_job_invocations: true,
16
+ edit_hosts: true,
17
+ }),
18
+ }));
9
19
 
10
20
  const contentFacetAttributes = {
11
21
  id: 11,
@@ -15,6 +25,8 @@ const contentFacetAttributes = {
15
25
  };
16
26
 
17
27
  const hostname = 'test-host.example.com';
28
+ const packageBookmarks = foremanApi.getApiUrl('/bookmarks?search=controller%3Dkatello_host_installed_packages');
29
+
18
30
  const renderOptions = (facetAttributes = contentFacetAttributes) => ({
19
31
  apiNamespace: HOST_PACKAGES_KEY,
20
32
  initialState: {
@@ -34,21 +46,29 @@ const renderOptions = (facetAttributes = contentFacetAttributes) => ({
34
46
  const hostPackages = foremanApi.getApiUrl('/hosts/1/packages');
35
47
  const jobInvocations = foremanApi.getApiUrl('/job_invocations');
36
48
  const autocompleteUrl = '/hosts/1/packages/auto_complete_search';
37
- const defaultQueryWithoutSearch = {
49
+ const baseQuery = {
38
50
  include_latest_upgradable: true,
39
51
  per_page: 20,
40
52
  page: 1,
41
53
  };
54
+
55
+ const defaultQueryWithoutSearch = {
56
+ ...baseQuery,
57
+ sort_by: 'nvra',
58
+ sort_order: 'asc',
59
+ };
42
60
  const defaultQuery = { ...defaultQueryWithoutSearch, search: '' };
43
61
 
44
62
  let firstPackage;
45
63
  let secondPackage;
46
64
  let searchDelayScope;
47
65
  let autoSearchScope;
66
+ let bookmarkScope;
48
67
 
49
68
  beforeEach(() => {
50
69
  const { results } = mockPackagesData;
51
70
  [firstPackage, secondPackage] = results;
71
+ bookmarkScope = nockInstance.get(packageBookmarks).reply(200, mockBookmarkData);
52
72
  searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
53
73
  autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
54
74
  });
@@ -56,6 +76,7 @@ beforeEach(() => {
56
76
  afterEach(() => {
57
77
  assertNockRequest(searchDelayScope);
58
78
  assertNockRequest(autoSearchScope);
79
+ assertNockRequest(bookmarkScope);
59
80
  });
60
81
 
61
82
  test('Can call API for packages and show on screen on page load', async (done) => {
@@ -390,3 +411,25 @@ test('Remove is disabled when in select all mode', async (done) => {
390
411
  assertNockRequest(autocompleteScope);
391
412
  assertNockRequest(scope, done);
392
413
  });
414
+
415
+ test('Sets initial search query from url params', async (done) => {
416
+ // Setup autocomplete with mockForemanAutoComplete since we aren't adding /katello
417
+ const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
418
+ const scope = nockInstance
419
+ .get(hostPackages)
420
+ .query({ ...defaultQuery, search: `name=${firstPackage.name}` })
421
+ .reply(200, { ...mockPackagesData, results: [firstPackage] });
422
+
423
+ jest.spyOn(hooks, 'useUrlParams').mockImplementation(() => ({
424
+ searchParam: `name=${firstPackage.name}`,
425
+ }));
426
+
427
+ const { getAllByText, queryByText } = renderWithRedux(<PackagesTab />, renderOptions());
428
+
429
+ await patientlyWaitFor(() => expect(getAllByText(firstPackage.name)[0]).toBeInTheDocument());
430
+ expect(queryByText(secondPackage.name)).not.toBeInTheDocument();
431
+
432
+ assertNockRequest(autocompleteScope);
433
+ assertNockRequest(scope, done); // Pass jest callback to confirm test is done
434
+ });
435
+
@@ -41,6 +41,7 @@
41
41
  "type": "yum",
42
42
  "gpgUrl": null,
43
43
  "contentUrl": "/custom/ParthaProduct/empty_repo",
44
+ "osRestricted": null,
44
45
  "override": "default",
45
46
  "overrides": [],
46
47
  "enabled_content_override": null
@@ -75,6 +76,7 @@
75
76
  "type": "yum",
76
77
  "gpgUrl": null,
77
78
  "contentUrl": "/custom/ParthaProduct/partha_multi-errata",
79
+ "osRestricted": "rhel-7",
78
80
  "override": "0",
79
81
  "overrides": [
80
82
  {
@@ -107,6 +109,7 @@
107
109
  "type": "yum",
108
110
  "gpgUrl": null,
109
111
  "contentUrl": "/custom/Pull_Provider/yggdrasil",
112
+ "osRestricted": null,
110
113
  "override": "1",
111
114
  "overrides": [
112
115
  {
@@ -117,4 +120,4 @@
117
120
  "enabled_content_override": true
118
121
  }
119
122
  ]
120
- }
123
+ }
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { renderWithRedux, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper';
2
+ import { renderWithRedux, patientlyWaitFor, within, fireEvent } from 'react-testing-lib-wrapper';
3
3
  import { nockInstance, assertNockRequest, mockAutocomplete, mockSetting } from '../../../../../test-utils/nockWrapper';
4
4
  import katelloApi, { foremanApi } from '../../../../../services/api';
5
5
  import { REPOSITORY_SETS_KEY } from '../RepositorySetsTab/RepositorySetsConstants';
@@ -8,6 +8,16 @@ import mockRepoSetData from './repositorySets.fixtures.json';
8
8
  import mockBookmarkData from './bookmarks.fixtures.json';
9
9
  import mockContentOverride from './contentOverrides.fixtures.json';
10
10
 
11
+ jest.mock('../../hostDetailsHelpers', () => ({
12
+ ...jest.requireActual('../../hostDetailsHelpers'),
13
+ userPermissionsFromHostDetails: () => ({
14
+ view_hosts: true,
15
+ view_activation_keys: true,
16
+ view_products: true,
17
+ edit_hosts: true,
18
+ }),
19
+ }));
20
+
11
21
  const contentFacetAttributes = {
12
22
  id: 11,
13
23
  uuid: 'e5761ea3-4117-4ecf-83d0-b694f99b389e',
@@ -43,6 +53,8 @@ const defaultQuery = {
43
53
  per_page: 20,
44
54
  page: 1,
45
55
  search: '',
56
+ sort_by: 'name',
57
+ sort_order: 'asc',
46
58
  };
47
59
  const libraryQuery = {
48
60
  ...defaultQuery,
@@ -50,6 +62,7 @@ const libraryQuery = {
50
62
  };
51
63
 
52
64
  let firstRepoSet;
65
+ let secondRepoSet;
53
66
  let searchDelayScope;
54
67
  let autoSearchScope;
55
68
  let bookmarkScope;
@@ -57,7 +70,7 @@ let bookmarkScope;
57
70
  beforeEach(() => {
58
71
  // jest.resetModules();
59
72
  const { results } = mockRepoSetData;
60
- [firstRepoSet] = results;
73
+ [firstRepoSet, secondRepoSet] = results;
61
74
  bookmarkScope = nockInstance.get(repositorySetBookmarks).reply(200, mockBookmarkData);
62
75
  searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
63
76
  autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
@@ -204,9 +217,11 @@ test('Can override to disabled', async (done) => {
204
217
  .get(hostRepositorySets)
205
218
  .query(defaultQuery)
206
219
  .reply(200, mockRepoSetData);
220
+ const overrides = JSON.parse(JSON.stringify(mockContentOverride));
221
+ overrides.results[0].enabled_content_override = false;
207
222
  const contentOverrideScope = nockInstance
208
223
  .put(contentOverride)
209
- .reply(200, mockContentOverride);
224
+ .reply(200, overrides);
210
225
 
211
226
  const { getByText, getAllByText, getAllByLabelText } =
212
227
  renderWithRedux(<RepositorySetsTab />, renderOptions());
@@ -240,9 +255,12 @@ test('Can override to enabled', async (done) => {
240
255
  .get(hostRepositorySets)
241
256
  .query(defaultQuery)
242
257
  .reply(200, mockRepoSetData);
258
+ const overrides = JSON.parse(JSON.stringify(mockContentOverride));
259
+ overrides.results[1].enabled_content_override = true;
260
+
243
261
  const contentOverrideScope = nockInstance
244
262
  .put(contentOverride)
245
- .reply(200, mockContentOverride);
263
+ .reply(200, overrides);
246
264
 
247
265
  const {
248
266
  getByText, queryByText, getAllByText, getAllByLabelText,
@@ -276,10 +294,12 @@ test('Can reset to default', async (done) => {
276
294
  .get(hostRepositorySets)
277
295
  .query(defaultQuery)
278
296
  .reply(200, mockRepoSetData);
297
+ const overrides = JSON.parse(JSON.stringify(mockContentOverride));
298
+ overrides.results[1].enabled_content_override = null;
299
+
279
300
  const contentOverrideScope = nockInstance
280
301
  .put(contentOverride)
281
- .reply(200, mockContentOverride);
282
-
302
+ .reply(200, overrides);
283
303
  const {
284
304
  getByText, queryByText, getAllByText, getAllByLabelText,
285
305
  } = renderWithRedux(<RepositorySetsTab />, renderOptions());
@@ -288,6 +308,7 @@ test('Can reset to default', async (done) => {
288
308
  await patientlyWaitFor(() => expect(getByText(firstRepoSet.contentUrl)).toBeInTheDocument());
289
309
  expect(getAllByText('Enabled')).toHaveLength(2);
290
310
  expect(getAllByText('Disabled')).toHaveLength(1);
311
+
291
312
  // The second item is overridden to disabled but would normally be enabled; we're going to reset
292
313
  const actionMenu = getAllByLabelText('Actions')[1].closest('button');
293
314
  fireEvent.click(actionMenu);
@@ -305,3 +326,81 @@ test('Can reset to default', async (done) => {
305
326
  assertNockRequest(scope);
306
327
  assertNockRequest(contentOverrideScope, done); // Pass jest callback to confirm test is done
307
328
  });
329
+
330
+ test('Can override in bulk', async (done) => {
331
+ const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
332
+ const scope = nockInstance
333
+ .get(hostRepositorySets)
334
+ .query(defaultQuery)
335
+ .reply(200, mockRepoSetData);
336
+ const contentOverrideScope = nockInstance
337
+ .put(contentOverride)
338
+ .reply(200, mockContentOverride);
339
+
340
+ const {
341
+ getByText, getByLabelText, queryByText,
342
+ } = renderWithRedux(<RepositorySetsTab />, renderOptions());
343
+
344
+ await patientlyWaitFor(() => expect(getByText(firstRepoSet.contentUrl)).toBeInTheDocument());
345
+ getByLabelText('Select row 0').click();
346
+ getByLabelText('Select row 1').click();
347
+ const actionMenu = getByLabelText('bulk_actions');
348
+ actionMenu.click();
349
+ const resetToDefault = queryByText('Reset to default');
350
+ expect(resetToDefault).toBeInTheDocument();
351
+ resetToDefault.click();
352
+
353
+ assertNockRequest(autocompleteScope);
354
+ assertNockRequest(scope);
355
+ assertNockRequest(contentOverrideScope, done); // Pass jest callback to confirm test is done});
356
+ });
357
+
358
+ test('Can filter by status', async (done) => {
359
+ const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
360
+ const scope = nockInstance
361
+ .get(hostRepositorySets)
362
+ .query(defaultQuery)
363
+ .reply(200, mockRepoSetData);
364
+
365
+ const scope2 = nockInstance
366
+ .get(hostRepositorySets)
367
+ .query({ ...defaultQuery, status: 'overridden' })
368
+ .reply(200, { ...mockRepoSetData, results: [secondRepoSet] });
369
+
370
+ const {
371
+ getByText, queryByLabelText, getByRole,
372
+ } = renderWithRedux(<RepositorySetsTab />, renderOptions());
373
+
374
+ await patientlyWaitFor(() => expect(getByText(firstRepoSet.contentUrl)).toBeInTheDocument());
375
+
376
+ const statusContainer = queryByLabelText('select Status container', { ignore: 'th' });
377
+ const statusDropdown = within(statusContainer).queryByText('Status');
378
+ expect(statusDropdown).toBeInTheDocument();
379
+ fireEvent.click(statusDropdown);
380
+ const overridden = getByRole('option', { name: 'select Overridden' });
381
+ fireEvent.click(overridden);
382
+ await patientlyWaitFor(() => {
383
+ expect(getByText('Overridden')).toBeInTheDocument();
384
+ });
385
+ assertNockRequest(autocompleteScope);
386
+ assertNockRequest(scope);
387
+ assertNockRequest(searchDelayScope);
388
+ assertNockRequest(autoSearchScope);
389
+ assertNockRequest(scope2, done); // Pass jest callback to confirm test is done
390
+ });
391
+
392
+ test('Can display osRestricted as a label', async (done) => {
393
+ const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
394
+ const scope = nockInstance
395
+ .get(hostRepositorySets)
396
+ .query(defaultQuery)
397
+ .reply(200, mockRepoSetData);
398
+
399
+ const { getByText } = renderWithRedux(<RepositorySetsTab />, renderOptions());
400
+
401
+ await patientlyWaitFor(() => expect(getByText(secondRepoSet.contentUrl)).toBeInTheDocument());
402
+ expect(secondRepoSet.osRestricted).not.toBeNull();
403
+ expect(getByText(secondRepoSet.osRestricted)).toBeInTheDocument();
404
+ assertNockRequest(autocompleteScope);
405
+ assertNockRequest(scope, done); // Pass jest callback to confirm test is done
406
+ });