import { NvmeSubsystemViewBreadcrumbResolver } from './nvme-subsystem-view/nvme-subsystem-view-breadcrumb.resolver';
import { NvmeSubsystemViewComponent } from './nvme-subsystem-view/nvme-subsystem-view.component';
import { NvmeofSubsystemPerformanceComponent } from './nvmeof-subsystem-performance/nvmeof-subsystem-performance.component';
+import { NvmeofTabsComponent } from './nvmeof-tabs/nvmeof-tabs.component';
@NgModule({
imports: [
NvmeofEditHostKeyModalComponent,
NvmeofSubsystemsStepFourComponent,
NvmeofSubsystemOverviewComponent,
- NvmeofSubsystemPerformanceComponent
+ NvmeofSubsystemPerformanceComponent,
+ NvmeofTabsComponent
],
exports: [RbdConfigurationListComponent, RbdConfigurationFormComponent]
{ path: '', redirectTo: 'gateways', pathMatch: 'full' },
{
path: 'gateways',
- component: NvmeofGatewayComponent,
data: { breadcrumbs: 'Gateways' },
children: [
{
- path: `${URLVerbs.EDIT}/:subsystem_nqn/namespace/:nsid`,
- component: NvmeofNamespaceExpandModalComponent,
- outlet: 'modal'
- }
- ]
- },
- {
- path: `gateways/${URLVerbs.CREATE}`,
- component: NvmeofGroupFormComponent,
- data: { breadcrumbs: `${ActionLabels.CREATE}${URLVerbs.GATEWAY_GROUP}` }
- },
-
- {
- path: `gateways/${URLVerbs.VIEW}/:group`,
- component: NvmeGatewayViewComponent,
- data: { breadcrumbs: NvmeGatewayViewBreadcrumbResolver }, // Use resolver here
- children: [
- { path: '', redirectTo: 'nodes', pathMatch: 'full' },
+ path: '',
+ component: NvmeofGatewayGroupComponent
+ },
{
- path: 'nodes',
- component: NvmeofGatewayNodeComponent,
- data: { breadcrumbs: $localize`Gateway nodes`, mode: NvmeofGatewayNodeMode.DETAILS }
+ path: URLVerbs.CREATE,
+ component: NvmeofGroupFormComponent,
+ data: {
+ breadcrumbs: ActionLabels.CREATE,
+ pageHeader: {
+ title: $localize`Create Gateway Group`,
+ description: $localize`A logical group of gateways that hosts will connect to.`
+ }
+ }
},
{
- path: 'subsystems',
- component: NvmeofGatewaySubsystemComponent,
- data: { breadcrumbs: $localize`Subsystems` }
+ path: `${URLVerbs.VIEW}/:group`,
+ component: NvmeGatewayViewComponent,
+ data: { breadcrumbs: NvmeGatewayViewBreadcrumbResolver },
+ children: [
+ { path: '', redirectTo: 'nodes', pathMatch: 'full' },
+ {
+ path: 'nodes',
+ component: NvmeofGatewayNodeComponent,
+ data: { breadcrumbs: $localize`Gateway nodes`, mode: NvmeofGatewayNodeMode.DETAILS }
+ },
+ {
+ path: 'subsystems',
+ component: NvmeofGatewaySubsystemComponent,
+ data: { breadcrumbs: $localize`Subsystems` }
+ }
+ ]
}
]
},
- {
- path: `namespaces/${URLVerbs.CREATE}`,
- component: NvmeofNamespacesFormComponent,
- data: { breadcrumbs: ActionLabels.CREATE + ' ' + $localize`Namespace` }
- },
{
path: 'subsystems',
- component: NvmeofSubsystemsComponent,
data: { breadcrumbs: 'Subsystems' },
children: [
- // subsystems
-
- {
- path: URLVerbs.CREATE,
- component: NvmeofSubsystemsFormComponent,
- outlet: 'modal'
- },
- // listeners
- {
- path: `${URLVerbs.CREATE}/:subsystem_nqn/listener`,
- component: NvmeofListenersFormComponent,
- outlet: 'modal'
- },
- // namespaces
- {
- path: `${URLVerbs.CREATE}/:subsystem_nqn/namespace`,
- component: NvmeofNamespacesFormComponent,
- data: { breadcrumbs: ActionLabels.CREATE + ' ' + $localize`Namespace` }
- },
{
- path: `${URLVerbs.EDIT}/:subsystem_nqn/namespace/:nsid`,
- component: NvmeofNamespaceExpandModalComponent,
- outlet: 'modal'
+ path: '',
+ component: NvmeofSubsystemsComponent,
+ children: [
+ {
+ path: URLVerbs.CREATE,
+ component: NvmeofSubsystemsFormComponent,
+ outlet: 'modal'
+ },
+ {
+ path: `${URLVerbs.CREATE}/:subsystem_nqn/listener`,
+ component: NvmeofListenersFormComponent,
+ outlet: 'modal'
+ },
+ {
+ path: `${URLVerbs.EDIT}/:subsystem_nqn/namespace/:nsid`,
+ component: NvmeofNamespaceExpandModalComponent,
+ outlet: 'modal'
+ },
+ {
+ path: `${URLVerbs.ADD}/:subsystem_nqn/initiator`,
+ component: NvmeofInitiatorsFormComponent,
+ outlet: 'modal'
+ }
+ ]
},
- // initiators
{
- path: `${URLVerbs.ADD}/:subsystem_nqn/initiator`,
- component: NvmeofInitiatorsFormComponent,
- outlet: 'modal'
+ path: ':subsystem_nqn',
+ component: NvmeSubsystemViewComponent,
+ data: { breadcrumbs: NvmeSubsystemViewBreadcrumbResolver },
+ children: [
+ { path: '', redirectTo: 'overview', pathMatch: 'full' },
+ {
+ path: 'overview',
+ component: NvmeofSubsystemOverviewComponent
+ },
+ {
+ path: 'hosts',
+ component: NvmeofInitiatorsListComponent
+ },
+ {
+ path: 'namespaces',
+ component: NvmeofSubsystemNamespacesListComponent
+ },
+ {
+ path: 'listeners',
+ component: NvmeofListenersListComponent
+ },
+ {
+ path: 'performance',
+ component: NvmeofSubsystemPerformanceComponent
+ },
+ {
+ path: `${URLVerbs.ADD}/initiator`,
+ component: NvmeofInitiatorsFormComponent,
+ outlet: 'modal'
+ },
+ {
+ path: `${URLVerbs.ADD}/listener`,
+ component: NvmeofListenersFormComponent,
+ outlet: 'modal'
+ },
+ {
+ path: `${URLVerbs.EDIT}/:subsystem_nqn/namespace/:nsid`,
+ component: NvmeofNamespaceExpandModalComponent,
+ outlet: 'modal'
+ }
+ ]
}
]
},
{
- path: `subsystems/:subsystem_nqn`,
- component: NvmeSubsystemViewComponent,
- data: { breadcrumbs: NvmeSubsystemViewBreadcrumbResolver },
+ path: 'namespaces',
+ data: { breadcrumbs: 'Namespaces' },
children: [
- { path: '', redirectTo: 'overview', pathMatch: 'full' },
- {
- path: 'overview',
- component: NvmeofSubsystemOverviewComponent
- },
- {
- path: 'hosts',
- component: NvmeofInitiatorsListComponent
- },
-
- {
- path: 'namespaces',
- component: NvmeofSubsystemNamespacesListComponent
- },
{
- path: 'listeners',
- component: NvmeofListenersListComponent
+ path: '',
+ component: NvmeofNamespacesListComponent,
+ children: [
+ {
+ path: `${URLVerbs.EDIT}/:subsystem_nqn/namespace/:nsid`,
+ component: NvmeofNamespaceExpandModalComponent,
+ outlet: 'modal'
+ }
+ ]
},
{
- path: 'performance',
- component: NvmeofSubsystemPerformanceComponent
- },
- {
- path: `${URLVerbs.ADD}/initiator`,
- component: NvmeofInitiatorsFormComponent,
- outlet: 'modal'
- },
- {
- path: `${URLVerbs.ADD}/listener`,
- component: NvmeofListenersFormComponent,
- outlet: 'modal'
- },
- {
- path: `${URLVerbs.EDIT}/:subsystem_nqn/namespace/:nsid`,
- component: NvmeofNamespaceExpandModalComponent,
- outlet: 'modal'
+ path: URLVerbs.CREATE,
+ component: NvmeofNamespacesFormComponent,
+ data: { breadcrumbs: ActionLabels.CREATE }
}
]
}
--- /dev/null
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { Router } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { TabsModule } from 'carbon-components-angular';
+
+import { NvmeofTabsComponent } from './nvmeof-tabs.component';
+import { SharedModule } from '~/app/shared/shared.module';
+
+describe('NvmeofTabsComponent', () => {
+ let component: NvmeofTabsComponent;
+ let fixture: ComponentFixture<NvmeofTabsComponent>;
+ let router: Router;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [NvmeofTabsComponent],
+ imports: [RouterTestingModule, SharedModule, TabsModule]
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(NvmeofTabsComponent);
+ component = fixture.componentInstance;
+ router = TestBed.inject(Router);
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should default activeTab to gateways', () => {
+ jest.spyOn(router, 'url', 'get').mockReturnValue('/block/nvmeof/gateways');
+ component.ngOnInit();
+ expect(component.activeTab).toBe(component.Tabs.gateways);
+ });
+
+ it('should set activeTab to subsystems when URL contains subsystems', () => {
+ jest.spyOn(router, 'url', 'get').mockReturnValue('/block/nvmeof/subsystems');
+ component.ngOnInit();
+ expect(component.activeTab).toBe(component.Tabs.subsystems);
+ });
+
+ it('should set activeTab to namespaces when URL contains namespaces', () => {
+ jest.spyOn(router, 'url', 'get').mockReturnValue('/block/nvmeof/namespaces');
+ component.ngOnInit();
+ expect(component.activeTab).toBe(component.Tabs.namespaces);
+ });
+
+ it('should fallback to gateways when URL does not match any tab', () => {
+ jest.spyOn(router, 'url', 'get').mockReturnValue('/block/nvmeof/unknown');
+ component.ngOnInit();
+ expect(component.activeTab).toBe(component.Tabs.gateways);
+ });
+
+ it('should navigate to correct path on tab selection', () => {
+ spyOn(router, 'navigate');
+ component.onSelected(component.Tabs.subsystems);
+ expect(component.selectedTab).toBe(component.Tabs.subsystems);
+ expect(router.navigate).toHaveBeenCalledWith(['block/nvmeof/subsystems']);
+ });
+
+ it('should navigate to gateways on selecting gateways tab', () => {
+ spyOn(router, 'navigate');
+ component.onSelected(component.Tabs.gateways);
+ expect(component.selectedTab).toBe(component.Tabs.gateways);
+ expect(router.navigate).toHaveBeenCalledWith(['block/nvmeof/gateways']);
+ });
+
+ it('should navigate to namespaces on selecting namespaces tab', () => {
+ spyOn(router, 'navigate');
+ component.onSelected(component.Tabs.namespaces);
+ expect(component.selectedTab).toBe(component.Tabs.namespaces);
+ expect(router.navigate).toHaveBeenCalledWith(['block/nvmeof/namespaces']);
+ });
+
+ it('should expose TABS enum via Tabs getter', () => {
+ const tabs = component.Tabs;
+ expect(tabs.gateways).toBe('gateways');
+ expect(tabs.subsystems).toBe('subsystems');
+ expect(tabs.namespaces).toBe('namespaces');
+ });
+});