mgr/dashboard: fixed unit tests

* fixed unit tests due to upgrade to angular v18
* run npm fix in order to fix code style violations
* upgraded eslint/* packages' versions
* fixed eslint errors and warnings

Fixes: https://tracker.ceph.com/issues/68896
Signed-off-by: Ivo Almeida <ialmeida@redhat.com>
This commit is contained in:
Ivo Almeida 2024-11-13 12:16:23 +00:00
parent 6803f28124
commit 3f16e0c593
76 changed files with 1162 additions and 2044 deletions

6
package-lock.json generated Normal file
View File

@ -0,0 +1,6 @@
{
"name": "ceph",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

View File

@ -6,6 +6,10 @@
"plugins/index.js"
],
"compilerOptions": {
"typeRoots": [
"../node_modules",
"../node_modules/@types"
],
"sourceMap": false,
"types": [
"cypress",
@ -14,4 +18,4 @@
],
"target": "es6"
}
}
}

View File

@ -9,32 +9,38 @@ const esModules = [
'@ng-bootstrap'
];
const jestConfig = {
globals: {
'ts-jest': {
useESM: true,
stringifyContentPathRegex: '\\.(html|svg)$',
tsconfig: '<rootDir>/tsconfig.spec.json',
isolatedModules: true
}
},
globalSetup: 'jest-preset-angular/global-setup',
moduleNameMapper: {
'\\.scss$': 'identity-obj-proxy',
'~/(.*)$': '<rootDir>/src/$1',
'^@carbon/icons/es/(.*)$': '@carbon/icons/lib/$1.js',
'^@carbon/icons/es/(.*)$': '@carbon/icons/lib/$1.js'
},
moduleFileExtensions: ['ts', 'html', 'js', 'json', 'mjs', 'cjs'],
preset: 'jest-preset-angular',
setupFilesAfterEnv: ['<rootDir>/src/setupJest.ts'],
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$|'.concat(esModules.join('|'), ')')],
transform: {
'^.+\\.(ts|html|mjs)$': 'jest-preset-angular',
'^.+\\.(ts|html|mjs)$': [
'jest-preset-angular',
{
useESM: true,
stringifyContentPathRegex: '\\.(html|svg)$',
tsconfig: '<rootDir>/tsconfig.spec.json',
isolatedModules: true
}
],
'^.+\\.(js)$': 'babel-jest'
},
setupFiles: ['jest-canvas-mock'],
coverageReporters: ['cobertura', 'html'],
modulePathIgnorePatterns: ['<rootDir>/coverage/', '<rootDir>/node_modules/simplebar-angular', '<rootDir>/cypress'],
modulePathIgnorePatterns: [
'<rootDir>/coverage/',
'<rootDir>/node_modules/simplebar-angular',
'<rootDir>/cypress'
],
testMatch: ['**/*.spec.ts'],
testRunner: 'jest-jasmine2'
testRunner: 'jest-jasmine2',
testEnvironmentOptions: {
detectOpenHandles: true
}
};
module.exports = jestConfig;

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,7 @@
"i18n:merge": "npx i18ntool merge -c i18n.config.json",
"i18n:token": "npx i18ntool config token",
"test": "jest --watch",
"test:ci": "jest --clearCache && JEST_SILENT_REPORTER_DOTS=true jest --coverage --reporters jest-silent-reporter",
"test:ci": "jest --clearCache && JEST_SILENT_REPORTER_DOTS=true jest --detectOpenHandles --coverage --reporters jest-silent-reporter",
"pree2e": "rm -f cypress/reports/results-*.xml || true",
"e2e": "start-test 4200 'cypress open'",
"pree2e:ci": "npm run pree2e",
@ -28,7 +28,6 @@
"lint:gherkin": "gherkin-lint -c .gherkin-lintrc cypress/e2e",
"lint:prettier": "prettier --list-different \"{src,cypress}/**/*.{ts,scss}\"",
"lint:html": "htmllint src/app/**/*.html && html-linter --config html-linter.config.json",
"prelint:tsc": "npm run postinstall",
"lint:tsc": "tsc -p tsconfig.app.json --noEmit && tsc -p tsconfig.spec.json --noEmit && tsc -p cypress/tsconfig.json --noEmit",
"lint:scss": "stylelint '**/*.scss'",
"lint": "run-p -csl --aggregate-output lint:*",
@ -61,9 +60,9 @@
"@popperjs/core": "2.10.2",
"@types/file-saver": "2.0.1",
"async-mutex": "0.2.4",
"bootstrap": "5.2.3",
"bootstrap": "5.3.2",
"carbon-components-angular": "5.56.2",
"chart.js": "4.4.0",
"chart.js": "4.4.7",
"chartjs-adapter-moment": "1.0.1",
"detect-browser": "5.2.0",
"file-saver": "2.0.2",
@ -72,7 +71,7 @@
"moment": "2.29.4",
"ng-block-ui": "4.0.1",
"ng-click-outside": "9.0.1",
"ng2-charts": "4.1.1",
"ng2-charts": "7.0.0",
"ngx-cookie-service": "18.0.0",
"ngx-toastr": "17.0.2",
"rxjs": "6.6.3",
@ -86,43 +85,46 @@
},
"devDependencies": {
"@angular-devkit/build-angular": "18.2.11",
"@angular-eslint/builder": "13.5.0",
"@angular-eslint/eslint-plugin": "13.5.0",
"@angular-eslint/eslint-plugin-template": "13.5.0",
"@angular-eslint/schematics": "18.3.1",
"@angular-eslint/template-parser": "13.5.0",
"@angular-eslint/builder": "18.4.0",
"@angular-eslint/eslint-plugin": "18.4.0",
"@angular-eslint/eslint-plugin-template": "18.4.0",
"@angular-eslint/schematics": "18.4.0",
"@angular-eslint/template-parser": "18.4.0",
"@angular/cli": "18.2.11",
"@angular/compiler-cli": "18.2.11",
"@angular/language-service": "18.2.11",
"@applitools/eyes-cypress": "3.22.5",
"@compodoc/compodoc": "1.1.18",
"@cypress/browserify-preprocessor": "3.0.2",
"@juggle/resize-observer": "3.4.0",
"@types/brace-expansion": "1.1.0",
"@types/cypress": "0.1.6",
"@types/cypress-axe": "0.8.0",
"@types/cypress-cucumber-preprocessor": "4.0.1",
"@types/jest": "29.5.4",
"@types/lodash": "4.14.161",
"@types/node": "18.17.12",
"@types/swagger-ui": "3.52.0",
"@types/xml2js": "0.4.14",
"@typescript-eslint/eslint-plugin": "5.27.1",
"@typescript-eslint/parser": "5.27.1",
"@typescript-eslint/eslint-plugin": "8.14.0",
"@typescript-eslint/parser": "8.14.0",
"axe-core": "4.4.3",
"cypress": "12.17.4",
"cypress-axe": "1.5.0",
"cypress-cucumber-preprocessor": "4.3.1",
"cypress-iframe": "1.0.1",
"cypress-multi-reporters": "1.5.0",
"eslint": "8.17.0",
"eslint": "9.14.0",
"gherkin-lint": "4.2.2",
"html-linter": "1.1.1",
"htmllint-cli": "0.0.7",
"identity-obj-proxy": "3.0.0",
"isomorphic-form-data": "2.0.0",
"jest": "29.6.4",
"jest": "29.7.0",
"jest-canvas-mock": "2.4.0",
"jest-jasmine2": "28.1.3",
"jest-preset-angular": "14.2.4",
"jest-silent-reporter": "0.5.0",
"jest-silent-reporter": "0.6.0",
"mocha-junit-reporter": "2.1.0",
"ng-mocks": "14.13.1",
"npm-run-all": "4.1.5",

View File

@ -14,32 +14,38 @@ import { ApiInterceptorService } from './shared/services/api-interceptor.service
import { JsErrorHandler } from './shared/services/js-error-handler.service';
import { SharedModule } from './shared/shared.module';
@NgModule({ declarations: [AppComponent],
exports: [SharedModule],
bootstrap: [AppComponent], imports: [BrowserModule,
BrowserAnimationsModule,
ToastrModule.forRoot({
positionClass: 'toast-top-right',
preventDuplicates: true,
enableHtml: true
}),
AppRoutingModule,
CoreModule,
SharedModule,
CephModule], providers: [
{
provide: ErrorHandler,
useClass: JsErrorHandler
},
{
provide: HTTP_INTERCEPTORS,
useClass: ApiInterceptorService,
multi: true
},
{
provide: APP_BASE_HREF,
useValue: '/' + (window.location.pathname.split('/', 1)[1] || '')
},
provideHttpClient(withInterceptorsFromDi())
] })
@NgModule({
declarations: [AppComponent],
exports: [SharedModule],
bootstrap: [AppComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
ToastrModule.forRoot({
positionClass: 'toast-top-right',
preventDuplicates: true,
enableHtml: true
}),
AppRoutingModule,
CoreModule,
SharedModule,
CephModule
],
providers: [
{
provide: ErrorHandler,
useClass: JsErrorHandler
},
{
provide: HTTP_INTERCEPTORS,
useClass: ApiInterceptorService,
multi: true
},
{
provide: APP_BASE_HREF,
useValue: '/' + (window.location.pathname.split('/', 1)[1] || '')
},
provideHttpClient(withInterceptorsFromDi())
]
})
export class AppModule {}

View File

@ -6,7 +6,6 @@ import { RouterTestingModule } from '@angular/router/testing';
import { ToastrModule } from 'ngx-toastr';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { SelectOption } from '~/app/shared/components/select/select-option.model';
import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
import { SharedModule } from '~/app/shared/shared.module';
@ -137,25 +136,22 @@ describe('IscsiTargetFormComponent', () => {
}
];
configureTestBed(
{
declarations: [IscsiTargetFormComponent],
imports: [
SharedModule,
ReactiveFormsModule,
HttpClientTestingModule,
RouterTestingModule,
ToastrModule.forRoot()
],
providers: [
{
provide: ActivatedRoute,
useValue: new ActivatedRouteStub({ target_iqn: undefined })
}
]
},
[LoadingPanelComponent]
);
configureTestBed({
declarations: [IscsiTargetFormComponent],
imports: [
SharedModule,
ReactiveFormsModule,
HttpClientTestingModule,
RouterTestingModule,
ToastrModule.forRoot()
],
providers: [
{
provide: ActivatedRoute,
useValue: new ActivatedRouteStub({ target_iqn: undefined })
}
]
});
beforeEach(() => {
fixture = TestBed.createComponent(IscsiTargetFormComponent);

View File

@ -1,4 +1,4 @@
import { Component, TemplateRef, ViewChild } from '@angular/core';
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import _ from 'lodash';
@ -28,7 +28,7 @@ type Gateway = {
templateUrl: './nvmeof-gateway.component.html',
styleUrls: ['./nvmeof-gateway.component.scss']
})
export class NvmeofGatewayComponent {
export class NvmeofGatewayComponent implements OnInit {
@ViewChild('statusTpl', { static: true })
statusTpl: TemplateRef<any>;

View File

@ -4,7 +4,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterTestingModule } from '@angular/router/testing';
import { NgbDropdownModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
import { NgChartsModule } from 'ng2-charts';
import { BaseChartDirective } from 'ng2-charts';
import { ComponentsModule } from '~/app/shared/components/components.module';
import { RbdConfigurationEntry } from '~/app/shared/models/configuration';
@ -25,7 +25,7 @@ describe('RbdConfigurationListComponent', () => {
RouterTestingModule,
ComponentsModule,
NgbDropdownModule,
NgChartsModule,
BaseChartDirective,
SharedModule,
NgbTooltipModule
],

View File

@ -10,7 +10,6 @@ import { Subject, throwError as observableThrowError } from 'rxjs';
import { RbdService } from '~/app/shared/api/rbd.service';
import { ComponentsModule } from '~/app/shared/components/components.module';
import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
import { DataTableModule } from '~/app/shared/datatable/datatable.module';
import { TableActionsComponent } from '~/app/shared/datatable/table-actions/table-actions.component';
@ -55,38 +54,35 @@ describe('RbdSnapshotListComponent', () => {
}
};
configureTestBed(
{
declarations: [
RbdSnapshotListComponent,
RbdTabsComponent,
MockComponent(RbdSnapshotFormModalComponent),
BaseModal
],
imports: [
BrowserAnimationsModule,
ComponentsModule,
DataTableModule,
HttpClientTestingModule,
PipesModule,
RouterTestingModule,
NgbNavModule,
ToastrModule.forRoot(),
ModalModule,
PlaceholderModule,
CoreModule
],
providers: [
{ provide: AuthStorageService, useValue: fakeAuthStorageService },
TaskListService,
ModalService,
PlaceholderService,
BaseModalService
],
schemas: [NO_ERRORS_SCHEMA]
},
[CriticalConfirmationModalComponent]
);
configureTestBed({
declarations: [
RbdSnapshotListComponent,
RbdTabsComponent,
MockComponent(RbdSnapshotFormModalComponent),
BaseModal
],
imports: [
BrowserAnimationsModule,
ComponentsModule,
DataTableModule,
HttpClientTestingModule,
PipesModule,
RouterTestingModule,
NgbNavModule,
ToastrModule.forRoot(),
ModalModule,
PlaceholderModule,
CoreModule
],
providers: [
{ provide: AuthStorageService, useValue: fakeAuthStorageService },
TaskListService,
ModalService,
PlaceholderService,
BaseModalService
],
schemas: [NO_ERRORS_SCHEMA]
});
beforeEach(() => {
fixture = TestBed.createComponent(RbdSnapshotListComponent);

View File

@ -90,7 +90,6 @@
formControlName="directory"
[skeleton]="directoryStore.isLoading"
[invalid]="!form.controls['directory'].valid && (form.controls['directory'].dirty)"
[disabled]="directoryStore.isLoading"
[ngbTypeahead]="search">
</cds-text-label>
<ng-template #directoryError>

View File

@ -83,6 +83,11 @@ export class CephfsAuthModalComponent extends CdForm implements OnInit, AfterVie
this.directoryStore.loadDirectories(this.id, '/', 3);
this.createForm();
this.loadingReady();
if (this.directoryStore?.isLoading) {
this.form.get('directory').disable();
} else {
this.form.get('directory').disable();
}
}
createForm() {

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NgChartsModule } from 'ng2-charts';
import { BaseChartDirective } from 'ng2-charts';
import { configureTestBed } from '~/testing/unit-test-helper';
import { CephfsChartComponent } from './cephfs-chart.component';
@ -18,7 +18,7 @@ describe('CephfsChartComponent', () => {
];
configureTestBed({
imports: [NgChartsModule],
imports: [BaseChartDirective],
declarations: [CephfsChartComponent]
});

View File

@ -3,6 +3,7 @@ import { Component, ElementRef, Input, OnChanges, OnInit, ViewChild } from '@ang
import _ from 'lodash';
import moment from 'moment';
import 'chartjs-adapter-moment';
import { Chart, registerables } from 'chart.js';
import { ChartTooltip } from '~/app/shared/models/chart-tooltip';
@ -102,6 +103,10 @@ export class CephfsChartComponent implements OnChanges, OnInit {
chartType: 'line'
};
constructor() {
Chart.register(...registerables);
}
ngOnInit() {
if (_.isUndefined(this.mdsCounter)) {
return;

View File

@ -12,7 +12,6 @@ import _ from 'lodash';
import { CephfsService } from '~/app/shared/api/cephfs.service';
import { ConfirmationModalComponent } from '~/app/shared/components/confirmation-modal/confirmation-modal.component';
import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
import { FormModalComponent } from '~/app/shared/components/form-modal/form-modal.component';
import { NotificationType } from '~/app/shared/enum/notification-type.enum';
import { CdValidators } from '~/app/shared/forms/cd-validators';
@ -388,21 +387,18 @@ describe('CephfsDirectoriesComponent', () => {
}
};
configureTestBed(
{
imports: [
HttpClientTestingModule,
SharedModule,
RouterTestingModule,
TreeviewModule,
ToastrModule.forRoot(),
NgbModalModule
],
declarations: [CephfsDirectoriesComponent],
providers: [NgbActiveModal]
},
[CriticalConfirmationModalComponent, FormModalComponent, ConfirmationModalComponent]
);
configureTestBed({
imports: [
HttpClientTestingModule,
SharedModule,
RouterTestingModule,
TreeviewModule,
ToastrModule.forRoot(),
NgbModalModule
],
declarations: [CephfsDirectoriesComponent],
providers: [NgbActiveModal]
});
beforeEach(() => {
noAsyncUpdate = false;
@ -674,7 +670,6 @@ describe('CephfsDirectoriesComponent', () => {
mockLib.selectNode('/a/c');
mockLib.selectNode('/a/c/a');
component.selectOrigin('/a');
console.debug('component.selectedDir', component.selectedDir);
expect(component.selectedDir.path).toBe('/a');
});

View File

@ -68,26 +68,7 @@ export class CephfsSnapshotscheduleListComponent
errorMessage: string = '';
selectedName: string = '';
icons = Icons;
tableActions: CdTableAction[] = [
{
name: this.actionLabels.CREATE,
permission: 'create',
icon: Icons.add,
click: () => this.openModal(false)
},
{
name: this.actionLabels.EDIT,
permission: 'update',
icon: Icons.edit,
click: () => this.openModal(true)
},
{
name: this.actionLabels.DELETE,
permission: 'delete',
icon: Icons.trash,
click: () => this.deleteSnapshotSchedule()
}
];
tableActions!: CdTableAction[];
MODULE_NAME = 'snap_schedule';
ENABLE_MODULE_TIMER = 2 * 1000;
@ -112,6 +93,27 @@ export class CephfsSnapshotscheduleListComponent
}
ngOnInit(): void {
this.tableActions = [
{
name: this.actionLabels.CREATE,
permission: 'create',
icon: Icons.add,
click: () => this.openModal(false)
},
{
name: this.actionLabels.EDIT,
permission: 'update',
icon: Icons.edit,
click: () => this.openModal(true)
},
{
name: this.actionLabels.DELETE,
permission: 'delete',
icon: Icons.trash,
click: () => this.deleteSnapshotSchedule()
}
];
this.moduleServiceListSub = this.mgrModuleService
.list()
.pipe(

View File

@ -9,7 +9,7 @@ import {
NgbTooltipModule,
NgbTypeaheadModule
} from '@ng-bootstrap/ng-bootstrap';
import { NgChartsModule } from 'ng2-charts';
import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts';
import { AppRoutingModule } from '~/app/app-routing.module';
import { SharedModule } from '~/app/shared/shared.module';
@ -59,7 +59,6 @@ import Trash from '@carbon/icons/es/trash-can/32';
CommonModule,
SharedModule,
AppRoutingModule,
NgChartsModule,
TreeviewModule,
NgbNavModule,
FormsModule,
@ -83,7 +82,8 @@ import Trash from '@carbon/icons/es/trash-can/32';
NumberModule,
LayoutModule,
ComboBoxModule,
IconModule
IconModule,
BaseChartDirective
],
declarations: [
CephfsDetailComponent,
@ -104,7 +104,8 @@ import Trash from '@carbon/icons/es/trash-can/32';
CephfsSubvolumeSnapshotsFormComponent,
CephfsMountDetailsComponent,
CephfsAuthModalComponent
]
],
providers: [provideCharts(withDefaultRegisterables())]
})
export class CephfsModule {
constructor(private iconService: IconService) {

View File

@ -45,7 +45,7 @@
<div cdsCol
[columnNumbers]="{'lg': 14, 'md': 14, 'sm': 14}">
<ng-container [ngSwitch]="currentStep?.stepIndex">
<div *ngSwitchCase="'0'"
<div *ngSwitchCase="0"
class="ms-5">
<h4 class="title"
i18n>Add Hosts</h4>
@ -56,7 +56,7 @@
[showGeneralActionsOnly]="true"
[showExpandClusterBtn]="false"></cd-hosts>
</div>
<div *ngSwitchCase="'1'"
<div *ngSwitchCase="1"
class="ms-5">
<h4 class="title"
i18n>Create OSDs</h4>
@ -68,7 +68,7 @@
(emitMode)="setDeploymentMode($event)"></cd-osd-form>
</div>
</div>
<div *ngSwitchCase="'2'"
<div *ngSwitchCase="2"
class="ms-5">
<h4 class="title"
i18n>Create Services</h4>
@ -77,7 +77,7 @@
[hiddenColumns]="['status.running', 'status.size', 'status.last_refresh']"
[routedModal]="false"></cd-services>
</div>
<div *ngSwitchCase="'3'"
<div *ngSwitchCase="3"
class="ms-5">
<cd-create-cluster-review></cd-create-cluster-review>
</div>

View File

@ -10,7 +10,6 @@ import { CoreModule } from '~/app/core/core.module';
import { HostService } from '~/app/shared/api/host.service';
import { OsdService } from '~/app/shared/api/osd.service';
import { ConfirmationModalComponent } from '~/app/shared/components/confirmation-modal/confirmation-modal.component';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { AppConstants } from '~/app/shared/constants/app.constants';
import { ModalService } from '~/app/shared/services/modal.service';
import { WizardStepsService } from '~/app/shared/services/wizard-steps.service';
@ -27,19 +26,16 @@ describe('CreateClusterComponent', () => {
let modalServiceShowSpy: jasmine.Spy;
const projectConstants: typeof AppConstants = AppConstants;
configureTestBed(
{
imports: [
HttpClientTestingModule,
RouterTestingModule,
ToastrModule.forRoot(),
SharedModule,
CoreModule,
CephModule
]
},
[LoadingPanelComponent]
);
configureTestBed({
imports: [
HttpClientTestingModule,
RouterTestingModule,
ToastrModule.forRoot(),
SharedModule,
CoreModule,
CephModule
]
});
beforeEach(() => {
fixture = TestBed.createComponent(CreateClusterComponent);

View File

@ -1,4 +1,6 @@
import {
AfterViewInit,
ChangeDetectorRef,
Component,
EventEmitter,
OnDestroy,
@ -39,7 +41,7 @@ import { Step } from 'carbon-components-angular';
templateUrl: './create-cluster.component.html',
styleUrls: ['./create-cluster.component.scss']
})
export class CreateClusterComponent implements OnInit, OnDestroy {
export class CreateClusterComponent implements OnInit, OnDestroy, AfterViewInit {
@ViewChild('skipConfirmTpl', { static: true })
skipConfirmTpl: TemplateRef<any>;
currentStep: WizardStepModel;
@ -88,7 +90,8 @@ export class CreateClusterComponent implements OnInit, OnDestroy {
private taskWrapper: TaskWrapperService,
private osdService: OsdService,
private route: ActivatedRoute,
private location: Location
private location: Location,
private changeDetectorRef: ChangeDetectorRef
) {
this.permissions = this.authStorageService.getPermissions();
this.currentStepSub = this.wizardStepsService
@ -98,6 +101,9 @@ export class CreateClusterComponent implements OnInit, OnDestroy {
});
this.currentStep.stepIndex = 0;
}
ngAfterViewInit(): void {
this.changeDetectorRef.detectChanges();
}
ngOnInit(): void {
this.stepTitles.forEach((steps, index) => {

View File

@ -6,7 +6,6 @@ import { RouterTestingModule } from '@angular/router/testing';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { ToastrModule } from 'ngx-toastr';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { SharedModule } from '~/app/shared/shared.module';
import { configureTestBed, FormHelper } from '~/testing/unit-test-helper';
import { HostFormComponent } from './host-form.component';
@ -17,22 +16,19 @@ describe('HostFormComponent', () => {
let fixture: ComponentFixture<HostFormComponent>;
let formHelper: FormHelper;
configureTestBed(
{
imports: [
SharedModule,
HttpClientTestingModule,
RouterTestingModule,
ReactiveFormsModule,
ToastrModule.forRoot(),
InputModule,
ModalModule
],
declarations: [HostFormComponent],
providers: [NgbActiveModal]
},
[LoadingPanelComponent]
);
configureTestBed({
imports: [
SharedModule,
HttpClientTestingModule,
RouterTestingModule,
ReactiveFormsModule,
ToastrModule.forRoot(),
InputModule,
ModalModule
],
declarations: [HostFormComponent],
providers: [NgbActiveModal]
});
beforeEach(() => {
fixture = TestBed.createComponent(HostFormComponent);

View File

@ -18,8 +18,7 @@
[maxLimit]="25"
(setExpandedRow)="setExpandedRow($event)"
(updateSelection)="updateSelection($event)"
[toolHeader]="!hideToolHeader"
[showMenu]="showMenu">
[toolHeader]="!hideToolHeader">
<div class="table-actions">
<cd-table-actions [permission]="permissions.hosts"
[selection]="selection"

View File

@ -5,7 +5,6 @@ import { RouterTestingModule } from '@angular/router/testing';
import { ToastrModule } from 'ngx-toastr';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { SharedModule } from '~/app/shared/shared.module';
import { configureTestBed } from '~/testing/unit-test-helper';
import { MgrModuleFormComponent } from './mgr-module-form.component';
@ -14,19 +13,16 @@ describe('MgrModuleFormComponent', () => {
let component: MgrModuleFormComponent;
let fixture: ComponentFixture<MgrModuleFormComponent>;
configureTestBed(
{
declarations: [MgrModuleFormComponent],
imports: [
HttpClientTestingModule,
ReactiveFormsModule,
RouterTestingModule,
SharedModule,
ToastrModule.forRoot()
]
},
[LoadingPanelComponent]
);
configureTestBed({
declarations: [MgrModuleFormComponent],
imports: [
HttpClientTestingModule,
ReactiveFormsModule,
RouterTestingModule,
SharedModule,
ToastrModule.forRoot()
]
});
beforeEach(() => {
fixture = TestBed.createComponent(MgrModuleFormComponent);

View File

@ -86,7 +86,7 @@ describe('SilenceFormComponent', () => {
});
const changeAction = (action: string) => {
const modes = {
const modes: Record<string, string> = {
add: '/monitoring/silences/add',
alertAdd: '/monitoring/silences/add/alert0',
recreate: '/monitoring/silences/recreate/someExpiredId',
@ -180,7 +180,7 @@ describe('SilenceFormComponent', () => {
let navigateSpy: jasmine.Spy;
const expectError = (action: string, redirected: boolean) => {
Object.defineProperty(router, 'url', { value: action });
Object.defineProperty(router, 'url', { value: action, configurable: true });
if (redirected) {
expect(() => callInit()).toThrowError(DashboardNotFoundError);
} else {

View File

@ -9,8 +9,6 @@ import { ToastrModule } from 'ngx-toastr';
import { of as observableOf } from 'rxjs';
import { MgrModuleService } from '~/app/shared/api/mgr-module.service';
import { DownloadButtonComponent } from '~/app/shared/components/download-button/download-button.component';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { SharedModule } from '~/app/shared/shared.module';
import { configureTestBed } from '~/testing/unit-test-helper';
import { TelemetryComponent } from './telemetry.component';
@ -46,19 +44,16 @@ describe('TelemetryComponent', () => {
'url'
];
configureTestBed(
{
declarations: [TelemetryComponent],
imports: [
HttpClientTestingModule,
ReactiveFormsModule,
RouterTestingModule,
SharedModule,
ToastrModule.forRoot()
]
},
[LoadingPanelComponent, DownloadButtonComponent]
);
configureTestBed({
declarations: [TelemetryComponent],
imports: [
HttpClientTestingModule,
ReactiveFormsModule,
RouterTestingModule,
SharedModule,
ToastrModule.forRoot()
]
});
describe('configForm', () => {
beforeEach(() => {

View File

@ -1,4 +1,11 @@
import { Component, Input, ViewChild, OnChanges, SimpleChanges } from '@angular/core';
import {
Component,
Input,
ViewChild,
OnChanges,
SimpleChanges,
AfterViewInit
} from '@angular/core';
import { CssHelper } from '~/app/shared/classes/css-helper';
import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe';
@ -14,7 +21,7 @@ import 'chartjs-adapter-moment';
templateUrl: './dashboard-area-chart.component.html',
styleUrls: ['./dashboard-area-chart.component.scss']
})
export class DashboardAreaChartComponent implements OnChanges {
export class DashboardAreaChartComponent implements OnChanges, AfterViewInit {
@ViewChild(BaseChartDirective) chart: BaseChartDirective;
@Input()
@ -44,32 +51,7 @@ export class DashboardAreaChartComponent implements OnChanges {
options: any = {};
currentChartData: any = {};
chartColors: any[] = [
[
this.cssHelper.propertyValue('chart-color-strong-blue'),
this.cssHelper.propertyValue('chart-color-translucent-blue')
],
[
this.cssHelper.propertyValue('chart-color-orange'),
this.cssHelper.propertyValue('chart-color-translucent-orange')
],
[
this.cssHelper.propertyValue('chart-color-green'),
this.cssHelper.propertyValue('chart-color-translucent-green')
],
[
this.cssHelper.propertyValue('chart-color-cyan'),
this.cssHelper.propertyValue('chart-color-translucent-cyan')
],
[
this.cssHelper.propertyValue('chart-color-purple'),
this.cssHelper.propertyValue('chart-color-translucent-purple')
],
[
this.cssHelper.propertyValue('chart-color-red'),
this.cssHelper.propertyValue('chart-color-translucent-red')
]
];
chartColors!: any[];
public chartAreaBorderPlugin: any[] = [
{
@ -100,6 +82,33 @@ export class DashboardAreaChartComponent implements OnChanges {
private formatter: FormatterService,
private numberFormatter: NumberFormatterService
) {
this.chartColors = [
[
this.cssHelper.propertyValue('chart-color-strong-blue'),
this.cssHelper.propertyValue('chart-color-translucent-blue')
],
[
this.cssHelper.propertyValue('chart-color-orange'),
this.cssHelper.propertyValue('chart-color-translucent-orange')
],
[
this.cssHelper.propertyValue('chart-color-green'),
this.cssHelper.propertyValue('chart-color-translucent-green')
],
[
this.cssHelper.propertyValue('chart-color-cyan'),
this.cssHelper.propertyValue('chart-color-translucent-cyan')
],
[
this.cssHelper.propertyValue('chart-color-purple'),
this.cssHelper.propertyValue('chart-color-translucent-purple')
],
[
this.cssHelper.propertyValue('chart-color-red'),
this.cssHelper.propertyValue('chart-color-translucent-red')
]
];
this.options = {
plugins: {
legend: {

View File

@ -4,7 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { NgbNavModule, NgbPopoverModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
import { NgChartsModule } from 'ng2-charts';
import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts';
import { SimplebarAngularModule } from 'simplebar-angular';
import { SharedModule } from '~/app/shared/shared.module';
@ -21,15 +21,14 @@ import { PgSummaryPipe } from './pg-summary.pipe';
CommonModule,
NgbNavModule,
SharedModule,
NgChartsModule,
RouterModule,
NgbPopoverModule,
NgbTooltipModule,
FormsModule,
ReactiveFormsModule,
SimplebarAngularModule
SimplebarAngularModule,
BaseChartDirective
],
declarations: [
DashboardV3Component,
DashboardPieComponent,
@ -37,12 +36,12 @@ import { PgSummaryPipe } from './pg-summary.pipe';
DashboardAreaChartComponent,
DashboardTimeSelectorComponent
],
exports: [
DashboardV3Component,
DashboardAreaChartComponent,
DashboardTimeSelectorComponent,
DashboardPieComponent
]
],
providers: [provideCharts(withDefaultRegisterables())]
})
export class DashboardV3Module {}

View File

@ -4,7 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { NgbNavModule, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap';
import { NgChartsModule } from 'ng2-charts';
import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts';
import { SharedModule } from '~/app/shared/shared.module';
import { DashboardV3Module } from '../dashboard-v3/dashboard-v3.module';
@ -15,10 +15,10 @@ import { HealthPieComponent } from './health-pie/health-pie.component';
import { HealthComponent } from './health/health.component';
import { InfoCardComponent } from './info-card/info-card.component';
import { InfoGroupComponent } from './info-group/info-group.component';
import { MdsSummaryPipe } from './mds-summary.pipe';
import { MgrSummaryPipe } from './mgr-summary.pipe';
import { MdsDashboardSummaryPipe } from './mds-dashboard-summary.pipe';
import { MgrDashboardSummaryPipe } from './mgr-dashboard-summary.pipe';
import { MonSummaryPipe } from './mon-summary.pipe';
import { OsdSummaryPipe } from './osd-summary.pipe';
import { osdDashboardSummaryPipe } from './osd-dashboard-summary.pipe';
@NgModule({
imports: [
@ -26,25 +26,25 @@ import { OsdSummaryPipe } from './osd-summary.pipe';
CommonModule,
NgbNavModule,
SharedModule,
NgChartsModule,
RouterModule,
NgbPopoverModule,
FormsModule,
ReactiveFormsModule,
DashboardV3Module
DashboardV3Module,
BaseChartDirective
],
declarations: [
HealthComponent,
DashboardComponent,
MonSummaryPipe,
OsdSummaryPipe,
MgrSummaryPipe,
MdsSummaryPipe,
osdDashboardSummaryPipe,
MgrDashboardSummaryPipe,
MdsDashboardSummaryPipe,
HealthPieComponent,
InfoCardComponent,
InfoGroupComponent,
FeedbackComponent
]
],
providers: [provideCharts(withDefaultRegisterables())]
})
export class DashboardModule {}

View File

@ -2,36 +2,36 @@
class="container-fluid">
<cd-info-group groupTitle="Status"
i18n-groupTitle
*ngIf="healthData.health?.status
|| healthData.mon_status
|| healthData.osd_map
|| healthData.mgr_map
|| healthData.hosts != null
|| healthData.rgw != null
|| healthData.fs_map
|| healthData.iscsi_daemons != null">
*ngIf="healthData?.health?.status
|| healthData?.mon_status
|| healthData?.osd_map
|| healthData?.mgr_map
|| healthData?.hosts != null
|| healthData?.rgw != null
|| healthData?.fs_map
|| healthData?.iscsi_daemons != null">
<cd-info-card cardTitle="Cluster Status"
i18n-cardTitle
class="cd-status-card"
contentClass="content-highlight"
*ngIf="healthData.health?.status">
<ng-container *ngIf="healthData.health?.checks?.length > 0">
*ngIf="healthData?.health?.status">
<ng-container *ngIf="healthData?.health?.checks?.length > 0">
<ng-template #healthChecks>
<cd-health-checks [healthData]="healthData"></cd-health-checks>
</ng-template>
<div class="info-card-content-clickable"
[ngStyle]="healthData.health.status | healthColor"
[ngStyle]="healthData?.health?.status | healthColor"
[ngbPopover]="healthChecks"
popoverClass="info-card-popover-cluster-status">
{{ healthData.health.status | healthLabel | uppercase }}
<i *ngIf="healthData.health?.status !== 'HEALTH_OK'"
{{ healthData?.health?.status | healthLabel | uppercase }}
<i *ngIf="healthData?.health?.status !== 'HEALTH_OK'"
class="fa fa-exclamation-triangle"></i>
</div>
</ng-container>
<ng-container *ngIf="!healthData.health?.checks?.length">
<div [ngStyle]="healthData.health.status | healthColor">
{{ healthData.health.status | healthLabel | uppercase }}
<ng-container *ngIf="!healthData?.health?.checks?.length">
<div [ngStyle]="healthData?.health.status | healthColor">
{{ healthData?.health.status | healthLabel | uppercase }}
</div>
</ng-container>
</cd-info-card>
@ -41,8 +41,8 @@
link="/hosts"
class="cd-status-card"
contentClass="content-highlight"
*ngIf="healthData.hosts != null">
{{ healthData.hosts }} total
*ngIf="healthData?.hosts != null">
{{ healthData?.hosts }} total
</cd-info-card>
<cd-info-card cardTitle="Monitors"
@ -50,15 +50,15 @@
link="/monitor"
class="cd-status-card"
contentClass="content-highlight"
*ngIf="healthData.mon_status">
{{ healthData.mon_status | monSummary }}
*ngIf="healthData?.mon_status">
{{ healthData?.mon_status | monSummary }}
</cd-info-card>
<cd-info-card cardTitle="OSDs"
i18n-cardTitle
link="/osd"
class="cd-status-card"
*ngIf="(healthData.osd_map | osdSummary) as transformedResult"
*ngIf="(healthData?.osd_map | osdDashboardSummary) as transformedResult"
contentClass="content-highlight">
<span *ngFor="let result of transformedResult"
[ngClass]="result.class">
@ -70,8 +70,8 @@
i18n-cardTitle
class="cd-status-card"
contentClass="content-highlight"
*ngIf="healthData.mgr_map">
<span *ngFor="let result of (healthData.mgr_map | mgrSummary)"
*ngIf="healthData?.mgr_map">
<span *ngFor="let result of (healthData?.mgr_map | mgrDashboardSummary)"
[ngClass]="result.class"
[title]="result.titleText != null ? result.titleText : ''">
{{ result.content }}
@ -83,14 +83,14 @@
link="/rgw/daemon"
class="cd-status-card"
contentClass="content-highlight"
*ngIf="enabledFeature.rgw && healthData?.rgw != null">
{{ healthData.rgw }} total
*ngIf="enabledFeature?.rgw && healthData?.rgw != null">
{{ healthData?.rgw }} total
</cd-info-card>
<cd-info-card cardTitle="Metadata Servers"
i18n-cardTitle
class="cd-status-card"
*ngIf="(enabledFeature.cephfs && healthData.fs_map | mdsSummary) as transformedResult"
*ngIf="(enabledFeature?.cephfs && healthData?.fs_map | mdsDashboardSummary) as transformedResult"
[contentClass]="(transformedResult.length > 1 ? 'text-area-size-2' : '') + ' content-highlight'">
<!-- TODO: check text-area-size-2 -->
<span *ngFor="let result of transformedResult"
@ -105,25 +105,25 @@
link="/block/iscsi"
class="cd-status-card"
contentClass="content-highlight"
*ngIf="enabledFeature.iscsi && healthData?.iscsi_daemons != null">
{{ healthData.iscsi_daemons.up + healthData.iscsi_daemons.down }} total
*ngIf="enabledFeature?.iscsi && healthData?.iscsi_daemons != null">
{{ healthData?.iscsi_daemons.up + healthData?.iscsi_daemons.down }} total
<span class="card-text-line-break"></span>
{{ healthData.iscsi_daemons.up }} up,
<span [ngClass]="{'card-text-error': healthData.iscsi_daemons.down > 0}">{{ healthData.iscsi_daemons.down }}
{{ healthData?.iscsi_daemons.up }} up,
<span [ngClass]="{'card-text-error': healthData?.iscsi_daemons.down > 0}">{{ healthData?.iscsi_daemons.down }}
down</span>
</cd-info-card>
</cd-info-group>
<cd-info-group groupTitle="Capacity"
i18n-groupTitle
*ngIf="healthData.pools
|| healthData.df
|| healthData.pg_info">
*ngIf="healthData?.pools
|| healthData?.df
|| healthData?.pg_info">
<cd-info-card cardTitle="Raw Capacity"
i18n-cardTitle
class="cd-capacity-card cd-chart-card"
contentClass="content-chart"
*ngIf="healthData.df">
*ngIf="healthData?.df">
<cd-health-pie [data]="healthData"
[config]="rawCapacityChartConfig"
[isBytesData]="true"
@ -135,7 +135,7 @@
i18n-cardTitle
class="cd-capacity-card cd-chart-card"
contentClass="content-chart"
*ngIf="healthData.pg_info?.object_stats?.num_objects != null">
*ngIf="healthData?.pg_info?.object_stats?.num_objects != null">
<cd-health-pie [data]="healthData"
(prepareFn)="prepareObjects($event[0], $event[1])">
</cd-health-pie>
@ -145,11 +145,11 @@
i18n-cardTitle
class="cd-capacity-card cd-chart-card"
contentClass="content-chart"
*ngIf="healthData.pg_info">
*ngIf="healthData?.pg_info">
<ng-template #pgStatus>
<ng-container *ngTemplateOutlet="logsLink"></ng-container>
<ul>
<li *ngFor="let pgStatesText of healthData.pg_info.statuses | keyvalue">
<li *ngFor="let pgStatesText of healthData?.pg_info.statuses | keyvalue">
{{ pgStatesText.key }}: {{ pgStatesText.value }}
</li>
</ul>
@ -169,27 +169,27 @@
link="/pool"
class="cd-capacity-card"
contentClass="content-highlight"
*ngIf="healthData.pools">
{{ healthData.pools.length }}
*ngIf="healthData?.pools">
{{ healthData?.pools.length }}
</cd-info-card>
<cd-info-card cardTitle="PGs per OSD"
i18n-cardTitle
class="cd-capacity-card"
contentClass="content-highlight"
*ngIf="healthData.pg_info">
{{ healthData.pg_info.pgs_per_osd | dimless }}
*ngIf="healthData?.pg_info">
{{ healthData?.pg_info.pgs_per_osd | dimless }}
</cd-info-card>
</cd-info-group>
<cd-info-group groupTitle="Performance"
i18n-groupTitle
*ngIf="healthData.client_perf || healthData.scrub_status">
*ngIf="healthData?.client_perf || healthData?.scrub_status">
<cd-info-card cardTitle="Client Read/Write"
i18n-cardTitle
class="cd-performance-card cd-chart-card"
contentClass="content-chart"
*ngIf="healthData.client_perf">
*ngIf="healthData?.client_perf">
<cd-health-pie [data]="healthData"
[config]="clientStatsConfig"
(prepareFn)="prepareReadWriteRatio($event[0], $event[1])">
@ -200,7 +200,7 @@
i18n-cardTitle
class="cd-performance-card cd-chart-card"
contentClass="content-chart"
*ngIf="healthData.client_perf">
*ngIf="healthData?.client_perf">
<cd-health-pie [data]="healthData"
[config]="clientStatsConfig"
(prepareFn)="prepareClientThroughput($event[0], $event[1])">
@ -211,21 +211,21 @@
i18n-cardTitle
class="cd-performance-card"
contentClass="content-highlight"
*ngIf="healthData.client_perf">
{{ (healthData.client_perf.recovering_bytes_per_sec | dimlessBinary) + '/s' }}
*ngIf="healthData?.client_perf">
{{ (healthData?.client_perf.recovering_bytes_per_sec | dimlessBinary) + '/s' }}
</cd-info-card>
<cd-info-card cardTitle="Scrubbing"
i18n-cardTitle
class="cd-performance-card"
contentClass="content-highlight"
*ngIf="healthData.scrub_status">
{{ healthData.scrub_status }}
*ngIf="healthData?.scrub_status">
{{ healthData?.scrub_status }}
</cd-info-card>
</cd-info-group>
<ng-template #logsLink>
<ng-container *ngIf="permissions.log.read">
<ng-container *ngIf="permissions?.log?.read">
<p class="logs-link"
i18n><i [ngClass]="[icons.infoCircle]"></i> See <a routerLink="/logs">Logs</a> for more details.</p>
</ng-container>

View File

@ -16,10 +16,10 @@ import { RefreshIntervalService } from '~/app/shared/services/refresh-interval.s
import { SharedModule } from '~/app/shared/shared.module';
import { configureTestBed } from '~/testing/unit-test-helper';
import { HealthPieComponent } from '../health-pie/health-pie.component';
import { MdsSummaryPipe } from '../mds-summary.pipe';
import { MgrSummaryPipe } from '../mgr-summary.pipe';
import { MdsDashboardSummaryPipe } from '../mds-dashboard-summary.pipe';
import { MgrDashboardSummaryPipe } from '../mgr-dashboard-summary.pipe';
import { MonSummaryPipe } from '../mon-summary.pipe';
import { OsdSummaryPipe } from '../osd-summary.pipe';
import { osdDashboardSummaryPipe } from '../osd-dashboard-summary.pipe';
import { HealthComponent } from './health.component';
describe('HealthComponent', () => {
@ -54,9 +54,9 @@ describe('HealthComponent', () => {
HealthComponent,
HealthPieComponent,
MonSummaryPipe,
OsdSummaryPipe,
MdsSummaryPipe,
MgrSummaryPipe
osdDashboardSummaryPipe,
MdsDashboardSummaryPipe,
MgrDashboardSummaryPipe
],
schemas: [NO_ERRORS_SCHEMA],
providers: [

View File

@ -1,17 +1,17 @@
import { TestBed } from '@angular/core/testing';
import { configureTestBed } from '~/testing/unit-test-helper';
import { MdsSummaryPipe } from './mds-summary.pipe';
import { MdsDashboardSummaryPipe } from './mds-dashboard-summary.pipe';
describe('MdsSummaryPipe', () => {
let pipe: MdsSummaryPipe;
describe('MdsDashboardSummaryPipe', () => {
let pipe: MdsDashboardSummaryPipe;
configureTestBed({
providers: [MdsSummaryPipe]
providers: [MdsDashboardSummaryPipe]
});
beforeEach(() => {
pipe = TestBed.inject(MdsSummaryPipe);
pipe = TestBed.inject(MdsDashboardSummaryPipe);
});
it('create an instance', () => {

View File

@ -3,9 +3,9 @@ import { Pipe, PipeTransform } from '@angular/core';
import _ from 'lodash';
@Pipe({
name: 'mdsSummary'
name: 'mdsDashboardSummary'
})
export class MdsSummaryPipe implements PipeTransform {
export class MdsDashboardSummaryPipe implements PipeTransform {
transform(value: any): any {
if (!value) {
return '';

View File

@ -1,17 +1,17 @@
import { TestBed } from '@angular/core/testing';
import { configureTestBed } from '~/testing/unit-test-helper';
import { MgrSummaryPipe } from './mgr-summary.pipe';
import { MgrDashboardSummaryPipe } from './mgr-dashboard-summary.pipe';
describe('MgrSummaryPipe', () => {
let pipe: MgrSummaryPipe;
describe('MgrDashboardSummaryPipe', () => {
let pipe: MgrDashboardSummaryPipe;
configureTestBed({
providers: [MgrSummaryPipe]
providers: [MgrDashboardSummaryPipe]
});
beforeEach(() => {
pipe = TestBed.inject(MgrSummaryPipe);
pipe = TestBed.inject(MgrDashboardSummaryPipe);
});
it('create an instance', () => {

View File

@ -3,9 +3,9 @@ import { Pipe, PipeTransform } from '@angular/core';
import _ from 'lodash';
@Pipe({
name: 'mgrSummary'
name: 'mgrDashboardSummary'
})
export class MgrSummaryPipe implements PipeTransform {
export class MgrDashboardSummaryPipe implements PipeTransform {
transform(value: any): any {
if (!value) {
return '';

View File

@ -1,17 +1,17 @@
import { TestBed } from '@angular/core/testing';
import { configureTestBed } from '~/testing/unit-test-helper';
import { OsdSummaryPipe } from './osd-summary.pipe';
import { osdDashboardSummaryPipe } from './osd-dashboard-summary.pipe';
describe('OsdSummaryPipe', () => {
let pipe: OsdSummaryPipe;
describe('osdDashboardSummaryPipe', () => {
let pipe: osdDashboardSummaryPipe;
configureTestBed({
providers: [OsdSummaryPipe]
providers: [osdDashboardSummaryPipe]
});
beforeEach(() => {
pipe = TestBed.inject(OsdSummaryPipe);
pipe = TestBed.inject(osdDashboardSummaryPipe);
});
it('create an instance', () => {

View File

@ -3,9 +3,9 @@ import { Pipe, PipeTransform } from '@angular/core';
import _ from 'lodash';
@Pipe({
name: 'osdSummary'
name: 'osdDashboardSummary'
})
export class OsdSummaryPipe implements PipeTransform {
export class osdDashboardSummaryPipe implements PipeTransform {
transform(value: any): any {
if (!value) {
return '';

View File

@ -11,7 +11,6 @@ import { Observable, of } from 'rxjs';
import { NfsFormClientComponent } from '~/app/ceph/nfs/nfs-form-client/nfs-form-client.component';
import { NfsFormComponent } from '~/app/ceph/nfs/nfs-form/nfs-form.component';
import { Directory } from '~/app/shared/api/nfs.service';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { SharedModule } from '~/app/shared/shared.module';
import { ActivatedRouteStub } from '~/testing/activated-route-stub';
import { configureTestBed, RgwHelper } from '~/testing/unit-test-helper';
@ -23,26 +22,23 @@ describe('NfsFormComponent', () => {
let activatedRoute: ActivatedRouteStub;
let router: Router;
configureTestBed(
{
declarations: [NfsFormComponent, NfsFormClientComponent],
imports: [
HttpClientTestingModule,
ReactiveFormsModule,
RouterTestingModule,
SharedModule,
ToastrModule.forRoot(),
NgbTypeaheadModule
],
providers: [
{
provide: ActivatedRoute,
useValue: new ActivatedRouteStub({ cluster_id: 'mynfs', export_id: '1' })
}
]
},
[LoadingPanelComponent]
);
configureTestBed({
declarations: [NfsFormComponent, NfsFormClientComponent],
imports: [
HttpClientTestingModule,
ReactiveFormsModule,
RouterTestingModule,
SharedModule,
ToastrModule.forRoot(),
NgbTypeaheadModule
],
providers: [
{
provide: ActivatedRoute,
useValue: new ActivatedRouteStub({ cluster_id: 'mynfs', export_id: '1' })
}
]
});
const matchSquash = (backendSquashValue: string, uiSquashValue: string) => {
component.ngOnInit();

View File

@ -23,7 +23,7 @@ export class CrushRuleFormModalComponent extends CrushNodeSelectionClass impleme
@Output()
submitAction = new EventEmitter();
tooltips = this.crushRuleService.formTooltips;
tooltips!: Record<string, string>;
form: CdFormGroup;
names: string[];
@ -67,6 +67,8 @@ export class CrushRuleFormModalComponent extends CrushNodeSelectionClass impleme
}
ngOnInit() {
this.tooltips = this.crushRuleService.formTooltips;
this.crushRuleService
.getInfo()
.subscribe(({ names, nodes }: { names: string[]; nodes: CrushNode[] }) => {

View File

@ -26,7 +26,7 @@ export class ErasureCodeProfileFormModalComponent
@Output()
submitAction = new EventEmitter();
tooltips = this.ecpService.formTooltips;
tooltips!: Record<string, any>;
PLUGIN = {
LRC: 'lrc', // Locally Repairable Erasure Code
SHEC: 'shec', // Shingled Erasure Code
@ -365,6 +365,8 @@ export class ErasureCodeProfileFormModalComponent
}
ngOnInit() {
this.tooltips = this.ecpService.formTooltips;
this.ecpService
.getInfo()
.subscribe(

View File

@ -135,28 +135,25 @@ describe('PoolFormComponent', () => {
const routes: Routes = [{ path: '404', component: ErrorComponent }];
configureTestBed(
{
declarations: [ErrorComponent],
imports: [
BrowserAnimationsModule,
HttpClientTestingModule,
RouterTestingModule.withRoutes(routes),
ToastrModule.forRoot(),
NgbNavModule,
PoolModule,
SharedModule,
NgbModalModule
],
providers: [
ErasureCodeProfileService,
NgbActiveModal,
SelectBadgesComponent,
{ provide: ActivatedRoute, useValue: { params: of({ name: 'somePoolName' }) } }
]
},
[CriticalConfirmationModalComponent]
);
configureTestBed({
declarations: [ErrorComponent],
imports: [
BrowserAnimationsModule,
HttpClientTestingModule,
RouterTestingModule.withRoutes(routes),
ToastrModule.forRoot(),
NgbNavModule,
PoolModule,
SharedModule,
NgbModalModule
],
providers: [
ErasureCodeProfileService,
NgbActiveModal,
SelectBadgesComponent,
{ provide: ActivatedRoute, useValue: { params: of({ name: 'somePoolName' }) } }
]
});
let navigationSpy: jasmine.Spy;

View File

@ -4,6 +4,7 @@ import { BucketTagModalComponent } from './bucket-tag-modal.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('BucketTagModalComponent', () => {
let component: BucketTagModalComponent;
@ -13,6 +14,7 @@ describe('BucketTagModalComponent', () => {
await TestBed.configureTestingModule({
declarations: [BucketTagModalComponent],
imports: [HttpClientTestingModule, ReactiveFormsModule],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
providers: [NgbActiveModal]
}).compileComponents();

View File

@ -62,7 +62,6 @@
for="default_realm"
formControlName="default_realm"
name="default_realm"
[disabled]="action === actionLabels.EDIT"
i18n
>Default
<cd-help-text *ngIf="action === actionLabels.EDIT && info.data.is_default">

View File

@ -93,6 +93,12 @@ export class RgwMultisiteRealmFormComponent extends BaseModal implements OnInit
this.defaultRealmDisabled = true;
}
this.docUrl = this.docService.urlGenerator('rgw-multisite');
if (this.action === this.actionLabels?.EDIT) {
this.multisiteRealmForm.get('default_realm').disable();
} else {
this.multisiteRealmForm.get('default_realm').enable();
}
}
submit() {

View File

@ -8,6 +8,7 @@ import { ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service';
import { of } from 'rxjs';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
enum FlowType {
symmetrical = 'symmetrical',
@ -33,6 +34,7 @@ describe('RgwMultisiteSyncFlowModalComponent', () => {
ReactiveFormsModule,
CommonModule
],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
providers: [NgbActiveModal, { provide: RgwMultisiteService, useClass: MultisiteServiceMock }]
}).compileComponents();

View File

@ -9,6 +9,7 @@ import { CommonModule } from '@angular/common';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { of } from 'rxjs';
import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
class MultisiteServiceMock {
createEditSyncPipe = jest.fn().mockReturnValue(of(null));
@ -29,6 +30,7 @@ describe('RgwMultisiteSyncPipeModalComponent', () => {
ReactiveFormsModule,
CommonModule
],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
providers: [NgbActiveModal, { provide: RgwMultisiteService, useClass: MultisiteServiceMock }]
}).compileComponents();

View File

@ -6,6 +6,7 @@ import { ReactiveFormsModule } from '@angular/forms';
import { PipesModule } from '~/app/shared/pipes/pipes.module';
import { ComponentsModule } from '~/app/shared/components/components.module';
import { RouterTestingModule } from '@angular/router/testing';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('RgwMultisiteSyncPolicyFormComponent', () => {
let component: RgwMultisiteSyncPolicyFormComponent;
@ -22,6 +23,7 @@ describe('RgwMultisiteSyncPolicyFormComponent', () => {
ComponentsModule,
RouterTestingModule
],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
providers: []
}).compileComponents();

View File

@ -7,6 +7,7 @@ import { SharedModule } from '~/app/shared/shared.module';
import { ReactiveFormsModule } from '@angular/forms';
import { ToastrModule } from 'ngx-toastr';
import { RouterTestingModule } from '@angular/router/testing';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('RgwMultisiteWizardComponent', () => {
let component: RgwMultisiteWizardComponent;
@ -22,6 +23,7 @@ describe('RgwMultisiteWizardComponent', () => {
ToastrModule.forRoot(),
RouterTestingModule
],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
providers: [NgbActiveModal]
}).compileComponents();

View File

@ -62,8 +62,8 @@ describe('RgwSyncDataInfoComponent', () => {
const syncStatus = fixture.debugElement.query(By.css('.text-primary'));
expect(syncStatus).toBeTruthy();
expect(syncStatus.nativeElement.textContent).toEqual('Syncing');
const syncPopover = fixture.debugElement.query(By.css('a'));
syncPopover.triggerEventHandler('click', null);
const syncPopover = fixture.nativeElement.querySelector('a');
syncPopover.dispatchEvent(new Event('click'));
fixture.detectChanges();
expect(syncPopover).toBeTruthy();
const syncPopoverText = fixture.debugElement.query(By.css('.text-center'));

View File

@ -65,8 +65,8 @@ describe('RgwSyncMetadataInfoComponent', () => {
const syncStatus = fixture.debugElement.query(By.css('.text-primary'));
expect(syncStatus).toBeTruthy();
expect(syncStatus.nativeElement.textContent).toEqual('Syncing');
const syncPopover = fixture.debugElement.query(By.css('a'));
syncPopover.triggerEventHandler('click', null);
const syncPopover = fixture.nativeElement.querySelector('a');
syncPopover.dispatchEvent(new Event('click'));
fixture.detectChanges();
expect(syncPopover).toBeTruthy();
const syncPopoverText = fixture.debugElement.query(By.css('.text-center'));

View File

@ -4,6 +4,7 @@ import { HealthChecksComponent } from './health-checks.component';
import { HealthColorPipe } from '~/app/shared/pipes/health-color.pipe';
import { By } from '@angular/platform-browser';
import { CssHelper } from '~/app/shared/classes/css-helper';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
describe('HealthChecksComponent', () => {
let component: HealthChecksComponent;
@ -12,7 +13,8 @@ describe('HealthChecksComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [HealthChecksComponent, HealthColorPipe],
providers: [CssHelper]
providers: [CssHelper],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
fixture = TestBed.createComponent(HealthChecksComponent);

View File

@ -49,7 +49,7 @@ export class SmbClusterFormComponent extends CdForm implements OnInit {
resource: string;
icons = Icons;
domainSettingsObject: DomainSettings;
modalData$ = this.smbService.modalData$;
modalData$!: Observable<DomainSettings>;
constructor(
private hostService: HostService,
@ -63,6 +63,7 @@ export class SmbClusterFormComponent extends CdForm implements OnInit {
) {
super();
this.resource = $localize`Cluster`;
this.modalData$ = this.smbService.modalData$;
}
ngOnInit() {
this.action = this.actionLabels.CREATE;

View File

@ -8,6 +8,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { NgbActiveModal, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
import { InputModule, ModalModule, SelectModule } from 'carbon-components-angular';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('SmbDomainSettingModalComponent', () => {
let component: SmbDomainSettingModalComponent;
@ -27,6 +28,7 @@ describe('SmbDomainSettingModalComponent', () => {
InputModule,
SelectModule
],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
providers: [NgbActiveModal, { provide: 'domainSettingsObject', useValue: [[]] }]
}).compileComponents();

View File

@ -2,7 +2,7 @@ import Close from '@carbon/icons/es/close/32';
import { SmbClusterListComponent } from './smb-cluster-list/smb-cluster-list.component';
import { SmbClusterFormComponent } from './smb-cluster-form/smb-cluster-form.component';
import { AppRoutingModule } from '~/app/app-routing.module';
import { NgChartsModule } from 'ng2-charts';
import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts';
import { DataTableModule } from '~/app/shared/datatable/datatable.module';
import { SmbDomainSettingModalComponent } from './smb-domain-setting-modal/smb-domain-setting-modal.component';
import {
@ -33,7 +33,7 @@ import { NgModule } from '@angular/core';
CommonModule,
SharedModule,
AppRoutingModule,
NgChartsModule,
BaseChartDirective,
CommonModule,
FormsModule,
ReactiveFormsModule,
@ -53,7 +53,8 @@ import { NgModule } from '@angular/core';
IconModule
],
exports: [SmbClusterListComponent, SmbClusterFormComponent],
declarations: [SmbClusterListComponent, SmbClusterFormComponent, SmbDomainSettingModalComponent]
declarations: [SmbClusterListComponent, SmbClusterFormComponent, SmbDomainSettingModalComponent],
providers: [provideCharts(withDefaultRegisterables())]
})
export class SmbModule {
constructor(private iconService: IconService) {

View File

@ -10,7 +10,6 @@ import { of } from 'rxjs';
import { RoleService } from '~/app/shared/api/role.service';
import { ScopeService } from '~/app/shared/api/scope.service';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
import { NotificationService } from '~/app/shared/services/notification.service';
import { SharedModule } from '~/app/shared/shared.module';
@ -32,19 +31,16 @@ describe('RoleFormComponent', () => {
const routes: Routes = [{ path: 'roles', component: FakeComponent }];
configureTestBed(
{
imports: [
RouterTestingModule.withRoutes(routes),
HttpClientTestingModule,
ReactiveFormsModule,
ToastrModule.forRoot(),
SharedModule
],
declarations: [RoleFormComponent, FakeComponent]
},
[LoadingPanelComponent]
);
configureTestBed({
imports: [
RouterTestingModule.withRoutes(routes),
HttpClientTestingModule,
ReactiveFormsModule,
ToastrModule.forRoot(),
SharedModule
],
declarations: [RoleFormComponent, FakeComponent]
});
beforeEach(() => {
fixture = TestBed.createComponent(RoleFormComponent);

View File

@ -13,7 +13,6 @@ import { RoleService } from '~/app/shared/api/role.service';
import { SettingsService } from '~/app/shared/api/settings.service';
import { UserService } from '~/app/shared/api/user.service';
import { ComponentsModule } from '~/app/shared/components/components.module';
import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component';
import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
import { NotificationService } from '~/app/shared/services/notification.service';
@ -44,21 +43,18 @@ describe('UserFormComponent', () => {
{ path: 'users', component: FakeComponent }
];
configureTestBed(
{
imports: [
RouterTestingModule.withRoutes(routes),
HttpClientTestingModule,
ReactiveFormsModule,
ComponentsModule,
ToastrModule.forRoot(),
SharedModule,
NgbPopoverModule
],
declarations: [UserFormComponent, FakeComponent]
},
[LoadingPanelComponent]
);
configureTestBed({
imports: [
RouterTestingModule.withRoutes(routes),
HttpClientTestingModule,
ReactiveFormsModule,
ComponentsModule,
ToastrModule.forRoot(),
SharedModule,
NgbPopoverModule
],
declarations: [UserFormComponent, FakeComponent]
});
beforeEach(() => {
spyOn(TestBed.inject(PasswordPolicyService), 'getHelpText').and.callFake(() => of(''));

View File

@ -13,7 +13,7 @@ import {
NgbTooltipModule
} from '@ng-bootstrap/ng-bootstrap';
import { ClickOutsideModule } from 'ng-click-outside';
import { NgChartsModule } from 'ng2-charts';
import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts';
import { SimplebarAngularModule } from 'simplebar-angular';
import {
UIShellModule,
@ -93,7 +93,6 @@ import InfoIcon from '@carbon/icons/es/information/16';
NgbPopoverModule,
NgbProgressbarModule,
NgbTooltipModule,
NgChartsModule,
ReactiveFormsModule,
PipesModule,
DirectivesModule,
@ -121,7 +120,8 @@ import InfoIcon from '@carbon/icons/es/information/16';
DropdownModule,
SelectModule,
ComboBoxModule,
ProgressIndicatorModule
ProgressIndicatorModule,
BaseChartDirective
],
declarations: [
SparklineComponent,
@ -165,7 +165,7 @@ import InfoIcon from '@carbon/icons/es/information/16';
UpgradableComponent,
ProgressComponent
],
providers: [],
providers: [provideCharts(withDefaultRegisterables())],
exports: [
SparklineComponent,
HelperComponent,

View File

@ -1,4 +1,4 @@
import { Component, NgModule, NO_ERRORS_SCHEMA, TemplateRef, ViewChild } from '@angular/core';
import { Component, NgModule, TemplateRef, ViewChild } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { NgForm, ReactiveFormsModule } from '@angular/forms';
@ -9,7 +9,7 @@ import { configureTestBed, modalServiceShow } from '~/testing/unit-test-helper';
import { AlertPanelComponent } from '../alert-panel/alert-panel.component';
import { LoadingPanelComponent } from '../loading-panel/loading-panel.component';
import { CriticalConfirmationModalComponent } from './critical-confirmation-modal.component';
import { ModalService, PlaceholderService } from 'carbon-components-angular';
import { CheckboxModule, ModalService, PlaceholderService } from 'carbon-components-angular';
import { ModalCdsService } from '../../services/modal-cds.service';
@NgModule({})
@ -88,26 +88,22 @@ describe('CriticalConfirmationModalComponent', () => {
let component: CriticalConfirmationModalComponent;
let mockFixture: ComponentFixture<MockComponent>;
configureTestBed(
{
declarations: [
MockComponent,
CriticalConfirmationModalComponent,
LoadingPanelComponent,
AlertPanelComponent
],
schemas: [NO_ERRORS_SCHEMA],
imports: [ReactiveFormsModule, MockModule, DirectivesModule],
providers: [
ModalService,
PlaceholderService,
{ provide: 'itemNames', useValue: [] },
{ provide: 'itemDescription', useValue: 'entry' },
{ provide: 'actionDescription', useValue: 'delete' }
]
},
[CriticalConfirmationModalComponent]
);
configureTestBed({
declarations: [
MockComponent,
CriticalConfirmationModalComponent,
LoadingPanelComponent,
AlertPanelComponent
],
imports: [ReactiveFormsModule, MockModule, DirectivesModule, CheckboxModule],
providers: [
ModalService,
PlaceholderService,
{ provide: 'itemNames', useValue: [] },
{ provide: 'itemDescription', useValue: 'entry' },
{ provide: 'actionDescription', useValue: 'delete' }
]
});
beforeEach(() => {
mockFixture = TestBed.createComponent(MockComponent);

View File

@ -1,6 +1,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormAdvancedFieldsetComponent } from './form-advanced-fieldset.component';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('FormAdvancedFieldsetComponent', () => {
let component: FormAdvancedFieldsetComponent;
@ -8,7 +9,8 @@ describe('FormAdvancedFieldsetComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [FormAdvancedFieldsetComponent]
declarations: [FormAdvancedFieldsetComponent],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
fixture = TestBed.createComponent(FormAdvancedFieldsetComponent);

View File

@ -18,10 +18,9 @@
<ng-container *ngFor="let field of fields">
<div class="form-item">
<cds-text-label *ngIf="field.type === 'text'"
[for]="field.name"
[labelInputID]="field.name"
[invalid]="getError(field)"
[invalidText]="getError(field)"
[label]="field.label"
[cdRequiredField]="field?.required === true ? field.label : ''"
i18n>
{{ field.label }}
@ -34,18 +33,15 @@
autofocus>
</cds-text-label>
<cds-number *ngIf="field.type === 'number'"
[for]="field.name"
[invalid]="getError(field)"
[invalidText]="getError(field)"
[label]="field.label"
[cdRequiredField]="field?.required === true ? field.label : ''"
[formControlName]="field.name"
[id]="field.name"
[name]="field.name"
i18n></cds-number>
<cds-text-label *ngIf="field.type === 'binary'"
[for]="field.name"
[label]="field.label"
[labelInputID]="field.name"
[invalid]="getError(field)"
[invalidText]="getError(field)"
[cdRequiredField]="field?.required === true ? field.label : ''"

View File

@ -1,6 +1,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ProgressComponent } from './progress.component';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
describe('ProgressComponent', () => {
let component: ProgressComponent;
@ -8,7 +9,8 @@ describe('ProgressComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ProgressComponent]
declarations: [ProgressComponent],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
fixture = TestBed.createComponent(ProgressComponent);

View File

@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { Observable, Subscription } from 'rxjs';
import { UpgradeService } from '../../api/upgrade.service';
@ -13,7 +13,7 @@ import { ExecutingTask } from '../../models/executing-task';
templateUrl: './upgradable.component.html',
styleUrls: ['./upgradable.component.scss']
})
export class UpgradableComponent {
export class UpgradableComponent implements OnInit, OnDestroy {
orchAvailable: boolean = false;
upgradeInfo$: Observable<UpgradeInfoInterface>;
upgradeStatus$: Observable<UpgradeStatusInterface>;

View File

@ -26,7 +26,7 @@ describe('TableKeyValueComponent', () => {
RouterTestingModule,
NgbDropdownModule,
PipesModule,
NgbTooltipModule,
NgbTooltipModule
]
});

View File

@ -5,8 +5,6 @@ import { By } from '@angular/platform-browser';
import { NgbAlertModule } from '@ng-bootstrap/ng-bootstrap';
import { configureTestBed } from '~/testing/unit-test-helper';
import { AlertPanelComponent } from '../components/alert-panel/alert-panel.component';
import { LoadingPanelComponent } from '../components/loading-panel/loading-panel.component';
import { CdForm } from '../forms/cd-form';
import { SharedModule } from '../shared.module';
import { FormLoadingDirective } from './form-loading.directive';
@ -28,13 +26,10 @@ describe('FormLoadingDirective', () => {
expect(fixture.debugElement.queryAll(By.css('cd-loading-panel')).length).toEqual(loading);
};
configureTestBed(
{
declarations: [TestComponent],
imports: [SharedModule, NgbAlertModule]
},
[LoadingPanelComponent, AlertPanelComponent]
);
configureTestBed({
declarations: [TestComponent],
imports: [SharedModule, NgbAlertModule]
});
afterEach(() => {
fixture = null;

View File

@ -5,7 +5,7 @@ import { AfterViewInit, Directive, ElementRef, Input, Renderer2 } from '@angular
})
export class RequiredFieldDirective implements AfterViewInit {
@Input('cdRequiredField') label: string;
@Input('skeleton') skeleton: boolean;
@Input() skeleton: boolean;
constructor(private elementRef: ElementRef, private renderer: Renderer2) {}
ngAfterViewInit() {

View File

@ -1,15 +1,29 @@
import { NgbConfig, NgbNav, NgbNavChangeEvent, NgbNavConfig } from '@ng-bootstrap/ng-bootstrap';
import { NgbNav, NgbNavChangeEvent } from '@ng-bootstrap/ng-bootstrap';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
import { StatefulTabDirective } from './stateful-tab.directive';
import { TestBed } from '@angular/core/testing';
class NgbNavMock {
select() {}
}
describe('StatefulTabDirective', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [StatefulTabDirective],
providers: [{ provide: NgbNav, useClass: NgbNavMock }],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
});
it('should create an instance', () => {
const directive = new StatefulTabDirective(null);
expect(directive).toBeTruthy();
});
it('should get and select active tab', () => {
const nav = new NgbNav('tablist', new NgbNavConfig(new NgbConfig()), <any>null, null);
const nav = TestBed.inject(NgbNav);
spyOn(nav, 'select');
const directive = new StatefulTabDirective(nav);
directive.cdStatefulTab = 'bar';
@ -27,7 +41,7 @@ describe('StatefulTabDirective', () => {
});
it('should select the default tab if provided', () => {
const nav = new NgbNav('tablist', new NgbNavConfig(new NgbConfig()), <any>null, null);
const nav = TestBed.inject(NgbNav);
spyOn(nav, 'select');
const directive = new StatefulTabDirective(nav);
directive.cdStatefulTab = 'bar';

View File

@ -26,7 +26,7 @@ import { ActivatedRouteSnapshot, UrlSegment } from '@angular/router';
import { Observable, of } from 'rxjs';
export class BreadcrumbsResolver {
export class BreadcrumbsResolver {
public resolve(
route: ActivatedRouteSnapshot
): Observable<IBreadcrumb[]> | Promise<IBreadcrumb[]> | IBreadcrumb[] {

View File

@ -125,7 +125,8 @@ import { PipeFunctionPipe } from './pipe-function.pipe';
PathPipe,
PluralizePipe,
XmlPipe,
MbpersecondPipe
MbpersecondPipe,
PipeFunctionPipe
],
providers: [
ArrayPipe,

View File

@ -1,4 +1,10 @@
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import {
HttpErrorResponse,
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest
} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';

View File

@ -6,7 +6,7 @@ import { AuthStorageService } from './auth-storage.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuardService {
export class AuthGuardService {
constructor(private router: Router, private authStorageService: AuthStorageService) {}
canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {

View File

@ -10,7 +10,7 @@ import { AuthStorageService } from './auth-storage.service';
@Injectable({
providedIn: 'root'
})
export class ChangePasswordGuardService {
export class ChangePasswordGuardService {
constructor(private router: Router, private authStorageService: AuthStorageService) {}
canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {

View File

@ -9,7 +9,7 @@ import { FeatureTogglesMap, FeatureTogglesService } from './feature-toggles.serv
@Injectable({
providedIn: 'root'
})
export class FeatureTogglesGuardService {
export class FeatureTogglesGuardService {
constructor(private featureToggles: FeatureTogglesService) {}
canActivate(route: ActivatedRouteSnapshot) {

View File

@ -19,7 +19,7 @@ describe('ModalService', () => {
let service: ModalService;
let ngbModal: NgbModal;
configureTestBed({ declarations: [MockComponent], imports: [NgbModalModule] }, [MockComponent]);
configureTestBed({ declarations: [MockComponent], imports: [NgbModalModule] });
beforeEach(() => {
service = TestBed.inject(ModalService);

View File

@ -36,7 +36,7 @@ import { Icons } from '~/app/shared/enum/icons.enum';
@Injectable({
providedIn: 'root'
})
export class ModuleStatusGuardService {
export class ModuleStatusGuardService {
// TODO: Hotfix - remove ALLOWLIST'ing when a generic ErrorComponent is implemented
static readonly ALLOWLIST: string[] = ['501'];

View File

@ -1,6 +1,5 @@
import { Injectable } from '@angular/core';
import { DashboardUserDeniedError } from '~/app/core/error/error';
import { AuthStorageService } from './auth-storage.service';
@ -11,7 +10,7 @@ import { AuthStorageService } from './auth-storage.service';
@Injectable({
providedIn: 'root'
})
export class NoSsoGuardService {
export class NoSsoGuardService {
constructor(private authStorageService: AuthStorageService) {}
canActivate() {

View File

@ -1,8 +1,7 @@
import { DebugElement, Type } from '@angular/core';
import { CUSTOM_ELEMENTS_SCHEMA, DebugElement, NO_ERRORS_SCHEMA, Type } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AbstractControl } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing';
import { NgbModal, NgbNav, NgbNavItem, NgbNavLink } from '@ng-bootstrap/ng-bootstrap';
import _ from 'lodash';
@ -29,20 +28,12 @@ import {
PrometheusRule
} from '~/app/shared/models/prometheus-alerts';
export function configureTestBed(configuration: any, entryComponents?: any) {
beforeEach(async () => {
if (entryComponents) {
// Declare entryComponents without having to add them to a module
// This is needed since Jest doesn't yet support not declaring entryComponents
await TestBed.configureTestingModule(configuration).overrideModule(
BrowserDynamicTestingModule,
{
set: { entryComponents: entryComponents }
}
);
} else {
await TestBed.configureTestingModule(configuration);
}
export function configureTestBed(configuration: any) {
beforeEach(() => {
TestBed.configureTestingModule({
...configuration,
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
});
});
}

View File

@ -18,8 +18,8 @@
"noImplicitAny": true,
"ignoreDeprecations": "5.0",
"suppressImplicitAnyIndexErrors": true,
"target": "ES2020",
"module": "es2020",
"target": "ES2022",
"module": "ES2022",
"baseUrl": "./",
"resolveJsonModule": true,
"paths": {