1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Fix cluster frame display issue (#5518)

* Fix cluster frame display issue

- Add some defensive code to prevent this sort of infinite loop

- Add some unit tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix unit tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix build

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix lint

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Factor out injectable for getting of cluster config data

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-06-20 22:23:15 -04:00 committed by GitHub
parent 8c31e56462
commit de43df1cca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 2126 additions and 815 deletions

View File

@ -24,10 +24,8 @@ exports[`cluster - order of sidebar items when rendered renders 1`] = `
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -60,10 +58,8 @@ exports[`cluster - order of sidebar items when rendered renders 1`] = `
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -89,10 +85,8 @@ exports[`cluster - order of sidebar items when rendered renders 1`] = `
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-parent-id" data-testid="sidebar-item-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -118,10 +112,8 @@ exports[`cluster - order of sidebar items when rendered renders 1`] = `
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -157,10 +149,8 @@ exports[`cluster - order of sidebar items when rendered renders 1`] = `
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -186,10 +176,8 @@ exports[`cluster - order of sidebar items when rendered renders 1`] = `
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-another-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-another-parent-id" data-testid="sidebar-item-some-another-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -205,10 +193,8 @@ exports[`cluster - order of sidebar items when rendered renders 1`] = `
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -241,10 +227,8 @@ exports[`cluster - order of sidebar items when rendered renders 1`] = `
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -270,10 +254,8 @@ exports[`cluster - order of sidebar items when rendered renders 1`] = `
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -309,10 +291,8 @@ exports[`cluster - order of sidebar items when rendered renders 1`] = `
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-other-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-other-parent-id" data-testid="sidebar-item-some-other-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -358,10 +338,8 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -394,10 +372,8 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -423,10 +399,8 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-parent-id" data-testid="sidebar-item-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -454,11 +428,9 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-child-id"
data-is-active-test="false" data-is-active-test="false"
data-parent-id-test="some-parent-id" data-parent-id-test="some-parent-id"
data-test-id="some-child-id" data-testid="sidebar-item-some-child-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -474,11 +446,9 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-another-child-id"
data-is-active-test="false" data-is-active-test="false"
data-parent-id-test="some-parent-id" data-parent-id-test="some-parent-id"
data-test-id="some-another-child-id" data-testid="sidebar-item-some-another-child-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -494,11 +464,9 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-other-child-id"
data-is-active-test="false" data-is-active-test="false"
data-parent-id-test="some-parent-id" data-parent-id-test="some-parent-id"
data-test-id="some-other-child-id" data-testid="sidebar-item-some-other-child-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -516,10 +484,8 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -555,10 +521,8 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -584,10 +548,8 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-another-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-another-parent-id" data-testid="sidebar-item-some-another-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -603,10 +565,8 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -639,10 +599,8 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -668,10 +626,8 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -707,10 +663,8 @@ exports[`cluster - order of sidebar items when rendered when parent is expanded
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-other-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-other-parent-id" data-testid="sidebar-item-some-other-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"

View File

@ -24,10 +24,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -60,10 +58,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -89,10 +85,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-parent-id" data-testid="sidebar-item-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -121,10 +115,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -160,10 +152,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -189,10 +179,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -225,10 +213,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -254,10 +240,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -323,10 +307,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -359,10 +341,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -388,10 +368,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-parent-id" data-testid="sidebar-item-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -420,10 +398,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -459,10 +435,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -488,10 +462,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -524,10 +496,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -553,10 +523,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -622,10 +590,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -658,10 +624,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -687,10 +651,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-parent-id" data-testid="sidebar-item-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -721,11 +683,9 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-child-id"
data-is-active-test="false" data-is-active-test="false"
data-parent-id-test="some-parent-id" data-parent-id-test="some-parent-id"
data-test-id="some-child-id" data-testid="sidebar-item-some-child-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -743,10 +703,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -782,10 +740,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -811,10 +767,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -847,10 +801,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -876,10 +828,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -945,10 +895,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -981,10 +929,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1010,10 +956,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-parent-id"
data-is-active-test="true" data-is-active-test="true"
data-test-id="some-parent-id" data-testid="sidebar-item-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
aria-current="page" aria-current="page"
@ -1045,11 +989,9 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-child-id"
data-is-active-test="true" data-is-active-test="true"
data-parent-id-test="some-parent-id" data-parent-id-test="some-parent-id"
data-test-id="some-child-id" data-testid="sidebar-item-some-child-id"
data-testid="sidebar-item"
> >
<a <a
aria-current="page" aria-current="page"
@ -1068,10 +1010,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1107,10 +1047,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1136,10 +1074,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1172,10 +1108,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1201,10 +1135,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1273,10 +1205,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1309,10 +1239,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1338,10 +1266,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-parent-id"
data-is-active-test="true" data-is-active-test="true"
data-test-id="some-parent-id" data-testid="sidebar-item-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
aria-current="page" aria-current="page"
@ -1371,10 +1297,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1410,10 +1334,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1439,10 +1361,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1475,10 +1395,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1504,10 +1422,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1576,10 +1492,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1612,10 +1526,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1641,10 +1553,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-parent-id" data-testid="sidebar-item-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1675,11 +1585,9 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-child-id"
data-is-active-test="false" data-is-active-test="false"
data-parent-id-test="some-parent-id" data-parent-id-test="some-parent-id"
data-test-id="some-child-id" data-testid="sidebar-item-some-child-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1697,10 +1605,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1736,10 +1642,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1765,10 +1669,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1801,10 +1703,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1830,10 +1730,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1899,10 +1797,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1935,10 +1831,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1964,10 +1858,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-parent-id" data-testid="sidebar-item-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1996,10 +1888,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -2035,10 +1925,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -2064,10 +1952,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -2100,10 +1986,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -2129,10 +2013,8 @@ exports[`cluster - sidebar and tab navigation for core given core registrations
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"

View File

@ -24,10 +24,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -60,10 +58,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -89,10 +85,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -128,10 +122,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -157,10 +149,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -193,10 +183,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -222,10 +210,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -261,10 +247,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-extension-name-some-parent-id" data-testid="sidebar-item-some-extension-name-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -323,10 +307,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -359,10 +341,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -388,10 +368,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -427,10 +405,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -456,10 +432,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -492,10 +466,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -521,10 +493,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -560,10 +530,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-extension-name-some-parent-id" data-testid="sidebar-item-some-extension-name-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -622,10 +590,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -658,10 +624,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -687,10 +651,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -726,10 +688,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -755,10 +715,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -791,10 +749,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -820,10 +776,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -859,10 +813,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-extension-name-some-parent-id" data-testid="sidebar-item-some-extension-name-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -893,11 +845,9 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-child-id"
data-is-active-test="false" data-is-active-test="false"
data-parent-id-test="some-extension-name-some-parent-id" data-parent-id-test="some-extension-name-some-parent-id"
data-test-id="some-extension-name-some-child-id" data-testid="sidebar-item-some-extension-name-some-child-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -913,11 +863,9 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-other-child-id"
data-is-active-test="false" data-is-active-test="false"
data-parent-id-test="some-extension-name-some-parent-id" data-parent-id-test="some-extension-name-some-parent-id"
data-test-id="some-extension-name-some-other-child-id" data-testid="sidebar-item-some-extension-name-some-other-child-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -965,10 +913,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1001,10 +947,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1030,10 +974,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1069,10 +1011,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1098,10 +1038,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1134,10 +1072,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1163,10 +1099,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1202,10 +1136,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-parent-id"
data-is-active-test="true" data-is-active-test="true"
data-test-id="some-extension-name-some-parent-id" data-testid="sidebar-item-some-extension-name-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
aria-current="page" aria-current="page"
@ -1237,11 +1169,9 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-child-id"
data-is-active-test="true" data-is-active-test="true"
data-parent-id-test="some-extension-name-some-parent-id" data-parent-id-test="some-extension-name-some-parent-id"
data-test-id="some-extension-name-some-child-id" data-testid="sidebar-item-some-extension-name-some-child-id"
data-testid="sidebar-item"
> >
<a <a
aria-current="page" aria-current="page"
@ -1258,11 +1188,9 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-other-child-id"
data-is-active-test="false" data-is-active-test="false"
data-parent-id-test="some-extension-name-some-parent-id" data-parent-id-test="some-extension-name-some-parent-id"
data-test-id="some-extension-name-some-other-child-id" data-testid="sidebar-item-some-extension-name-some-other-child-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1352,10 +1280,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1388,10 +1314,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1417,10 +1341,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1456,10 +1378,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1485,10 +1405,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1521,10 +1439,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1550,10 +1466,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1589,10 +1503,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-parent-id"
data-is-active-test="true" data-is-active-test="true"
data-test-id="some-extension-name-some-parent-id" data-testid="sidebar-item-some-extension-name-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
aria-current="page" aria-current="page"
@ -1624,11 +1536,9 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-child-id"
data-is-active-test="false" data-is-active-test="false"
data-parent-id-test="some-extension-name-some-parent-id" data-parent-id-test="some-extension-name-some-parent-id"
data-test-id="some-extension-name-some-child-id" data-testid="sidebar-item-some-extension-name-some-child-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1644,11 +1554,9 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-other-child-id"
data-is-active-test="true" data-is-active-test="true"
data-parent-id-test="some-extension-name-some-parent-id" data-parent-id-test="some-extension-name-some-parent-id"
data-test-id="some-extension-name-some-other-child-id" data-testid="sidebar-item-some-extension-name-some-other-child-id"
data-testid="sidebar-item"
> >
<a <a
aria-current="page" aria-current="page"
@ -1739,10 +1647,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1775,10 +1681,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1804,10 +1708,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1843,10 +1745,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1872,10 +1772,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1908,10 +1806,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -1937,10 +1833,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -1976,10 +1870,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-parent-id"
data-is-active-test="true" data-is-active-test="true"
data-test-id="some-extension-name-some-parent-id" data-testid="sidebar-item-some-extension-name-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
aria-current="page" aria-current="page"
@ -2081,10 +1973,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -2117,10 +2007,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -2146,10 +2034,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -2185,10 +2071,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -2214,10 +2098,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -2250,10 +2132,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -2279,10 +2159,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -2318,10 +2196,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-extension-name-some-parent-id" data-testid="sidebar-item-some-extension-name-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -2352,11 +2228,9 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-child-id"
data-is-active-test="false" data-is-active-test="false"
data-parent-id-test="some-extension-name-some-parent-id" data-parent-id-test="some-extension-name-some-parent-id"
data-test-id="some-extension-name-some-child-id" data-testid="sidebar-item-some-extension-name-some-child-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -2372,11 +2246,9 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-other-child-id"
data-is-active-test="false" data-is-active-test="false"
data-parent-id-test="some-extension-name-some-parent-id" data-parent-id-test="some-extension-name-some-parent-id"
data-test-id="some-extension-name-some-other-child-id" data-testid="sidebar-item-some-extension-name-some-other-child-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -2424,10 +2296,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -2460,10 +2330,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -2489,10 +2357,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -2528,10 +2394,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -2557,10 +2421,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -2593,10 +2455,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -2622,10 +2482,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -2661,10 +2519,8 @@ exports[`cluster - sidebar and tab navigation for extensions given extension wit
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-extension-name-some-parent-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-extension-name-some-parent-id" data-testid="sidebar-item-some-extension-name-some-parent-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"

View File

@ -24,10 +24,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -60,10 +58,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -89,10 +85,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -128,10 +122,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -157,10 +149,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -193,10 +183,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -222,10 +210,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -291,10 +277,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -327,10 +311,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -356,10 +338,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="some-item-id"
data-is-active-test="false" data-is-active-test="false"
data-test-id="some-item-id" data-testid="sidebar-item-some-item-id"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -375,10 +355,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -414,10 +392,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -443,10 +419,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="namespaces"
data-is-active-test="false" data-is-active-test="false"
data-test-id="namespaces" data-testid="sidebar-item-namespaces"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -472,10 +446,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="false" data-is-active-test="false"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -508,10 +480,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -537,10 +507,8 @@ exports[`cluster - visibility of sidebar items given kube resource for route is
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"

View File

@ -8,7 +8,7 @@ import { fireEvent } from "@testing-library/react";
import type { SidebarItemRegistration } from "../../renderer/components/layout/sidebar-items.injectable"; import type { SidebarItemRegistration } from "../../renderer/components/layout/sidebar-items.injectable";
import { sidebarItemsInjectionToken } from "../../renderer/components/layout/sidebar-items.injectable"; import { sidebarItemsInjectionToken } from "../../renderer/components/layout/sidebar-items.injectable";
import { computed } from "mobx"; import { computed } from "mobx";
import { get, includes, noop } from "lodash/fp"; import { noop } from "lodash/fp";
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
@ -35,22 +35,13 @@ describe("cluster - order of sidebar items", () => {
it("has parent items in order", () => { it("has parent items in order", () => {
const actual = rendered const actual = rendered
.queryAllByTestId("sidebar-item") .queryAllByTestId(/^sidebar-item-(some-parent-id|some-other-parent-id|some-another-parent-id)/)
.map(elem => elem.dataset.testid);
.filter((element) =>
includes(element.dataset.idTest)([
"some-parent-id",
"some-other-parent-id",
"some-another-parent-id",
]),
)
.map(get("dataset.idTest"));
expect(actual).toEqual([ expect(actual).toEqual([
"some-parent-id", "sidebar-item-some-parent-id",
"some-another-parent-id", "sidebar-item-some-another-parent-id",
"some-other-parent-id", "sidebar-item-some-other-parent-id",
]); ]);
}); });
@ -69,16 +60,14 @@ describe("cluster - order of sidebar items", () => {
it("has child items in order", () => { it("has child items in order", () => {
const actual = rendered const actual = rendered
.queryAllByTestId("sidebar-item") .queryAllByTestId(/^sidebar-item-*/)
.filter( .filter((element) => element.dataset.parentIdTest === "some-parent-id")
(element) => element.dataset.parentIdTest === "some-parent-id", .map(elem => elem.dataset.testid);
)
.map(get("dataset.idTest"));
expect(actual).toEqual([ expect(actual).toEqual([
"some-child-id", "sidebar-item-some-child-id",
"some-another-child-id", "sidebar-item-some-another-child-id",
"some-other-child-id", "sidebar-item-some-other-child-id",
]); ]);
}); });
}); });

View File

@ -21,7 +21,6 @@ import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable"
import pathExistsInjectable from "../../common/fs/path-exists.injectable"; import pathExistsInjectable from "../../common/fs/path-exists.injectable";
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable"; import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token";
import { getSidebarItem } from "../utils";
import sidebarStorageInjectable from "../../renderer/components/layout/sidebar-storage/sidebar-storage.injectable"; import sidebarStorageInjectable from "../../renderer/components/layout/sidebar-storage/sidebar-storage.injectable";
describe("cluster - sidebar and tab navigation for core", () => { describe("cluster - sidebar and tab navigation for core", () => {
@ -72,15 +71,15 @@ describe("cluster - sidebar and tab navigation for core", () => {
}); });
it("parent is highlighted", () => { it("parent is highlighted", () => {
const parent = getSidebarItem(rendered, "some-parent-id"); const parent = rendered.queryByTestId("sidebar-item-some-parent-id");
expect(parent?.dataset.isActiveTest).toBe("true"); expect(parent?.dataset.isActiveTest).toBe("true");
}); });
it("parent sidebar item is not expanded", () => { it("parent sidebar item is not expanded", () => {
const child = getSidebarItem(rendered, "some-child-id"); const child = rendered.queryByTestId("sidebar-item-some-child-id");
expect(child).toBeUndefined(); expect(child).toBeNull();
}); });
it("child page is shown", () => { it("child page is shown", () => {
@ -118,15 +117,15 @@ describe("cluster - sidebar and tab navigation for core", () => {
}); });
it("parent sidebar item is not highlighted", () => { it("parent sidebar item is not highlighted", () => {
const parent = getSidebarItem(rendered, "some-parent-id"); const parent = rendered.queryByTestId("sidebar-item-some-parent-id");
expect(parent?.dataset.isActiveTest).toBe("false"); expect(parent?.dataset.isActiveTest).toBe("false");
}); });
it("parent sidebar item is expanded", () => { it("parent sidebar item is expanded", () => {
const child = getSidebarItem(rendered, "some-child-id"); const child = rendered.queryByTestId("sidebar-item-some-child-id");
expect(child).not.toBeUndefined(); expect(child).not.toBeNull();
}); });
}); });
@ -154,9 +153,9 @@ describe("cluster - sidebar and tab navigation for core", () => {
}); });
it("parent sidebar item is not expanded", () => { it("parent sidebar item is not expanded", () => {
const child = getSidebarItem(rendered, "some-child-id"); const child = rendered.queryByTestId("sidebar-item-some-child-id");
expect(child).toBeUndefined(); expect(child).toBeNull();
}); });
}); });
@ -181,9 +180,9 @@ describe("cluster - sidebar and tab navigation for core", () => {
}); });
it("parent sidebar item is not expanded", () => { it("parent sidebar item is not expanded", () => {
const child = getSidebarItem(rendered, "some-child-id"); const child = rendered.queryByTestId("sidebar-item-some-child-id");
expect(child).toBeUndefined(); expect(child).toBeNull();
}); });
}); });
@ -197,15 +196,15 @@ describe("cluster - sidebar and tab navigation for core", () => {
}); });
it("parent sidebar item is not highlighted", () => { it("parent sidebar item is not highlighted", () => {
const parent = getSidebarItem(rendered, "some-parent-id"); const parent = rendered.queryByTestId("sidebar-item-some-parent-id");
expect(parent?.dataset.isActiveTest).toBe("false"); expect(parent?.dataset.isActiveTest).toBe("false");
}); });
it("parent sidebar item is not expanded", () => { it("parent sidebar item is not expanded", () => {
const child = getSidebarItem(rendered, "some-child-id"); const child = rendered.queryByTestId("sidebar-item-some-child-id");
expect(child).toBeUndefined(); expect(child).toBeNull();
}); });
describe("when a parent sidebar item is expanded", () => { describe("when a parent sidebar item is expanded", () => {
@ -222,15 +221,15 @@ describe("cluster - sidebar and tab navigation for core", () => {
}); });
it("parent sidebar item is not highlighted", () => { it("parent sidebar item is not highlighted", () => {
const parent = getSidebarItem(rendered, "some-parent-id"); const parent = rendered.queryByTestId("sidebar-item-some-parent-id");
expect(parent?.dataset.isActiveTest).toBe("false"); expect(parent?.dataset.isActiveTest).toBe("false");
}); });
it("parent sidebar item is expanded", () => { it("parent sidebar item is expanded", () => {
const child = getSidebarItem(rendered, "some-child-id"); const child = rendered.queryByTestId("sidebar-item-some-child-id");
expect(child).not.toBeUndefined(); expect(child).not.toBeNull();
}); });
describe("when a child of the parent is selected", () => { describe("when a child of the parent is selected", () => {
@ -247,13 +246,13 @@ describe("cluster - sidebar and tab navigation for core", () => {
}); });
it("parent is highlighted", () => { it("parent is highlighted", () => {
const parent = getSidebarItem(rendered, "some-parent-id"); const parent = rendered.queryByTestId("sidebar-item-some-parent-id");
expect(parent?.dataset.isActiveTest).toBe("true"); expect(parent?.dataset.isActiveTest).toBe("true");
}); });
it("child is highlighted", () => { it("child is highlighted", () => {
const child = getSidebarItem(rendered, "some-child-id"); const child = rendered.queryByTestId("sidebar-item-some-child-id");
expect(child?.dataset.isActiveTest).toBe("true"); expect(child?.dataset.isActiveTest).toBe("true");
}); });

View File

@ -16,7 +16,6 @@ import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token";
import assert from "assert"; import assert from "assert";
import { getSidebarItem } from "../utils";
import type { FakeExtensionData } from "../../renderer/components/test-utils/get-renderer-extension-fake"; import type { FakeExtensionData } from "../../renderer/components/test-utils/get-renderer-extension-fake";
import { getRendererExtensionFakeFor } from "../../renderer/components/test-utils/get-renderer-extension-fake"; import { getRendererExtensionFakeFor } from "../../renderer/components/test-utils/get-renderer-extension-fake";
@ -74,21 +73,15 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
}); });
it("parent is highlighted", () => { it("parent is highlighted", () => {
const parent = getSidebarItem( const parent = rendered.getByTestId("sidebar-item-some-extension-name-some-parent-id");
rendered,
"some-extension-name-some-parent-id",
);
expect(parent?.dataset.isActiveTest).toBe("true"); expect(parent?.dataset.isActiveTest).toBe("true");
}); });
it("parent sidebar item is not expanded", () => { it("parent sidebar item is not expanded", () => {
const child = getSidebarItem( const child = rendered.queryByTestId("sidebar-item-some-extension-name-some-child-id");
rendered,
"some-extension-name-some-child-id",
);
expect(child).toBeUndefined(); expect(child).toBeNull();
}); });
it("child page is shown", () => { it("child page is shown", () => {
@ -120,21 +113,15 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
}); });
it("parent sidebar item is not highlighted", () => { it("parent sidebar item is not highlighted", () => {
const parent = getSidebarItem( const parent = rendered.getByTestId("sidebar-item-some-extension-name-some-parent-id");
rendered,
"some-extension-name-some-parent-id",
);
expect(parent?.dataset.isActiveTest).toBe("false"); expect(parent?.dataset.isActiveTest).toBe("false");
}); });
it("parent sidebar item is expanded", () => { it("parent sidebar item is expanded", () => {
const child = getSidebarItem( const child = rendered.queryByTestId("sidebar-item-some-extension-name-some-child-id");
rendered,
"some-extension-name-some-child-id",
);
expect(child).not.toBeUndefined(); expect(child).not.toBeNull();
}); });
}); });
@ -162,12 +149,9 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
}); });
it("parent sidebar item is not expanded", () => { it("parent sidebar item is not expanded", () => {
const child = getSidebarItem( const child = rendered.queryByTestId("sidebar-item-some-extension-name-some-child-id");
rendered,
"some-extension-name-some-child-id",
);
expect(child).toBeUndefined(); expect(child).toBeNull();
}); });
}); });
@ -192,12 +176,9 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
}); });
it("parent sidebar item is not expanded", () => { it("parent sidebar item is not expanded", () => {
const child = getSidebarItem( const child = rendered.queryByTestId("sidebar-item-some-extension-name-some-child-id");
rendered,
"some-extension-name-some-child-id",
);
expect(child).toBeUndefined(); expect(child).toBeNull();
}); });
}); });
@ -211,21 +192,15 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
}); });
it("parent sidebar item is not highlighted", () => { it("parent sidebar item is not highlighted", () => {
const parent = getSidebarItem( const parent = rendered.getByTestId("sidebar-item-some-extension-name-some-parent-id");
rendered,
"some-extension-name-some-parent-id",
);
expect(parent?.dataset.isActiveTest).toBe("false"); expect(parent?.dataset.isActiveTest).toBe("false");
}); });
it("parent sidebar item is not expanded", () => { it("parent sidebar item is not expanded", () => {
const child = getSidebarItem( const child = rendered.queryByTestId("sidebar-item-some-extension-name-some-child-id");
rendered,
"some-extension-name-some-child-id",
);
expect(child).toBeUndefined(); expect(child).toBeNull();
}); });
describe("when a parent sidebar item is expanded", () => { describe("when a parent sidebar item is expanded", () => {
@ -242,21 +217,15 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
}); });
it("parent sidebar item is not highlighted", () => { it("parent sidebar item is not highlighted", () => {
const parent = getSidebarItem( const parent = rendered.getByTestId("sidebar-item-some-extension-name-some-parent-id");
rendered,
"some-extension-name-some-parent-id",
);
expect(parent?.dataset.isActiveTest).toBe("false"); expect(parent?.dataset.isActiveTest).toBe("false");
}); });
it("parent sidebar item is expanded", () => { it("parent sidebar item is expanded", () => {
const child = getSidebarItem( const child = rendered.queryByTestId("sidebar-item-some-extension-name-some-child-id");
rendered,
"some-extension-name-some-child-id",
);
expect(child).not.toBeUndefined(); expect(child).not.toBeNull();
}); });
describe("when a child of the parent is selected", () => { describe("when a child of the parent is selected", () => {
@ -273,19 +242,13 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
}); });
it("parent is highlighted", () => { it("parent is highlighted", () => {
const parent = getSidebarItem( const parent = rendered.getByTestId("sidebar-item-some-extension-name-some-parent-id");
rendered,
"some-extension-name-some-parent-id",
);
expect(parent?.dataset.isActiveTest).toBe("true"); expect(parent?.dataset.isActiveTest).toBe("true");
}); });
it("child is highlighted", () => { it("child is highlighted", () => {
const child = getSidebarItem( const child = rendered.getByTestId("sidebar-item-some-extension-name-some-child-id");
rendered,
"some-extension-name-some-child-id",
);
expect(child?.dataset.isActiveTest).toBe("true"); expect(child?.dataset.isActiveTest).toBe("true");
}); });

View File

@ -14,7 +14,6 @@ import { frontEndRouteInjectionToken } from "../../common/front-end-routing/fron
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token"; import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token";
import { getSidebarItem } from "../utils";
describe("cluster - visibility of sidebar items", () => { describe("cluster - visibility of sidebar items", () => {
let applicationBuilder: ApplicationBuilder; let applicationBuilder: ApplicationBuilder;
@ -42,9 +41,9 @@ describe("cluster - visibility of sidebar items", () => {
}); });
it("related sidebar item does not exist", () => { it("related sidebar item does not exist", () => {
const item = getSidebarItem(rendered, "some-item-id"); const item = rendered.queryByTestId("sidebar-item-some-item-id");
expect(item).toBeUndefined(); expect(item).toBeNull();
}); });
describe("when kube resource becomes allowed", () => { describe("when kube resource becomes allowed", () => {
@ -57,9 +56,9 @@ describe("cluster - visibility of sidebar items", () => {
}); });
it("related sidebar item exists", () => { it("related sidebar item exists", () => {
const item = getSidebarItem(rendered, "some-item-id"); const item = rendered.queryByTestId("sidebar-item-some-item-id");
expect(item).not.toBeUndefined(); expect(item).not.toBeNull();
}); });
}); });
}); });

View File

@ -24,10 +24,8 @@ exports[`helm-charts - navigation to Helm charts when navigating to Helm charts
> >
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="workloads"
data-is-active-test="false" data-is-active-test="false"
data-test-id="workloads" data-testid="sidebar-item-workloads"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -60,10 +58,8 @@ exports[`helm-charts - navigation to Helm charts when navigating to Helm charts
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="config"
data-is-active-test="false" data-is-active-test="false"
data-test-id="config" data-testid="sidebar-item-config"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -89,10 +85,8 @@ exports[`helm-charts - navigation to Helm charts when navigating to Helm charts
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="network"
data-is-active-test="false" data-is-active-test="false"
data-test-id="network" data-testid="sidebar-item-network"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"
@ -128,10 +122,8 @@ exports[`helm-charts - navigation to Helm charts when navigating to Helm charts
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="storage"
data-is-active-test="false" data-is-active-test="false"
data-test-id="storage" data-testid="sidebar-item-storage"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -157,10 +149,8 @@ exports[`helm-charts - navigation to Helm charts when navigating to Helm charts
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="helm"
data-is-active-test="true" data-is-active-test="true"
data-test-id="helm" data-testid="sidebar-item-helm"
data-testid="sidebar-item"
> >
<a <a
aria-current="page" aria-current="page"
@ -194,10 +184,8 @@ exports[`helm-charts - navigation to Helm charts when navigating to Helm charts
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="user-management"
data-is-active-test="false" data-is-active-test="false"
data-test-id="user-management" data-testid="sidebar-item-user-management"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center" class="nav-item flex gaps align-center"
@ -223,10 +211,8 @@ exports[`helm-charts - navigation to Helm charts when navigating to Helm charts
</div> </div>
<div <div
class="SidebarItem" class="SidebarItem"
data-id-test="custom-resources"
data-is-active-test="false" data-is-active-test="false"
data-test-id="custom-resources" data-testid="sidebar-item-custom-resources"
data-testid="sidebar-item"
> >
<a <a
class="nav-item flex gaps align-center expandable" class="nav-item flex gaps align-center expandable"

View File

@ -1,12 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { RenderResult } from "@testing-library/react";
export function getSidebarItem(rendered: RenderResult, itemId: string) {
return rendered
.queryAllByTestId("sidebar-item")
.find((x) => x.dataset.idTest === itemId);
}

View File

@ -7,14 +7,13 @@ import fs from "fs";
import mockFs from "mock-fs"; import mockFs from "mock-fs";
import path from "path"; import path from "path";
import fse from "fs-extra"; import fse from "fs-extra";
import type { Cluster } from "../cluster/cluster";
import type { ClusterStore } from "../cluster-store/cluster-store"; import type { ClusterStore } from "../cluster-store/cluster-store";
import { Console } from "console"; import { Console } from "console";
import { stdout, stderr } from "process"; import { stdout, stderr } from "process";
import getCustomKubeConfigDirectoryInjectable from "../app-paths/get-custom-kube-config-directory/get-custom-kube-config-directory.injectable"; import getCustomKubeConfigDirectoryInjectable from "../app-paths/get-custom-kube-config-directory/get-custom-kube-config-directory.injectable";
import clusterStoreInjectable from "../cluster-store/cluster-store.injectable"; import clusterStoreInjectable from "../cluster-store/cluster-store.injectable";
import type { ClusterModel } from "../cluster-types";
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import type { CreateCluster } from "../cluster/create-cluster-injection-token";
import { createClusterInjectionToken } from "../cluster/create-cluster-injection-token"; import { createClusterInjectionToken } from "../cluster/create-cluster-injection-token";
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable"; import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting"; import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
@ -25,17 +24,19 @@ import directoryForTempInjectable from "../app-paths/directory-for-temp/director
import kubectlBinaryNameInjectable from "../../main/kubectl/binary-name.injectable"; import kubectlBinaryNameInjectable from "../../main/kubectl/binary-name.injectable";
import kubectlDownloadingNormalizedArchInjectable from "../../main/kubectl/normalized-arch.injectable"; import kubectlDownloadingNormalizedArchInjectable from "../../main/kubectl/normalized-arch.injectable";
import normalizedPlatformInjectable from "../vars/normalized-platform.injectable"; import normalizedPlatformInjectable from "../vars/normalized-platform.injectable";
import fsInjectable from "../fs/fs.injectable";
console = new Console(stdout, stderr); console = new Console(stdout, stderr);
const testDataIcon = fs.readFileSync( const testDataIcon = fs.readFileSync(
"test-data/cluster-store-migration-icon.png", "test-data/cluster-store-migration-icon.png",
); );
const clusterServerUrl = "https://localhost";
const kubeconfig = ` const kubeconfig = `
apiVersion: v1 apiVersion: v1
clusters: clusters:
- cluster: - cluster:
server: https://localhost server: ${clusterServerUrl}
name: test name: test
contexts: contexts:
- context: - context:
@ -78,7 +79,7 @@ jest.mock("electron", () => ({
describe("cluster-store", () => { describe("cluster-store", () => {
let mainDi: DiContainer; let mainDi: DiContainer;
let clusterStore: ClusterStore; let clusterStore: ClusterStore;
let createCluster: (model: ClusterModel) => Cluster; let createCluster: CreateCluster;
beforeEach(async () => { beforeEach(async () => {
mainDi = getDiForUnitTesting({ doGeneralOverrides: true }); mainDi = getDiForUnitTesting({ doGeneralOverrides: true });
@ -94,6 +95,7 @@ describe("cluster-store", () => {
mainDi.permitSideEffects(getConfigurationFileModelInjectable); mainDi.permitSideEffects(getConfigurationFileModelInjectable);
mainDi.permitSideEffects(appVersionInjectable); mainDi.permitSideEffects(appVersionInjectable);
mainDi.permitSideEffects(clusterStoreInjectable); mainDi.permitSideEffects(clusterStoreInjectable);
mainDi.permitSideEffects(fsInjectable);
mainDi.unoverride(clusterStoreInjectable); mainDi.unoverride(clusterStoreInjectable);
}); });
@ -143,6 +145,8 @@ describe("cluster-store", () => {
getCustomKubeConfigDirectory("foo"), getCustomKubeConfigDirectory("foo"),
kubeconfig, kubeconfig,
), ),
}, {
clusterServerUrl,
}); });
clusterStore.addCluster(cluster); clusterStore.addCluster(cluster);

View File

@ -78,12 +78,12 @@ describe("kube helpers", () => {
describe("with default validation options", () => { describe("with default validation options", () => {
describe("with valid kubeconfig", () => { describe("with valid kubeconfig", () => {
it("does not return an error", () => { it("does not return an error", () => {
expect(validateKubeConfig(kc, "valid")).toBeUndefined(); expect(validateKubeConfig(kc, "valid")).toBeDefined();
}); });
}); });
describe("with invalid context object", () => { describe("with invalid context object", () => {
it("returns an error", () => { it("returns an error", () => {
expect(String(validateKubeConfig(kc, "invalid"))).toEqual( expect(validateKubeConfig(kc, "invalid").error?.toString()).toEqual(
expect.stringContaining("No valid context object provided in kubeconfig for context 'invalid'"), expect.stringContaining("No valid context object provided in kubeconfig for context 'invalid'"),
); );
}); });
@ -91,7 +91,7 @@ describe("kube helpers", () => {
describe("with invalid cluster object", () => { describe("with invalid cluster object", () => {
it("returns an error", () => { it("returns an error", () => {
expect(String(validateKubeConfig(kc, "invalidCluster"))).toEqual( expect(validateKubeConfig(kc, "invalidCluster").error?.toString()).toEqual(
expect.stringContaining("No valid cluster object provided in kubeconfig for context 'invalidCluster'"), expect.stringContaining("No valid cluster object provided in kubeconfig for context 'invalidCluster'"),
); );
}); });
@ -99,7 +99,7 @@ describe("kube helpers", () => {
describe("with invalid user object", () => { describe("with invalid user object", () => {
it("returns an error", () => { it("returns an error", () => {
expect(String(validateKubeConfig(kc, "invalidUser"))).toEqual( expect(validateKubeConfig(kc, "invalidUser").error?.toString()).toEqual(
expect.stringContaining("No valid user object provided in kubeconfig for context 'invalidUser'"), expect.stringContaining("No valid user object provided in kubeconfig for context 'invalidUser'"),
); );
}); });

View File

@ -5,6 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { ClusterStore } from "./cluster-store"; import { ClusterStore } from "./cluster-store";
import { createClusterInjectionToken } from "../cluster/create-cluster-injection-token"; import { createClusterInjectionToken } from "../cluster/create-cluster-injection-token";
import readClusterConfigSyncInjectable from "./read-cluster-config.injectable";
const clusterStoreInjectable = getInjectable({ const clusterStoreInjectable = getInjectable({
id: "cluster-store", id: "cluster-store",
@ -14,6 +15,7 @@ const clusterStoreInjectable = getInjectable({
return ClusterStore.createInstance({ return ClusterStore.createInstance({
createCluster: di.inject(createClusterInjectionToken), createCluster: di.inject(createClusterInjectionToken),
readClusterConfigSync: di.inject(readClusterConfigSyncInjectable),
}); });
}, },

View File

@ -16,13 +16,16 @@ import { disposer, toJS } from "../utils";
import type { ClusterModel, ClusterId, ClusterState } from "../cluster-types"; import type { ClusterModel, ClusterId, ClusterState } from "../cluster-types";
import { requestInitialClusterStates } from "../../renderer/ipc"; import { requestInitialClusterStates } from "../../renderer/ipc";
import { clusterStates } from "../ipc/cluster"; import { clusterStates } from "../ipc/cluster";
import type { CreateCluster } from "../cluster/create-cluster-injection-token";
import type { ReadClusterConfigSync } from "./read-cluster-config.injectable";
export interface ClusterStoreModel { export interface ClusterStoreModel {
clusters?: ClusterModel[]; clusters?: ClusterModel[];
} }
interface Dependencies { interface Dependencies {
createCluster: (model: ClusterModel) => Cluster; createCluster: CreateCluster;
readClusterConfigSync: ReadClusterConfigSync;
} }
export class ClusterStore extends BaseStore<ClusterStoreModel> { export class ClusterStore extends BaseStore<ClusterStoreModel> {
@ -116,7 +119,10 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
const cluster = clusterOrModel instanceof Cluster const cluster = clusterOrModel instanceof Cluster
? clusterOrModel ? clusterOrModel
: this.dependencies.createCluster(clusterOrModel); : this.dependencies.createCluster(
clusterOrModel,
this.dependencies.readClusterConfigSync(clusterOrModel),
);
this.clusters.set(cluster.id, cluster); this.clusters.set(cluster.id, cluster);
@ -136,7 +142,10 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
if (cluster) { if (cluster) {
cluster.updateModel(clusterModel); cluster.updateModel(clusterModel);
} else { } else {
cluster = this.dependencies.createCluster(clusterModel); cluster = this.dependencies.createCluster(
clusterModel,
this.dependencies.readClusterConfigSync(clusterModel),
);
} }
newClusters.set(clusterModel.id, cluster); newClusters.set(clusterModel.id, cluster);
} catch (error) { } catch (error) {

View File

@ -0,0 +1,31 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { ClusterConfigData, ClusterModel } from "../cluster-types";
import readFileSyncInjectable from "../fs/read-file-sync.injectable";
import { loadConfigFromString, validateKubeConfig } from "../kube-helpers";
export type ReadClusterConfigSync = (model: ClusterModel) => ClusterConfigData;
const readClusterConfigSyncInjectable = getInjectable({
id: "read-cluster-config-sync",
instantiate: (di): ReadClusterConfigSync => {
const readFileSync = di.inject(readFileSyncInjectable);
return ({ kubeConfigPath, contextName }) => {
const kubeConfigData = readFileSync(kubeConfigPath);
const { config } = loadConfigFromString(kubeConfigData);
const result = validateKubeConfig(config, contextName);
if (result.error) {
throw result.error;
}
return { clusterServerUrl: result.cluster.server };
};
},
});
export default readClusterConfigSyncInjectable;

View File

@ -67,6 +67,15 @@ export interface ClusterModel {
labels?: Record<string, string>; labels?: Record<string, string>;
} }
/**
* This data is retreived from the kubeconfig file before calling the cluster constructor.
*
* That is done to remove the external dependency on the construction of Cluster instances.
*/
export interface ClusterConfigData {
clusterServerUrl: string;
}
/** /**
* The complete set of cluster settings or preferences * The complete set of cluster settings or preferences
*/ */

View File

@ -10,13 +10,13 @@ import type { KubeConfig } from "@kubernetes/client-node";
import { HttpError } from "@kubernetes/client-node"; import { HttpError } from "@kubernetes/client-node";
import type { Kubectl } from "../../main/kubectl/kubectl"; import type { Kubectl } from "../../main/kubectl/kubectl";
import type { KubeconfigManager } from "../../main/kubeconfig-manager/kubeconfig-manager"; import type { KubeconfigManager } from "../../main/kubeconfig-manager/kubeconfig-manager";
import { loadConfigFromFile, loadConfigFromFileSync, validateKubeConfig } from "../kube-helpers"; import { loadConfigFromFile } from "../kube-helpers";
import type { KubeApiResource, KubeResource } from "../rbac"; import type { KubeApiResource, KubeResource } from "../rbac";
import { apiResourceRecord, apiResources } from "../rbac"; import { apiResourceRecord, apiResources } from "../rbac";
import type { VersionDetector } from "../../main/cluster-detectors/version-detector"; import type { VersionDetector } from "../../main/cluster-detectors/version-detector";
import type { DetectorRegistry } from "../../main/cluster-detectors/detector-registry"; import type { DetectorRegistry } from "../../main/cluster-detectors/detector-registry";
import plimit from "p-limit"; import plimit from "p-limit";
import type { ClusterState, ClusterRefreshOptions, ClusterMetricsResourceType, ClusterId, ClusterMetadata, ClusterModel, ClusterPreferences, ClusterPrometheusPreferences, UpdateClusterModel, KubeAuthUpdate } from "../cluster-types"; import type { ClusterState, ClusterRefreshOptions, ClusterMetricsResourceType, ClusterId, ClusterMetadata, ClusterModel, ClusterPreferences, ClusterPrometheusPreferences, UpdateClusterModel, KubeAuthUpdate, ClusterConfigData } from "../cluster-types";
import { ClusterMetadataKey, initialNodeShellImage, ClusterStatus } from "../cluster-types"; import { ClusterMetadataKey, initialNodeShellImage, ClusterStatus } from "../cluster-types";
import { disposer, isDefined, isRequestError, toJS } from "../utils"; import { disposer, isDefined, isRequestError, toJS } from "../utils";
import type { Response } from "request"; import type { Response } from "request";
@ -236,27 +236,11 @@ export class Cluster implements ClusterModel, ClusterState {
return this.preferences.defaultNamespace; return this.preferences.defaultNamespace;
} }
constructor(private readonly dependencies: ClusterDependencies, model: ClusterModel) { constructor(private readonly dependencies: ClusterDependencies, model: ClusterModel, configData: ClusterConfigData) {
makeObservable(this); makeObservable(this);
this.id = model.id; this.id = model.id;
this.updateModel(model); this.updateModel(model);
this.apiUrl = configData.clusterServerUrl;
const { config } = loadConfigFromFileSync(this.kubeConfigPath);
const validationError = validateKubeConfig(config, this.contextName);
if (validationError) {
throw validationError;
}
const context = config.getContextObject(this.contextName);
assert(context);
const cluster = config.getCluster(context.cluster);
assert(cluster);
this.apiUrl = cluster.server;
// for the time being, until renderer gets its own cluster type // for the time being, until renderer gets its own cluster type
this._contextHandler = this.dependencies.createContextHandler(this); this._contextHandler = this.dependencies.createContextHandler(this);

View File

@ -3,10 +3,10 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectionToken } from "@ogre-tools/injectable"; import { getInjectionToken } from "@ogre-tools/injectable";
import type { ClusterModel } from "../cluster-types"; import type { ClusterConfigData, ClusterModel } from "../cluster-types";
import type { Cluster } from "./cluster"; import type { Cluster } from "./cluster";
export type CreateCluster = (model: ClusterModel) => Cluster; export type CreateCluster = (model: ClusterModel, configData: ClusterConfigData) => Cluster;
export const createClusterInjectionToken = getInjectionToken<CreateCluster>({ export const createClusterInjectionToken = getInjectionToken<CreateCluster>({
id: "create-cluster-token", id: "create-cluster-token",

View File

@ -0,0 +1,19 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import fsInjectable from "./fs.injectable";
export type ReadFileSync = (filePath: string) => string;
const readFileSyncInjectable = getInjectable({
id: "read-file-sync",
instantiate: (di): ReadFileSync => {
const { readFileSync } = di.inject(fsInjectable);
return (filePath) => readFileSync(filePath, "utf-8");
},
});
export default readFileSyncInjectable;

View File

@ -150,7 +150,7 @@ export function loadConfigFromString(content: string): ConfigResult {
export interface SplitConfigEntry { export interface SplitConfigEntry {
config: KubeConfig; config: KubeConfig;
error?: string; validationResult: ValidateKubeConfigResult;
} }
/** /**
@ -179,7 +179,7 @@ export function splitConfig(kubeConfig: KubeConfig): SplitConfigEntry[] {
return { return {
config, config,
error: validateKubeConfig(config, ctx.name)?.toString(), validationResult: validateKubeConfig(config, ctx.name),
}; };
}); });
} }
@ -243,25 +243,44 @@ export function dumpConfigYaml(kubeConfig: PartialDeep<KubeConfig>): string {
return yaml.dump(config, { skipInvalid: true }); return yaml.dump(config, { skipInvalid: true });
} }
export type ValidateKubeConfigResult = {
error: Error;
} | {
error?: undefined;
context: Context;
cluster: Cluster;
user: User;
};
/** /**
* Checks if `config` has valid `Context`, `User`, `Cluster`, and `exec` fields (if present when required) * Checks if `config` has valid `Context`, `User`, `Cluster`, and `exec` fields (if present when required)
* *
* Note: This function returns an error instead of throwing it, returning `undefined` if the validation passes * Note: This function returns an error instead of throwing it, returning `undefined` if the validation passes
*/ */
export function validateKubeConfig(config: KubeConfig, contextName: string): Error | undefined { export function validateKubeConfig(config: KubeConfig, contextName: string): ValidateKubeConfigResult {
const contextObject = config.getContextObject(contextName); const context = config.getContextObject(contextName);
if (!contextObject) { if (!context) {
return new Error(`No valid context object provided in kubeconfig for context '${contextName}'`); return {
error: new Error(`No valid context object provided in kubeconfig for context '${contextName}'`),
};
} }
if (!config.getCluster(contextObject.cluster)) { const cluster = config.getCluster(context.cluster);
return new Error(`No valid cluster object provided in kubeconfig for context '${contextName}'`);
if (!cluster) {
return {
error: new Error(`No valid cluster object provided in kubeconfig for context '${contextName}'`),
};
} }
if (!config.getUser(contextObject.user)) { const user = config.getUser(context.user);
return new Error(`No valid user object provided in kubeconfig for context '${contextName}'`);
if (!user) {
return {
error: new Error(`No valid user object provided in kubeconfig for context '${contextName}'`),
};
} }
return undefined; return { cluster, user, context };
} }

View File

@ -2,4 +2,5 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import "@testing-library/jest-dom/extend-expect";
import "@testing-library/jest-dom";

View File

@ -8,11 +8,10 @@ jest.mock("request");
jest.mock("request-promise-native"); jest.mock("request-promise-native");
import { Console } from "console"; import { Console } from "console";
import mockFs from "mock-fs";
import type { Cluster } from "../../common/cluster/cluster"; import type { Cluster } from "../../common/cluster/cluster";
import { Kubectl } from "../kubectl/kubectl"; import { Kubectl } from "../kubectl/kubectl";
import { getDiForUnitTesting } from "../getDiForUnitTesting"; import { getDiForUnitTesting } from "../getDiForUnitTesting";
import type { ClusterModel } from "../../common/cluster-types"; import type { CreateCluster } from "../../common/cluster/create-cluster-injection-token";
import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token"; import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token";
import authorizationReviewInjectable from "../../common/cluster/authorization-review.injectable"; import authorizationReviewInjectable from "../../common/cluster/authorization-review.injectable";
import listNamespacesInjectable from "../../common/cluster/list-namespaces.injectable"; import listNamespacesInjectable from "../../common/cluster/list-namespaces.injectable";
@ -29,36 +28,13 @@ console = new Console(process.stdout, process.stderr); // fix mockFS
describe("create clusters", () => { describe("create clusters", () => {
let cluster: Cluster; let cluster: Cluster;
let createCluster: (model: ClusterModel) => Cluster; let createCluster: CreateCluster;
beforeEach(() => { beforeEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
const di = getDiForUnitTesting({ doGeneralOverrides: true }); const di = getDiForUnitTesting({ doGeneralOverrides: true });
const clusterServerUrl = "https://192.168.64.3:8443";
mockFs({
"minikube-config.yml": JSON.stringify({
apiVersion: "v1",
clusters: [{
name: "minikube",
cluster: {
server: "https://192.168.64.3:8443",
},
}],
contexts: [{
context: {
cluster: "minikube",
user: "minikube",
},
name: "minikube",
}],
users: [{
name: "minikube",
}],
kind: "Config",
preferences: {},
}),
});
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data"); di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
di.override(directoryForTempInjectable, () => "some-directory-for-temp"); di.override(directoryForTempInjectable, () => "some-directory-for-temp");
@ -87,12 +63,13 @@ describe("create clusters", () => {
id: "foo", id: "foo",
contextName: "minikube", contextName: "minikube",
kubeConfigPath: "minikube-config.yml", kubeConfigPath: "minikube-config.yml",
}, {
clusterServerUrl,
}); });
}); });
afterEach(() => { afterEach(() => {
cluster.disconnect(); cluster.disconnect();
mockFs.restore();
}); });
it("should be able to create a cluster from a cluster model and apiURL should be decoded", () => { it("should be able to create a cluster from a cluster model and apiURL should be decoded", () => {
@ -108,12 +85,6 @@ describe("create clusters", () => {
}); });
it("activating cluster should try to connect to cluster and do a refresh", async () => { it("activating cluster should try to connect to cluster and do a refresh", async () => {
const cluster = createCluster({
id: "foo",
contextName: "minikube",
kubeConfigPath: "minikube-config.yml",
});
jest.spyOn(cluster, "reconnect"); jest.spyOn(cluster, "reconnect");
jest.spyOn(cluster, "refreshConnectionStatus"); jest.spyOn(cluster, "refreshConnectionStatus");

View File

@ -3,8 +3,6 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import type { ClusterModel } from "../../common/cluster-types";
jest.mock("winston", () => ({ jest.mock("winston", () => ({
format: { format: {
colorize: jest.fn(), colorize: jest.fn(),
@ -51,6 +49,7 @@ import { stdout, stderr } from "process";
import mockFs from "mock-fs"; import mockFs from "mock-fs";
import { getDiForUnitTesting } from "../getDiForUnitTesting"; import { getDiForUnitTesting } from "../getDiForUnitTesting";
import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable"; import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable";
import type { CreateCluster } from "../../common/cluster/create-cluster-injection-token";
import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token"; import { createClusterInjectionToken } from "../../common/cluster/create-cluster-injection-token";
import path from "path"; import path from "path";
import spawnInjectable from "../child-process/spawn.injectable"; import spawnInjectable from "../child-process/spawn.injectable";
@ -67,9 +66,10 @@ console = new Console(stdout, stderr);
const mockBroadcastIpc = broadcastMessage as jest.MockedFunction<typeof broadcastMessage>; const mockBroadcastIpc = broadcastMessage as jest.MockedFunction<typeof broadcastMessage>;
const mockSpawn = spawn as jest.MockedFunction<typeof spawn>; const mockSpawn = spawn as jest.MockedFunction<typeof spawn>;
const mockWaitUntilUsed = waitUntilUsed as jest.MockedFunction<typeof waitUntilUsed>; const mockWaitUntilUsed = waitUntilUsed as jest.MockedFunction<typeof waitUntilUsed>;
const clusterServerUrl = "https://192.168.64.3:8443";
describe("kube auth proxy tests", () => { describe("kube auth proxy tests", () => {
let createCluster: (model: ClusterModel) => Cluster; let createCluster: CreateCluster;
let createKubeAuthProxy: (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy; let createKubeAuthProxy: (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy;
beforeEach(async () => { beforeEach(async () => {
@ -81,7 +81,7 @@ describe("kube auth proxy tests", () => {
clusters: [{ clusters: [{
name: "minikube", name: "minikube",
cluster: { cluster: {
server: "https://192.168.64.3:8443", server: clusterServerUrl,
}, },
}], }],
"current-context": "minikube", "current-context": "minikube",
@ -130,6 +130,8 @@ describe("kube auth proxy tests", () => {
id: "foobar", id: "foobar",
kubeConfigPath: "minikube-config.yml", kubeConfigPath: "minikube-config.yml",
contextName: "minikube", contextName: "minikube",
}, {
clusterServerUrl,
}); });
const kap = createKubeAuthProxy(cluster, {}); const kap = createKubeAuthProxy(cluster, {});
@ -222,6 +224,8 @@ describe("kube auth proxy tests", () => {
id: "foobar", id: "foobar",
kubeConfigPath: "minikube-config.yml", kubeConfigPath: "minikube-config.yml",
contextName: "minikube", contextName: "minikube",
}, {
clusterServerUrl,
}); });
proxy = createKubeAuthProxy(cluster, {}); proxy = createKubeAuthProxy(cluster, {});

View File

@ -26,6 +26,8 @@ import kubectlDownloadingNormalizedArchInjectable from "../kubectl/normalized-ar
console = new Console(process.stdout, process.stderr); // fix mockFS console = new Console(process.stdout, process.stderr); // fix mockFS
const clusterServerUrl = "https://192.168.64.3:8443";
describe("kubeconfig manager tests", () => { describe("kubeconfig manager tests", () => {
let clusterFake: Cluster; let clusterFake: Cluster;
let createKubeconfigManager: (cluster: Cluster) => KubeconfigManager | undefined; let createKubeconfigManager: (cluster: Cluster) => KubeconfigManager | undefined;
@ -57,7 +59,7 @@ describe("kubeconfig manager tests", () => {
clusters: [{ clusters: [{
name: "minikube", name: "minikube",
cluster: { cluster: {
server: "https://192.168.64.3:8443", server: clusterServerUrl,
}, },
}], }],
contexts: [{ contexts: [{
@ -95,6 +97,8 @@ describe("kubeconfig manager tests", () => {
id: "foo", id: "foo",
contextName: "minikube", contextName: "minikube",
kubeConfigPath: "minikube-config.yml", kubeConfigPath: "minikube-config.yml",
}, {
clusterServerUrl,
}); });
jest.spyOn(KubeconfigManager.prototype, "resolveProxyUrl", "get").mockReturnValue("http://127.0.0.1:9191/foo"); jest.spyOn(KubeconfigManager.prototype, "resolveProxyUrl", "get").mockReturnValue("http://127.0.0.1:9191/foo");

View File

@ -14,7 +14,6 @@ import clusterStoreInjectable from "../../../common/cluster-store/cluster-store.
import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import { getDiForUnitTesting } from "../../getDiForUnitTesting";
import { createClusterInjectionToken } from "../../../common/cluster/create-cluster-injection-token"; import { createClusterInjectionToken } from "../../../common/cluster/create-cluster-injection-token";
import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
import { ClusterStore } from "../../../common/cluster-store/cluster-store";
import getConfigurationFileModelInjectable from "../../../common/get-configuration-file-model/get-configuration-file-model.injectable"; import getConfigurationFileModelInjectable from "../../../common/get-configuration-file-model/get-configuration-file-model.injectable";
import appVersionInjectable from "../../../common/get-configuration-file-model/app-version/app-version.injectable"; import appVersionInjectable from "../../../common/get-configuration-file-model/app-version/app-version.injectable";
import clusterManagerInjectable from "../../cluster-manager.injectable"; import clusterManagerInjectable from "../../cluster-manager.injectable";
@ -23,6 +22,8 @@ import directoryForTempInjectable from "../../../common/app-paths/directory-for-
import kubectlBinaryNameInjectable from "../../kubectl/binary-name.injectable"; import kubectlBinaryNameInjectable from "../../kubectl/binary-name.injectable";
import kubectlDownloadingNormalizedArchInjectable from "../../kubectl/normalized-arch.injectable"; import kubectlDownloadingNormalizedArchInjectable from "../../kubectl/normalized-arch.injectable";
import normalizedPlatformInjectable from "../../../common/vars/normalized-platform.injectable"; import normalizedPlatformInjectable from "../../../common/vars/normalized-platform.injectable";
import { iter } from "../../../common/utils";
import fsInjectable from "../../../common/fs/fs.injectable";
jest.mock("electron", () => ({ jest.mock("electron", () => ({
app: { app: {
@ -54,10 +55,9 @@ describe("kubeconfig-sync.source tests", () => {
di.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64"); di.override(kubectlDownloadingNormalizedArchInjectable, () => "amd64");
di.override(normalizedPlatformInjectable, () => "darwin"); di.override(normalizedPlatformInjectable, () => "darwin");
di.override(clusterStoreInjectable, () => di.permitSideEffects(fsInjectable);
ClusterStore.createInstance({ createCluster: () => null as never }), di.unoverride(clusterStoreInjectable);
); di.permitSideEffects(clusterStoreInjectable);
di.permitSideEffects(getConfigurationFileModelInjectable); di.permitSideEffects(getConfigurationFileModelInjectable);
di.permitSideEffects(appVersionInjectable); di.permitSideEffects(appVersionInjectable);
@ -66,13 +66,10 @@ describe("kubeconfig-sync.source tests", () => {
createCluster: di.inject(createClusterInjectionToken), createCluster: di.inject(createClusterInjectionToken),
clusterManager: di.inject(clusterManagerInjectable), clusterManager: di.inject(clusterManagerInjectable),
}); });
di.inject(clusterStoreInjectable);
}); });
afterEach(() => { afterEach(() => {
mockFs.restore(); mockFs.restore();
ClusterStore.resetInstance();
}); });
describe("configsToModels", () => { describe("configsToModels", () => {
@ -108,8 +105,8 @@ describe("kubeconfig-sync.source tests", () => {
const models = configToModels(config, "/bar"); const models = configToModels(config, "/bar");
expect(models.length).toBe(1); expect(models.length).toBe(1);
expect(models[0].contextName).toBe("context-name"); expect(models[0][0].contextName).toBe("context-name");
expect(models[0].kubeConfigPath).toBe("/bar"); expect(models[0][0].kubeConfigPath).toBe("/bar");
}); });
}); });
@ -160,7 +157,8 @@ describe("kubeconfig-sync.source tests", () => {
expect(rootSource.size).toBe(1); expect(rootSource.size).toBe(1);
const c = rootSource.values().next().value[0] as Cluster; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const c = (iter.first(rootSource.values())!)[0];
expect(c.kubeConfigPath).toBe("/bar"); expect(c.kubeConfigPath).toBe("/bar");
expect(c.contextName).toBe("context-name"); expect(c.contextName).toBe("context-name");

View File

@ -25,9 +25,10 @@ import { createHash } from "crypto";
import { homedir } from "os"; import { homedir } from "os";
import globToRegExp from "glob-to-regexp"; import globToRegExp from "glob-to-regexp";
import { inspect } from "util"; import { inspect } from "util";
import type { ClusterModel, UpdateClusterModel } from "../../../common/cluster-types"; import type { ClusterConfigData, UpdateClusterModel } from "../../../common/cluster-types";
import type { Cluster } from "../../../common/cluster/cluster"; import type { Cluster } from "../../../common/cluster/cluster";
import type { CatalogEntityRegistry } from "../../catalog/entity-registry"; import type { CatalogEntityRegistry } from "../../catalog/entity-registry";
import type { CreateCluster } from "../../../common/cluster/create-cluster-injection-token";
const logPrefix = "[KUBECONFIG-SYNC]:"; const logPrefix = "[KUBECONFIG-SYNC]:";
@ -56,7 +57,7 @@ interface KubeconfigSyncManagerDependencies {
readonly directoryForKubeConfigs: string; readonly directoryForKubeConfigs: string;
readonly entityRegistry: CatalogEntityRegistry; readonly entityRegistry: CatalogEntityRegistry;
readonly clusterManager: ClusterManager; readonly clusterManager: ClusterManager;
createCluster: (model: ClusterModel) => Cluster; createCluster: CreateCluster;
} }
const kubeConfigSyncName = "lens:kube-sync"; const kubeConfigSyncName = "lens:kube-sync";
@ -147,17 +148,22 @@ export class KubeconfigSyncManager {
} }
// exported for testing // exported for testing
export function configToModels(rootConfig: KubeConfig, filePath: string): UpdateClusterModel[] { export function configToModels(rootConfig: KubeConfig, filePath: string): [UpdateClusterModel, ClusterConfigData][] {
const validConfigs = []; const validConfigs: ReturnType<typeof configToModels> = [];
for (const { config, error } of splitConfig(rootConfig)) { for (const { config, validationResult } of splitConfig(rootConfig)) {
if (error) { if (validationResult.error) {
logger.debug(`${logPrefix} context failed validation: ${error}`, { context: config.currentContext, filePath }); logger.debug(`${logPrefix} context failed validation: ${validationResult.error}`, { context: config.currentContext, filePath });
} else { } else {
validConfigs.push({ validConfigs.push([
kubeConfigPath: filePath, {
contextName: config.currentContext, kubeConfigPath: filePath,
}); contextName: config.currentContext,
},
{
clusterServerUrl: validationResult.cluster.server,
},
]);
} }
} }
@ -169,7 +175,7 @@ type RootSource = ObservableMap<string, RootSourceValue>;
interface ComputeDiffDependencies { interface ComputeDiffDependencies {
directoryForKubeConfigs: string; directoryForKubeConfigs: string;
createCluster: (model: ClusterModel) => Cluster; createCluster: CreateCluster;
clusterManager: ClusterManager; clusterManager: ClusterManager;
} }
@ -184,15 +190,15 @@ export const computeDiff = ({ directoryForKubeConfigs, createCluster, clusterMan
} }
const rawModels = configToModels(config, filePath); const rawModels = configToModels(config, filePath);
const models = new Map(rawModels.map(m => [m.contextName, m])); const models = new Map(rawModels.map(([model, configData]) => [model.contextName, [model, configData] as const]));
logger.debug(`${logPrefix} File now has ${models.size} entries`, { filePath }); logger.debug(`${logPrefix} File now has ${models.size} entries`, { filePath });
for (const [contextName, value] of source) { for (const [contextName, value] of source) {
const model = models.get(contextName); const data = models.get(contextName);
// remove and disconnect clusters that were removed from the config // remove and disconnect clusters that were removed from the config
if (!model) { if (!data) {
// remove from the deleting set, so that if a new context of the same name is added, it isn't marked as deleting // remove from the deleting set, so that if a new context of the same name is added, it isn't marked as deleting
clusterManager.deleting.delete(value[0].id); clusterManager.deleting.delete(value[0].id);
@ -207,17 +213,17 @@ export const computeDiff = ({ directoryForKubeConfigs, createCluster, clusterMan
// diff against that // diff against that
// or update the model and mark it as not needed to be added // or update the model and mark it as not needed to be added
value[0].updateModel(model); value[0].updateModel(data[0]);
models.delete(contextName); models.delete(contextName);
logger.debug(`${logPrefix} Updated old cluster from sync`, { filePath, contextName }); logger.debug(`${logPrefix} Updated old cluster from sync`, { filePath, contextName });
} }
for (const [contextName, model] of models) { for (const [contextName, [model, configData]] of models) {
// add new clusters to the source // add new clusters to the source
try { try {
const clusterId = createHash("md5").update(`${filePath}:${contextName}`).digest("hex"); const clusterId = createHash("md5").update(`${filePath}:${contextName}`).digest("hex");
const cluster = ClusterStore.getInstance().getById(clusterId) || createCluster({ ...model, id: clusterId }); const cluster = ClusterStore.getInstance().getById(clusterId) || createCluster({ ...model, id: clusterId }, configData);
if (!cluster.apiUrl) { if (!cluster.apiUrl) {
throw new Error("Cluster constructor failed, see above error"); throw new Error("Cluster constructor failed, see above error");

View File

@ -32,7 +32,7 @@ const createClusterInjectable = getInjectable({
createVersionDetector: di.inject(createVersionDetectorInjectable), createVersionDetector: di.inject(createVersionDetectorInjectable),
}; };
return (model) => new Cluster(dependencies, model); return (model, configData) => new Cluster(dependencies, model, configData);
}, },
injectionToken: createClusterInjectionToken, injectionToken: createClusterInjectionToken,

View File

@ -39,9 +39,9 @@ interface Dependencies {
function getContexts(config: KubeConfig): Map<string, Option> { function getContexts(config: KubeConfig): Map<string, Option> {
return new Map( return new Map(
splitConfig(config) splitConfig(config)
.map(({ config, error }) => [config.currentContext, { .map(({ config, validationResult }) => [config.currentContext, {
config, config,
error, error: validationResult.error?.toString(),
}]), }]),
); );
} }

View File

@ -17,7 +17,6 @@ import { ClusterIssues } from "./cluster-issues";
import { ClusterMetrics } from "./cluster-metrics"; import { ClusterMetrics } from "./cluster-metrics";
import type { ClusterOverviewStore } from "./cluster-overview-store/cluster-overview-store"; import type { ClusterOverviewStore } from "./cluster-overview-store/cluster-overview-store";
import { ClusterPieCharts } from "./cluster-pie-charts"; import { ClusterPieCharts } from "./cluster-pie-charts";
import { getActiveClusterEntity } from "../../api/catalog/entity/legacy-globals";
import { ClusterMetricsResourceType } from "../../../common/cluster-types"; import { ClusterMetricsResourceType } from "../../../common/cluster-types";
import type { EventStore } from "../+events/store"; import type { EventStore } from "../+events/store";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
@ -71,7 +70,7 @@ class NonInjectedClusterOverview extends React.Component<Dependencies> {
this.metricPoller.stop(); this.metricPoller.stop();
} }
renderMetrics(isMetricsHidden?: boolean) { renderMetrics(isMetricsHidden: boolean) {
if (isMetricsHidden) { if (isMetricsHidden) {
return null; return null;
} }
@ -84,7 +83,7 @@ class NonInjectedClusterOverview extends React.Component<Dependencies> {
); );
} }
renderClusterOverview(isLoaded: boolean, isMetricsHidden?: boolean) { renderClusterOverview(isLoaded: boolean, isMetricsHidden: boolean) {
if (!isLoaded) { if (!isLoaded) {
return <Spinner center/>; return <Spinner center/>;
} }
@ -98,9 +97,9 @@ class NonInjectedClusterOverview extends React.Component<Dependencies> {
} }
render() { render() {
const { eventStore, nodeStore } = this.props; const { eventStore, nodeStore, hostedCluster } = this.props;
const isLoaded = nodeStore.isLoaded && eventStore.isLoaded; const isLoaded = nodeStore.isLoaded && eventStore.isLoaded;
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Cluster); const isMetricHidden = hostedCluster.isMetricHidden(ClusterMetricsResourceType.Cluster);
return ( return (
<TabLayout> <TabLayout>

View File

@ -12,51 +12,48 @@ import { CommandDialog } from "./command-dialog";
import type { ClusterId } from "../../../common/cluster-types"; import type { ClusterId } from "../../../common/cluster-types";
import type { CommandOverlay } from "./command-overlay.injectable"; import type { CommandOverlay } from "./command-overlay.injectable";
import commandOverlayInjectable from "./command-overlay.injectable"; import commandOverlayInjectable from "./command-overlay.injectable";
import { isMac } from "../../../common/vars"; import type { ipcRendererOn } from "../../../common/ipc";
import type { CatalogEntityRegistry } from "../../api/catalog/entity/registry"; import { broadcastMessage } from "../../../common/ipc";
import { broadcastMessage, ipcRendererOn } from "../../../common/ipc";
import type { Disposer } from "../../utils";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { AddWindowEventListener } from "../../window/event-listener.injectable";
import windowAddEventListenerInjectable from "../../window/event-listener.injectable"; import windowAddEventListenerInjectable from "../../window/event-listener.injectable";
import type { IComputedValue } from "mobx"; import type { IComputedValue } from "mobx";
import matchedClusterIdInjectable from "../../navigation/matched-cluster-id.injectable"; import matchedClusterIdInjectable from "../../navigation/matched-cluster-id.injectable";
import catalogEntityRegistryInjectable from "../../api/catalog/entity/registry.injectable";
import hostedClusterIdInjectable from "../../cluster-frame-context/hosted-cluster-id.injectable"; import hostedClusterIdInjectable from "../../cluster-frame-context/hosted-cluster-id.injectable";
import isMacInjectable from "../../../common/vars/is-mac.injectable";
import legacyOnChannelListenInjectable from "../../ipc/legacy-channel-listen.injectable";
interface Dependencies { interface Dependencies {
addWindowEventListener: <K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions) => Disposer; addWindowEventListener: AddWindowEventListener;
commandOverlay: CommandOverlay; commandOverlay: CommandOverlay;
clusterId?: ClusterId; clusterId: ClusterId | undefined;
matchedClusterId: IComputedValue<ClusterId>; matchedClusterId: IComputedValue<ClusterId | undefined>;
entityRegistry: CatalogEntityRegistry; isMac: boolean;
legacyOnChannelListen: typeof ipcRendererOn;
} }
@observer @observer
class NonInjectedCommandContainer extends React.Component<Dependencies> { class NonInjectedCommandContainer extends React.Component<Dependencies> {
private escHandler(event: KeyboardEvent) { private escHandler = (event: KeyboardEvent) => {
const { commandOverlay } = this.props;
if (event.key === "Escape") { if (event.key === "Escape") {
event.stopPropagation(); event.stopPropagation();
commandOverlay.close(); this.props.commandOverlay.close();
} }
} };
handleCommandPalette = () => { handleCommandPalette = () => {
const { commandOverlay, entityRegistry } = this.props; const matchedClusterId = this.props.matchedClusterId.get();
const clusterIsActive = this.props.matchedClusterId.get() !== undefined;
if (clusterIsActive) { if (matchedClusterId !== undefined) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion broadcastMessage(`command-palette:${matchedClusterId}:open`);
broadcastMessage(`command-palette:${entityRegistry.activeEntity!.getId()}:open`);
} else { } else {
commandOverlay.open(<CommandDialog />); this.props.commandOverlay.open(<CommandDialog />);
} }
}; };
onKeyboardShortcut(action: () => void) { onKeyboardShortcut(action: () => void) {
return ({ key, shiftKey, ctrlKey, altKey, metaKey }: KeyboardEvent) => { return ({ key, shiftKey, ctrlKey, altKey, metaKey }: KeyboardEvent) => {
const ctrlOrCmd = isMac ? metaKey && !ctrlKey : !metaKey && ctrlKey; const ctrlOrCmd = this.props.isMac ? metaKey && !ctrlKey : !metaKey && ctrlKey;
if (key === "p" && shiftKey && ctrlOrCmd && !altKey) { if (key === "p" && shiftKey && ctrlOrCmd && !altKey) {
action(); action();
@ -75,9 +72,9 @@ class NonInjectedCommandContainer extends React.Component<Dependencies> {
: "command-palette:open"; : "command-palette:open";
disposeOnUnmount(this, [ disposeOnUnmount(this, [
ipcRendererOn(ipcChannel, action), this.props.legacyOnChannelListen(ipcChannel, action),
addWindowEventListener("keydown", this.onKeyboardShortcut(action)), addWindowEventListener("keydown", this.onKeyboardShortcut(action)),
addWindowEventListener("keyup", (e) => this.escHandler(e), true), addWindowEventListener("keyup", this.escHandler, true),
]); ]);
} }
@ -106,6 +103,7 @@ export const CommandContainer = withInjectables<Dependencies>(NonInjectedCommand
addWindowEventListener: di.inject(windowAddEventListenerInjectable), addWindowEventListener: di.inject(windowAddEventListenerInjectable),
commandOverlay: di.inject(commandOverlayInjectable), commandOverlay: di.inject(commandOverlayInjectable),
matchedClusterId: di.inject(matchedClusterIdInjectable), matchedClusterId: di.inject(matchedClusterIdInjectable),
entityRegistry: di.inject(catalogEntityRegistryInjectable), isMac: di.inject(isMacInjectable),
legacyOnChannelListen: di.inject(legacyOnChannelListenInjectable),
}), }),
}); });

View File

@ -9,9 +9,8 @@ import type { RenderResult } from "@testing-library/react";
import mockFs from "mock-fs"; import mockFs from "mock-fs";
import React from "react"; import React from "react";
import * as selectEvent from "react-select-event"; import * as selectEvent from "react-select-event";
import type { Cluster } from "../../../../common/cluster/cluster";
import { DeleteClusterDialog } from "../view"; import { DeleteClusterDialog } from "../view";
import type { ClusterModel } from "../../../../common/cluster-types"; import type { CreateCluster } from "../../../../common/cluster/create-cluster-injection-token";
import { createClusterInjectionToken } from "../../../../common/cluster/create-cluster-injection-token"; import { createClusterInjectionToken } from "../../../../common/cluster/create-cluster-injection-token";
import createContextHandlerInjectable from "../../../../main/context-handler/create-context-handler.injectable"; import createContextHandlerInjectable from "../../../../main/context-handler/create-context-handler.injectable";
import type { OpenDeleteClusterDialog } from "../open.injectable"; import type { OpenDeleteClusterDialog } from "../open.injectable";
@ -46,14 +45,16 @@ jest.mock("electron", () => ({
}, },
})); }));
const currentClusterServerUrl = "https://localhost";
const nonCurrentClusterServerUrl = "http://localhost";
const multiClusterConfig = ` const multiClusterConfig = `
apiVersion: v1 apiVersion: v1
clusters: clusters:
- cluster: - cluster:
server: https://localhost server: ${currentClusterServerUrl}
name: some-current-context-cluster name: some-current-context-cluster
- cluster: - cluster:
server: http://localhost server: ${nonCurrentClusterServerUrl}
name: some-non-current-context-cluster name: some-non-current-context-cluster
contexts: contexts:
- context: - context:
@ -73,11 +74,12 @@ users:
token: kubeconfig-user-q4lm4:xxxyyyy token: kubeconfig-user-q4lm4:xxxyyyy
`; `;
const singleClusterServerUrl = "http://localhost";
const singleClusterConfig = ` const singleClusterConfig = `
apiVersion: v1 apiVersion: v1
clusters: clusters:
- cluster: - cluster:
server: http://localhost server: ${singleClusterServerUrl}
name: some-cluster name: some-cluster
contexts: contexts:
- context: - context:
@ -97,7 +99,7 @@ let config: KubeConfig;
describe("<DeleteClusterDialog />", () => { describe("<DeleteClusterDialog />", () => {
let applicationBuilder: ApplicationBuilder; let applicationBuilder: ApplicationBuilder;
let createCluster: (model: ClusterModel) => Cluster; let createCluster: CreateCluster;
let openDeleteClusterDialog: OpenDeleteClusterDialog; let openDeleteClusterDialog: OpenDeleteClusterDialog;
beforeEach(async () => { beforeEach(async () => {
@ -157,6 +159,8 @@ describe("<DeleteClusterDialog />", () => {
clusterName: "some-current-context-cluster", clusterName: "some-current-context-cluster",
}, },
kubeConfigPath: "./temp-kube-config", kubeConfigPath: "./temp-kube-config",
}, {
clusterServerUrl: currentClusterServerUrl,
}); });
openDeleteClusterDialog({ cluster, config }); openDeleteClusterDialog({ cluster, config });
@ -204,6 +208,8 @@ describe("<DeleteClusterDialog />", () => {
clusterName: "minikube", clusterName: "minikube",
}, },
kubeConfigPath: "./temp-kube-config", kubeConfigPath: "./temp-kube-config",
}, {
clusterServerUrl: nonCurrentClusterServerUrl,
}); });
openDeleteClusterDialog({ cluster, config }); openDeleteClusterDialog({ cluster, config });
@ -221,6 +227,8 @@ describe("<DeleteClusterDialog />", () => {
clusterName: "some-current-context-cluster", clusterName: "some-current-context-cluster",
}, },
kubeConfigPath: "./temp-kube-config", kubeConfigPath: "./temp-kube-config",
}, {
clusterServerUrl: currentClusterServerUrl,
}); });
openDeleteClusterDialog({ cluster, config }); openDeleteClusterDialog({ cluster, config });
@ -236,6 +244,8 @@ describe("<DeleteClusterDialog />", () => {
clusterName: "some-current-context-cluster", clusterName: "some-current-context-cluster",
}, },
kubeConfigPath: "./temp-kube-config", kubeConfigPath: "./temp-kube-config",
}, {
clusterServerUrl: currentClusterServerUrl,
}); });
openDeleteClusterDialog({ cluster, config }); openDeleteClusterDialog({ cluster, config });
@ -259,12 +269,12 @@ describe("<DeleteClusterDialog />", () => {
const cluster = createCluster({ const cluster = createCluster({
id: "some-non-current-context-cluster", id: "some-non-current-context-cluster",
contextName: "some-non-current-context", contextName: "some-non-current-context",
preferences: { preferences: {
clusterName: "some-non-current-context-cluster", clusterName: "some-non-current-context-cluster",
}, },
kubeConfigPath: "./temp-kube-config", kubeConfigPath: "./temp-kube-config",
}, {
clusterServerUrl: nonCurrentClusterServerUrl,
}); });
const spy = jest.spyOn(cluster, "isInLocalKubeconfig").mockImplementation(() => true); const spy = jest.spyOn(cluster, "isInLocalKubeconfig").mockImplementation(() => true);
@ -301,6 +311,8 @@ describe("<DeleteClusterDialog />", () => {
clusterName: "some-cluster", clusterName: "some-cluster",
}, },
kubeConfigPath: "./temp-kube-config", kubeConfigPath: "./temp-kube-config",
}, {
clusterServerUrl: singleClusterServerUrl,
}); });
openDeleteClusterDialog({ cluster, config }); openDeleteClusterDialog({ cluster, config });

View File

@ -80,9 +80,7 @@ class NonInjectedSidebarItem extends React.Component<
return ( return (
<div <div
className={cssNames("SidebarItem")} className={cssNames("SidebarItem")}
data-testid="sidebar-item" data-testid={`sidebar-item-${this.id}`}
data-test-id={this.id}
data-id-test={this.id}
data-is-active-test={this.isActive} data-is-active-test={this.isActive}
data-parent-id-test={this.registration.parentId} data-parent-id-test={this.registration.parentId}
> >

View File

@ -28,7 +28,7 @@ const createClusterInjectable = getInjectable({
createVersionDetector: () => { throw new Error("Tried to access back-end feature in front-end."); }, createVersionDetector: () => { throw new Error("Tried to access back-end feature in front-end."); },
}; };
return (model) => new Cluster(dependencies, model); return (model, configData) => new Cluster(dependencies, model, configData);
}, },
injectionToken: createClusterInjectionToken, injectionToken: createClusterInjectionToken,

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
.centering {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}

View File

@ -0,0 +1,124 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { DiContainer } from "@ogre-tools/injectable";
import type { RenderResult } from "@testing-library/react";
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
import { render as testingLibraryRender } from "@testing-library/react";
import React from "react";
import { DiContextProvider } from "@ogre-tools/injectable-react";
import { Router } from "react-router";
import { DefaultProps } from "../../mui-base-theme";
import { ClusterFrame } from "./cluster-frame";
import historyInjectable from "../../navigation/history.injectable";
import { computed } from "mobx";
import type { Cluster } from "../../../common/cluster/cluster";
import createClusterInjectable from "../../create-cluster/create-cluster.injectable";
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
import legacyOnChannelListenInjectable from "../../ipc/legacy-channel-listen.injectable";
import currentRouteComponentInjectable from "../../routes/current-route-component.injectable";
import allowedResourcesInjectable from "../../cluster-frame-context/allowed-resources.injectable";
import hostedClusterIdInjectable from "../../cluster-frame-context/hosted-cluster-id.injectable";
import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable";
describe("<ClusterFrame />", () => {
let render: () => RenderResult;
let di: DiContainer;
let cluster: Cluster;
beforeEach(() => {
di = getDiForUnitTesting({ doGeneralOverrides: true });
render = () => testingLibraryRender((
<DiContextProvider value={{ di }}>
<Router history={di.inject(historyInjectable)}>
{DefaultProps(ClusterFrame)}
</Router>
</DiContextProvider>
));
di.override(subscribeStoresInjectable, () => jest.fn().mockImplementation(() => jest.fn()));
di.override(legacyOnChannelListenInjectable, () => jest.fn().mockImplementation(() => jest.fn()));
di.override(directoryForUserDataInjectable, () => "/some/irrelavent/path");
di.override(storesAndApisCanBeCreatedInjectable, () => true);
const createCluster = di.inject(createClusterInjectable);
cluster = createCluster(
{
contextName: "my-cluster",
id: "123456",
kubeConfigPath: "/irrelavent",
},
{
clusterServerUrl: "https://localhost",
},
);
di.override(hostedClusterInjectable, () => cluster);
di.override(hostedClusterIdInjectable, () => cluster.id);
});
describe("given cluster with list nodes and namespaces permissions", () => {
beforeEach(() => {
di.override(allowedResourcesInjectable, () => computed(() => new Set(["nodes", "namespaces"])));
});
it("renders", () => {
const result = render();
expect(result.container).toMatchSnapshot();
});
it("shows cluster overview sidebar item as active", () => {
const result = render();
const clusterOverviewSidebarItem = result.getByTestId("sidebar-item-cluster-overview");
expect(clusterOverviewSidebarItem.getAttribute("data-is-active-test")).toBe("true");
});
describe("given no matching component", () => {
beforeEach(() => {
di.override(currentRouteComponentInjectable, () => computed(() => undefined));
});
describe("given current url is starting url", () => {
it("renders", () => {
const result = render();
expect(result.container).toMatchSnapshot();
});
it("shows warning message", () => {
const result = render();
expect(
result.getByText("An error has occured. No route can be found matching the current route, which is also the starting route."),
).toBeInTheDocument();
});
});
});
});
describe("given cluster without list nodes, but with namespaces permissions", () => {
beforeEach(() => {
di.override(allowedResourcesInjectable, () => computed(() => new Set(["namespaces"])));
});
it("renders", () => {
const result = render();
expect(result.container).toMatchSnapshot();
});
it("shows workloads overview sidebar item as active", () => {
const result = render();
const workloadsOverviewSidebarItem = result.getByTestId("sidebar-item-workloads");
expect(workloadsOverviewSidebarItem.getAttribute("data-is-active-test")).toBe("true");
});
});
});

View File

@ -2,6 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved. * Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import styles from "./cluster-frame.module.css";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import type { IComputedValue } from "mobx"; import type { IComputedValue } from "mobx";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
@ -30,12 +31,14 @@ import { disposer } from "../../utils";
import currentRouteComponentInjectable from "../../routes/current-route-component.injectable"; import currentRouteComponentInjectable from "../../routes/current-route-component.injectable";
import startUrlInjectable from "./start-url.injectable"; import startUrlInjectable from "./start-url.injectable";
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable"; import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
import currentPathInjectable from "../../routes/current-path.injectable";
interface Dependencies { interface Dependencies {
namespaceStore: NamespaceStore; namespaceStore: NamespaceStore;
currentRouteComponent: IComputedValue<React.ElementType<{}> | undefined | null>; currentRouteComponent: IComputedValue<React.ElementType<{}> | undefined>;
startUrl: IComputedValue<string>; startUrl: IComputedValue<string>;
subscribeStores: SubscribeStores; subscribeStores: SubscribeStores;
currentPath: IComputedValue<string>;
} }
export const NonInjectedClusterFrame = observer(({ export const NonInjectedClusterFrame = observer(({
@ -43,6 +46,7 @@ export const NonInjectedClusterFrame = observer(({
currentRouteComponent, currentRouteComponent,
startUrl, startUrl,
subscribeStores, subscribeStores,
currentPath,
}: Dependencies) => { }: Dependencies) => {
useEffect(() => disposer( useEffect(() => disposer(
subscribeStores([ subscribeStores([
@ -52,6 +56,8 @@ export const NonInjectedClusterFrame = observer(({
), []); ), []);
const Component = currentRouteComponent.get(); const Component = currentRouteComponent.get();
const starting = startUrl.get();
const current = currentPath.get();
return ( return (
<ErrorBoundary> <ErrorBoundary>
@ -62,7 +68,16 @@ export const NonInjectedClusterFrame = observer(({
{ {
Component Component
? <Component /> ? <Component />
: <Redirect to={startUrl.get()} /> // NOTE: this check is to prevent an infinite loop
: starting !== current
? <Redirect to={startUrl.get()} />
: (
<div className={styles.centering}>
<div className="error">
An error has occured. No route can be found matching the current route, which is also the starting route.
</div>
</div>
)
} }
</MainLayout> </MainLayout>
@ -87,6 +102,7 @@ export const ClusterFrame = withInjectables<Dependencies>(NonInjectedClusterFram
subscribeStores: di.inject(subscribeStoresInjectable), subscribeStores: di.inject(subscribeStoresInjectable),
startUrl: di.inject(startUrlInjectable), startUrl: di.inject(startUrlInjectable),
currentRouteComponent: di.inject(currentRouteComponentInjectable), currentRouteComponent: di.inject(currentRouteComponentInjectable),
currentPath: di.inject(currentPathInjectable),
}), }),
}); });

View File

@ -4,29 +4,30 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx"; import { computed } from "mobx";
import type { KubeResource } from "../../../common/rbac";
import isAllowedResourceInjectable from "../../../common/utils/is-allowed-resource.injectable";
import clusterOverviewRouteInjectable from "../../../common/front-end-routing/routes/cluster/overview/cluster-overview-route.injectable"; import clusterOverviewRouteInjectable from "../../../common/front-end-routing/routes/cluster/overview/cluster-overview-route.injectable";
import workloadsOverviewRouteInjectable from "../../../common/front-end-routing/routes/cluster/workloads/overview/workloads-overview-route.injectable"; import workloadsOverviewRouteInjectable from "../../../common/front-end-routing/routes/cluster/workloads/overview/workloads-overview-route.injectable";
import { buildURL } from "../../../common/utils/buildUrl";
const startUrlInjectable = getInjectable({ const startUrlInjectable = getInjectable({
id: "start-url", id: "start-url",
instantiate: (di) => { instantiate: (di) => {
const isAllowedResource = (resourceName: string) => di.inject(isAllowedResourceInjectable, resourceName);
const clusterOverviewRoute = di.inject(clusterOverviewRouteInjectable); const clusterOverviewRoute = di.inject(clusterOverviewRouteInjectable);
const workloadOverviewRoute = di.inject(workloadsOverviewRouteInjectable); const workloadOverviewRoute = di.inject(workloadsOverviewRouteInjectable);
const clusterOverviewUrl = buildURL(clusterOverviewRoute.path);
const workloadOverviewUrl = buildURL(workloadOverviewRoute.path);
return computed(() => { return computed(() => {
const resources: KubeResource[] = ["events", "nodes", "pods"]; if (clusterOverviewRoute.isEnabled.get()) {
return clusterOverviewRoute.path;
}
return resources.every((resourceName) => isAllowedResource(resourceName)) if (workloadOverviewRoute.isEnabled.get()) {
? clusterOverviewUrl return workloadOverviewRoute.path;
: workloadOverviewUrl; }
/**
* NOTE: This will never be executed as `workloadOverviewRoute.isEnabled` always is true. It
* is here is guard against accidental changes at a distance within `workloadOverviewRoute`.
*/
throw new Error("Exhausted all possible starting locations and none are active. This is a bug.");
}); });
}, },
}); });

View File

@ -0,0 +1,15 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { ipcRendererOn } from "../../common/ipc";
const legacyOnChannelListenInjectable = getInjectable({
id: "legacy-on-channel-listen",
instantiate: () => ipcRendererOn,
causesSideEffects: true,
});
export default legacyOnChannelListenInjectable;

View File

@ -6,6 +6,8 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { Disposer } from "../utils"; import type { Disposer } from "../utils";
export type AddWindowEventListener = typeof addWindowEventListener;
function addWindowEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): Disposer { function addWindowEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): Disposer {
window.addEventListener(type, listener, options); window.addEventListener(type, listener, options);