@rancher/shell 3.0.12-rc.2 → 3.0.12-rc.4

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 (473) hide show
  1. package/apis/impl/apis.ts +6 -0
  2. package/apis/index.ts +26 -0
  3. package/apis/intf/resources-api/cluster-api.ts +18 -0
  4. package/apis/intf/resources-api/mgmt-api.ts +15 -0
  5. package/apis/intf/resources-api/resource-base.ts +107 -0
  6. package/apis/intf/resources-api/resource-constants.ts +147 -0
  7. package/apis/intf/resources-api/resources-api.ts +143 -0
  8. package/apis/intf/resources.ts +49 -0
  9. package/apis/intf/{modal.ts → shell-api/modal.ts} +21 -26
  10. package/apis/intf/shell-api/proxy.ts +216 -0
  11. package/apis/intf/{slide-in.ts → shell-api/slide-in.ts} +4 -3
  12. package/apis/intf/{system.ts → shell-api/system.ts} +4 -1
  13. package/apis/intf/shell.ts +12 -6
  14. package/apis/resources/__tests__/resources-api-class.test.ts +550 -0
  15. package/apis/resources/index.ts +22 -0
  16. package/apis/resources/resources-api-class.ts +187 -0
  17. package/apis/shell/__tests__/proxy.test.ts +369 -0
  18. package/apis/shell/index.ts +8 -1
  19. package/apis/shell/modal.ts +4 -1
  20. package/apis/shell/notifications.ts +9 -6
  21. package/apis/shell/proxy.ts +256 -0
  22. package/apis/shell/slide-in.ts +4 -1
  23. package/apis/vue-shim.d.ts +2 -1
  24. package/assets/data/aws-regions.json +4 -0
  25. package/assets/fonts/lato/LatoLatin-Black.woff +0 -0
  26. package/assets/fonts/lato/LatoLatin-Black.woff2 +0 -0
  27. package/assets/fonts/lato/LatoLatin-BlackItalic.woff +0 -0
  28. package/assets/fonts/lato/LatoLatin-BlackItalic.woff2 +0 -0
  29. package/assets/fonts/lato/LatoLatin-Bold.woff +0 -0
  30. package/assets/fonts/lato/LatoLatin-Bold.woff2 +0 -0
  31. package/assets/fonts/lato/LatoLatin-BoldItalic.woff +0 -0
  32. package/assets/fonts/lato/LatoLatin-BoldItalic.woff2 +0 -0
  33. package/assets/fonts/lato/LatoLatin-Heavy.woff +0 -0
  34. package/assets/fonts/lato/LatoLatin-Heavy.woff2 +0 -0
  35. package/assets/fonts/lato/LatoLatin-HeavyItalic.woff +0 -0
  36. package/assets/fonts/lato/LatoLatin-HeavyItalic.woff2 +0 -0
  37. package/assets/fonts/lato/LatoLatin-Italic.woff +0 -0
  38. package/assets/fonts/lato/LatoLatin-Italic.woff2 +0 -0
  39. package/assets/fonts/lato/LatoLatin-Light.woff +0 -0
  40. package/assets/fonts/lato/LatoLatin-Light.woff2 +0 -0
  41. package/assets/fonts/lato/LatoLatin-LightItalic.woff +0 -0
  42. package/assets/fonts/lato/LatoLatin-LightItalic.woff2 +0 -0
  43. package/assets/fonts/lato/LatoLatin-Medium.woff +0 -0
  44. package/assets/fonts/lato/LatoLatin-Medium.woff2 +0 -0
  45. package/assets/fonts/lato/LatoLatin-MediumItalic.woff +0 -0
  46. package/assets/fonts/lato/LatoLatin-MediumItalic.woff2 +0 -0
  47. package/assets/fonts/lato/LatoLatin-Regular.woff +0 -0
  48. package/assets/fonts/lato/LatoLatin-Regular.woff2 +0 -0
  49. package/assets/fonts/lato/LatoLatin-Semibold.woff +0 -0
  50. package/assets/fonts/lato/LatoLatin-Semibold.woff2 +0 -0
  51. package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff +0 -0
  52. package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff2 +0 -0
  53. package/assets/styles/base/_variables.scss +2 -0
  54. package/assets/styles/fonts/_fontstack.scss +132 -8
  55. package/assets/styles/global/_layout.scss +4 -0
  56. package/assets/translations/en-us.yaml +165 -45
  57. package/assets/translations/zh-hans.yaml +1 -7
  58. package/chart/monitoring/ClusterSelector.vue +0 -21
  59. package/chart/monitoring/index.vue +10 -1
  60. package/chart/monitoring/prometheus/index.vue +6 -3
  61. package/components/ActionDropdownShell.vue +2 -1
  62. package/components/CruResource.vue +161 -14
  63. package/components/CruResourceFooter.vue +9 -5
  64. package/components/ExplorerMembers.vue +8 -4
  65. package/components/ExplorerProjectsNamespaces.vue +11 -7
  66. package/components/GrowlManager.vue +4 -0
  67. package/components/InstallHelmCharts.vue +2 -2
  68. package/components/LandingPagePreference.vue +14 -5
  69. package/components/MgmtNodeList.vue +184 -0
  70. package/components/Resource/Detail/Card/StateCard/__tests__/composables.test.ts +90 -1
  71. package/components/Resource/Detail/Card/StateCard/composables.ts +57 -87
  72. package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +61 -0
  73. package/components/Resource/Detail/Card/StatusCard/index.vue +61 -15
  74. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +17 -1
  75. package/components/Resource/Detail/Metadata/KeyValue.vue +5 -2
  76. package/components/Resource/Detail/Metadata/KeyValueRow.vue +2 -6
  77. package/components/Resource/Detail/Metadata/index.vue +6 -0
  78. package/components/Resource/Detail/ResourcePopover/index.vue +12 -1
  79. package/components/Resource/Detail/SpacedRow.vue +3 -1
  80. package/components/Resource/Detail/TitleBar/index.vue +10 -11
  81. package/components/ResourceDetail/index.vue +1 -1
  82. package/components/ResourceList/Masthead.vue +19 -9
  83. package/components/ResourceList/index.vue +82 -1
  84. package/components/RichTranslation.vue +5 -2
  85. package/components/SelectIconGrid.vue +0 -10
  86. package/components/Setting.vue +1 -0
  87. package/components/SingleClusterInfo.vue +1 -0
  88. package/components/SortableTable/__tests__/sorting.test.ts +126 -0
  89. package/components/SortableTable/index.vue +6 -9
  90. package/components/SortableTable/selection.js +23 -5
  91. package/components/SortableTable/sorting.js +6 -3
  92. package/components/SubtleLink.vue +31 -6
  93. package/components/Tabbed/Tab.vue +29 -3
  94. package/components/Tabbed/index.vue +25 -3
  95. package/components/TableOfContents/TableOfContents.vue +109 -0
  96. package/components/TableOfContents/composables.ts +258 -0
  97. package/components/Window/ContainerShell.vue +21 -11
  98. package/components/Window/__tests__/ContainerShell.test.ts +107 -37
  99. package/components/Wizard.vue +23 -17
  100. package/components/fleet/AppCoChartGrid.vue +401 -0
  101. package/components/fleet/AppCoEmptyState.vue +127 -0
  102. package/components/fleet/AppCoPageHeader.vue +119 -0
  103. package/components/fleet/AppCoVersionSelect.vue +70 -0
  104. package/components/fleet/FleetBundles.vue +100 -12
  105. package/components/fleet/FleetClusterTargets/ClusterSelectionFields.vue +217 -0
  106. package/components/fleet/FleetClusterTargets/TargetsList.vue +123 -35
  107. package/components/fleet/FleetClusterTargets/index.vue +226 -161
  108. package/components/fleet/FleetIntro.vue +7 -3
  109. package/components/fleet/FleetNoWorkspaces.vue +7 -3
  110. package/components/fleet/FleetSecretSelector.vue +5 -3
  111. package/components/fleet/FleetValuesFrom.vue +8 -2
  112. package/components/fleet/GitRepoTargetTab.vue +0 -2
  113. package/components/fleet/HelmOpAdvancedTab.vue +19 -53
  114. package/components/fleet/HelmOpAppCoConfigTab.vue +593 -0
  115. package/components/fleet/HelmOpAppCoResourcesSection.vue +162 -0
  116. package/components/fleet/HelmOpResourcesSection.vue +82 -0
  117. package/components/fleet/HelmOpTargetOptionsSection.vue +89 -0
  118. package/components/fleet/HelmOpTargetTab.vue +64 -60
  119. package/components/fleet/HelmOpValuesTab.vue +129 -105
  120. package/components/fleet/__tests__/AppCoEmptyState.test.ts +71 -0
  121. package/components/fleet/__tests__/AppCoVersionSelect.test.ts +36 -0
  122. package/components/fleet/__tests__/ClusterSelectionFields.test.ts +62 -0
  123. package/components/fleet/__tests__/FleetClusterTargets.test.ts +402 -115
  124. package/components/fleet/__tests__/FleetClusters.test.ts +12 -12
  125. package/components/fleet/__tests__/FleetSecretSelector.test.ts +16 -0
  126. package/components/fleet/__tests__/FleetValuesFrom.test.ts +44 -0
  127. package/components/fleet/__tests__/HelmOpAppCoConfigTab.test.ts +59 -0
  128. package/components/fleet/__tests__/HelmOpAppCoResourcesSection.test.ts +62 -0
  129. package/components/fleet/__tests__/HelmOpResourcesSection.test.ts +43 -0
  130. package/components/fleet/__tests__/HelmOpTargetOptionsSection.test.ts +34 -0
  131. package/components/fleet/__tests__/HelmOpValuesTab.test.ts +39 -0
  132. package/components/fleet/__tests__/__snapshots__/AppCoEmptyState.test.ts.snap +97 -0
  133. package/components/fleet/__tests__/__snapshots__/AppCoVersionSelect.test.ts.snap +30 -0
  134. package/components/fleet/__tests__/__snapshots__/ClusterSelectionFields.test.ts.snap +209 -0
  135. package/components/fleet/__tests__/__snapshots__/HelmOpTargetOptionsSection.test.ts.snap +140 -0
  136. package/components/fleet/dashboard/Empty.vue +8 -4
  137. package/components/fleet/dashboard/ResourceCard.vue +28 -0
  138. package/components/fleet/dashboard/ResourceDetails.vue +28 -0
  139. package/components/fleet/dashboard/__tests__/ResourceCard.test.ts +87 -0
  140. package/components/form/ArrayList.vue +61 -4
  141. package/components/form/KeyValue.vue +23 -2
  142. package/components/form/LabeledSelect.vue +59 -4
  143. package/components/form/Labels.vue +22 -3
  144. package/components/form/NameNsDescription.vue +24 -5
  145. package/components/form/ResourceTabs/index.vue +1 -0
  146. package/components/form/Security.vue +6 -2
  147. package/components/form/WorkloadPorts.vue +2 -7
  148. package/components/form/__tests__/NameNsDescription.test.ts +75 -0
  149. package/components/form/__tests__/Security.test.ts +76 -0
  150. package/components/formatter/Autoscaler.vue +4 -4
  151. package/components/formatter/ClusterKubeVersion.vue +27 -0
  152. package/components/formatter/ClusterLink.vue +1 -7
  153. package/components/formatter/ClusterProvider.vue +6 -10
  154. package/components/formatter/FleetSummaryGraph.vue +0 -3
  155. package/components/formatter/InternalExternalIP.vue +10 -4
  156. package/components/formatter/MachineSummaryGraph.vue +1 -1
  157. package/components/formatter/PodsUsage.vue +2 -2
  158. package/components/formatter/ServiceTargets.vue +26 -7
  159. package/components/formatter/__tests__/Autoscaler.test.ts +19 -22
  160. package/components/formatter/__tests__/FleetSummaryGraph.test.ts +216 -0
  161. package/components/formatter/__tests__/InternalExternalIP.test.ts +132 -0
  162. package/components/formatter/__tests__/PodsUsage.test.ts +6 -10
  163. package/components/formatter/__tests__/ServiceTargets.test.ts +412 -0
  164. package/components/nav/Header.vue +4 -0
  165. package/components/nav/NamespaceFilter.vue +2 -2
  166. package/components/nav/TopLevelMenu.helper.ts +15 -3
  167. package/components/nav/TopLevelMenu.vue +22 -6
  168. package/components/nav/__tests__/Header.test.ts +15 -0
  169. package/components/nav/__tests__/TopLevelMenu.test.ts +263 -21
  170. package/components/templates/default.vue +9 -4
  171. package/components/templates/home.vue +23 -0
  172. package/components/templates/plain.vue +23 -0
  173. package/components/templates/standalone.vue +17 -0
  174. package/composables/useFormValidation.ts +93 -0
  175. package/composables/useHelmOpResources.test.ts +56 -0
  176. package/composables/useHelmOpResources.ts +32 -0
  177. package/composables/useStateColor.test.ts +325 -0
  178. package/composables/useStateColor.ts +128 -0
  179. package/composables/useVeeValidateField.test.ts +159 -0
  180. package/composables/useVeeValidateField.ts +67 -0
  181. package/config/home-links.js +1 -1
  182. package/config/labels-annotations.js +1 -0
  183. package/config/pagination-table-headers.js +18 -1
  184. package/config/product/explorer.js +17 -4
  185. package/config/product/manager.js +84 -21
  186. package/config/router/index.js +16 -0
  187. package/config/router/navigation-guards/__tests__/authentication.test.ts +130 -0
  188. package/config/router/navigation-guards/authentication.js +10 -4
  189. package/config/router/routes.js +26 -6
  190. package/config/settings.ts +0 -2
  191. package/config/table-headers.js +23 -5
  192. package/config/types.js +11 -1
  193. package/core/__tests__/plugin-products.test.ts +904 -20
  194. package/core/plugin-products-base.ts +110 -10
  195. package/core/plugin-products.ts +4 -0
  196. package/core/plugin-types.ts +194 -31
  197. package/core/plugin.ts +18 -7
  198. package/core/productDebugger.js +9 -4
  199. package/core/types-provisioning.ts +77 -31
  200. package/core/types.ts +72 -22
  201. package/detail/__tests__/pod.test.ts +41 -0
  202. package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +114 -0
  203. package/detail/__tests__/workload.test.ts +3 -152
  204. package/detail/catalog.cattle.io.clusterrepo.vue +1 -1
  205. package/detail/harvesterhci.io.management.cluster.vue +6 -2
  206. package/detail/pod.vue +1 -1
  207. package/detail/provisioning.cattle.io.cluster.vue +34 -14
  208. package/detail/workload/index.vue +12 -55
  209. package/edit/__tests__/catalog.cattle.io.clusterrepo.test.ts +248 -0
  210. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +105 -0
  211. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
  212. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/index.test.ts.snap +1 -0
  213. package/edit/auth/__tests__/azuread.test.ts +247 -39
  214. package/edit/auth/__tests__/github.test.ts +234 -0
  215. package/edit/auth/__tests__/oidc.test.ts +26 -6
  216. package/edit/auth/__tests__/saml.test.ts +196 -0
  217. package/edit/auth/azuread.vue +197 -56
  218. package/edit/auth/github.vue +72 -13
  219. package/edit/auth/ldap/__tests__/index.test.ts +206 -0
  220. package/edit/auth/ldap/config.vue +8 -0
  221. package/edit/auth/ldap/index.vue +75 -1
  222. package/edit/auth/oidc.vue +119 -73
  223. package/edit/auth/saml.vue +76 -12
  224. package/edit/catalog.cattle.io.clusterrepo.vue +140 -32
  225. package/edit/fleet.cattle.io.helmop.vue +491 -136
  226. package/edit/management.cattle.io.user.vue +5 -2
  227. package/edit/networking.k8s.io.ingress/DefaultBackend.vue +13 -4
  228. package/edit/networking.k8s.io.ingress/RulePath.vue +8 -4
  229. package/edit/networking.k8s.io.ingress/index.vue +75 -20
  230. package/edit/provisioning.cattle.io.cluster/__tests__/MachinePool.test.ts +104 -0
  231. package/edit/provisioning.cattle.io.cluster/index.vue +11 -7
  232. package/edit/provisioning.cattle.io.cluster/rke2.vue +92 -14
  233. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +22 -0
  234. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +37 -4
  235. package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +132 -7
  236. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -1
  237. package/edit/secret/__tests__/ssh.test.ts +5 -6
  238. package/edit/secret/basic.vue +31 -0
  239. package/edit/secret/index.vue +68 -17
  240. package/edit/secret/registry.vue +38 -0
  241. package/edit/secret/ssh.vue +29 -0
  242. package/edit/secret/tls.vue +30 -0
  243. package/edit/service.vue +4 -4
  244. package/edit/workload/Upgrading.vue +3 -3
  245. package/edit/workload/__tests__/Upgrading.test.ts +6 -9
  246. package/edit/workload/mixins/workload.js +2 -1
  247. package/list/fleet.cattle.io.bundle.vue +7 -104
  248. package/list/fleet.cattle.io.clusterregistrationtoken.vue +20 -0
  249. package/list/group.principal.vue +5 -4
  250. package/list/harvesterhci.io.management.cluster.vue +8 -9
  251. package/list/management.cattle.io.user.vue +12 -9
  252. package/list/provisioning.cattle.io.cluster.vue +268 -180
  253. package/list/utils/management.cattle.io.cluster.utils.ts +128 -0
  254. package/mixins/__tests__/auth-config.test.ts +90 -0
  255. package/mixins/__tests__/chart.test.ts +206 -0
  256. package/mixins/__tests__/resource-fetch-api-pagination.test.ts +48 -0
  257. package/mixins/auth-config.js +7 -0
  258. package/mixins/brand.js +2 -1
  259. package/mixins/chart.js +22 -9
  260. package/mixins/child-hook.js +12 -6
  261. package/mixins/create-edit-view/impl.js +5 -3
  262. package/mixins/resource-fetch-api-pagination.js +62 -6
  263. package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +57 -0
  264. package/models/__tests__/compliance.cattle.io.clusterscan.test.ts +144 -0
  265. package/models/__tests__/ext.cattle.io.kubeconfig.test.ts +67 -67
  266. package/models/__tests__/fleet-application.test.ts +175 -0
  267. package/models/__tests__/fleet.cattle.io.bundle.test.ts +169 -0
  268. package/models/__tests__/fleet.cattle.io.helmop.test.ts +84 -0
  269. package/models/__tests__/management.cattle.io.cluster.test.ts +1 -1
  270. package/models/__tests__/management.cattle.io.node.ts +28 -5
  271. package/models/__tests__/management.cattle.io.nodepool.ts +5 -4
  272. package/models/__tests__/namespace.test.ts +36 -0
  273. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +81 -11
  274. package/models/__tests__/workload.test.ts +401 -26
  275. package/models/base-cluster.x-k8s.io.js +26 -0
  276. package/models/catalog.cattle.io.clusterrepo.js +28 -4
  277. package/models/cluster.js +1 -1
  278. package/models/cluster.x-k8s.io.machine.js +4 -22
  279. package/models/cluster.x-k8s.io.machinedeployment.js +2 -20
  280. package/models/cluster.x-k8s.io.machineset.js +2 -20
  281. package/models/compliance.cattle.io.clusterscan.js +165 -2
  282. package/models/ext.cattle.io.kubeconfig.ts +4 -7
  283. package/models/fleet-application.js +7 -1
  284. package/models/fleet.cattle.io.helmop.js +20 -1
  285. package/models/management.cattle.io.cluster.js +434 -41
  286. package/models/management.cattle.io.node.js +50 -7
  287. package/models/management.cattle.io.nodepool.js +1 -1
  288. package/models/namespace.js +1 -1
  289. package/models/networking.k8s.io.ingress.js +12 -4
  290. package/models/pod.js +33 -1
  291. package/models/provisioning.cattle.io.cluster.js +51 -334
  292. package/models/rke.cattle.io.etcdsnapshot.js +1 -2
  293. package/models/workload.js +108 -13
  294. package/models/workload.service.js +5 -0
  295. package/package.json +22 -39
  296. package/pages/__tests__/readme.test.ts +49 -0
  297. package/pages/about.vue +5 -6
  298. package/pages/auth/login.vue +0 -35
  299. package/pages/auth/setup.vue +13 -3
  300. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +2 -2
  301. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +10 -1
  302. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +76 -0
  303. package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +93 -0
  304. package/pages/c/_cluster/apps/charts/chart.vue +62 -9
  305. package/pages/c/_cluster/apps/charts/index.vue +48 -10
  306. package/pages/c/_cluster/apps/charts/install.vue +122 -113
  307. package/pages/c/_cluster/auth/roles/index.vue +5 -4
  308. package/pages/c/_cluster/explorer/__tests__/index.test.ts +23 -25
  309. package/pages/c/_cluster/explorer/index.vue +5 -49
  310. package/pages/c/_cluster/explorer/workload-dashboard/ByNamespaceSection.vue +31 -0
  311. package/pages/c/_cluster/explorer/workload-dashboard/ByStateSection.vue +138 -0
  312. package/pages/c/_cluster/explorer/workload-dashboard/ByTypeSection.vue +30 -0
  313. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadCard.vue +155 -0
  314. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadNamespaceCard.vue +142 -0
  315. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadTypeCard.vue +159 -0
  316. package/pages/c/_cluster/explorer/workload-dashboard/__tests__/composable.test.ts +561 -0
  317. package/pages/c/_cluster/explorer/workload-dashboard/composable.ts +440 -0
  318. package/pages/c/_cluster/explorer/workload-dashboard/index.vue +187 -0
  319. package/pages/c/_cluster/explorer/workload-dashboard/types.ts +80 -0
  320. package/pages/c/_cluster/fleet/application/create.vue +187 -136
  321. package/pages/c/_cluster/fleet/application/index.vue +5 -3
  322. package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailBody.vue +338 -0
  323. package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailHeader.vue +121 -0
  324. package/pages/c/_cluster/fleet/application/suse-app-collection/chart.vue +369 -0
  325. package/pages/c/_cluster/fleet/application/suse-app-collection/charts.vue +248 -0
  326. package/pages/c/_cluster/fleet/application/suse-app-collection/credentials.vue +310 -0
  327. package/pages/c/_cluster/fleet/index.vue +2 -2
  328. package/pages/c/_cluster/istio/__tests__/istio.index.test.ts +194 -0
  329. package/pages/c/_cluster/istio/index.vue +21 -6
  330. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -0
  331. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +815 -2
  332. package/pages/c/_cluster/uiplugins/index.vue +218 -197
  333. package/pages/diagnostic.vue +13 -17
  334. package/pages/fail-whale.vue +30 -7
  335. package/pages/home.vue +93 -306
  336. package/pages/readme.vue +88 -0
  337. package/plugins/clean-html.d.ts +9 -0
  338. package/plugins/dashboard-store/__tests__/resource-class.test.ts +181 -0
  339. package/plugins/dashboard-store/actions.js +40 -18
  340. package/plugins/dashboard-store/resource-class.js +67 -9
  341. package/plugins/steve/__tests__/actions.test.ts +212 -0
  342. package/plugins/steve/__tests__/subscribe.spec.ts +6 -3
  343. package/plugins/steve/actions.js +96 -0
  344. package/plugins/steve/steve-pagination-utils.ts +12 -4
  345. package/plugins/steve/subscribe.js +35 -5
  346. package/rancher-components/Accordion/Accordion.vue +53 -9
  347. package/rancher-components/Form/Checkbox/Checkbox.vue +14 -0
  348. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +10 -4
  349. package/rancher-components/Form/LabeledInput/LabeledInput.vue +7 -52
  350. package/rancher-components/Form/Radio/RadioButton.vue +17 -1
  351. package/rancher-components/Form/Radio/RadioGroup.vue +10 -0
  352. package/rancher-components/Pill/RcTag/RcTag.vue +3 -2
  353. package/rancher-components/RcButton/RcButton.test.ts +140 -1
  354. package/rancher-components/RcButton/RcButton.vue +126 -17
  355. package/rancher-components/RcButton/types.ts +3 -0
  356. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -8
  357. package/rancher-components/RcItemCard/RcItemCard.test.ts +18 -0
  358. package/rancher-components/RcItemCard/RcItemCard.vue +2 -2
  359. package/rancher-components/RcSection/RcSection.vue +28 -3
  360. package/scripts/extension/helm/package/Dockerfile +1 -1
  361. package/scripts/test-plugins-build.sh +2 -1
  362. package/store/__tests__/catalog.test.ts +115 -1
  363. package/store/__tests__/notifications.test.ts +434 -0
  364. package/store/__tests__/type-map.test.ts +556 -1
  365. package/store/action-menu.js +8 -3
  366. package/store/auth.js +1 -1
  367. package/store/aws.js +27 -16
  368. package/store/catalog.js +84 -3
  369. package/store/digitalocean.js +20 -38
  370. package/store/index.js +2 -0
  371. package/store/linode.js +25 -40
  372. package/store/plugins.js +7 -4
  373. package/store/pnap.js +1 -0
  374. package/store/type-map.js +111 -29
  375. package/tsconfig.paths.json +8 -8
  376. package/types/components/buttonGroup.ts +5 -0
  377. package/types/kube/kube-api.ts +14 -1
  378. package/types/rancher/steve.api.ts +12 -12
  379. package/types/resources/settings.d.ts +2 -1
  380. package/types/shell/index.d.ts +206 -72
  381. package/types/store/dashboard-store.types.ts +108 -11
  382. package/types/store/pagination.types.ts +6 -3
  383. package/utils/__tests__/alertmanagerconfig.test.ts +117 -0
  384. package/utils/__tests__/async.test.ts +87 -0
  385. package/utils/__tests__/auth.test.ts +273 -0
  386. package/utils/__tests__/aws.test.ts +140 -0
  387. package/utils/__tests__/banners.test.ts +176 -0
  388. package/utils/__tests__/chart.test.ts +64 -1
  389. package/utils/__tests__/color.test.ts +226 -0
  390. package/utils/__tests__/computed.test.ts +193 -0
  391. package/utils/__tests__/cspAdaptor.test.ts +163 -0
  392. package/utils/__tests__/dom.test.ts +81 -0
  393. package/utils/__tests__/duration.test.ts +176 -0
  394. package/utils/__tests__/dynamic-importer.test.ts +102 -0
  395. package/utils/__tests__/fleet-appco.test.ts +312 -0
  396. package/utils/__tests__/fleet.test.ts +340 -0
  397. package/utils/__tests__/ingress.test.ts +553 -0
  398. package/utils/__tests__/kube.test.ts +68 -0
  399. package/utils/__tests__/monitoring.test.ts +130 -0
  400. package/utils/__tests__/namespace-filter.test.ts +109 -0
  401. package/utils/__tests__/object.test.ts +22 -0
  402. package/utils/__tests__/pagination-utils.test.ts +361 -0
  403. package/utils/__tests__/parse-externalid.test.ts +137 -0
  404. package/utils/__tests__/perf-setting.utils.test.ts +98 -0
  405. package/utils/__tests__/platform.test.ts +91 -0
  406. package/utils/__tests__/poller-sequential.test.ts +177 -0
  407. package/utils/__tests__/poller.test.ts +170 -0
  408. package/utils/__tests__/position.test.ts +237 -0
  409. package/utils/__tests__/promise.test.ts +346 -0
  410. package/utils/__tests__/provider.test.ts +51 -1
  411. package/utils/__tests__/queue.test.ts +232 -0
  412. package/utils/__tests__/release-notes.test.ts +221 -0
  413. package/utils/__tests__/router.test.js +254 -1
  414. package/utils/__tests__/select.test.ts +208 -0
  415. package/utils/__tests__/settings.test.ts +140 -0
  416. package/utils/__tests__/sort-utils.test.ts +301 -0
  417. package/utils/__tests__/string-utils.test.ts +798 -0
  418. package/utils/__tests__/string.test.ts +23 -1
  419. package/utils/__tests__/style.test.ts +154 -0
  420. package/utils/__tests__/svg-filter.test.ts +184 -0
  421. package/utils/__tests__/time.test.ts +265 -1
  422. package/utils/__tests__/title.test.ts +47 -0
  423. package/utils/__tests__/units.test.ts +417 -0
  424. package/utils/__tests__/versions.test.ts +128 -0
  425. package/utils/__tests__/width.test.ts +53 -0
  426. package/utils/__tests__/window.test.ts +158 -0
  427. package/utils/__tests__/xccdf.test.ts +511 -0
  428. package/utils/chart.js +36 -0
  429. package/utils/crypto/__tests__/browserHashUtils.test.ts +98 -0
  430. package/utils/crypto/__tests__/index.test.ts +144 -0
  431. package/utils/duration.ts +104 -0
  432. package/utils/dynamic-content/__tests__/notification-handler.test.ts +196 -0
  433. package/utils/dynamic-content/info.ts +2 -1
  434. package/utils/error.js +13 -0
  435. package/utils/fleet-appco.ts +323 -0
  436. package/utils/fleet.ts +13 -3
  437. package/utils/gatekeeper/__tests__/util.test.ts +174 -0
  438. package/utils/gc/__tests__/gc-interval.test.ts +119 -0
  439. package/utils/gc/__tests__/gc-root-store.test.ts +225 -0
  440. package/utils/gc/__tests__/gc-route-changed.test.ts +96 -0
  441. package/utils/gc/__tests__/gc.test.ts +487 -0
  442. package/utils/ingress.ts +9 -1
  443. package/utils/object.js +22 -2
  444. package/utils/pagination-utils.ts +2 -1
  445. package/utils/provider.ts +12 -0
  446. package/utils/string.js +25 -2
  447. package/utils/uiplugins.ts +5 -5
  448. package/utils/validators/__tests__/cluster-name.test.ts +110 -0
  449. package/utils/validators/__tests__/container-images.test.ts +104 -0
  450. package/utils/validators/__tests__/cron-schedule.test.ts +79 -0
  451. package/utils/validators/__tests__/flow-output.test.ts +91 -0
  452. package/utils/validators/__tests__/index.test.ts +481 -0
  453. package/utils/validators/__tests__/kubernetes-name.test.ts +163 -0
  454. package/utils/validators/__tests__/logging-outputs.test.ts +58 -0
  455. package/utils/validators/__tests__/misc-validators.test.ts +246 -0
  456. package/utils/validators/__tests__/monitoring-route.test.ts +119 -0
  457. package/utils/validators/__tests__/pod-affinity.test.ts +382 -0
  458. package/utils/validators/__tests__/prometheusrule.test.ts +211 -0
  459. package/utils/validators/__tests__/role-template.test.ts +149 -0
  460. package/utils/validators/__tests__/service.test.ts +283 -0
  461. package/utils/validators/__tests__/setting.test.js +32 -0
  462. package/utils/validators/formRules/__tests__/index.test.ts +50 -0
  463. package/utils/validators/formRules/index.ts +5 -5
  464. package/utils/validators/machine-pool.ts +1 -1
  465. package/utils/validators/setting.js +18 -3
  466. package/utils/xccdf.ts +415 -0
  467. package/vue.config.js +1 -1
  468. package/assets/fonts/lato/lato-v17-latin-700.woff +0 -0
  469. package/assets/fonts/lato/lato-v17-latin-700.woff2 +0 -0
  470. package/assets/fonts/lato/lato-v17-latin-regular.woff +0 -0
  471. package/assets/fonts/lato/lato-v17-latin-regular.woff2 +0 -0
  472. package/pages/support/index.vue +0 -264
  473. package/utils/duration.js +0 -43
@@ -1,8 +1,9 @@
1
1
  import { nextTick } from 'vue';
2
2
  /* eslint-disable jest/no-hooks */
3
- import { mount } from '@vue/test-utils';
3
+ import { mount, flushPromises } from '@vue/test-utils';
4
4
  import AzureAD from '@shell/edit/auth/azuread.vue';
5
5
  import { _EDIT } from '@shell/config/query-params';
6
+ import { SLO_OPTION_VALUES } from '@shell/mixins/auth-config';
6
7
 
7
8
  jest.mock('@shell/utils/clipboard', () => {
8
9
  return { copyTextToClipboard: jest.fn(() => Promise.resolve({})) };
@@ -28,46 +29,72 @@ const mockModel = {
28
29
  type: 'azureADConfig',
29
30
  };
30
31
 
31
- describe('edit: azureAD should', () => {
32
- let wrapper: any;
33
- const requiredSetup = () => ({
34
- data() {
35
- return {
36
- isEnabling: true,
37
- editConfig: false,
38
- model: { ...mockModel },
39
- serverSetting: null,
40
- errors: [],
41
- originalModel: null,
42
- principals: [],
43
- authConfigName: 'azuread',
44
- };
45
- },
46
- global: {
47
- mocks: {
48
- $fetchState: { pending: false },
49
- $store: {
50
- getters: {
51
- currentStore: () => 'current_store',
52
- 'current_store/schemaFor': jest.fn(),
53
- 'current_store/all': jest.fn(),
54
- 'i18n/t': (val: string) => val,
55
- 'i18n/exists': jest.fn(),
56
- },
57
- dispatch: jest.fn()
32
+ const requiredSetup = (modelOverrides = {}) => ({
33
+ data() {
34
+ return {
35
+ isEnabling: true,
36
+ editConfig: false,
37
+ model: { ...mockModel, ...modelOverrides },
38
+ serverSetting: null,
39
+ errors: [],
40
+ originalModel: null,
41
+ principals: [],
42
+ authConfigName: 'azuread',
43
+ };
44
+ },
45
+ global: {
46
+ mocks: {
47
+ $fetchState: { pending: false },
48
+ $store: {
49
+ getters: {
50
+ currentStore: () => 'current_store',
51
+ 'current_store/schemaFor': jest.fn(),
52
+ 'current_store/all': jest.fn(),
53
+ 'i18n/t': (val: string) => val,
54
+ 'i18n/exists': jest.fn(),
58
55
  },
59
- $route: { query: { AS: '' }, params: { id: 'azure' } },
60
- $router: { applyQuery: jest.fn() },
56
+ dispatch: jest.fn()
61
57
  },
58
+ $route: { query: { AS: '' }, params: { id: 'azure' } },
59
+ $router: { applyQuery: jest.fn() },
62
60
  },
63
- propsData: {
64
- value: { applicationSecret: '' },
65
- mode: _EDIT,
66
- },
61
+ },
62
+ propsData: {
63
+ value: { applicationSecret: '' },
64
+ mode: _EDIT,
65
+ },
66
+ });
67
+
68
+ describe('edit: azureAD accessMode default', () => {
69
+ let wrapper: any;
70
+
71
+ afterEach(() => {
72
+ wrapper.unmount();
73
+ });
74
+
75
+ it('should default accessMode to required when not set', async() => {
76
+ wrapper = mount(AzureAD, { ...requiredSetup({ accessMode: '' }) });
77
+ wrapper.setData({ model: { tenantId: 'trigger-watcher' } });
78
+ await nextTick();
79
+
80
+ expect(wrapper.vm.model.accessMode).toStrictEqual('unrestricted');
67
81
  });
68
82
 
69
- beforeEach(() => {
83
+ it('should not override accessMode when already set', async() => {
84
+ wrapper = mount(AzureAD, { ...requiredSetup({ accessMode: 'required' }) });
85
+ wrapper.setData({ model: { tenantId: 'trigger-watcher' } });
86
+ await nextTick();
87
+
88
+ expect(wrapper.vm.model.accessMode).toStrictEqual('required');
89
+ });
90
+ });
91
+
92
+ describe('edit: azureAD should', () => {
93
+ let wrapper: any;
94
+
95
+ beforeEach(async() => {
70
96
  wrapper = mount(AzureAD, { ...requiredSetup() });
97
+ await flushPromises();
71
98
  });
72
99
  afterEach(() => {
73
100
  wrapper.unmount();
@@ -119,7 +146,7 @@ describe('edit: azureAD should', () => {
119
146
  tenantIdInputField.setValue(testCase.tenantId);
120
147
  applicationIdInputField.setValue(testCase.applicationId);
121
148
  applicationSecretInputField.setValue(testCase.applicationSecret);
122
- await nextTick();
149
+ await flushPromises();
123
150
 
124
151
  expect(saveButton.disabled).toBe(testCase.result);
125
152
  });
@@ -215,11 +242,11 @@ describe('edit: azureAD should', () => {
215
242
  tenantIdInputField.setValue(validTenantId);
216
243
  applicationIdInputField.setValue(validApplicationId);
217
244
  applicationSecretInputField.setValue(validAppSecret);
218
- await nextTick();
245
+ await flushPromises();
219
246
 
220
247
  expect(saveButton.disabled).toBe(false);
221
248
  customButton.trigger('click');
222
- await nextTick();
249
+ await flushPromises();
223
250
  expect(saveButton.disabled).toBe(true);
224
251
 
225
252
  const endpointInputField = wrapper.find('[data-testid="input-azureAD-endpoint"]');
@@ -231,8 +258,189 @@ describe('edit: azureAD should', () => {
231
258
  graphEndpointInputField.setValue(testCase.graphEndpoint);
232
259
  tokenEndpointInputField.setValue(testCase.tokenEndpoint);
233
260
  authEndpointInputField.setValue(testCase.authEndpoint);
234
- await nextTick();
261
+ await flushPromises();
235
262
 
236
263
  expect(saveButton.disabled).toBe(testCase.result);
237
264
  });
238
265
  });
266
+
267
+ describe('edit: azureAD SSO logout should', () => {
268
+ let wrapper: any;
269
+
270
+ afterEach(() => {
271
+ wrapper.unmount();
272
+ });
273
+
274
+ it('not render SLO section when logoutAllSupported is false', () => {
275
+ wrapper = mount(AzureAD, { ...requiredSetup({ logoutAllSupported: false }) });
276
+ const sloSection = wrapper.find('[data-testid="azuread-sloType"]');
277
+
278
+ expect(sloSection.exists()).toBe(false);
279
+ });
280
+
281
+ it('render SLO section when logoutAllSupported is true', async() => {
282
+ wrapper = mount(AzureAD, { ...requiredSetup({ logoutAllSupported: true }) });
283
+ await nextTick();
284
+ const sloSection = wrapper.find('[data-testid="azuread-sloType"]');
285
+
286
+ expect(sloSection.exists()).toBe(true);
287
+ });
288
+
289
+ it('not render endSessionEndpoint field when sloType is rancher', async() => {
290
+ wrapper = mount(AzureAD, {
291
+ ...requiredSetup({ logoutAllSupported: true }),
292
+ data() {
293
+ return {
294
+ ...requiredSetup({ logoutAllSupported: true }).data(),
295
+ sloType: SLO_OPTION_VALUES.rancher,
296
+ };
297
+ },
298
+ });
299
+ await nextTick();
300
+ const endSessionEndpointField = wrapper.find('[data-testid="azuread-endSessionEndpoint"]');
301
+
302
+ expect(endSessionEndpointField.exists()).toBe(false);
303
+ });
304
+
305
+ it('render endSessionEndpoint field when sloType is all', async() => {
306
+ wrapper = mount(AzureAD, {
307
+ ...requiredSetup({ logoutAllSupported: true }),
308
+ data() {
309
+ return {
310
+ ...requiredSetup({ logoutAllSupported: true }).data(),
311
+ sloType: SLO_OPTION_VALUES.all,
312
+ };
313
+ },
314
+ });
315
+ await flushPromises();
316
+ const endSessionEndpointField = wrapper.find('[data-testid="azuread-endSessionEndpoint"]');
317
+
318
+ expect(endSessionEndpointField.exists()).toBe(true);
319
+ });
320
+
321
+ it('render endSessionEndpoint field when sloType is both', async() => {
322
+ wrapper = mount(AzureAD, {
323
+ ...requiredSetup({ logoutAllSupported: true }),
324
+ data() {
325
+ return {
326
+ ...requiredSetup({ logoutAllSupported: true }).data(),
327
+ sloType: SLO_OPTION_VALUES.both,
328
+ };
329
+ },
330
+ });
331
+ await flushPromises();
332
+ const endSessionEndpointField = wrapper.find('[data-testid="azuread-endSessionEndpoint"]');
333
+
334
+ expect(endSessionEndpointField.exists()).toBe(true);
335
+ });
336
+
337
+ it.each([
338
+ {
339
+ sloType: SLO_OPTION_VALUES.all, endSessionEndpoint: '', disabled: true
340
+ },
341
+ {
342
+ sloType: SLO_OPTION_VALUES.all, endSessionEndpoint: 'not-a-url', disabled: true
343
+ },
344
+ {
345
+ sloType: SLO_OPTION_VALUES.all, endSessionEndpoint: 'https://login.microsoftonline.com/tenant/oauth2/v2.0/logout', disabled: false
346
+ },
347
+ {
348
+ sloType: SLO_OPTION_VALUES.both, endSessionEndpoint: '', disabled: true
349
+ },
350
+ {
351
+ sloType: SLO_OPTION_VALUES.both, endSessionEndpoint: 'https://login.microsoftonline.com/tenant/oauth2/v2.0/logout', disabled: false
352
+ },
353
+ ])('has save button disabled=$disabled when sloType=$sloType and endSessionEndpoint=$endSessionEndpoint', async(testCase) => {
354
+ wrapper = mount(AzureAD, {
355
+ ...requiredSetup({
356
+ logoutAllSupported: true,
357
+ tenantId: validTenantId,
358
+ applicationId: validApplicationId,
359
+ applicationSecret: validAppSecret,
360
+ endSessionEndpoint: testCase.endSessionEndpoint,
361
+ }),
362
+ data() {
363
+ return {
364
+ isEnabling: true,
365
+ editConfig: false,
366
+ model: {
367
+ ...mockModel,
368
+ logoutAllSupported: true,
369
+ tenantId: validTenantId,
370
+ applicationId: validApplicationId,
371
+ applicationSecret: validAppSecret,
372
+ graphEndpoint: validGraphEndpoint,
373
+ tokenEndpoint: validTokenEndpoint,
374
+ authEndpoint: validAuthEndpoint,
375
+ endSessionEndpoint: testCase.endSessionEndpoint,
376
+ },
377
+ sloType: testCase.sloType,
378
+ serverSetting: null,
379
+ errors: [],
380
+ originalModel: null,
381
+ principals: [],
382
+ authConfigName: 'azuread',
383
+ };
384
+ },
385
+ });
386
+ await flushPromises();
387
+ const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
388
+
389
+ expect(saveButton.disabled).toBe(testCase.disabled);
390
+ });
391
+
392
+ it('sets logoutAllEnabled=false and logoutAllForced=false when sloType changes to rancher', async() => {
393
+ wrapper = mount(AzureAD, {
394
+ ...requiredSetup({ logoutAllSupported: true }),
395
+ data() {
396
+ return {
397
+ ...requiredSetup({ logoutAllSupported: true }).data(),
398
+ sloType: SLO_OPTION_VALUES.all,
399
+ };
400
+ },
401
+ });
402
+ await nextTick();
403
+ wrapper.vm.sloType = SLO_OPTION_VALUES.rancher;
404
+ await nextTick();
405
+
406
+ expect(wrapper.vm.model.logoutAllEnabled).toBe(false);
407
+ expect(wrapper.vm.model.logoutAllForced).toBe(false);
408
+ expect(wrapper.vm.model.endSessionEndpoint).toBe('');
409
+ });
410
+
411
+ it('sets logoutAllEnabled=true and logoutAllForced=true when sloType changes to all', async() => {
412
+ wrapper = mount(AzureAD, {
413
+ ...requiredSetup({ logoutAllSupported: true }),
414
+ data() {
415
+ return {
416
+ ...requiredSetup({ logoutAllSupported: true }).data(),
417
+ sloType: SLO_OPTION_VALUES.rancher,
418
+ };
419
+ },
420
+ });
421
+ await nextTick();
422
+ wrapper.vm.sloType = SLO_OPTION_VALUES.all;
423
+ await nextTick();
424
+
425
+ expect(wrapper.vm.model.logoutAllEnabled).toBe(true);
426
+ expect(wrapper.vm.model.logoutAllForced).toBe(true);
427
+ });
428
+
429
+ it('sets logoutAllEnabled=true and logoutAllForced=false when sloType changes to both', async() => {
430
+ wrapper = mount(AzureAD, {
431
+ ...requiredSetup({ logoutAllSupported: true }),
432
+ data() {
433
+ return {
434
+ ...requiredSetup({ logoutAllSupported: true }).data(),
435
+ sloType: SLO_OPTION_VALUES.rancher,
436
+ };
437
+ },
438
+ });
439
+ await nextTick();
440
+ wrapper.vm.sloType = SLO_OPTION_VALUES.both;
441
+ await nextTick();
442
+
443
+ expect(wrapper.vm.model.logoutAllEnabled).toBe(true);
444
+ expect(wrapper.vm.model.logoutAllForced).toBe(false);
445
+ });
446
+ });
@@ -0,0 +1,234 @@
1
+ import { nextTick } from 'vue';
2
+ import { mount, type VueWrapper, flushPromises } from '@vue/test-utils';
3
+ import { _EDIT } from '@shell/config/query-params';
4
+
5
+ import GitHub from '@shell/edit/auth/github.vue';
6
+
7
+ jest.mock('@shell/utils/clipboard', () => {
8
+ return { copyTextToClipboard: jest.fn(() => Promise.resolve({})) };
9
+ });
10
+
11
+ const validClientId = 'github-client-id';
12
+ const validClientSecret = 'github-client-secret';
13
+ const validAppId = '12345';
14
+ const validPrivateKey = '-----BEGIN RSA PRIVATE KEY-----\ntest\n-----END RSA PRIVATE KEY-----';
15
+ const validTargetUrl = 'https://github.mycompany.com';
16
+
17
+ const mockGitHubModel = {
18
+ enabled: false,
19
+ id: 'github',
20
+ clientId: validClientId,
21
+ clientSecret: validClientSecret,
22
+ hostname: 'github.com',
23
+ tls: true,
24
+ };
25
+
26
+ const mockGitHubAppModel = {
27
+ ...mockGitHubModel,
28
+ id: 'githubapp',
29
+ appId: validAppId,
30
+ privateKey: validPrivateKey,
31
+ };
32
+
33
+ const requiredSetup = (modelOverrides = {}, dataOverrides = {}) => ({
34
+ data() {
35
+ return {
36
+ isEnabling: false,
37
+ editConfig: false,
38
+ model: { ...mockGitHubModel, ...modelOverrides },
39
+ serverSetting: null,
40
+ errors: [],
41
+ originalModel: null,
42
+ principals: [],
43
+ authConfigName: 'github',
44
+ targetType: 'public',
45
+ targetUrl: '',
46
+ ...dataOverrides,
47
+ } as any;
48
+ },
49
+ global: {
50
+ mocks: {
51
+ $fetchState: { pending: false },
52
+ $store: {
53
+ getters: {
54
+ currentStore: () => 'current_store',
55
+ 'current_store/schemaFor': jest.fn(),
56
+ 'current_store/all': jest.fn(),
57
+ 'i18n/t': (val: string) => val,
58
+ 'i18n/exists': jest.fn(),
59
+ },
60
+ dispatch: jest.fn(),
61
+ },
62
+ $route: { query: { AS: '' }, params: { id: 'github' } },
63
+ $router: { applyQuery: jest.fn() },
64
+ },
65
+ },
66
+ props: {
67
+ value: {},
68
+ mode: _EDIT,
69
+ },
70
+ });
71
+
72
+ describe('github.vue', () => {
73
+ describe('GitHub provider', () => {
74
+ let wrapper: VueWrapper<any, any>;
75
+
76
+ beforeEach(() => {
77
+ wrapper = mount(GitHub, { ...requiredSetup() });
78
+ });
79
+
80
+ afterEach(() => {
81
+ wrapper.unmount();
82
+ });
83
+
84
+ describe('save button disabled', () => {
85
+ it('when clientId is empty', async() => {
86
+ wrapper.setData({ model: { clientId: '' } });
87
+ await wrapper.vm.validateAllFields();
88
+ await flushPromises();
89
+
90
+ const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
91
+
92
+ expect(saveButton.disabled).toBe(true);
93
+ });
94
+
95
+ it('when clientSecret is empty', async() => {
96
+ wrapper.setData({ model: { clientSecret: '' } });
97
+ await wrapper.vm.validateAllFields();
98
+ await flushPromises();
99
+
100
+ const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
101
+
102
+ expect(saveButton.disabled).toBe(true);
103
+ });
104
+
105
+ it('when both clientId and clientSecret are empty', async() => {
106
+ wrapper.setData({ model: { clientId: '' } });
107
+ wrapper.setData({ model: { clientSecret: '' } });
108
+ await wrapper.vm.validateAllFields();
109
+ await flushPromises();
110
+
111
+ const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
112
+
113
+ expect(saveButton.disabled).toBe(true);
114
+ });
115
+ });
116
+
117
+ describe('save button enabled', () => {
118
+ it('when clientId and clientSecret are filled', async() => {
119
+ await nextTick();
120
+
121
+ const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
122
+
123
+ expect(saveButton.disabled).toBe(false);
124
+ });
125
+
126
+ it('when provider is already enabled and not editing config', async() => {
127
+ wrapper.setData({ model: { ...mockGitHubModel, enabled: true }, editConfig: false });
128
+ await nextTick();
129
+
130
+ const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
131
+
132
+ expect(saveButton.disabled).toBe(false);
133
+ });
134
+ });
135
+ });
136
+
137
+ describe('GitHub App provider', () => {
138
+ let wrapper: VueWrapper<any, any>;
139
+
140
+ beforeEach(() => {
141
+ wrapper = mount(GitHub, { ...requiredSetup(mockGitHubAppModel) });
142
+ });
143
+
144
+ afterEach(() => {
145
+ wrapper.unmount();
146
+ });
147
+
148
+ describe('save button disabled', () => {
149
+ it('when appId is empty', async() => {
150
+ wrapper.setData({ model: { appId: '' } });
151
+ await wrapper.vm.validateAllFields();
152
+ await flushPromises();
153
+
154
+ const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
155
+
156
+ expect(saveButton.disabled).toBe(true);
157
+ });
158
+
159
+ it('when privateKey is empty', async() => {
160
+ wrapper.vm.model.privateKey = '';
161
+ wrapper.setData({ model: { privateKey: '' } });
162
+ await wrapper.vm.validateAllFields();
163
+ await flushPromises();
164
+
165
+ const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
166
+
167
+ expect(saveButton.disabled).toBe(true);
168
+ });
169
+ });
170
+
171
+ describe('save button enabled', () => {
172
+ it('when all required fields are filled', async() => {
173
+ await nextTick();
174
+
175
+ const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
176
+
177
+ expect(saveButton.disabled).toBe(false);
178
+ });
179
+ });
180
+ });
181
+
182
+ describe('GitHub App fields not required for GitHub provider', () => {
183
+ let wrapper: VueWrapper<any, any>;
184
+
185
+ beforeEach(() => {
186
+ wrapper = mount(GitHub, { ...requiredSetup() });
187
+ });
188
+
189
+ afterEach(() => {
190
+ wrapper.unmount();
191
+ });
192
+
193
+ it('save button is enabled even when appId and privateKey are absent', async() => {
194
+ await nextTick();
195
+
196
+ const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
197
+
198
+ expect(saveButton.disabled).toBe(false);
199
+ });
200
+ });
201
+
202
+ describe('private GitHub Enterprise target', () => {
203
+ let wrapper: VueWrapper<any, any>;
204
+
205
+ beforeEach(() => {
206
+ wrapper = mount(
207
+ GitHub,
208
+ { ...requiredSetup({}, { targetType: 'private', targetUrl: validTargetUrl }) }
209
+ );
210
+ });
211
+
212
+ afterEach(() => {
213
+ wrapper.unmount();
214
+ });
215
+
216
+ it('save button is disabled when targetUrl is empty', async() => {
217
+ wrapper.setData({ targetType: 'private', targetUrl: '' });
218
+ await wrapper.vm.validateAllFields();
219
+ await flushPromises();
220
+
221
+ const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
222
+
223
+ expect(saveButton.disabled).toBe(true);
224
+ });
225
+
226
+ it('save button is enabled when targetUrl is filled', async() => {
227
+ await nextTick();
228
+
229
+ const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
230
+
231
+ expect(saveButton.disabled).toBe(false);
232
+ });
233
+ });
234
+ });
@@ -1,6 +1,6 @@
1
1
  import { nextTick } from 'vue';
2
2
  /* eslint-disable jest/no-hooks */
3
- import { mount, type VueWrapper } from '@vue/test-utils';
3
+ import { mount, type VueWrapper, flushPromises } from '@vue/test-utils';
4
4
  import { _EDIT } from '@shell/config/query-params';
5
5
 
6
6
  import oidc from '@shell/edit/auth/oidc.vue';
@@ -9,6 +9,18 @@ jest.mock('@shell/utils/clipboard', () => {
9
9
  return { copyTextToClipboard: jest.fn(() => Promise.resolve({})) };
10
10
  });
11
11
 
12
+ const mockStore = {
13
+ getters: {
14
+ 'i18n/t': (key: string) => key,
15
+ 'i18n/exists': () => false,
16
+ },
17
+ };
18
+
19
+ jest.mock('vuex', () => ({
20
+ ...jest.requireActual('vuex'),
21
+ useStore: () => mockStore,
22
+ }));
23
+
12
24
  const validClientId = 'rancheroidc';
13
25
  const validClientSecret = 'TOkUxg0P67m1UXWNkJLHDPkUZFIKOWSq';
14
26
  const validUrl = 'https://localhost:8080';
@@ -79,20 +91,26 @@ describe('oidc.vue', () => {
79
91
  });
80
92
 
81
93
  describe('have "Create" button disabled', () => {
82
- it('given missing Auth endpoint URL', () => {
94
+ // validateAllFields() replicates what happens on blur in a real browser: it runs
95
+ // the toTypedSchema validators for every registered field and flushes async errors.
96
+ it('given missing Auth endpoint URL', async() => {
83
97
  wrapper.vm.model.authEndpoint = '';
84
98
  wrapper.vm.model.scopes = 'openid profile email'; // set scope to be sure
85
99
  wrapper.vm.oidcScope = ['openid', 'profile', 'email']; // TODO #13457: this is duplicated due wrong format of scopes
100
+ await wrapper.vm.validateAllFields();
101
+ await flushPromises();
86
102
 
87
103
  const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
88
104
 
89
105
  expect(saveButton.disabled).toBe(true);
90
106
  });
91
107
 
92
- it('given missing required basic scopes', () => {
93
- wrapper.vm.model.authEndpoint = 'whatever'; // set auth endpoint to be sure
108
+ it('given missing required basic scopes', async() => {
109
+ wrapper.vm.model.authEndpoint = validAuthEndpoint; // set auth endpoint to be sure
94
110
  wrapper.vm.model.scopes = 'something else'; // set wrong scope
95
111
  wrapper.vm.oidcScope = ['something', 'else']; // TODO #13457: this is duplicated due wrong format of scopes
112
+ await wrapper.vm.validateAllFields();
113
+ await flushPromises();
96
114
 
97
115
  const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
98
116
 
@@ -101,7 +119,8 @@ describe('oidc.vue', () => {
101
119
 
102
120
  it('when provider is disabled and editing config before fields are filled in', async() => {
103
121
  wrapper.setData({ model: {}, editConfig: true });
104
- await nextTick();
122
+ await wrapper.vm.validateAllFields();
123
+ await flushPromises();
105
124
 
106
125
  const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
107
126
 
@@ -110,7 +129,8 @@ describe('oidc.vue', () => {
110
129
 
111
130
  it('when provider is disabled and editing config after required fields and scope is missing openid', async() => {
112
131
  wrapper.setData({ oidcUrls: { url: validUrl, realm: validRealm } });
113
- await nextTick();
132
+ await wrapper.vm.validateAllFields();
133
+ await flushPromises();
114
134
 
115
135
  const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
116
136