Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue3: Fixed navigation active style not applied #12015

Merged
merged 3 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading