Skip to content
This repository has been archived by the owner on Mar 25, 2023. It is now read-only.

fix(so-classes): Store SO classes in config.json #955

Merged
merged 5 commits into from
Feb 13, 2018
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
8 changes: 6 additions & 2 deletions config-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,15 @@ In this section you can specify classes for service offerings in the following f
"description": {
"ru": "class_description_ru",
"en": "class_description_en"
}
},
"serviceOfferings": [
"so-id1",
"so-id2"
]
}
]

Each classes should have a unique id, name, and description. Name and description should be localized for used languages.
Each classes should have a unique id, name, description and list of service offering ids, which belong to this class. Name and description should be localized for used languages.

### Session Timeout

Expand Down
227 changes: 227 additions & 0 deletions src/app/reducers/account-tags/redux/account-tags.effects.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { Injectable } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { Actions } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';
import { cold, hot } from 'jasmine-marbles';
import { Observable } from 'rxjs/Observable';
import { empty } from 'rxjs/observable/empty';
import { of } from 'rxjs/observable/of';
import { MockDialogService } from '../../../../testutils/mocks/mock-dialog.service';
import { DialogService } from '../../../dialog/dialog-service/dialog.service';
import * as fromAccountTags from './account-tags.reducers';
import * as accountTagActions from './account-tags.actions';
import { AccountTagsEffects } from './account-tags.effects';
import { Tag } from '../../../shared/models/tag.model';
import { TagService } from '../../../shared/services/tags/tag.service';
import { AccountTagService } from '../../../shared/services/tags/account-tag.service';
import { ConfigService } from '../../../shared/services/config.service';
import { ServiceOffering } from '../../../shared/models/service-offering.model';
import { StorageTypes } from '../../../shared/models/offering.model';

@Injectable()
class MockAsyncJobService {
public completeAllJobs(): void {
}
}

@Injectable()
class MockTagService {
public getList(): void {
}
public setServiceOfferingParams(): void {
}
}


@Injectable()
class MockStorageService {
private storage: any = {
user: {
userid: '1'
}
};

public write(key: string, value: string): void {
this.storage[key] = value;
}

public read(key: string): string {
return this.storage[key] || null;
}

public remove(key: string): void {
delete this.storage[key];
}

public resetInMemoryStorage(): void {
this.storage = {};
}
}

class MockMatDialog {
public open(): void {
}
public closeAll(): void {
}
}

export class TestActions extends Actions {
constructor() {
super(empty());
}

public set stream(source: Observable<Tag>) {
this.source = source;
}
}

export function getActions() {
return new TestActions();
}


describe('Account tags Effects', () => {
let actions$: TestActions;
let service: TagService;
let accountService: AccountTagService;
let configService: ConfigService;
let dialogService: DialogService;

let effects: AccountTagsEffects;

const list: Array<Tag> = [];


beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
StoreModule.forRoot({ ...fromAccountTags.accountTagsReducers}),
],
providers: [
AccountTagsEffects,
ConfigService,
{ provide: Actions, useFactory: getActions },
{ provide: TagService, useClass: MockTagService },
{ provide: AccountTagService, useClass: MockTagService },
{ provide: DialogService, useClass: MockDialogService },
]
});
actions$ = TestBed.get(Actions);
service = TestBed.get(TagService);
accountService = TestBed.get(AccountTagService);
configService = TestBed.get(ConfigService);
dialogService = TestBed.get(DialogService);
effects = TestBed.get(AccountTagsEffects);
});

it('should return a collection from LoadAccountTagsResponse', () => {
const spyGetList = spyOn(service, 'getList').and.returnValue(of(list));
const spyAccountTag = spyOn(configService, 'get').and.returnValue(true);

const action = new accountTagActions.LoadAccountTagsRequest();
const completion = new accountTagActions.LoadAccountTagsResponse(list);

actions$.stream = hot('-a', { a: action });
const expected = cold('-b', { b: completion });

expect(effects.loadAccountTags$).toBeObservable(expected);
expect(spyGetList).toHaveBeenCalled();
});

it('should not return a collection from LoadAccountTagsResponse', () => {
const spyGetList = spyOn(service, 'getList');
const spyAccountTag = spyOn(configService, 'get').and.returnValue(false);

const action = new accountTagActions.LoadAccountTagsRequest();

actions$.stream = hot('-a', { a: action });
const expected = cold('', []);

expect(effects.loadAccountTags$).toBeObservable(expected);
expect(spyGetList).not.toHaveBeenCalled();
});

it('should return an empty collection from LoadAccountTagsResponse', () => {
const spyGetList = spyOn(service, 'getList').and
.returnValue(Observable.throw(new Error('Error occurred!')));
const spyAccountTag = spyOn(configService, 'get').and.returnValue(true);

const action = new accountTagActions.LoadAccountTagsRequest();
const completion = new accountTagActions.LoadAccountTagsResponse([]);

actions$.stream = hot('a', { a: action });
const expected = cold('b', { b: completion });

expect(effects.loadAccountTags$).toBeObservable(expected);
});

it('should update custom SO params', () => {
const offering = <ServiceOffering>{
id: '1', name: 'off1', hosttags: 't1,t2',
storagetype: StorageTypes.local,
cpunumber: 2, memory: 2, iscustomized: true
};
const spySetParam = spyOn(accountService, 'setServiceOfferingParams').and.returnValue(of(offering));
const spyAccountTag = spyOn(configService, 'get').and.returnValue(true);

const action = new accountTagActions.UpdateCustomServiceOfferingParams(offering);
const completion = new accountTagActions.UpdateCustomServiceOfferingParamsSuccess(offering);

actions$.stream = hot('-a', { a: action });
const expected = cold('-b', { b: completion });

expect(effects.updateCustomServiceOfferingParams$).toBeObservable(expected);
expect(spySetParam).toHaveBeenCalled();
});

it('should not update custom SO params', () => {
const offering = <ServiceOffering>{
id: '1', name: 'off1', hosttags: 't1,t2',
storagetype: StorageTypes.local,
cpunumber: 2, memory: 2, iscustomized: true
};
const spySetParam = spyOn(accountService, 'setServiceOfferingParams');
const spyAccountTag = spyOn(configService, 'get').and.returnValue(false);

const action = new accountTagActions.UpdateCustomServiceOfferingParams(offering);

actions$.stream = hot('-a', { a: action });
const expected = cold('', []);

expect(effects.updateCustomServiceOfferingParams$).toBeObservable(expected);
expect(spySetParam).not.toHaveBeenCalled();
});

it('should return an error during updating custom SO params', () => {
const offering = <ServiceOffering>{
id: '1', name: 'off1', hosttags: 't1,t2',
storagetype: StorageTypes.local,
cpunumber: 2, memory: 2, iscustomized: true
};
const spySetParam = spyOn(accountService, 'setServiceOfferingParams').and.
returnValue(Observable.throw(new Error('Error occurred!')));
const spyAccountTag = spyOn(configService, 'get').and.returnValue(true);

const action = new accountTagActions.UpdateCustomServiceOfferingParams(offering);
const completion = new accountTagActions.UpdateCustomServiceOfferingParamsError(new Error('Error occurred!'));

actions$.stream = hot('a', { a: action });
const expected = cold('a', { a: completion });

expect(effects.updateCustomServiceOfferingParams$).toBeObservable(expected);
});

it('should show alert after updating error', () => {
const spyAlert = spyOn(dialogService, 'alert');
const action = new accountTagActions.UpdateCustomServiceOfferingParamsError(new Error('Error occurred!'));

actions$.stream = hot('a', { a: action });
const expected = cold('a', { a: action });

expect(effects.updateCustomServiceOfferingParamsError$).toBeObservable(expected);
expect(spyAlert).toHaveBeenCalled();
});

});
7 changes: 0 additions & 7 deletions src/app/reducers/account-tags/redux/account-tags.reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,6 @@ export const isLoading = createSelector(
state => state.loading
);

export const selectServiceOfferingClassTags = createSelector(
selectAll,
(tags) => {
return tags.filter(tag => tag.key.includes(AccountTagKeys.serviceOfferingClass));
}
);

export const selectServiceOfferingParamTags = createSelector(
selectAll,
(tags) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export class ServiceOfferingClassEffects {
@Effect()
loadServiceOfferingClasses$: Observable<Action> = this.actions$
.ofType(actions.LOAD_SERVICE_OFFERING_CLASS_REQUEST)
.filter(() => this.isAccountTagEnabled())
.switchMap((action: actions.LoadServiceOfferingClassRequest) => {
return Observable.of(this.configService.get('serviceOfferingClasses'))
.map(classList => new actions.LoadServiceOfferingClassResponse(classList))
Expand All @@ -22,8 +21,4 @@ export class ServiceOfferingClassEffects {
private actions$: Actions,
private configService: ConfigService
) { }

public isAccountTagEnabled(): boolean {
return this.configService.get<boolean>('accountTagsEnabled');
}
}
Loading