@rancher/shell 3.0.5-rc.5 → 3.0.5-rc.7

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 (361) hide show
  1. package/assets/data/aws-regions.json +1 -0
  2. package/assets/images/key.svg +17 -0
  3. package/assets/styles/base/_spacing.scss +2 -2
  4. package/assets/styles/base/_variables.scss +17 -11
  5. package/assets/styles/global/_form.scss +1 -1
  6. package/assets/styles/global/_labeled-input.scss +1 -1
  7. package/assets/styles/themes/_dark.scss +5 -0
  8. package/assets/styles/themes/_light.scss +11 -2
  9. package/assets/styles/vendor/vue-select.scss +1 -1
  10. package/assets/translations/en-us.yaml +426 -64
  11. package/assets/translations/zh-hans.yaml +3 -4
  12. package/cloud-credential/gcp.vue +9 -1
  13. package/components/AppModal.vue +2 -0
  14. package/components/CodeMirror.vue +2 -2
  15. package/components/ConfigMapSettings/Settings.vue +377 -0
  16. package/components/ConfigMapSettings/index.vue +354 -0
  17. package/components/CruResource.vue +1 -2
  18. package/components/DetailText.vue +61 -11
  19. package/components/Drawer/Chrome.vue +115 -0
  20. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +61 -0
  21. package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +48 -0
  22. package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +54 -0
  23. package/components/Drawer/ResourceDetailDrawer/__tests__/YamlTab.test.ts +80 -0
  24. package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +106 -0
  25. package/components/Drawer/ResourceDetailDrawer/__tests__/helpers.test.ts +42 -0
  26. package/components/Drawer/ResourceDetailDrawer/composables.ts +53 -0
  27. package/components/Drawer/ResourceDetailDrawer/helpers.ts +10 -0
  28. package/components/Drawer/ResourceDetailDrawer/index.vue +111 -0
  29. package/components/GrowlManager.vue +16 -15
  30. package/components/IconOrSvg.vue +5 -0
  31. package/components/KeyValueView.vue +1 -1
  32. package/components/Loading.vue +1 -1
  33. package/components/LocaleSelector.vue +9 -1
  34. package/components/PaginatedResourceTable.vue +46 -1
  35. package/components/ProgressBarMulti.vue +1 -0
  36. package/components/PromptModal.vue +6 -1
  37. package/components/PromptRestore.vue +22 -44
  38. package/components/RelatedResources.vue +4 -12
  39. package/components/Resource/Detail/Additional.vue +46 -0
  40. package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +1 -1
  41. package/components/Resource/Detail/Metadata/Annotations/index.vue +5 -0
  42. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +223 -0
  43. package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +47 -256
  44. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +317 -0
  45. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +34 -5
  46. package/components/Resource/Detail/Metadata/KeyValue.vue +32 -22
  47. package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +1 -1
  48. package/components/Resource/Detail/Metadata/Labels/index.vue +4 -0
  49. package/components/Resource/Detail/Metadata/Rectangle.vue +3 -1
  50. package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +1 -1
  51. package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +1 -1
  52. package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +75 -0
  53. package/components/Resource/Detail/Metadata/composables.ts +60 -11
  54. package/components/Resource/Detail/Metadata/index.vue +12 -5
  55. package/components/Resource/Detail/Page.vue +15 -0
  56. package/components/Resource/Detail/ResourceRow.vue +37 -18
  57. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/composables.test.ts +29 -0
  58. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/index.test.ts +48 -0
  59. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/composables.ts +31 -0
  60. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/index.vue +50 -0
  61. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/__tests__/composables.test.ts +66 -0
  62. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/composables.ts +21 -0
  63. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/index.vue +31 -0
  64. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Basic.vue +45 -0
  65. package/components/Resource/Detail/ResourceTabs/SecretDataTab/BasicAuth.vue +31 -0
  66. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Certificate.vue +31 -0
  67. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Registry.vue +22 -0
  68. package/components/Resource/Detail/ResourceTabs/SecretDataTab/ServiceAccountToken.vue +31 -0
  69. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Ssh.vue +32 -0
  70. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Basic.test.ts +40 -0
  71. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/BasicAuth.test.ts +33 -0
  72. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Certificate.test.ts +33 -0
  73. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Registry.test.ts +27 -0
  74. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/ServiceAccountToken.test.ts +33 -0
  75. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Ssh.test.ts +33 -0
  76. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/auth-types.test.ts +186 -0
  77. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/composables.test.ts +102 -0
  78. package/components/Resource/Detail/ResourceTabs/SecretDataTab/auth-types.ts +109 -0
  79. package/components/Resource/Detail/ResourceTabs/SecretDataTab/composeables.ts +52 -0
  80. package/components/Resource/Detail/ResourceTabs/SecretDataTab/index.vue +71 -0
  81. package/components/Resource/Detail/SpacedRow.vue +1 -1
  82. package/components/Resource/Detail/TitleBar/Title.vue +2 -1
  83. package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +1 -1
  84. package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +1 -1
  85. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +63 -0
  86. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +1 -1
  87. package/components/Resource/Detail/TitleBar/composables.ts +45 -0
  88. package/components/Resource/Detail/TitleBar/index.vue +85 -13
  89. package/components/Resource/Detail/composables.ts +45 -0
  90. package/components/ResourceDetail/Masthead/__tests__/index.test.ts +70 -0
  91. package/components/ResourceDetail/{__tests__/Masthead.test.ts → Masthead/__tests__/legacy.test.ts} +3 -3
  92. package/components/ResourceDetail/Masthead/index.vue +65 -0
  93. package/components/ResourceDetail/Masthead/latest.vue +44 -0
  94. package/components/ResourceDetail/{Masthead.vue → Masthead/legacy.vue} +1 -1
  95. package/components/ResourceDetail/__tests__/index.test.ts +26 -5
  96. package/components/ResourceDetail/index.vue +33 -17
  97. package/components/ResourceDetail/legacy.vue +18 -1
  98. package/components/ResourceList/Masthead.vue +6 -0
  99. package/components/ResourceList/index.vue +1 -0
  100. package/components/ResourceTable.vue +6 -1
  101. package/components/ResourceYaml.vue +15 -2
  102. package/components/RichTranslation.vue +106 -0
  103. package/components/SlideInPanelManager.vue +46 -11
  104. package/components/SortableTable/index.vue +1 -1
  105. package/components/SortableTable/selection.js +0 -1
  106. package/components/StateDot/index.vue +28 -0
  107. package/components/Tabbed/index.vue +17 -16
  108. package/components/Wizard.vue +4 -2
  109. package/components/__tests__/ConfigMapSettings.test.ts +376 -0
  110. package/components/__tests__/GrowlManager.test.ts +0 -25
  111. package/components/__tests__/PromptRestore.test.ts +1 -65
  112. package/components/__tests__/RichTranslation.test.ts +115 -0
  113. package/components/auth/login/ldap.vue +1 -1
  114. package/components/fleet/FleetApplications.vue +0 -7
  115. package/components/fleet/FleetClusterTargets/TargetsList.vue +66 -0
  116. package/components/fleet/FleetClusterTargets/index.vue +455 -0
  117. package/components/fleet/FleetClusters.vue +25 -6
  118. package/components/fleet/FleetGitRepoPaths.vue +476 -0
  119. package/components/fleet/FleetHelmOps.vue +8 -0
  120. package/components/fleet/FleetRepos.vue +1 -6
  121. package/components/fleet/FleetResources.vue +4 -5
  122. package/components/fleet/FleetValuesFrom.vue +295 -0
  123. package/components/fleet/__tests__/FleetClusterTargets.test.ts +1224 -0
  124. package/components/fleet/__tests__/FleetGitRepoPaths.test.ts +265 -0
  125. package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +13 -13
  126. package/components/fleet/__tests__/FleetValuesFrom.test.ts +300 -0
  127. package/components/fleet/dashboard/ResourceCard.vue +1 -0
  128. package/components/fleet/dashboard/ResourceCardSummary.vue +1 -5
  129. package/components/fleet/dashboard/ResourceDetails.vue +8 -10
  130. package/components/fleet/dashboard/ResourcePanel.vue +17 -9
  131. package/components/form/ArrayList.vue +13 -2
  132. package/components/form/ChangePassword.vue +3 -1
  133. package/components/form/FileImageSelector.vue +1 -1
  134. package/components/form/Footer.vue +10 -4
  135. package/components/form/KeyValue.vue +81 -43
  136. package/components/form/LabeledSelect.vue +56 -16
  137. package/components/form/Labels.vue +90 -17
  138. package/components/form/MatchExpressions.vue +46 -5
  139. package/components/form/NameNsDescription.vue +2 -1
  140. package/components/form/Networking.vue +24 -19
  141. package/components/form/ResourceLabeledSelect.vue +4 -3
  142. package/components/form/ResourceSelector.vue +1 -0
  143. package/components/form/ResourceTabs/index.vue +5 -0
  144. package/components/form/SecretSelector.vue +9 -2
  145. package/components/form/Select.vue +57 -19
  146. package/components/form/SelectOrCreateAuthSecret.vue +6 -3
  147. package/components/form/SimpleSecretSelector.vue +9 -2
  148. package/components/form/Taints.vue +21 -2
  149. package/components/form/UnitInput.vue +8 -0
  150. package/components/form/ValueFromResource.vue +1 -1
  151. package/components/form/__tests__/LabeledSelect.test.ts +8 -4
  152. package/components/form/__tests__/Labels.test.ts +360 -0
  153. package/components/form/__tests__/MatchExpressions.test.ts +16 -13
  154. package/components/form/__tests__/Networking.test.ts +116 -0
  155. package/components/form/__tests__/Select.test.ts +5 -2
  156. package/components/formatter/FleetApplicationSource.vue +1 -1
  157. package/components/formatter/PodImages.vue +1 -1
  158. package/components/formatter/WorkloadHealthScale.vue +1 -1
  159. package/components/formatter/__tests__/LiveDate.test.ts +10 -2
  160. package/components/google/AccountAccess.vue +209 -0
  161. package/components/google/types/gcp.d.ts +136 -0
  162. package/components/google/types/index.d.ts +101 -0
  163. package/components/google/util/__mocks__/gcp.ts +465 -0
  164. package/components/google/util/formatter.ts +82 -0
  165. package/components/google/util/gcp.ts +134 -0
  166. package/components/google/util/index.d.ts +11 -0
  167. package/components/nav/Favorite.vue +1 -1
  168. package/components/nav/Group.vue +71 -45
  169. package/components/nav/Header.vue +5 -1
  170. package/components/nav/NamespaceFilter.vue +13 -1
  171. package/components/nav/NotificationCenter/Notification.vue +510 -0
  172. package/components/nav/NotificationCenter/NotificationHeader.vue +112 -0
  173. package/components/nav/NotificationCenter/index.vue +148 -0
  174. package/composables/drawer.ts +26 -0
  175. package/composables/resources.test.ts +63 -0
  176. package/composables/resources.ts +38 -0
  177. package/composables/useIsNewDetailPageEnabled.ts +17 -0
  178. package/config/labels-annotations.js +8 -0
  179. package/config/pagination-table-headers.js +8 -1
  180. package/config/product/auth.js +16 -1
  181. package/config/product/{cis.js → compliance.js} +23 -26
  182. package/config/product/explorer.js +32 -3
  183. package/config/product/fleet.js +7 -0
  184. package/config/product/manager.js +0 -1
  185. package/config/product/settings.js +22 -11
  186. package/config/query-params.js +13 -0
  187. package/config/roles.ts +1 -1
  188. package/config/router/navigation-guards/authentication.js +51 -2
  189. package/config/router/routes.js +47 -31
  190. package/config/settings.ts +21 -3
  191. package/config/store.js +2 -0
  192. package/config/system-namespaces.js +1 -1
  193. package/config/table-headers.js +32 -3
  194. package/config/types.js +16 -7
  195. package/config/version.js +1 -1
  196. package/core/plugin.ts +32 -7
  197. package/core/types.ts +18 -1
  198. package/detail/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +22 -18
  199. package/detail/management.cattle.io.fleetworkspace.vue +18 -27
  200. package/detail/management.cattle.io.oidcclient.vue +369 -0
  201. package/detail/node.vue +2 -2
  202. package/detail/pod.vue +2 -2
  203. package/detail/provisioning.cattle.io.cluster.vue +3 -47
  204. package/detail/service.vue +10 -1
  205. package/detail/workload/index.vue +8 -2
  206. package/dialog/ExtensionCatalogUninstallDialog.vue +7 -4
  207. package/dialog/GenericPrompt.vue +1 -1
  208. package/dialog/ImportDialog.vue +8 -8
  209. package/dialog/OidcClientSecretDialog.vue +117 -0
  210. package/dialog/RotateEncryptionKeyDialog.vue +10 -30
  211. package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +3 -3
  212. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +5 -2
  213. package/edit/auth/ldap/__tests__/config.test.ts +14 -0
  214. package/edit/auth/ldap/config.vue +24 -0
  215. package/edit/autoscaling.horizontalpodautoscaler/index.vue +4 -1
  216. package/edit/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +30 -31
  217. package/edit/{cis.cattle.io.clusterscanbenchmark.vue → compliance.cattle.io.clusterscanbenchmark.vue} +4 -4
  218. package/edit/{cis.cattle.io.clusterscanprofile.vue → compliance.cattle.io.clusterscanprofile.vue} +5 -5
  219. package/edit/configmap.vue +8 -2
  220. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  221. package/edit/fleet.cattle.io.gitrepo.vue +44 -222
  222. package/edit/fleet.cattle.io.helmop.vue +44 -269
  223. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  224. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  225. package/edit/logging-flow/index.vue +1 -0
  226. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  227. package/edit/management.cattle.io.fleetworkspace.vue +1 -0
  228. package/edit/management.cattle.io.oidcclient.vue +162 -0
  229. package/edit/management.cattle.io.project.vue +4 -1
  230. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +1 -1
  231. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +5 -0
  232. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  233. package/edit/monitoring.coreos.com.receiver/auth.vue +30 -30
  234. package/edit/monitoring.coreos.com.receiver/index.vue +1 -0
  235. package/edit/monitoring.coreos.com.receiver/types/email.vue +1 -1
  236. package/edit/monitoring.coreos.com.route.vue +1 -0
  237. package/edit/namespace.vue +1 -0
  238. package/edit/networking.istio.io.destinationrule/index.vue +4 -1
  239. package/edit/networking.k8s.io.ingress/Certificate.vue +12 -12
  240. package/edit/networking.k8s.io.ingress/__tests__/Certificate.test.ts +165 -0
  241. package/edit/networking.k8s.io.ingress/index.vue +4 -1
  242. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +7 -2
  243. package/edit/networking.k8s.io.networkpolicy/index.vue +6 -2
  244. package/edit/node.vue +1 -0
  245. package/edit/persistentvolume/index.vue +4 -1
  246. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +3 -2
  247. package/edit/provisioning.cattle.io.cluster/rke2.vue +516 -426
  248. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +48 -39
  249. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +5 -0
  250. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +2 -2
  251. package/edit/resources.cattle.io.restore.vue +1 -1
  252. package/edit/secret/basic.vue +1 -0
  253. package/edit/secret/index.vue +127 -15
  254. package/edit/service.vue +4 -1
  255. package/edit/serviceaccount.vue +4 -1
  256. package/edit/storage.k8s.io.storageclass/index.vue +4 -1
  257. package/edit/workload/index.vue +5 -0
  258. package/list/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +2 -2
  259. package/list/management.cattle.io.oidcclient.vue +108 -0
  260. package/list/node.vue +2 -0
  261. package/list/projectsecret.vue +345 -0
  262. package/list/secret.vue +109 -0
  263. package/machine-config/amazonec2.vue +3 -24
  264. package/machine-config/components/GCEImage.vue +374 -0
  265. package/machine-config/google.vue +617 -0
  266. package/mixins/__tests__/brand.spec.ts +170 -0
  267. package/mixins/brand.js +16 -17
  268. package/mixins/create-edit-view/impl.js +10 -1
  269. package/mixins/create-edit-view/index.js +5 -0
  270. package/mixins/resource-fetch-api-pagination.js +24 -8
  271. package/mixins/resource-fetch.js +3 -1
  272. package/mixins/vue-select-overrides.js +1 -0
  273. package/models/cluster.x-k8s.io.machinedeployment.js +11 -2
  274. package/models/{cis.cattle.io.clusterscan.js → compliance.cattle.io.clusterscan.js} +8 -8
  275. package/models/{cis.cattle.io.clusterscanbenchmark.js → compliance.cattle.io.clusterscanbenchmark.js} +1 -1
  276. package/models/{cis.cattle.io.clusterscanprofile.js → compliance.cattle.io.clusterscanprofile.js} +5 -5
  277. package/models/{cis.cattle.io.clusterscanreport.js → compliance.cattle.io.clusterscanreport.js} +1 -1
  278. package/models/fleet-application.js +8 -79
  279. package/models/fleet.cattle.io.cluster.js +13 -2
  280. package/models/fleet.cattle.io.gitrepo.js +2 -2
  281. package/models/fleet.cattle.io.helmop.js +9 -39
  282. package/models/management.cattle.io.fleetworkspace.js +2 -1
  283. package/models/management.cattle.io.oidcclient.js +18 -0
  284. package/models/management.cattle.io.registration.js +3 -0
  285. package/models/provisioning.cattle.io.cluster.js +29 -33
  286. package/models/secret.js +157 -2
  287. package/models/service.js +4 -0
  288. package/models/workload.js +5 -0
  289. package/package.json +2 -2
  290. package/pages/about.vue +4 -58
  291. package/pages/auth/login.vue +1 -1
  292. package/pages/c/_cluster/apps/charts/AddRepoLink.vue +0 -1
  293. package/pages/c/_cluster/apps/charts/index.vue +296 -81
  294. package/pages/c/_cluster/auth/user.retention/index.vue +87 -78
  295. package/pages/c/_cluster/explorer/index.vue +3 -3
  296. package/pages/c/_cluster/explorer/projectsecret.vue +34 -0
  297. package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -1
  298. package/pages/c/_cluster/fleet/application/create.vue +3 -2
  299. package/pages/c/_cluster/fleet/index.vue +94 -57
  300. package/pages/c/_cluster/fleet/settings/index.vue +229 -0
  301. package/pages/c/_cluster/longhorn/index.vue +5 -2
  302. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +16 -1
  303. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +2 -2
  304. package/pages/explorer/resource/detail/configmap.vue +30 -7
  305. package/pages/explorer/resource/detail/projectsecret.vue +9 -0
  306. package/pages/explorer/resource/detail/secret.vue +63 -0
  307. package/pages/home.vue +9 -55
  308. package/pages/support/index.vue +4 -6
  309. package/plugins/dashboard-store/__tests__/normalize.test.ts +223 -0
  310. package/plugins/dashboard-store/__tests__/resource-class.test.ts +191 -0
  311. package/plugins/dashboard-store/__tests__/utils/normalize-usecases.ts +1526 -0
  312. package/plugins/dashboard-store/actions.js +19 -5
  313. package/plugins/dashboard-store/getters.js +4 -0
  314. package/plugins/dashboard-store/normalize.js +29 -17
  315. package/plugins/dashboard-store/resource-class.js +68 -19
  316. package/plugins/steve/steve-pagination-utils.ts +38 -19
  317. package/plugins/steve/subscribe.js +6 -1
  318. package/rancher-components/Banner/Banner.vue +13 -0
  319. package/rancher-components/Form/Checkbox/Checkbox.vue +9 -4
  320. package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
  321. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -0
  322. package/rancher-components/RcItemCard/RcItemCard.vue +8 -3
  323. package/store/auth.js +2 -0
  324. package/store/catalog.js +23 -1
  325. package/store/growl.js +97 -8
  326. package/store/index.js +6 -0
  327. package/store/notifications.ts +426 -0
  328. package/store/prefs.js +0 -1
  329. package/store/type-map.js +19 -16
  330. package/store/uiplugins.ts +15 -1
  331. package/types/fleet.d.ts +24 -0
  332. package/types/kube/kube-api.ts +12 -0
  333. package/types/notifications/index.ts +74 -0
  334. package/types/shell/index.d.ts +661 -589
  335. package/types/store/dashboard-store.types.ts +16 -0
  336. package/types/store/pagination.types.ts +16 -6
  337. package/utils/__tests__/create-yaml.test.ts +235 -0
  338. package/utils/__tests__/fleet.test.ts +148 -0
  339. package/utils/__tests__/object.test.ts +54 -1
  340. package/utils/__tests__/string.test.ts +273 -1
  341. package/utils/__tests__/time.test.ts +31 -0
  342. package/utils/auth.js +9 -2
  343. package/utils/create-yaml.js +103 -9
  344. package/utils/crypto/encryption.ts +103 -0
  345. package/utils/cspAdaptor.ts +51 -0
  346. package/utils/fleet.ts +54 -65
  347. package/utils/object.js +36 -0
  348. package/utils/pagination-utils.ts +19 -1
  349. package/utils/release-notes.ts +48 -0
  350. package/utils/selector-typed.ts +7 -2
  351. package/utils/string.js +24 -0
  352. package/utils/{time.js → time.ts} +25 -6
  353. package/utils/uiplugins.ts +22 -0
  354. package/utils/validators/formRules/index.ts +3 -0
  355. package/components/Resource/Detail/TitleBar/composable.ts +0 -31
  356. package/config/product/legacy.js +0 -62
  357. package/models/etcdbackup.js +0 -45
  358. package/pages/c/_cluster/legacy/pages/_page.vue +0 -29
  359. package/pages/c/_cluster/legacy/project/_page.vue +0 -57
  360. package/pages/c/_cluster/legacy/project/index.vue +0 -32
  361. package/pages/c/_cluster/legacy/project/pipelines.vue +0 -96
@@ -30,7 +30,19 @@ export default {
30
30
  effectValues: {
31
31
  type: Object,
32
32
  default: () => DEFAULT_EFFECT_VALUES
33
- }
33
+ },
34
+ title: {
35
+ type: String,
36
+ default: ''
37
+ },
38
+ addIcon: {
39
+ type: String,
40
+ default: '',
41
+ },
42
+ addClass: {
43
+ type: String,
44
+ default: '',
45
+ },
34
46
  },
35
47
 
36
48
  data() {
@@ -38,6 +50,10 @@ export default {
38
50
  },
39
51
 
40
52
  computed: {
53
+ _title() {
54
+ return this.title || this.t('tableHeaders.taints');
55
+ },
56
+
41
57
  localValue: {
42
58
  get() {
43
59
  return this.value;
@@ -60,7 +76,7 @@ export default {
60
76
  <KeyValue
61
77
  :value="value"
62
78
  data-testid="taints-keyvalue"
63
- :title="t('tableHeaders.taints')"
79
+ :title="_title"
64
80
  :mode="mode"
65
81
  :as-map="false"
66
82
  :read-allowed="false"
@@ -70,6 +86,8 @@ export default {
70
86
  :extra-columns="['effect']"
71
87
  :preserve-keys="['effect']"
72
88
  :add-label="t('labels.addTaint')"
89
+ :add-icon="addIcon"
90
+ :add-class="addClass"
73
91
  :disabled="disabled"
74
92
  @update:value="(e) => $emit('update:value', e)"
75
93
  >
@@ -82,6 +100,7 @@ export default {
82
100
  v-model:value="row.effect"
83
101
  :data-testid="`taints-effect-row-${i}`"
84
102
  :options="effectOptions"
103
+ :mode="mode"
85
104
  :disabled="disabled"
86
105
  class="compact-select"
87
106
  @update:value="queueUpdate"
@@ -140,6 +140,13 @@ export default {
140
140
  type: Boolean,
141
141
  default: false,
142
142
  },
143
+ /**
144
+ * The sub-label for the Labeled Input.
145
+ */
146
+ subLabel: {
147
+ type: String,
148
+ default: null
149
+ }
143
150
  },
144
151
 
145
152
  data() {
@@ -247,6 +254,7 @@ export default {
247
254
  :placeholder="placeholder"
248
255
  :hide-arrows="hideArrows"
249
256
  :aria-describedby="displayUnit ? describedById : undefined"
257
+ :sub-label="subLabel"
250
258
  @update:value="update"
251
259
  @blur="update($event.target.value)"
252
260
  >
@@ -32,7 +32,7 @@ export default {
32
32
  { value: 'simple', label: 'Key/Value Pair' },
33
33
  { value: 'resourceFieldRef', label: 'Resource' },
34
34
  { value: 'configMapKeyRef', label: 'ConfigMap Key' },
35
- { value: 'secretKeyRef', label: 'Secret key' },
35
+ { value: 'secretKeyRef', label: 'Secret Key' },
36
36
  { value: 'fieldRef', label: 'Pod Field' },
37
37
  { value: 'secretRef', label: 'Secret' },
38
38
  { value: 'configMapRef', label: 'ConfigMap' },
@@ -168,9 +168,9 @@ describe('component: LabeledSelect', () => {
168
168
 
169
169
  await wrapper.trigger('click');
170
170
 
171
- const dropdownOpen = wrapper.find('.vs--open');
171
+ const dropdownOpen = wrapper.vm.isOpen;
172
172
 
173
- expect(dropdownOpen.exists()).toBe(isOpen);
173
+ expect(dropdownOpen).toBe(isOpen);
174
174
  });
175
175
  });
176
176
 
@@ -208,6 +208,7 @@ describe('component: LabeledSelect', () => {
208
208
  const wrapper = mount(ParentComponent);
209
209
 
210
210
  // https://test-utils.vuejs.org/guide/essentials/event-handling#Asserting-the-arguments-of-the-event
211
+ await wrapper.trigger('click');
211
212
  await wrapper.find('input').trigger('focus');
212
213
  await wrapper.find('.vs__dropdown-option').trigger('click');
213
214
 
@@ -267,7 +268,8 @@ describe('component: LabeledSelect', () => {
267
268
  value,
268
269
  label: 'some-label',
269
270
  options,
270
- searchable: true
271
+ searchable: true,
272
+ loading: false,
271
273
  }
272
274
  });
273
275
 
@@ -281,7 +283,9 @@ describe('component: LabeledSelect', () => {
281
283
  await input.trigger('keydown.enter');
282
284
 
283
285
  // mimic pressing space on search box inside v-select
284
- await input.trigger('keydown.space', mockEvent);
286
+ const search = input.find('input');
287
+
288
+ await search.trigger('keydown.space', mockEvent);
285
289
 
286
290
  // eslint-disable-next-line
287
291
  expect(spyFocus).toHaveBeenCalled();
@@ -0,0 +1,360 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import Labels, { Factory } from '@shell/components/form/Labels.vue';
3
+ import KeyValue from '@shell/components/form/KeyValue.vue';
4
+ import { ToggleSwitch } from '@components/Form/ToggleSwitch';
5
+ import { _EDIT, _VIEW } from '@shell/config/query-params';
6
+
7
+ const mockT = jest.fn((key: string) => key);
8
+
9
+ describe('class: Factory', () => {
10
+ const mockProtectedWarning = 'Protected Key';
11
+
12
+ it('should correctly initialize with no protected keys or regexes', () => {
13
+ const factory = new Factory([], [], mockProtectedWarning, { a: '1', b: '2' });
14
+
15
+ expect((factory as any).protectedKeys).toStrictEqual([]);
16
+ expect((factory as any).protectedRegexes).toStrictEqual([]);
17
+ expect((factory as any).protectedWarning).toBe(mockProtectedWarning);
18
+ expect(factory.initValue).toStrictEqual({ a: '1', b: '2' });
19
+ expect(factory.value).toStrictEqual({ a: '1', b: '2' });
20
+ expect(factory.keyErrors).toStrictEqual({});
21
+ expect(factory.hasProtectedKeys).toBe(false);
22
+ });
23
+
24
+ it('should correctly initialize with protected keys', () => {
25
+ const factory = new Factory(['key1'], [], mockProtectedWarning, { key1: 'value1', key2: 'value2' });
26
+
27
+ expect((factory as any).protectedKeys).toStrictEqual(['key1']);
28
+ expect(factory.value).toStrictEqual({ key2: 'value2' });
29
+ expect(factory.hasProtectedKeys).toBe(true);
30
+ });
31
+
32
+ it('should correctly initialize with protected regexes', () => {
33
+ const factory = new Factory([], [/^key/], mockProtectedWarning, { key1: 'value1', other: 'value2' });
34
+
35
+ expect((factory as any).protectedRegexes.map((r: RegExp) => r.source)).toStrictEqual(['^key']);
36
+ expect(factory.value).toStrictEqual({ other: 'value2' });
37
+ expect(factory.hasProtectedKeys).toBe(true);
38
+ });
39
+
40
+ it('should omit protected keys from value but keep them in initValue', () => {
41
+ const factory = new Factory(['protected'], [], mockProtectedWarning, { protected: 'pVal', normal: 'nVal' });
42
+
43
+ expect(factory.initValue).toStrictEqual({ protected: 'pVal', normal: 'nVal' });
44
+ expect(factory.value).toStrictEqual({ normal: 'nVal' });
45
+ });
46
+
47
+ it('should update value and call callbackFn, preserving initial protected keys', () => {
48
+ const initialValue = {
49
+ system: 'sysVal', user: 'userVal', system2: 'sysVal'
50
+ };
51
+ const factory = new Factory(['system', 'system2'], [], mockProtectedWarning, initialValue);
52
+ const callback = jest.fn();
53
+
54
+ const newValue = {
55
+ newUser: 'newUVal', user: 'updatedUserVal', newProtected: 'newPVal', system: 'foo'
56
+ };
57
+
58
+ factory.update(newValue, callback);
59
+
60
+ // The internal factory.value is just the new set
61
+ expect(factory.value).toStrictEqual(newValue);
62
+
63
+ // The callback should receive the mix of new unprotected values and initial protected values
64
+ expect(callback).toHaveBeenCalledWith({
65
+ newProtected: 'newPVal',
66
+ newUser: 'newUVal',
67
+ user: 'updatedUserVal',
68
+ system: 'sysVal', // 'system' is the original protected from initialValue, sysVal is the original value
69
+ system2: 'sysVal' // 'system2' is the original protected from initialValue
70
+ });
71
+ });
72
+
73
+ it('should handle null/undefined update value gracefully', () => {
74
+ const initialValue = { system: 'sysVal', user: 'userVal' };
75
+ const factory = new Factory(['system'], [], mockProtectedWarning, initialValue);
76
+ const callback = jest.fn();
77
+
78
+ factory.update({}, callback);
79
+
80
+ expect(factory.value).toStrictEqual({});
81
+ expect(factory.keyErrors).toStrictEqual({});
82
+ expect(callback).toHaveBeenCalledWith({ system: 'sysVal' }); // Only the original protected values
83
+ });
84
+
85
+ it('should correctly identify protected keys based on both array and regex', () => {
86
+ const factory = new Factory(['staticKey'], [/^dynamic/], mockProtectedWarning, {});
87
+
88
+ expect((factory as any).isProtected('staticKey')).toBe(true);
89
+ expect((factory as any).isProtected('dynamicKey')).toBe(true);
90
+ expect((factory as any).isProtected('otherKey')).toBe(false);
91
+ });
92
+ });
93
+
94
+ describe('component: Labels', () => {
95
+ const mockValue = {
96
+ labels: {
97
+ 'kubernetes.io/hostname': 'test-app',
98
+ 'my-label': 'my-value'
99
+ },
100
+ systemLabels: ['kubernetes.io/hostname'],
101
+ annotations: {
102
+ 'cattle.io/system': 'user',
103
+ 'my-annotation': 'my-annotation'
104
+ },
105
+ systemAnnotations: ['cattle.io/system'],
106
+ setLabels: jest.fn(),
107
+ setAnnotations: jest.fn(),
108
+ };
109
+
110
+ it('should initialize with correct data properties', () => {
111
+ const wrapper = mount(Labels, {
112
+ props: {
113
+ value: mockValue,
114
+ mode: 'create',
115
+ },
116
+ global: { mocks: { t: mockT } },
117
+ });
118
+
119
+ const data = (wrapper.vm as any).$data;
120
+
121
+ expect(data.labels).toBeDefined();
122
+ expect(data.labels.initValue).toStrictEqual(mockValue.labels);
123
+ expect(data.labels.protectedKeys).toStrictEqual(mockValue.systemLabels);
124
+ expect(data.labels.value).toStrictEqual({ 'my-label': 'my-value' });
125
+ expect(data.labels.hasProtectedKeys).toBe(true);
126
+ expect(data.labels.keyErrors).toStrictEqual({}); // only when manually update
127
+
128
+ expect(data.annotations).toBeDefined();
129
+ expect(data.annotations.initValue).toStrictEqual(mockValue.annotations);
130
+ expect(data.annotations.protectedKeys).toStrictEqual(mockValue.systemAnnotations);
131
+ expect(data.annotations.value).toStrictEqual({ 'my-annotation': 'my-annotation' });
132
+ expect(data.annotations.hasProtectedKeys).toBe(true);
133
+ expect(data.annotations.keyErrors).toStrictEqual({}); // only when manually update
134
+
135
+ expect(data.toggler).toBe(false);
136
+ });
137
+
138
+ it('should render KeyValue for labels', () => {
139
+ const wrapper = mount(Labels, {
140
+ props: {
141
+ value: mockValue,
142
+ mode: 'create',
143
+ },
144
+ global: { mocks: { t: mockT } },
145
+ });
146
+
147
+ const labelsKeyValue = wrapper.findComponent(KeyValue);
148
+
149
+ expect(labelsKeyValue.exists()).toBe(true);
150
+ expect(labelsKeyValue.props('value')).toStrictEqual({ 'my-label': 'my-value' });
151
+ expect(labelsKeyValue.props('addLabel')).toBe('labels.addLabel');
152
+ expect(labelsKeyValue.props('mode')).toBe('create');
153
+ expect(labelsKeyValue.props('keyErrors')).toStrictEqual({});
154
+ });
155
+
156
+ it('should render KeyValue for annotations if showAnnotations is true', () => {
157
+ const wrapper = mount(Labels, {
158
+ props: {
159
+ value: mockValue,
160
+ mode: 'create',
161
+ showAnnotations: true,
162
+ },
163
+ global: { mocks: { t: mockT } },
164
+ });
165
+
166
+ const keyValueComponents = wrapper.findAllComponents(KeyValue);
167
+
168
+ expect(keyValueComponents).toHaveLength(2);
169
+ const annotationsKeyValue = keyValueComponents[1]; // The second KeyValue is for annotations
170
+
171
+ expect(annotationsKeyValue.exists()).toBe(true);
172
+ expect(annotationsKeyValue.props('value')).toStrictEqual({ 'my-annotation': 'my-annotation' });
173
+ expect(annotationsKeyValue.props('addLabel')).toBe('labels.addAnnotation');
174
+ expect(annotationsKeyValue.props('mode')).toBe('create');
175
+ expect(annotationsKeyValue.props('keyErrors')).toStrictEqual({});
176
+ });
177
+
178
+ it('should not render KeyValue for annotations if showAnnotations is false', () => {
179
+ const wrapper = mount(Labels, {
180
+ props: {
181
+ value: mockValue,
182
+ mode: 'create',
183
+ showAnnotations: false,
184
+ },
185
+ global: { mocks: { t: mockT } },
186
+ });
187
+
188
+ const keyValueComponents = wrapper.findAllComponents(KeyValue);
189
+
190
+ expect(keyValueComponents).toHaveLength(1); // Only the KeyValue for labels
191
+ });
192
+
193
+ it('should show ToggleSwitch in VIEW mode if there are protected keys', async() => {
194
+ const wrapper = mount(Labels, {
195
+ props: {
196
+ value: mockValue,
197
+ mode: _VIEW,
198
+ },
199
+ global: { mocks: { t: mockT } },
200
+ });
201
+
202
+ expect((wrapper.vm as any).showToggler).toBe(true);
203
+ const toggleSwitch = wrapper.findComponent(ToggleSwitch);
204
+
205
+ expect(toggleSwitch.exists()).toBe(true);
206
+ expect(toggleSwitch.props('onLabel')).toBe('labels.labels.show');
207
+ });
208
+
209
+ it('should not show ToggleSwitch in non-VIEW mode', () => {
210
+ const wrapper = mount(Labels, {
211
+ props: {
212
+ value: mockValue,
213
+ mode: _EDIT,
214
+ },
215
+ global: { mocks: { t: mockT } },
216
+ });
217
+
218
+ expect((wrapper.vm as any).showToggler).toBe(false);
219
+ expect(wrapper.findComponent(ToggleSwitch).exists()).toBe(false);
220
+ });
221
+
222
+ it('should not show ToggleSwitch in VIEW mode if no protected keys', () => {
223
+ const mockValueNoProtected = {
224
+ labels: { 'my-label': 'my-value' },
225
+ systemLabels: [],
226
+ annotations: { 'my-annotation': 'my-annotation' },
227
+ systemAnnotations: [],
228
+ setLabels: jest.fn(),
229
+ setAnnotations: jest.fn(),
230
+ };
231
+
232
+ const wrapper = mount(Labels, {
233
+ props: {
234
+ value: mockValueNoProtected,
235
+ mode: _VIEW,
236
+ },
237
+ global: { mocks: { t: mockT } },
238
+ });
239
+
240
+ expect((wrapper.vm as any).showToggler).toBe(false);
241
+ expect(wrapper.findComponent(ToggleSwitch).exists()).toBe(false);
242
+ });
243
+
244
+ it('should toggle label values when ToggleSwitch is activated', async() => {
245
+ const wrapper = mount(Labels, {
246
+ props: {
247
+ value: mockValue,
248
+ mode: _VIEW,
249
+ },
250
+ global: { mocks: { t: mockT } },
251
+ });
252
+
253
+ const labelsKeyValue = wrapper.findComponent(KeyValue);
254
+
255
+ expect(labelsKeyValue.props('value')).toStrictEqual({ 'my-label': 'my-value' }); // Initial: hidden protected
256
+
257
+ // Activate the toggle
258
+ await wrapper.findComponent(ToggleSwitch).vm.$emit('update:value', true);
259
+ await wrapper.vm.$nextTick();
260
+
261
+ expect((wrapper.vm as any).toggler).toBe(true);
262
+ expect(labelsKeyValue.props('value')).toStrictEqual(mockValue.labels); // Should show all labels including protected
263
+ });
264
+
265
+ it('should toggle annotation values when ToggleSwitch is activated', async() => {
266
+ const wrapper = mount(Labels, {
267
+ props: {
268
+ value: mockValue,
269
+ mode: _VIEW,
270
+ },
271
+ global: { mocks: { t: mockT } },
272
+ });
273
+
274
+ const annotationsKeyValue = wrapper.findAllComponents(KeyValue)[1];
275
+
276
+ expect(annotationsKeyValue.props('value')).toStrictEqual({ 'my-annotation': 'my-annotation' }); // Initial: hidden protected
277
+
278
+ // Activate the toggle
279
+ await wrapper.findComponent(ToggleSwitch).vm.$emit('update:value', true);
280
+ await wrapper.vm.$nextTick();
281
+
282
+ expect((wrapper.vm as any).toggler).toBe(true);
283
+ expect(annotationsKeyValue.props('value')).toStrictEqual(mockValue.annotations); // Should show all annotations including protected
284
+ });
285
+
286
+ it('should call setLabels when labels KeyValue emits update:value', async() => {
287
+ const wrapper = mount(Labels, {
288
+ props: {
289
+ value: mockValue,
290
+ mode: 'create',
291
+ },
292
+ global: { mocks: { t: mockT } },
293
+ });
294
+
295
+ const labelsKeyValue = wrapper.findComponent(KeyValue);
296
+ const newLabels = { 'new-label': 'new-value', 'my-label': 'my-value' };
297
+
298
+ await labelsKeyValue.vm.$emit('update:value', newLabels);
299
+
300
+ // We expect setLabels to be called with the new values, preserving initial protected ones
301
+ expect(mockValue.setLabels).toHaveBeenCalledWith({
302
+ 'new-label': 'new-value',
303
+ 'my-label': 'my-value',
304
+ 'kubernetes.io/hostname': 'test-app'
305
+ });
306
+ });
307
+
308
+ it('should call setAnnotations when annotations KeyValue emits update:value', async() => {
309
+ const wrapper = mount(Labels, {
310
+ props: {
311
+ value: mockValue,
312
+ mode: 'create',
313
+ showAnnotations: true,
314
+ },
315
+ global: { mocks: { t: mockT } },
316
+ });
317
+
318
+ const annotationsKeyValue = wrapper.findAllComponents(KeyValue)[1];
319
+ const newAnnotations = { 'new-anno': 'new-value', 'my-annotation': 'my-annotation' };
320
+
321
+ await annotationsKeyValue.vm.$emit('update:value', newAnnotations);
322
+
323
+ // We expect setAnnotations to be called with the new values, preserving initial protected ones
324
+ expect(mockValue.setAnnotations).toHaveBeenCalledWith({
325
+ 'new-anno': 'new-value',
326
+ 'my-annotation': 'my-annotation',
327
+ 'cattle.io/system': 'user'
328
+ });
329
+ });
330
+
331
+ it('should add newly entered protected keys to keyErrors', async() => {
332
+ const wrapper = mount(Labels, {
333
+ props: {
334
+ value: mockValue,
335
+ mode: 'create',
336
+ },
337
+ global: { mocks: { t: mockT } },
338
+ });
339
+
340
+ // Insert new protected key
341
+ const newLabels = {
342
+ 'my-label': 'my-value',
343
+ 'kubernetes.io/hostname': 'new-protected-value',
344
+ 'non-protected': 'value'
345
+ };
346
+
347
+ await wrapper.vm.labels.update(newLabels, () => {});
348
+ await wrapper.vm.$nextTick();
349
+
350
+ // Expect to add protected labels in keyErrors
351
+ expect((wrapper.vm as any).labels.keyErrors).toStrictEqual({ 'kubernetes.io/hostname': 'labels.protectedWarning' });
352
+
353
+ // On edit, should key the protected label in the list
354
+ expect((wrapper.vm as any).labels.value).toStrictEqual({
355
+ 'my-label': 'my-value',
356
+ 'kubernetes.io/hostname': 'new-protected-value',
357
+ 'non-protected': 'value'
358
+ });
359
+ });
360
+ });
@@ -53,19 +53,22 @@ describe('component: MatchExpressions', () => {
53
53
  it.each([
54
54
  'operator',
55
55
  ])('should emit an update on %p selection change', async(field) => {
56
- const wrapper = mount(MatchExpressions, {
57
- props: {
58
- mode: _CREATE,
59
- value: [
60
- {
61
- id: '123',
62
- key: '123',
63
- operator: 'anything',
64
- values: '123'
65
- }
66
- ]
67
- },
68
- });
56
+ const wrapper = mount(
57
+ MatchExpressions,
58
+ {
59
+ attachTo: document.body,
60
+ props: {
61
+ mode: _CREATE,
62
+ value: [
63
+ {
64
+ id: '123',
65
+ key: '123',
66
+ operator: 'anything',
67
+ values: '123'
68
+ }
69
+ ]
70
+ },
71
+ });
69
72
 
70
73
  const select = wrapper.find(`[data-testid="input-match-expression-${ field }-0"]`);
71
74
 
@@ -0,0 +1,116 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import Networking from '@shell/components/form/Networking.vue';
3
+ import { nextTick } from 'vue';
4
+
5
+ jest.mock('lodash/debounce', () => jest.fn((fn) => fn));
6
+
7
+ describe('component: Networking', () => {
8
+ it.each([
9
+ {
10
+ ip: '10.1.1.1',
11
+ hostnames: ['host1']
12
+ },
13
+ {
14
+ ip: '10.1.1.2',
15
+ hostnames: ['host1', 'host2']
16
+ },
17
+ {
18
+ ip: '10.1.1.3',
19
+ hostnames: []
20
+ }
21
+ ])('should render host aliases form if the value contains host aliases config: [%j]', (hostAliasesConfig) => {
22
+ const wrapper = mount(Networking, {
23
+ props: {
24
+ value: { hostAliases: [hostAliasesConfig] },
25
+ mode: 'create',
26
+ },
27
+ global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } }
28
+ });
29
+
30
+ const hostAliases = wrapper.findComponent('[data-test="hostAliases"]');
31
+ const keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
32
+ const valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
33
+
34
+ expect(keyInput.element.value).toBe(hostAliasesConfig.ip);
35
+ expect(valueInput.find('[data-testid="value-multiline"]').element.value).toBe(hostAliasesConfig.hostnames.join(', '));
36
+ });
37
+
38
+ it('should not render host aliases form, if there is no host aliases configuration', async() => {
39
+ const wrapper = mount(Networking, {
40
+ props: {
41
+ value: {},
42
+ 'onUpdate:value': (e) => wrapper.setProps({ value: e }),
43
+ mode: 'create',
44
+ },
45
+ global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } }
46
+ });
47
+
48
+ const hostAliases = wrapper.findComponent('[data-test="hostAliases"]');
49
+ const keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
50
+ const valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
51
+
52
+ expect(keyInput.exists()).toBe(false);
53
+ expect(valueInput.exists()).toBe(false);
54
+ expect(wrapper.props('value')).toStrictEqual({});
55
+ });
56
+
57
+ it('should render host aliases form correctly if click add host aliases button', async() => {
58
+ const wrapper = mount(Networking, {
59
+ props: {
60
+ value: {},
61
+ 'onUpdate:value': (e) => wrapper.setProps({ value: e }),
62
+ mode: 'create',
63
+ },
64
+ global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } }
65
+ });
66
+
67
+ const hostAliases = wrapper.findComponent('[data-test="hostAliases"]');
68
+ const addButton = hostAliases.find('[data-testid="add_row_item_button"]');
69
+
70
+ addButton.trigger('click');
71
+ await nextTick();
72
+
73
+ const keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
74
+ const valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
75
+ const v = wrapper.props('value');
76
+
77
+ expect(keyInput.exists()).toBe(true);
78
+ expect(valueInput.exists()).toBe(true);
79
+ expect(v.hostAliases).toHaveLength(1);
80
+ expect(v.hostAliases[0].ip).toBe('');
81
+ expect(v.hostAliases[0].hostnames).toStrictEqual([]);
82
+ });
83
+
84
+ it('should render host aliases form correctly if modify the form values', async() => {
85
+ const wrapper = mount(Networking, {
86
+ props: {
87
+ value: {},
88
+ 'onUpdate:value': (e) => wrapper.setProps({ value: e }),
89
+ mode: 'create',
90
+ },
91
+ global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } }
92
+ });
93
+
94
+ const hostAliases = wrapper.findComponent('[data-test="hostAliases"]');
95
+ const addButton = hostAliases.find('[data-testid="add_row_item_button"]');
96
+
97
+ addButton.trigger('click');
98
+ await nextTick();
99
+ let v = wrapper.props('value');
100
+ let keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
101
+ let valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
102
+
103
+ keyInput.setValue('10.1.1.1');
104
+ valueInput.find('[data-testid="value-multiline"]').setValue('test1, test2');
105
+ await nextTick();
106
+ v = wrapper.props('value');
107
+ keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
108
+ valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
109
+
110
+ expect(v.hostAliases).toHaveLength(1);
111
+ expect(v.hostAliases[0].ip).toBe('10.1.1.1');
112
+ expect(v.hostAliases[0].hostnames).toStrictEqual(['test1', 'test2']);
113
+ expect(keyInput.exists()).toBe(true);
114
+ expect(valueInput.exists()).toBe(true);
115
+ });
116
+ });
@@ -77,7 +77,8 @@ describe('select.vue', () => {
77
77
  value,
78
78
  label: 'some-label',
79
79
  options,
80
- searchable: true
80
+ searchable: true,
81
+ loading: false,
81
82
  }
82
83
  });
83
84
 
@@ -91,7 +92,9 @@ describe('select.vue', () => {
91
92
  await input.trigger('keydown.enter');
92
93
 
93
94
  // mimic pressing space on search box inside v-select
94
- await input.trigger('keydown.space', mockEvent);
95
+ const search = input.find('input');
96
+
97
+ await search.trigger('keydown.space', mockEvent);
95
98
 
96
99
  // eslint-disable-next-line
97
100
  expect(spyFocus).toHaveBeenCalled();
@@ -50,7 +50,7 @@ export default {
50
50
  :value="row.source.value || ''"
51
51
  />
52
52
  <template v-if="row.source.value && row.sourceSub.value">
53
- <div class="text-muted">
53
+ <div class="text-label">
54
54
  <Shortened
55
55
  long-value-key="sourceSub.value"
56
56
  :row="row"
@@ -56,7 +56,7 @@ export default {
56
56
 
57
57
  <template>
58
58
  <span class="formatter-pod-images">
59
- <span>{{ mainImage }}</span><br>
59
+ <span v-clean-tooltip.bottom="mainImage">{{ mainImage }}</span><br>
60
60
  <span
61
61
  v-if="images.length-1>0"
62
62
  v-clean-tooltip.bottom="imageLabels"