@rancher/shell 3.0.8-rc.1 → 3.0.8-rc.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (345) hide show
  1. package/assets/brand/suse/banner.svg +1 -0
  2. package/assets/brand/suse/dark/banner.svg +1 -0
  3. package/assets/brand/suse/dark/login-landscape.svg +1 -0
  4. package/assets/brand/suse/dark/rancher-logo.svg +1 -1
  5. package/assets/brand/suse/favicon.png +0 -0
  6. package/assets/brand/suse/login-landscape.svg +1 -0
  7. package/assets/brand/suse/metadata.json +11 -1
  8. package/assets/brand/suse/rancher-logo.svg +1 -1
  9. package/assets/fonts/suse/suse-v2-latin-300.woff +0 -0
  10. package/assets/fonts/suse/suse-v2-latin-300.woff2 +0 -0
  11. package/assets/fonts/suse/suse-v2-latin-600.woff +0 -0
  12. package/assets/fonts/suse/suse-v2-latin-600.woff2 +0 -0
  13. package/assets/fonts/suse/suse-v2-latin-700.woff +0 -0
  14. package/assets/fonts/suse/suse-v2-latin-700.woff2 +0 -0
  15. package/assets/fonts/suse/suse-v2-latin-800.woff +0 -0
  16. package/assets/fonts/suse/suse-v2-latin-800.woff2 +0 -0
  17. package/assets/fonts/suse/suse-v2-latin-regular.woff +0 -0
  18. package/assets/fonts/suse/suse-v2-latin-regular.woff2 +0 -0
  19. package/assets/images/content/README.md +5 -0
  20. package/assets/images/content/cloud-native.svg +84 -0
  21. package/assets/images/content/dark/cloud-native.svg +21 -0
  22. package/assets/images/content/dark/shield.svg +59 -0
  23. package/assets/images/content/dark/suse.svg +10 -0
  24. package/assets/images/content/shield.svg +59 -0
  25. package/assets/images/content/suse.svg +10 -0
  26. package/assets/styles/base/_typography.scss +1 -0
  27. package/assets/styles/fonts/_fontstack.scss +53 -1
  28. package/assets/styles/global/_cards.scss +0 -3
  29. package/assets/styles/global/_layout.scss +21 -35
  30. package/assets/styles/themes/_dark.scss +1 -1
  31. package/assets/styles/themes/_light.scss +1 -1
  32. package/assets/styles/themes/_modern.scss +11 -3
  33. package/assets/styles/themes/_suse.scss +116 -24
  34. package/assets/translations/en-us.yaml +94 -10
  35. package/components/AutoscalerCard.vue +113 -0
  36. package/components/AutoscalerTab.vue +94 -0
  37. package/components/BackLink.vue +8 -0
  38. package/components/BannerGraphic.vue +36 -21
  39. package/components/BrandImage.vue +17 -6
  40. package/components/ClusterIconMenu.vue +1 -1
  41. package/components/ClusterProviderIcon.vue +1 -1
  42. package/components/Cron/CronExpressionEditor.vue +1 -1
  43. package/components/Cron/CronExpressionEditorModal.vue +1 -1
  44. package/components/Drawer/Chrome.vue +2 -6
  45. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +4 -9
  46. package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +3 -8
  47. package/components/Drawer/ResourceDetailDrawer/composables.ts +3 -4
  48. package/components/Drawer/ResourceDetailDrawer/index.vue +4 -9
  49. package/components/Drawer/ResourceDetailDrawer/types.ts +17 -0
  50. package/components/Drawer/types.ts +3 -0
  51. package/components/DynamicContent/DynamicContentBanner.vue +102 -0
  52. package/components/DynamicContent/DynamicContentCloseButton.vue +42 -0
  53. package/components/DynamicContent/DynamicContentIcon.vue +132 -0
  54. package/components/DynamicContent/DynamicContentPanel.vue +112 -0
  55. package/components/DynamicContent/content.ts +78 -0
  56. package/components/EmberPage.vue +1 -1
  57. package/components/IconOrSvg.vue +2 -2
  58. package/components/PaginatedResourceTable.vue +2 -6
  59. package/components/PopoverCard.vue +192 -0
  60. package/components/Questions/__tests__/index.test.ts +159 -0
  61. package/components/Resource/Detail/CopyToClipboard.vue +4 -1
  62. package/components/Resource/Detail/FetchLoader/composables.ts +18 -4
  63. package/components/Resource/Detail/Metadata/Annotations/index.vue +2 -2
  64. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +1 -1
  65. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +4 -0
  66. package/components/Resource/Detail/Metadata/KeyValueRow.vue +1 -1
  67. package/components/Resource/Detail/Metadata/Labels/index.vue +2 -2
  68. package/components/Resource/Detail/Metadata/composables.ts +9 -9
  69. package/components/Resource/Detail/Metadata/index.vue +3 -3
  70. package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +2 -19
  71. package/components/Resource/Detail/ResourcePopover/__tests__/ResourcePopoverCard.test.ts +0 -29
  72. package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +132 -150
  73. package/components/Resource/Detail/ResourcePopover/index.vue +54 -159
  74. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +0 -2
  75. package/components/Resource/Detail/TitleBar/composables.ts +2 -1
  76. package/components/Resource/Detail/TitleBar/index.vue +10 -6
  77. package/components/Resource/Detail/composables.ts +12 -0
  78. package/components/ResourceDetail/Masthead/latest.vue +29 -0
  79. package/components/ResourceDetail/index.vue +4 -1
  80. package/components/ResourceList/Masthead.vue +1 -1
  81. package/components/ResourceTable.vue +1 -1
  82. package/components/SortableTable/index.vue +2 -1
  83. package/components/Tabbed/__tests__/index.test.ts +86 -0
  84. package/components/{nav/WindowManager → Window}/ContainerLogs.vue +1 -1
  85. package/components/{nav/WindowManager → Window}/ContainerLogsActions.vue +1 -0
  86. package/components/{nav/WindowManager → Window}/__tests__/ContainerLogs.test.ts +1 -1
  87. package/components/{nav/WindowManager → Window}/__tests__/ContainerShell.test.ts +2 -2
  88. package/components/__tests__/AutoscalerCard.test.ts +154 -0
  89. package/components/__tests__/AutoscalerTab.test.ts +125 -0
  90. package/components/__tests__/PopoverCard.test.ts +204 -0
  91. package/components/auth/SelectPrincipal.vue +24 -6
  92. package/components/auth/__tests__/SelectPrincipal.test.ts +119 -0
  93. package/components/auth/login/ldap.vue +3 -3
  94. package/components/form/NodeScheduling.vue +2 -2
  95. package/components/formatter/Autoscaler.vue +97 -0
  96. package/components/formatter/InternalExternalIP.vue +198 -24
  97. package/components/formatter/__tests__/Autoscaler.test.ts +156 -0
  98. package/components/formatter/__tests__/InternalExternalIP.test.ts +133 -0
  99. package/components/google/util/__tests__/formatter.test.ts +47 -0
  100. package/components/google/util/formatter.ts +5 -2
  101. package/components/nav/Group.vue +21 -5
  102. package/components/nav/Header.vue +37 -17
  103. package/components/nav/NamespaceFilter.vue +13 -1
  104. package/components/nav/NotificationCenter/index.vue +2 -1
  105. package/components/nav/TopLevelMenu.helper.ts +16 -6
  106. package/components/nav/TopLevelMenu.vue +4 -2
  107. package/components/nav/Type.vue +8 -3
  108. package/components/{DraggableZone.vue → nav/WindowManager/PinArea.vue} +47 -80
  109. package/components/nav/WindowManager/composables/useComponentsMount.ts +70 -0
  110. package/components/nav/WindowManager/composables/useDimensionsHandler.ts +105 -0
  111. package/components/nav/WindowManager/composables/useDragHandler.ts +99 -0
  112. package/components/nav/WindowManager/composables/usePanelHandler.ts +72 -0
  113. package/components/nav/WindowManager/composables/usePanelsHandler.ts +14 -0
  114. package/components/nav/WindowManager/composables/useResizeHandler.ts +167 -0
  115. package/components/nav/WindowManager/composables/useTabsHandler.ts +51 -0
  116. package/components/nav/WindowManager/constants.ts +23 -0
  117. package/components/nav/WindowManager/index.vue +61 -575
  118. package/components/nav/WindowManager/panels/HorizontalPanel.vue +265 -0
  119. package/components/nav/WindowManager/panels/TabBodyContainer.vue +39 -0
  120. package/components/nav/WindowManager/panels/VerticalPanel.vue +308 -0
  121. package/components/nav/__tests__/Type.test.ts +59 -0
  122. package/components/templates/default.vue +4 -40
  123. package/components/templates/home.vue +31 -5
  124. package/components/templates/plain.vue +30 -4
  125. package/components/templates/standalone.vue +1 -1
  126. package/composables/useI18n.ts +10 -1
  127. package/composables/useInterval.ts +15 -0
  128. package/config/__test__/uiplugins.test.ts +309 -0
  129. package/config/labels-annotations.js +9 -1
  130. package/config/product/explorer.js +3 -1
  131. package/config/product/manager.js +20 -9
  132. package/config/router/navigation-guards/clusters.js +3 -3
  133. package/config/router/navigation-guards/products.js +1 -1
  134. package/config/router/routes.js +10 -2
  135. package/config/settings.ts +2 -1
  136. package/config/store.js +4 -2
  137. package/config/table-headers.js +8 -0
  138. package/config/types.js +9 -0
  139. package/config/uiplugins.js +46 -2
  140. package/config/version.js +1 -1
  141. package/core/__test__/extension-manager-impl.test.js +236 -0
  142. package/core/extension-manager-impl.js +21 -4
  143. package/core/plugin-helpers.ts +4 -2
  144. package/core/plugins-loader.js +2 -2
  145. package/core/types-provisioning.ts +8 -1
  146. package/detail/pod.vue +1 -0
  147. package/detail/provisioning.cattle.io.cluster.vue +19 -7
  148. package/dialog/DeveloperLoadExtensionDialog.vue +13 -4
  149. package/dialog/RollbackWorkloadDialog.vue +2 -5
  150. package/dialog/SearchDialog.vue +1 -0
  151. package/directives/ui-context.ts +103 -0
  152. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +2 -2
  153. package/edit/auth/__tests__/oidc.test.ts +26 -0
  154. package/edit/auth/github.vue +5 -0
  155. package/edit/auth/oidc.vue +5 -1
  156. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -0
  157. package/edit/cloudcredential.vue +1 -1
  158. package/edit/configmap.vue +1 -0
  159. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  160. package/edit/fleet.cattle.io.gitrepo.vue +0 -10
  161. package/edit/fleet.cattle.io.helmop.vue +6 -6
  162. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  163. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  164. package/edit/logging-flow/index.vue +1 -0
  165. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  166. package/edit/management.cattle.io.fleetworkspace.vue +1 -1
  167. package/edit/management.cattle.io.project.vue +1 -0
  168. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +4 -1
  169. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +2 -1
  170. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  171. package/edit/monitoring.coreos.com.receiver/index.vue +2 -1
  172. package/edit/monitoring.coreos.com.route.vue +1 -1
  173. package/edit/namespace.vue +1 -0
  174. package/edit/networking.istio.io.destinationrule/index.vue +1 -0
  175. package/edit/networking.k8s.io.ingress/index.vue +1 -0
  176. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -0
  177. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -0
  178. package/edit/node.vue +1 -0
  179. package/edit/persistentvolume/index.vue +27 -22
  180. package/edit/persistentvolume/plugins/awsElasticBlockStore.vue +13 -14
  181. package/edit/persistentvolume/plugins/azureDisk.vue +49 -48
  182. package/edit/persistentvolume/plugins/azureFile.vue +15 -14
  183. package/edit/persistentvolume/plugins/cephfs.vue +15 -14
  184. package/edit/persistentvolume/plugins/cinder.vue +15 -14
  185. package/edit/persistentvolume/plugins/csi.vue +18 -16
  186. package/edit/persistentvolume/plugins/fc.vue +13 -14
  187. package/edit/persistentvolume/plugins/flexVolume.vue +15 -14
  188. package/edit/persistentvolume/plugins/flocker.vue +1 -3
  189. package/edit/persistentvolume/plugins/gcePersistentDisk.vue +13 -14
  190. package/edit/persistentvolume/plugins/glusterfs.vue +15 -14
  191. package/edit/persistentvolume/plugins/hostPath.vue +40 -39
  192. package/edit/persistentvolume/plugins/iscsi.vue +13 -14
  193. package/edit/persistentvolume/plugins/local.vue +1 -3
  194. package/edit/persistentvolume/plugins/longhorn.vue +23 -22
  195. package/edit/persistentvolume/plugins/nfs.vue +15 -14
  196. package/edit/persistentvolume/plugins/photonPersistentDisk.vue +1 -14
  197. package/edit/persistentvolume/plugins/portworxVolume.vue +15 -14
  198. package/edit/persistentvolume/plugins/quobyte.vue +15 -14
  199. package/edit/persistentvolume/plugins/rbd.vue +15 -14
  200. package/edit/persistentvolume/plugins/scaleIO.vue +15 -14
  201. package/edit/persistentvolume/plugins/storageos.vue +15 -14
  202. package/edit/persistentvolume/plugins/vsphereVolume.vue +1 -3
  203. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +32 -5
  204. package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +35 -0
  205. package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +155 -0
  206. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +21 -21
  207. package/edit/provisioning.cattle.io.cluster/index.vue +28 -18
  208. package/edit/provisioning.cattle.io.cluster/rke2.vue +50 -16
  209. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +107 -5
  210. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +92 -4
  211. package/edit/secret/index.vue +1 -1
  212. package/edit/service.vue +9 -4
  213. package/edit/serviceaccount.vue +1 -0
  214. package/edit/storage.k8s.io.storageclass/index.vue +1 -0
  215. package/edit/workload/index.vue +2 -1
  216. package/edit/workload/mixins/workload.js +1 -1
  217. package/initialize/App.vue +4 -4
  218. package/initialize/install-directives.js +2 -0
  219. package/initialize/install-plugins.js +19 -2
  220. package/list/provisioning.cattle.io.cluster.vue +15 -2
  221. package/machine-config/amazonec2.vue +42 -135
  222. package/machine-config/components/EC2Networking.vue +490 -0
  223. package/machine-config/components/__tests__/EC2Networking.test.ts +148 -0
  224. package/machine-config/components/__tests__/utils/vpcSubnetMockData.js +294 -0
  225. package/machine-config/digitalocean.vue +11 -0
  226. package/machine-config/google.vue +1 -1
  227. package/mixins/__tests__/brand.spec.ts +2 -2
  228. package/mixins/__tests__/chart.test.ts +21 -0
  229. package/mixins/brand.js +1 -7
  230. package/mixins/chart.js +7 -1
  231. package/mixins/create-edit-view/index.js +5 -0
  232. package/models/__tests__/chart.test.ts +33 -4
  233. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +112 -5
  234. package/models/chart.js +25 -13
  235. package/models/cluster/node.js +13 -6
  236. package/models/cluster.x-k8s.io.machine.js +10 -20
  237. package/models/cluster.x-k8s.io.machinedeployment.js +5 -1
  238. package/models/management.cattle.io.cluster.js +21 -3
  239. package/models/management.cattle.io.kontainerdriver.js +1 -0
  240. package/models/provisioning.cattle.io.cluster.js +249 -33
  241. package/package.json +8 -7
  242. package/pages/auth/login.vue +41 -5
  243. package/pages/auth/setup.vue +1 -1
  244. package/pages/auth/verify.vue +3 -3
  245. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +135 -0
  246. package/pages/c/_cluster/apps/charts/chart.vue +33 -15
  247. package/pages/c/_cluster/apps/charts/index.vue +11 -13
  248. package/pages/c/_cluster/apps/charts/install.vue +1 -1
  249. package/pages/c/_cluster/explorer/index.vue +8 -6
  250. package/pages/c/_cluster/manager/hostedprovider/index.vue +220 -0
  251. package/pages/c/_cluster/settings/brand.vue +1 -1
  252. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +7 -0
  253. package/pages/c/_cluster/uiplugins/catalogs.vue +147 -0
  254. package/pages/c/_cluster/uiplugins/index.vue +126 -184
  255. package/pages/home.vue +14 -4
  256. package/pkg/auto-import.js +3 -3
  257. package/pkg/dynamic-importer.lib.js +5 -1
  258. package/pkg/import.js +1 -1
  259. package/plugins/dashboard-client-init.js +3 -0
  260. package/plugins/dashboard-store/getters.js +19 -2
  261. package/plugins/dashboard-store/model-loader.js +1 -1
  262. package/plugins/dashboard-store/resource-class.js +10 -6
  263. package/plugins/dynamic-content.js +13 -0
  264. package/plugins/i18n.js +8 -0
  265. package/plugins/plugin.js +2 -2
  266. package/plugins/steve/__tests__/steve-pagination-utils.test.ts +333 -0
  267. package/plugins/steve/steve-class.js +1 -1
  268. package/plugins/steve/steve-pagination-utils.ts +39 -20
  269. package/plugins/steve/subscribe.js +17 -9
  270. package/plugins/subscribe-events.ts +4 -2
  271. package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
  272. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +6 -34
  273. package/rancher-components/Pill/RcStatusBadge/index.ts +0 -1
  274. package/rancher-components/Pill/RcStatusBadge/types.ts +1 -1
  275. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +5 -28
  276. package/rancher-components/Pill/RcStatusIndicator/types.ts +2 -1
  277. package/rancher-components/Pill/types.ts +0 -1
  278. package/rancher-components/RcDropdown/RcDropdownItem.vue +1 -0
  279. package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +5 -1
  280. package/rancher-components/RcIcon/RcIcon.test.ts +51 -0
  281. package/rancher-components/RcIcon/RcIcon.vue +46 -0
  282. package/rancher-components/RcIcon/index.ts +1 -0
  283. package/rancher-components/RcIcon/types.ts +160 -0
  284. package/rancher-components/utils/status.test.ts +67 -0
  285. package/rancher-components/utils/status.ts +77 -0
  286. package/scripts/typegen.sh +1 -0
  287. package/store/__tests__/catalog.test.ts +1 -1
  288. package/store/action-menu.js +8 -0
  289. package/store/auth.js +4 -4
  290. package/store/catalog.js +6 -0
  291. package/store/features.js +1 -0
  292. package/store/i18n.js +3 -3
  293. package/store/index.js +40 -19
  294. package/store/notifications.ts +51 -4
  295. package/store/plugins.js +7 -3
  296. package/store/prefs.js +6 -6
  297. package/store/type-map.js +7 -7
  298. package/store/ui-context.ts +86 -0
  299. package/store/wm.ts +244 -0
  300. package/types/notifications/index.ts +27 -3
  301. package/types/shell/index.d.ts +80 -4
  302. package/types/store/__tests__/pagination.types.spec.ts +137 -0
  303. package/types/store/pagination.types.ts +157 -9
  304. package/types/store/subscribe-events.types.ts +8 -1
  305. package/types/store/subscribe.types.ts +1 -0
  306. package/types/window-manager.ts +24 -0
  307. package/utils/__tests__/object.test.ts +19 -0
  308. package/utils/__tests__/provider.test.ts +98 -0
  309. package/utils/__tests__/selector-typed.test.ts +263 -0
  310. package/utils/__tests__/version.test.ts +19 -1
  311. package/utils/autoscaler-utils.ts +7 -0
  312. package/utils/back-off.ts +3 -3
  313. package/utils/brand.ts +29 -0
  314. package/utils/chart.js +18 -0
  315. package/utils/color.js +1 -1
  316. package/utils/dynamic-content/__tests__/announcement.test.ts +498 -0
  317. package/utils/dynamic-content/__tests__/info.test.ts +21 -9
  318. package/utils/dynamic-content/announcement.ts +142 -0
  319. package/utils/dynamic-content/example.json +40 -0
  320. package/utils/dynamic-content/index.ts +6 -2
  321. package/utils/dynamic-content/info.ts +44 -2
  322. package/utils/dynamic-content/new-release.ts +1 -1
  323. package/utils/dynamic-content/notification-handler.ts +48 -0
  324. package/utils/dynamic-content/types.d.ts +53 -1
  325. package/utils/dynamic-importer.js +2 -2
  326. package/utils/favicon.js +4 -4
  327. package/utils/object.js +20 -2
  328. package/utils/pagination-utils.ts +2 -2
  329. package/utils/pagination-wrapper.ts +13 -9
  330. package/utils/provider.ts +14 -0
  331. package/utils/scroll.js +7 -0
  332. package/utils/selector-typed.ts +6 -2
  333. package/utils/settings.ts +15 -0
  334. package/utils/unit-tests/pagination-utils.spec.ts +8 -8
  335. package/utils/validators/machine-pool.ts +13 -3
  336. package/utils/version.js +15 -0
  337. package/vue.config.js +3 -3
  338. package/assets/images/icons/document.svg +0 -3
  339. package/plugins/nuxt-client-init.js +0 -3
  340. package/store/wm.js +0 -95
  341. /package/components/{nav/WindowManager → Window}/ChartReadme.vue +0 -0
  342. /package/components/{nav/WindowManager → Window}/ContainerShell.vue +0 -0
  343. /package/components/{nav/WindowManager → Window}/KubectlShell.vue +0 -0
  344. /package/components/{nav/WindowManager → Window}/MachineSsh.vue +0 -0
  345. /package/components/{nav/WindowManager → Window}/Window.vue +0 -0
@@ -8,7 +8,7 @@ export type Label = Row;
8
8
  export interface LabelsProps {
9
9
  labels: Label[];
10
10
 
11
- onShowConfiguration?: (returnFocusSelector: string) => void;
11
+ onShowConfiguration?: (returnFocusSelector: string, defaultTab: string) => void;
12
12
  }
13
13
 
14
14
  </script>
@@ -27,6 +27,6 @@ const i18n = useI18n(store);
27
27
  :propertyName="i18n.t('component.resource.detail.metadata.labels.title')"
28
28
  :rows="labels"
29
29
  type="active"
30
- @show-configuration="(returnFocusSelector: string) => emit('show-configuration', returnFocusSelector)"
30
+ @show-configuration="(returnFocusSelector: string) => emit('show-configuration', returnFocusSelector, 'labels-and-annotations')"
31
31
  />
32
32
  </template>
@@ -6,18 +6,19 @@ import { computed, toValue, Ref } from 'vue';
6
6
  import {
7
7
  useLiveDate, useNamespace, useProject, useResourceDetails, useWorkspace
8
8
  } from '@shell/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields';
9
+ import { useOnShowConfiguration } from '@shell/components/Resource/Detail/composables';
9
10
 
10
11
  export const useBasicMetadata = (resource: any) => {
11
12
  const labels = useDefaultLabels(resource);
12
13
  const annotations = useDefaultAnnotations(resource);
13
- const resourceValue = toValue(resource);
14
+ const onShowConfiguration = useOnShowConfiguration(resource);
14
15
 
15
16
  return computed(() => {
16
17
  return {
17
- resource: toValue(resource),
18
- labels: labels.value,
19
- annotations: annotations.value,
20
- onShowConfiguration: () => resourceValue.showConfiguration()
18
+ resource: toValue(resource),
19
+ labels: labels.value,
20
+ annotations: annotations.value,
21
+ onShowConfiguration
21
22
  };
22
23
  });
23
24
  };
@@ -28,7 +29,7 @@ export const useDefaultMetadataProps = (resource: any, additionalIdentifyingInfo
28
29
 
29
30
  const identifyingInformation = computed(() => [...defaultIdentifyingInformation.value, ...(additionalIdentifyingInformationValue || [])]);
30
31
  const basicMetaData = useBasicMetadata(resource);
31
- const resourceValue = toValue(resource);
32
+ const onShowConfiguration = useOnShowConfiguration(resource);
32
33
 
33
34
  return computed(() => {
34
35
  return {
@@ -36,7 +37,7 @@ export const useDefaultMetadataProps = (resource: any, additionalIdentifyingInfo
36
37
  identifyingInformation: identifyingInformation.value,
37
38
  labels: basicMetaData.value.labels,
38
39
  annotations: basicMetaData.value.annotations,
39
- onShowConfiguration: (returnFocusSelector: string) => resourceValue.showConfiguration(returnFocusSelector)
40
+ onShowConfiguration
40
41
  };
41
42
  });
42
43
  };
@@ -47,7 +48,6 @@ export const useDefaultMetadataForLegacyPagesProps = (resource: any) => {
47
48
  const workspace = useWorkspace(resource);
48
49
  const namespace = useNamespace(resource);
49
50
  const liveDate = useLiveDate(resource);
50
- const resourceValue = toValue(resource);
51
51
 
52
52
  const identifyingInformation = computed((): IdentifyingInformationRow[] => {
53
53
  const defaultInfo = [
@@ -71,7 +71,7 @@ export const useDefaultMetadataForLegacyPagesProps = (resource: any) => {
71
71
  identifyingInformation: identifyingInformation.value,
72
72
  labels: basicMetaData.value.labels,
73
73
  annotations: basicMetaData.value.annotations,
74
- onShowConfiguration: (returnFocusSelector?: string) => resourceValue.showConfiguration(returnFocusSelector)
74
+ onShowConfiguration: basicMetaData.value.onShowConfiguration
75
75
  };
76
76
  });
77
77
  };
@@ -48,7 +48,7 @@ const showBothEmpty = computed(() => labels.length === 0 && annotations.length =
48
48
  type="active"
49
49
  :rows="[]"
50
50
  :propertyName="i18n.t('component.resource.detail.metadata.labelsAndAnnotations')"
51
- @show-configuration="(returnFocusSelector: string) => emit('show-configuration', returnFocusSelector)"
51
+ @show-configuration="(returnFocusSelector: string, defaultTab: string) => emit('show-configuration', returnFocusSelector, defaultTab)"
52
52
  />
53
53
  </div>
54
54
  <!-- I'm not using v-else here so I can maintain the spacing correctly with the other columns in other rows. -->
@@ -58,7 +58,7 @@ const showBothEmpty = computed(() => labels.length === 0 && annotations.length =
58
58
  >
59
59
  <Labels
60
60
  :labels="labels"
61
- @show-configuration="(returnFocusSelector: string) => emit('show-configuration', returnFocusSelector)"
61
+ @show-configuration="(returnFocusSelector: string, defaultTab: string) => emit('show-configuration', returnFocusSelector, defaultTab)"
62
62
  />
63
63
  </div>
64
64
  <div
@@ -67,7 +67,7 @@ const showBothEmpty = computed(() => labels.length === 0 && annotations.length =
67
67
  >
68
68
  <Annotations
69
69
  :annotations="annotations"
70
- @show-configuration="(returnFocusSelector: string) => emit('show-configuration', returnFocusSelector)"
70
+ @show-configuration="(returnFocusSelector: string, defaultTab: string) => emit('show-configuration', returnFocusSelector, defaultTab)"
71
71
  />
72
72
  </div>
73
73
  </SpacedRow>
@@ -1,37 +1,20 @@
1
1
  <script lang="ts">
2
- import Card from '@shell/components/Resource/Detail/Card/index.vue';
3
- import { useStore } from 'vuex';
4
- import ActionMenu from '@shell/components/ActionMenuShell.vue';
5
- import { useI18n } from '@shell/composables/useI18n';
6
-
7
2
  export interface Props {
8
3
  resource: any;
9
4
  }
10
5
  </script>
11
6
 
12
7
  <script setup lang="ts">
13
- const emit = defineEmits(['action-invoked']);
14
8
  const props = defineProps<Props>();
15
- const store = useStore();
16
- const i18n = useI18n(store);
17
9
 
18
10
  const getGlanceItemValueId = (glanceItem: any): string => `value-${ glanceItem.label }:${ glanceItem.content }`.toLowerCase().replaceAll(' ', '');
19
11
  </script>
20
12
 
21
13
  <template>
22
- <Card
14
+ <div
23
15
  class="resource-popover-card"
24
16
  :title="resource.nameDisplay"
25
17
  >
26
- <template #heading-action>
27
- <ActionMenu
28
- :resource="props.resource"
29
- :button-aria-label="i18n.t('component.resource.detail.glance.ariaLabel.actionMenu', { resource: props.resource.nameDisplay })"
30
- data-testid="resource-popover-action-menu"
31
- @action-invoked="emit('action-invoked')"
32
- />
33
- </template>
34
-
35
18
  <div>
36
19
  <div
37
20
  v-for="(glanceItem, i) in props.resource.glance"
@@ -64,7 +47,7 @@ const getGlanceItemValueId = (glanceItem: any): string => `value-${ glanceItem.l
64
47
  </div>
65
48
  </div>
66
49
  </div>
67
- </Card>
50
+ </div>
68
51
  </template>
69
52
 
70
53
  <style lang="scss" scoped>
@@ -1,12 +1,6 @@
1
1
  import { mount, VueWrapper } from '@vue/test-utils';
2
2
  import { createStore } from 'vuex';
3
3
  import ResourcePopoverCard from '@shell/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue';
4
- import Card from '@shell/components/Resource/Detail/Card/index.vue';
5
- import ActionMenu from '@shell/components/ActionMenuShell.vue';
6
-
7
- const mockI18n = { t: (key: string) => key };
8
-
9
- jest.mock('@shell/composables/useI18n', () => ({ useI18n: () => mockI18n }));
10
4
 
11
5
  describe('component: ResourcePopoverCard.vue', () => {
12
6
  let wrapper: VueWrapper<any>;
@@ -44,7 +38,6 @@ describe('component: ResourcePopoverCard.vue', () => {
44
38
  props: { resource },
45
39
  global: {
46
40
  plugins: [store],
47
- stubs: { ActionMenu: true },
48
41
  components: { SomeFormatterComponent }
49
42
  },
50
43
  });
@@ -58,28 +51,6 @@ describe('component: ResourcePopoverCard.vue', () => {
58
51
  wrapper.unmount();
59
52
  });
60
53
 
61
- it('should render the Card with the correct title', () => {
62
- const card = wrapper.findComponent(Card);
63
-
64
- expect(card.exists()).toBe(true);
65
- expect(card.props('title')).toBe(mockResource.nameDisplay);
66
- });
67
-
68
- it('should render the ActionMenu with the correct resource prop', () => {
69
- const actionMenu = wrapper.findComponent(ActionMenu);
70
-
71
- expect(actionMenu.exists()).toBe(true);
72
- expect(actionMenu.props('resource')).toStrictEqual(mockResource);
73
- });
74
-
75
- it('should emit "action-invoked" when ActionMenu emits it', async() => {
76
- const actionMenu = wrapper.findComponent(ActionMenu);
77
-
78
- await actionMenu.vm.$emit('action-invoked');
79
-
80
- expect(wrapper.emitted('action-invoked')).toHaveLength(1);
81
- });
82
-
83
54
  it('should render a row for each item in resource.glance', () => {
84
55
  const rows = wrapper.findAll('.row');
85
56
 
@@ -1,12 +1,7 @@
1
1
  import { mount, RouterLinkStub } from '@vue/test-utils';
2
2
  import { createStore } from 'vuex';
3
3
  import ResourcePopover from '@shell/components/Resource/Detail/ResourcePopover/index.vue';
4
-
5
- const mockI18n = { t: (key: string, args: any) => JSON.stringify({ key, args }) };
6
- const mockFocusTrap = jest.fn();
7
-
8
- jest.mock('@shell/composables/useI18n', () => ({ useI18n: () => mockI18n }));
9
- jest.mock('@shell/composables/focusTrap', () => ({ useWatcherBasedSetupFocusTrapWithDestroyIncluded: (...args: any) => mockFocusTrap(...args) }));
4
+ import PopoverCard from '@shell/components/PopoverCard.vue';
10
5
 
11
6
  const mockResource = {
12
7
  id: 'test-ns/test-pod',
@@ -14,7 +9,6 @@ const mockResource = {
14
9
  nameDisplay: 'My Test Pod',
15
10
  stateBackground: 'bg-success',
16
11
  detailLocation: { name: 'pod-detail', params: { id: 'test-pod' } },
17
- glance: [{ label: 'Status', content: 'Active' }],
18
12
  parentNameOverride: 'Overridden Pod',
19
13
  };
20
14
 
@@ -23,223 +17,211 @@ describe('component: ResourcePopover/index.vue', () => {
23
17
  const mockClusterFind = jest.fn();
24
18
  const mockSomethingFind = jest.fn();
25
19
 
26
- const createWrapper = async(props: any = { type: 'pod', id: 'test-ns/test-pod' }) => {
27
- store = createStore({
28
- getters: {
29
- 'i18n/t': () => (key: string) => key,
30
- currentStore: () => () => 'cluster',
31
- 'cluster/schemaFor': () => () => ({ id: 'pod' }),
32
- 'type-map/labelFor': () => () => 'Pod',
33
- },
34
- actions: { 'cluster/find': mockClusterFind, 'something/find': mockSomethingFind }
35
- });
20
+ const defaultStore = {
21
+ getters: {
22
+ 'i18n/t': () => (key: string) => key,
23
+ currentStore: () => () => 'cluster',
24
+ 'cluster/schemaFor': () => () => ({ id: 'pod' }),
25
+ 'type-map/labelFor': () => () => 'Pod',
26
+ },
27
+ actions: { 'cluster/find': mockClusterFind, 'something/find': mockSomethingFind }
28
+ };
36
29
 
37
- const wrapper = mount(ResourcePopover, {
38
- props,
30
+ const PopoverCardStub = {
31
+ PopoverCard: {
32
+ template: `
33
+ <div>
34
+ <slot />
35
+ <slot name="heading-action" :close="() => {}" />
36
+ <slot name="card-body" />
37
+ </div>
38
+ `,
39
+ },
40
+ };
41
+
42
+ const createWrapper = (props: any = {}, storeConfig: any = defaultStore, stubs: any = {}) => {
43
+ store = createStore(storeConfig);
44
+
45
+ return mount(ResourcePopover, {
46
+ props: {
47
+ type: 'pod',
48
+ id: 'test-ns/test-pod',
49
+ ...props,
50
+ },
39
51
  global: {
40
52
  plugins: [store],
41
53
  stubs: {
42
- 'v-dropdown': { name: 'v-dropdown', template: '<div><slot /><slot name="popper" /></div>' },
43
- 'router-link': RouterLinkStub,
44
- ResourcePopoverCard: {
45
- name: 'ResourcePopoverCard',
46
- template: '<div id="resource-popover-card" />'
47
- },
48
- RcStatusIndicator: true,
54
+ RouterLink: RouterLinkStub,
55
+ RcStatusIndicator: true,
56
+ ActionMenu: true,
57
+ ResourcePopoverCard: true,
58
+ VDropdown: true,
59
+ ...stubs
49
60
  },
50
61
  },
51
62
  });
52
-
53
- // Requires two so the fetch can be resolved
54
- await wrapper.vm.$nextTick();
55
- await wrapper.vm.$nextTick();
56
-
57
- return wrapper;
58
63
  };
59
64
 
60
- // Reset mocks before each test
61
65
  beforeEach(() => {
62
66
  jest.clearAllMocks();
63
67
  });
64
68
 
65
- describe('data Fetching and Initial State', () => {
66
- it('should show loading state initially', async() => {
67
- const wrapper = await createWrapper(); // Override default fetch value
69
+ describe('data Fetching and Rendering', () => {
70
+ it('should display a loading indicator while fetching data', async() => {
71
+ mockClusterFind.mockImplementation(() => new Promise(() => { }));
72
+ const wrapper = createWrapper(undefined, undefined, PopoverCardStub);
73
+
74
+ await wrapper.vm.$nextTick();
75
+ await wrapper.vm.$nextTick();
76
+ await wrapper.vm.$nextTick();
68
77
 
69
- expect(wrapper.find('.display').exists()).toBe(false);
70
78
  expect(wrapper.text()).toContain('...');
79
+ expect(wrapper.find('.display').exists()).toBe(false);
71
80
  });
72
81
 
73
- it('should call the fetch composable and dispatch a store action', async() => {
74
- await createWrapper();
82
+ it('should fetch data using the default store', async() => {
83
+ const wrapper = createWrapper();
84
+
85
+ await wrapper.vm.$nextTick();
86
+ await wrapper.vm.$nextTick();
75
87
 
76
- expect(mockClusterFind).toHaveBeenCalledWith(expect.objectContaining({}), expect.objectContaining({ type: 'pod', id: 'test-ns/test-pod' }));
88
+ expect(mockClusterFind).toHaveBeenCalledWith(expect.any(Object), { type: 'pod', id: 'test-ns/test-pod' });
77
89
  });
78
90
 
79
- it('should dispatch to the specified store', async() => {
80
- await createWrapper({
81
- type: 'pod', id: 'test-ns/test-pod', currentStore: 'something'
82
- });
91
+ it('should fetch data using the store specified in props', async() => {
92
+ mockClusterFind.mockReturnValue(mockResource);
93
+ const wrapper = createWrapper({ currentStore: 'something' });
83
94
 
84
- expect(mockSomethingFind).toHaveBeenCalledWith(expect.objectContaining({}), expect.objectContaining({ type: 'pod', id: 'test-ns/test-pod' }));
95
+ await wrapper.vm.$nextTick();
96
+ await wrapper.vm.$nextTick();
97
+
98
+ expect(mockSomethingFind).toHaveBeenCalledWith(expect.any(Object), { type: 'pod', id: 'test-ns/test-pod' });
99
+ expect(mockClusterFind).not.toHaveBeenCalled();
85
100
  });
86
101
 
87
- it('should render resource name and link when data is loaded', async() => {
102
+ it('should display resource details after data is fetched', async() => {
88
103
  mockClusterFind.mockReturnValue(mockResource);
89
- const wrapper = await createWrapper();
104
+ const wrapper = createWrapper(undefined, undefined, PopoverCardStub);
105
+
106
+ await wrapper.vm.$nextTick();
107
+ await wrapper.vm.$nextTick();
108
+ await wrapper.vm.$nextTick();
109
+
90
110
  const link = wrapper.findComponent(RouterLinkStub);
91
111
 
92
- expect(link.exists()).toBe(true);
93
112
  expect(link.text()).toBe(mockResource.nameDisplay);
94
113
  expect(link.props('to')).toStrictEqual(mockResource.detailLocation);
95
114
  });
96
115
 
97
- it('should use `detailLocation` prop for router-link if provided', async() => {
98
- const detailLocationProp = { name: 'custom-route' };
116
+ it('should use detailLocation prop for the link if provided', async() => {
117
+ const customLocation = { name: 'custom-route' };
99
118
 
100
- const wrapper = await createWrapper({
101
- type: 'pod',
102
- id: 'test-ns/test-pod',
103
- detailLocation: detailLocationProp
104
- });
119
+ mockClusterFind.mockReturnValue(mockResource);
120
+ const wrapper = createWrapper({ detailLocation: customLocation }, undefined, PopoverCardStub);
121
+
122
+ await wrapper.vm.$nextTick();
123
+ await wrapper.vm.$nextTick();
124
+ await wrapper.vm.$nextTick();
105
125
 
106
126
  const link = wrapper.findComponent(RouterLinkStub);
107
127
 
108
- expect(link.props('to')).toStrictEqual(detailLocationProp);
128
+ expect(link.props('to')).toStrictEqual(customLocation);
109
129
  });
110
130
  });
111
131
 
112
132
  describe('computed Properties', () => {
113
- it('should return empty resourceTypeLabel if no data', async() => {
114
- mockClusterFind.mockReturnValue(null);
115
-
116
- const wrapper = await createWrapper();
133
+ it('resourceTypeLabel: should be empty if data is not loaded', async() => {
134
+ mockClusterFind.mockReturnValue(undefined);
135
+ const wrapper = createWrapper();
117
136
 
118
- expect(wrapper.vm.resourceTypeLabel).toBe('');
119
- });
120
-
121
- it('should return resourceTypeLabel from type-map getter', async() => {
122
- const resourceWithoutOverride = { ...mockResource, parentNameOverride: undefined };
137
+ await wrapper.vm.$nextTick();
138
+ await wrapper.vm.$nextTick();
139
+ await wrapper.vm.$nextTick();
123
140
 
124
- mockClusterFind.mockReturnValue(resourceWithoutOverride);
125
- const wrapper = await createWrapper();
141
+ const popoverCard = wrapper.findComponent(PopoverCard);
142
+ const ariaLabel = popoverCard.props('showPopoverAriaLabel');
126
143
 
127
- expect(wrapper.vm.resourceTypeLabel).toBe('Pod');
144
+ expect(ariaLabel).toBe('component.resource.detail.glance.ariaLabel.showDetails-{\"name\":\"\",\"resource\":\"\"}');
128
145
  });
129
146
 
130
- it('should generate correct aria-labels', async() => {
131
- mockClusterFind.mockReturnValue(mockResource);
132
- const wrapper = await createWrapper();
133
-
134
- const expectedAriaLabel = JSON.stringify({ key: 'component.resource.detail.glance.ariaLabel.showDetails', args: { name: mockResource.nameDisplay, resource: mockResource.parentNameOverride } });
135
- const dropdown = wrapper.findComponent({ name: 'v-dropdown' });
136
- const button = wrapper.find('.focus-button');
147
+ it('resourceTypeLabel: should use parentNameOverride when available', async() => {
148
+ mockClusterFind.mockResolvedValue(mockResource);
149
+ const wrapper = createWrapper();
137
150
 
138
- expect(dropdown.attributes('aria-label')).toBe(expectedAriaLabel);
139
- expect(button.attributes('aria-label')).toBe(expectedAriaLabel);
140
- });
141
- });
151
+ await wrapper.vm.$nextTick();
152
+ await wrapper.vm.$nextTick();
153
+ await wrapper.vm.$nextTick();
142
154
 
143
- describe('popover Visibility', () => {
144
- it('should not show popover card initially', async() => {
145
- mockClusterFind.mockReturnValue(mockResource);
146
- const wrapper = await createWrapper();
155
+ const popoverCard = wrapper.findComponent(PopoverCard);
156
+ const ariaLabel = popoverCard.props('showPopoverAriaLabel');
147
157
 
148
- expect(wrapper.findComponent({ name: 'ResourcePopoverCard' }).exists()).toBe(false);
158
+ expect(ariaLabel).toBe('component.resource.detail.glance.ariaLabel.showDetails-{\"name\":\"My Test Pod\",\"resource\":\"Overridden Pod\"}');
149
159
  });
150
160
 
151
- it('should show popover on mouseenter', async() => {
152
- mockClusterFind.mockReturnValue(mockResource);
153
- const wrapper = await createWrapper();
161
+ it('resourceTypeLabel: should use type-map label as a fallback', async() => {
162
+ const resourceWithoutOverride = { ...mockResource, parentNameOverride: null };
154
163
 
155
- await wrapper.find('.display').trigger('mouseenter');
156
- expect(wrapper.vm.showPopover).toBe(true);
157
- await wrapper.vm.$nextTick();
158
- expect(wrapper.findComponent({ name: 'ResourcePopoverCard' }).exists()).toBe(true);
159
- });
164
+ mockClusterFind.mockResolvedValue(resourceWithoutOverride);
165
+ const wrapper = createWrapper();
160
166
 
161
- it('should hide popover on mouseleave', async() => {
162
- mockClusterFind.mockReturnValue(mockResource);
163
- const wrapper = await createWrapper();
167
+ await wrapper.vm.$nextTick();
168
+ await wrapper.vm.$nextTick();
169
+ await wrapper.vm.$nextTick();
164
170
 
165
- await wrapper.find('.display').trigger('mouseenter');
166
- expect(wrapper.vm.showPopover).toBe(true);
171
+ const popoverCard = wrapper.findComponent(PopoverCard);
172
+ const ariaLabel = popoverCard.props('showPopoverAriaLabel');
167
173
 
168
- await wrapper.find('.resource-popover').trigger('mouseleave');
169
- expect(wrapper.vm.showPopover).toBe(false);
170
- await wrapper.vm.$nextTick();
171
- expect(wrapper.findComponent({ name: 'ResourcePopoverCard' }).exists()).toBe(false);
174
+ expect(ariaLabel).toBe('component.resource.detail.glance.ariaLabel.showDetails-{\"name\":\"My Test Pod\",\"resource\":\"Pod\"}');
172
175
  });
176
+ });
173
177
 
174
- it('should show popover on focus button click', async() => {
175
- mockClusterFind.mockReturnValue(mockResource);
176
- const wrapper = await createWrapper();
178
+ describe('props passed to child components', () => {
179
+ it('should pass correct props to PopoverCard', async() => {
180
+ mockClusterFind.mockResolvedValue(mockResource);
181
+ const wrapper = createWrapper();
177
182
 
178
- await wrapper.find('.focus-button').trigger('click');
179
- expect(wrapper.vm.showPopover).toBe(true);
180
- expect(wrapper.vm.focusOpen).toBe(true);
181
183
  await wrapper.vm.$nextTick();
182
- expect(wrapper.findComponent({ name: 'ResourcePopoverCard' }).exists()).toBe(true);
183
- });
184
+ await wrapper.vm.$nextTick();
185
+ await wrapper.vm.$nextTick();
184
186
 
185
- it('should hide popover when action is invoked from card', async() => {
186
- mockClusterFind.mockReturnValue(mockResource);
187
- const wrapper = await createWrapper();
187
+ const popoverCard = wrapper.findComponent(PopoverCard);
188
188
 
189
- await wrapper.find('.display').trigger('mouseenter');
190
- await wrapper.vm.$nextTick();
189
+ expect(popoverCard.props('cardTitle')).toBe(mockResource.nameDisplay);
190
+ expect(popoverCard.props('fallbackFocus')).toBe("[data-testid='resource-popover-action-menu']");
191
191
 
192
- const card = wrapper.findComponent({ name: 'ResourcePopoverCard' });
192
+ const expectedAriaLabel = 'component.resource.detail.glance.ariaLabel.showDetails-{\"name\":\"My Test Pod\",\"resource\":\"Overridden Pod\"}';
193
193
 
194
- await card.vm.$emit('action-invoked');
195
- expect(wrapper.vm.showPopover).toBe(false);
196
- await wrapper.vm.$nextTick();
197
- expect(wrapper.findComponent({ name: 'ResourcePopoverCard' }).exists()).toBe(false);
194
+ expect(popoverCard.props('showPopoverAriaLabel')).toBe(expectedAriaLabel);
198
195
  });
199
196
 
200
- it('should hide popover on Escape keydown', async() => {
201
- mockClusterFind.mockReturnValue(mockResource);
202
- const wrapper = await createWrapper();
197
+ it('should pass correct props to ActionMenu', async() => {
198
+ mockClusterFind.mockResolvedValue(mockResource);
199
+ const wrapper = createWrapper(undefined, undefined, PopoverCardStub);
203
200
 
204
- await wrapper.find('.focus-button').trigger('click');
205
201
  await wrapper.vm.$nextTick();
206
-
207
- const card = wrapper.findComponent({ name: 'ResourcePopoverCard' });
208
-
209
- await card.trigger('keydown.escape');
202
+ await wrapper.vm.$nextTick();
210
203
  await wrapper.vm.$nextTick();
211
204
 
212
- expect(wrapper.findComponent({ name: 'ResourcePopoverCard' }).exists()).toBe(false);
213
- });
214
- });
205
+ const actionMenu = wrapper.findComponent({ name: 'ActionMenu' });
215
206
 
216
- describe('focus Trap', () => {
217
- it('should not setup focus trap on mouseenter', async() => {
218
- mockClusterFind.mockReturnValue(mockResource);
219
- const wrapper = await createWrapper();
207
+ expect(actionMenu.props('resource')).toStrictEqual(mockResource);
220
208
 
221
- await wrapper.find('.display').trigger('mouseenter');
222
- await wrapper.vm.$nextTick();
209
+ const expectedAriaLabel = 'component.resource.detail.glance.ariaLabel.actionMenu-{\"resource\":\"My Test Pod\"}';
223
210
 
224
- expect(wrapper.vm.focusOpen).toBe(false);
225
- expect(mockFocusTrap).not.toHaveBeenCalled();
211
+ expect(actionMenu.props('buttonAriaLabel')).toBe(expectedAriaLabel);
226
212
  });
227
213
 
228
- it('should setup focus trap when opened via focus button', async() => {
229
- mockClusterFind.mockReturnValue(mockResource);
230
- const wrapper = await createWrapper();
214
+ it('should pass correct props to ResourcePopoverCard', async() => {
215
+ mockClusterFind.mockResolvedValue(mockResource);
216
+ const wrapper = createWrapper(undefined, undefined, PopoverCardStub);
231
217
 
232
- await wrapper.find('.focus-button').trigger('click');
233
- await wrapper.vm.$nextTick(); // Triggers the watch
234
-
235
- expect(wrapper.vm.focusOpen).toBe(true);
236
- expect(mockFocusTrap).toHaveBeenCalledTimes(1);
218
+ await wrapper.vm.$nextTick();
219
+ await wrapper.vm.$nextTick();
220
+ await wrapper.vm.$nextTick();
237
221
 
238
- // Verify the options passed to the focus trap
239
- const focusTrapOptions = mockFocusTrap.mock.calls[0][2];
222
+ const resourceCard = wrapper.findComponent({ name: 'ResourcePopoverCard' });
240
223
 
241
- expect(focusTrapOptions.fallbackFocus).toBe('#first-glance-item');
242
- expect(focusTrapOptions.setReturnFocus()).toBe('.focus-button');
224
+ expect(resourceCard.props('resource')).toStrictEqual(mockResource);
243
225
  });
244
226
  });
245
227
  });