From: Naman Munet Date: Thu, 16 Jul 2026 05:56:25 +0000 (+0530) Subject: mgr/dashboard: fix dashboard cephadm e2e X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3aa2b17a04b1d08ad1ad8b1798710c7eb44c0463;p=ceph.git mgr/dashboard: fix dashboard cephadm e2e fixes: https://tracker.ceph.com/issues/78279 Signed-off-by: Naman Munet --- diff --git a/src/pybind/mgr/dashboard/frontend/cypress/e2e/cluster/osds.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/e2e/cluster/osds.po.ts index a9c7c6e9a54..8ed64146135 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/e2e/cluster/osds.po.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/e2e/cluster/osds.po.ts @@ -52,12 +52,14 @@ export class OSDsPageHelper extends PageHelper { checkStatus(id: number, status: string[]) { this.searchTable(id.toString()); cy.wait(5 * 1000); - cy.get(`[cdstabledata]:nth-child(${this.columnIndex.status}) cds-tag`).should(($ele) => { - const allStatus = $ele.toArray().map((v) => v.innerText); - for (const s of status) { - expect(allStatus).to.include(s); + cy.get(`[cdstablerow] [cdstabledata]:nth-child(${this.columnIndex.status}) cds-tag`).should( + ($ele) => { + const allStatus = $ele.toArray().map((v) => v.innerText); + for (const s of status) { + expect(allStatus).to.include(s); + } } - }); + ); } @PageHelper.restrictTo(pages.index.url) diff --git a/src/pybind/mgr/dashboard/frontend/cypress/e2e/common/create-cluster/create-cluster.feature.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/e2e/common/create-cluster/create-cluster.feature.po.ts index 947b0431f6e..c23399fd6cf 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/e2e/common/create-cluster/create-cluster.feature.po.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/e2e/common/create-cluster/create-cluster.feature.po.ts @@ -6,4 +6,5 @@ Given('I am on the {string} section', (page: string) => { Then('I should see a message {string}', () => { cy.get('cd-create-cluster').should('contain.text', 'Welcome to Ceph Dashboard'); + cy.contains('Welcome to Ceph Dashboard').should('be.visible'); }); diff --git a/src/pybind/mgr/dashboard/frontend/cypress/e2e/common/table-helper.feature.po.ts b/src/pybind/mgr/dashboard/frontend/cypress/e2e/common/table-helper.feature.po.ts index b82916fb68a..18a2f4f2f82 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/e2e/common/table-helper.feature.po.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/e2e/common/table-helper.feature.po.ts @@ -46,12 +46,12 @@ When('I select a row {string} in the expanded row', (row: string) => { Then('I should see a row with {string}', (row: string) => { cy.get('.cds--search-input').first().clear().type(row); - cy.contains(`[cdstablerow] [cdstabledata]`, row).should('exist'); + cy.contains(`[cdstablerow]`, row).should('exist'); }); Then('I should not see a row with {string}', (row: string) => { cy.get('.cds--search-input').first().clear().type(row); - cy.contains(`[cdstablerow] [cdstabledata]`, row).should('not.exist'); + cy.contains(`[cdstablerow]`, row).should('not.exist'); }); Then('I should see a table in the expanded row', () => { diff --git a/src/pybind/mgr/dashboard/frontend/cypress/e2e/orchestrator/workflow/03-create-cluster-create-services.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/e2e/orchestrator/workflow/03-create-cluster-create-services.e2e-spec.ts index 9c96d2a19ed..aca084f4c02 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/e2e/orchestrator/workflow/03-create-cluster-create-services.e2e-spec.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/e2e/orchestrator/workflow/03-create-cluster-create-services.e2e-spec.ts @@ -21,7 +21,7 @@ describe('Create cluster create services page', () => { }); it('should check if title contains Create Services', () => { - cy.get('.title').should('contain.text', 'Create Services'); + cy.get('.tearsheet-body .tearsheet-content h4').should('contain.text', 'Create Services'); }); describe('when Orchestrator is available', () => { diff --git a/src/pybind/mgr/dashboard/frontend/cypress/e2e/orchestrator/workflow/04-create-cluster-create-osds.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/e2e/orchestrator/workflow/04-create-cluster-create-osds.e2e-spec.ts index 541fff0bcb4..d4620e7c2f7 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/e2e/orchestrator/workflow/04-create-cluster-create-osds.e2e-spec.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/e2e/orchestrator/workflow/04-create-cluster-create-osds.e2e-spec.ts @@ -16,7 +16,7 @@ describe('Add storage - create osds page', () => { }); it('should check if title contains Create OSDs', () => { - cy.get('.title').should('contain.text', 'Create OSDs'); + cy.get('.tearsheet-body .tearsheet-content h4').should('contain.text', 'Create OSDs'); }); describe('when Orchestrator is available', () => { diff --git a/src/pybind/mgr/dashboard/frontend/cypress/e2e/orchestrator/workflow/05-create-cluster-review.e2e-spec.ts b/src/pybind/mgr/dashboard/frontend/cypress/e2e/orchestrator/workflow/05-create-cluster-review.e2e-spec.ts index b81c388faab..b3da0ffc7a7 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/e2e/orchestrator/workflow/05-create-cluster-review.e2e-spec.ts +++ b/src/pybind/mgr/dashboard/frontend/cypress/e2e/orchestrator/workflow/05-create-cluster-review.e2e-spec.ts @@ -17,7 +17,7 @@ describe('Create Cluster Review page', () => { describe('fields check', () => { it('should check cluster resources table is present', () => { // check for table header 'Cluster Resources' - onboarding.getLegends().its(0).should('have.text', 'Cluster Resources'); + onboarding.getLegends().its(0).should('contain.text', 'Cluster Resources'); // check for fields in table onboarding.getStatusTables().should('contain.text', 'Hosts'); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.spec.ts index 18fe82a0959..f93f7edb74a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.spec.ts @@ -841,25 +841,53 @@ x4Ea7kGVgx9kWh5XjWz9wjZvY49UKIT5ppIAWPMbLl3UpfckiuNhTA== component.editing = true; }); - it('should check whether edit field is correctly loaded', () => { - const paginate_obs = new PaginateObservable(of({})); + it('should check whether edit field is correctly loaded', (done) => { + const mockService = { + service_type: 'mds', + service_id: 'test', + unmanaged: false, + placement: {} + }; + const paginate_obs = new PaginateObservable(of([mockService])); const cephServiceSpy = spyOn(cephServiceService, 'list').and.returnValue(paginate_obs); component.ngOnInit(); expect(cephServiceSpy).toBeCalledTimes(2); expect(component.action).toBe('Edit'); - const serviceType = fixture.componentInstance.serviceForm.get('service_type'); - const serviceId = fixture.componentInstance.serviceForm.get('service_id'); - expect(serviceType.disabled).toBeTruthy(); - expect(serviceId.disabled).toBeTruthy(); + + // Wait for async observable to complete before checking disabled state + setTimeout(() => { + const serviceType = fixture.componentInstance.serviceForm.get('service_type'); + const serviceId = fixture.componentInstance.serviceForm.get('service_id'); + expect(serviceType.disabled).toBeTruthy(); + expect(serviceId.disabled).toBeTruthy(); + done(); + }, 0); }); - it('should not edit groups for nvmeof service', () => { + it('should not edit groups for nvmeof service', (done) => { + const mockService = { + service_type: 'nvmeof', + service_id: 'default', + unmanaged: false, + placement: {}, + spec: { + group: 'default' + } + }; + const paginate_obs = new PaginateObservable(of([mockService])); + spyOn(cephServiceService, 'list').and.returnValue(paginate_obs); + component.serviceType = 'nvmeof'; formHelper.setValue('service_type', 'nvmeof'); component.ngOnInit(); - fixture.detectChanges(); - const groupId = fixture.debugElement.query(By.css('#group')).nativeElement; - expect(groupId.disabled).toBeTruthy(); + + // Wait for async observable to complete before checking disabled state + setTimeout(() => { + fixture.detectChanges(); + const groupId = fixture.debugElement.query(By.css('#group')).nativeElement; + expect(groupId.disabled).toBeTruthy(); + done(); + }, 0); }); it('should update nvmeof service to disable mTLS', () => { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts index 3371cc199e0..a695b958a0f 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts @@ -735,7 +735,6 @@ export class ServiceFormComponent extends CdForm implements OnInit { if (this.editing) { this.action = this.actionLabels.EDIT; - this.disableForEditing(this.serviceType); this.cephServiceService .list(new HttpParams({ fromObject: { limit: -1, offset: 0 } }), this.serviceName) .observable.subscribe((response: CephServiceSpec[]) => { @@ -743,6 +742,15 @@ export class ServiceFormComponent extends CdForm implements OnInit { formKeys.forEach((keys) => { this.serviceForm.get(keys).setValue(response[0][keys]); }); + // change is made because on editing mds service, a new service was created with mds.mds.service + // For non-prefixed services (mgr, mon, etc.), if service_id is empty, + // set it to the full service name + if (!response[0]['service_id'] && !this.isPrefixedNamedService) { + this.serviceForm.get('service_id').setValue(this.serviceName); + } + + // Disable fields AFTER setting values to ensure the view updates properly + this.disableForEditing(this.serviceType); if (response[0].certificate) { this.currentCertificate = response[0].certificate; } @@ -972,7 +980,9 @@ export class ServiceFormComponent extends CdForm implements OnInit { } break; default: - this.serviceForm.get('service_id').setValue(this.serviceName); + // No special handling needed for other service types (mds, nfs, etc.) + // service_id is already correctly set from API response at line 749 + break; } }); }