Skip to content

Commit

Permalink
Vue3: Fixed navigation active style not applied (#12015)
Browse files Browse the repository at this point in the history
  • Loading branch information
eva-vashkevich committed Sep 27, 2024
1 parent f1dce33 commit c3566e0
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 25 deletions.
34 changes: 34 additions & 0 deletions cypress/e2e/tests/navigation/side-nav/product-side-nav.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,21 @@ import HomePagePo from '@/cypress/e2e/po/pages/home.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
import WorkloadPagePo from '@/cypress/e2e/po/pages/explorer/workloads.po';
import { WorkloadsDeploymentsListPagePo } from '@/cypress/e2e/po/pages/explorer/workloads/workloads-deployments.po';
import { createDeploymentBlueprint } from '@/cypress/e2e/blueprints/explorer/workloads/deployments/deployment-create';

const { name: workloadName, namespace } = createDeploymentBlueprint.metadata;
const deploymentsListPage = new WorkloadsDeploymentsListPagePo('local');

Cypress.config();
describe('Side navigation: Cluster ', { tags: ['@navigation', '@adminUser'] }, () => {
before(() => {
cy.login();
cy.intercept('GET', `/v1/apps.deployments/${ namespace }/${ workloadName }`).as('testWorkload');

deploymentsListPage.goTo();
deploymentsListPage.createWithKubectl(createDeploymentBlueprint);
});
beforeEach(() => {
cy.login();

Expand Down Expand Up @@ -52,6 +64,21 @@ describe('Side navigation: Cluster ', { tags: ['@navigation', '@adminUser'] }, (
cy.get('@closedGroup').find('.router-link-active').should('have.length.gt', 0);
});

it('Going into resource detail should keep relevant group active', () => {
const productNavPo = new ProductNavPo();

productNavPo.groups().get('.expanded').as('openGroup');

productNavPo.visibleNavTypes().eq(1).should('be.visible').click(); // Go into Workloads
const workload = new WorkloadPagePo('local');

workload.goTo();
workload.waitForPage();
workload.goToDetailsPage(workloadName);
cy.get('@openGroup').should('be.visible');
cy.get('@openGroup').find('.router-link-active').should('have.length.gt', 0);
});

it('Should access to every navigation provided from the server link, including nested cases, without errors', () => {
const productNavPo = new ProductNavPo();
// iterate through top-level groups
Expand Down Expand Up @@ -97,4 +124,11 @@ describe('Side navigation: Cluster ', { tags: ['@navigation', '@adminUser'] }, (
productNavPo.tabHeaders().eq(1).click(1, 1).then(() => cy.url().should('equal', workloadsUrl));
});
});

after(() => {
cy.login();
deploymentsListPage?.goTo();

deploymentsListPage.deleteWithKubectl(workloadName, namespace);
});
});
22 changes: 21 additions & 1 deletion shell/components/nav/Type.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,26 @@ export default {
const inStore = this.$store.getters['currentStore'](this.type.name);
return this.$store.getters[`${ inStore }/count`]({ name: this.type.name });
},
isActive() {
const typeFullPath = this.$router.resolve(this.type.route)?.fullPath.toLowerCase();
const pageFullPath = this.$route.fullPath?.toLowerCase();
if ( !this.type.exact) {
const typeSplit = typeFullPath.split('/');
const pageSplit = pageFullPath.split('/');
for (let index = 0; index < typeSplit.length; ++index) {
if ( index >= pageSplit.length || typeSplit[index] !== pageSplit[index] ) {
return false;
}
}
return true;
}
return typeFullPath === pageFullPath;
}
},
Expand Down Expand Up @@ -81,7 +101,7 @@ export default {
<router-link
v-if="type.route"
:key="type.name"
v-slot="{ href, navigate, isActive, isExactActive }"
v-slot="{ href, navigate,isExactActive }"
custom
:to="type.route"
>
Expand Down
92 changes: 68 additions & 24 deletions shell/components/nav/__tests__/Type.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { nextTick } from 'vue';
import { shallowMount, RouterLinkStub } from '@vue/test-utils';
import Type from '@shell/components/nav/Type.vue';
import { createChildRenderingRouterLinkStub } from '@shell/utils/unit-tests/ChildRenderingRouterLinkStub';
import { TYPE_MODES } from '@shell/store/type-map';
import { TYPE_MODES } from '@shell/store/type-map.js';

// Configuration
const activeClass = 'router-link-active';
Expand All @@ -25,6 +25,12 @@ describe('component: Type', () => {
'cluster/count': () => defaultCount,
}
};
const routerMock = {
resolve: jest.fn((route) => {
return { fullPath: route };
})
};
const routeMock = { fullPath: 'route' };

describe('should pass props correctly', () => {
it('should forward Type props to router-link', () => {
Expand All @@ -33,8 +39,10 @@ describe('component: Type', () => {

global: {
directives: { cleanHtml: (identity) => identity },
mocks: { $store: storeMock },
stubs: { routerLink: RouterLinkStub },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},
stubs: { routerLink: RouterLinkStub },
},
});

Expand All @@ -51,7 +59,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},
stubs: { routerLink: createChildRenderingRouterLinkStub({ href: fakeHref }) },
},
});
Expand All @@ -69,8 +79,10 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
stubs: { routerLink: createChildRenderingRouterLinkStub({ isActive: true, navigate }) },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},
stubs: { routerLink: createChildRenderingRouterLinkStub({ navigate }) },
},
});

Expand All @@ -90,8 +102,10 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
stubs: { routerLink: createChildRenderingRouterLinkStub({ isActive: false }) },
mocks: {
$store: storeMock, $router: routerMock, $route: { fullPath: 'bad' }
},
stubs: { routerLink: createChildRenderingRouterLinkStub() },
},
});

Expand All @@ -107,7 +121,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},
stubs: { routerLink: createChildRenderingRouterLinkStub({ isExactActive: false }) },
},
});
Expand All @@ -124,7 +140,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},
stubs: { routerLink: createChildRenderingRouterLinkStub() },
},
});
Expand All @@ -143,8 +161,10 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
stubs: { routerLink: createChildRenderingRouterLinkStub({ isActive: true }) },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},
stubs: { routerLink: createChildRenderingRouterLinkStub() },
},
});

Expand All @@ -160,7 +180,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},
stubs: { routerLink: createChildRenderingRouterLinkStub({ isExactActive: true }) },
},
});
Expand All @@ -177,7 +199,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},
stubs: { routerLink: createChildRenderingRouterLinkStub() },
},
});
Expand All @@ -194,7 +218,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},
stubs: { routerLink: createChildRenderingRouterLinkStub() },
},
});
Expand All @@ -211,7 +237,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},
stubs: { routerLink: createChildRenderingRouterLinkStub() },
},
});
Expand All @@ -230,7 +258,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},

stubs: {
routerLink: createChildRenderingRouterLinkStub(),
Expand All @@ -256,7 +286,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},

stubs: {
routerLink: createChildRenderingRouterLinkStub(),
Expand All @@ -277,7 +309,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},

stubs: {
routerLink: createChildRenderingRouterLinkStub(),
Expand Down Expand Up @@ -306,7 +340,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},

stubs: {
routerLink: createChildRenderingRouterLinkStub(),
Expand All @@ -327,7 +363,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},

stubs: {
routerLink: createChildRenderingRouterLinkStub(),
Expand Down Expand Up @@ -355,7 +393,9 @@ describe('component: Type', () => {
currentStore: () => 'cluster',
'cluster/count': () => null,
}
}
},
$router: routerMock,
$route: routeMock
},

stubs: {
Expand All @@ -379,7 +419,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},

stubs: {
routerLink: createChildRenderingRouterLinkStub(),
Expand All @@ -400,7 +442,9 @@ describe('component: Type', () => {
global: {
directives: { cleanHtml: (identity) => identity },

mocks: { $store: storeMock },
mocks: {
$store: storeMock, $router: routerMock, $route: routeMock
},

stubs: {
routerLink: createChildRenderingRouterLinkStub(),
Expand Down

0 comments on commit c3566e0

Please sign in to comment.