diff --git a/modules/ui/src/app/app.component.html b/modules/ui/src/app/app.component.html
index 6a853db98..10ec58c4e 100644
--- a/modules/ui/src/app/app.component.html
+++ b/modules/ui/src/app/app.component.html
@@ -189,6 +189,28 @@
Testrun
>start testing.
+
+ Congratulations, the device is under test now! Do not forget to fill
+ Risk Assessment questionnaire. It is required to complete verification process.
+
diff --git a/modules/ui/src/app/app.component.spec.ts b/modules/ui/src/app/app.component.spec.ts
index df773ccff..9fa87d0b6 100644
--- a/modules/ui/src/app/app.component.spec.ts
+++ b/modules/ui/src/app/app.component.spec.ts
@@ -54,6 +54,7 @@ import {
selectError,
selectHasConnectionSettings,
selectHasDevices,
+ selectHasRiskProfiles,
selectInterfaces,
selectIsOpenStartTestrun,
selectIsOpenWaitSnackBar,
@@ -104,6 +105,7 @@ describe('AppComponent', () => {
'fetchDevices',
'getTestModules',
'testrunInProgress',
+ 'fetchProfiles',
'fetchCertificates',
]);
@@ -148,6 +150,7 @@ describe('AppComponent', () => {
{ selector: selectError, value: null },
{ selector: selectMenuOpened, value: false },
{ selector: selectHasDevices, value: false },
+ { selector: selectHasRiskProfiles, value: false },
{ selector: selectStatus, value: null },
{ selector: selectSystemStatus, value: null },
{ selector: selectIsOpenStartTestrun, value: false },
@@ -466,6 +469,38 @@ describe('AppComponent', () => {
});
});
+ describe('with systemStatus data IN Progress and without riskProfiles', () => {
+ beforeEach(() => {
+ store.overrideSelector(selectHasConnectionSettings, true);
+ store.overrideSelector(selectHasDevices, true);
+ store.overrideSelector(selectHasRiskProfiles, false);
+ store.overrideSelector(
+ selectStatus,
+ MOCK_PROGRESS_DATA_IN_PROGRESS.status
+ );
+ fixture.detectChanges();
+ });
+
+ it('should have callout component with "Congratulations" text', () => {
+ const callout = compiled.querySelector('app-callout');
+ const calloutContent = callout?.innerHTML.trim();
+
+ expect(callout).toBeTruthy();
+ expect(calloutContent).toContain('Congratulations');
+ });
+
+ it('should have callout component with "Risk Assessment" link', () => {
+ const callout = compiled.querySelector('app-callout');
+ const calloutLinkEl = compiled.querySelector(
+ '.message-link'
+ ) as HTMLAnchorElement;
+ const calloutLinkContent = calloutLinkEl.innerHTML.trim();
+
+ expect(callout).toBeTruthy();
+ expect(calloutLinkContent).toContain('Risk Assessment');
+ });
+ });
+
describe('with no devices setted', () => {
beforeEach(() => {
store.overrideSelector(selectHasDevices, false);
diff --git a/modules/ui/src/app/app.component.ts b/modules/ui/src/app/app.component.ts
index 97e017daf..877050393 100644
--- a/modules/ui/src/app/app.component.ts
+++ b/modules/ui/src/app/app.component.ts
@@ -74,6 +74,7 @@ export class AppComponent {
public appStore: AppStore
) {
this.appStore.getDevices();
+ this.appStore.getRiskProfiles();
this.appStore.getSystemStatus();
this.matIconRegistry.addSvgIcon(
'devices',
@@ -115,6 +116,10 @@ export class AppComponent {
this.appStore.setIsOpenStartTestrun();
}
+ navigateToRiskAssessment(): void {
+ this.route.navigate([Routes.RiskAssessment]);
+ }
+
async closeCertificates(): Promise {
await this.certDrawer.close();
}
diff --git a/modules/ui/src/app/app.store.spec.ts b/modules/ui/src/app/app.store.spec.ts
index 6f1a2dba3..2807bcc51 100644
--- a/modules/ui/src/app/app.store.spec.ts
+++ b/modules/ui/src/app/app.store.spec.ts
@@ -22,6 +22,7 @@ import {
selectError,
selectHasConnectionSettings,
selectHasDevices,
+ selectHasRiskProfiles,
selectInterfaces,
selectIsOpenWaitSnackBar,
selectMenuOpened,
@@ -30,8 +31,13 @@ import {
import { TestRunService } from './services/test-run.service';
import SpyObj = jasmine.SpyObj;
import { device } from './mocks/device.mock';
-import { fetchSystemStatus, setDevices } from './store/actions';
+import {
+ fetchSystemStatus,
+ setDevices,
+ setRiskProfiles,
+} from './store/actions';
import { MOCK_PROGRESS_DATA_IN_PROGRESS } from './mocks/testrun.mock';
+import { PROFILE_MOCK } from './mocks/profile.mock';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NotificationService } from './services/notification.service';
@@ -60,7 +66,10 @@ describe('AppStore', () => {
let mockNotificationService: SpyObj;
beforeEach(() => {
- mockService = jasmine.createSpyObj('mockService', ['fetchDevices']);
+ mockService = jasmine.createSpyObj('mockService', [
+ 'fetchDevices',
+ 'fetchProfiles',
+ ]);
mockNotificationService = jasmine.createSpyObj('mockNotificationService', [
'notify',
]);
@@ -84,6 +93,7 @@ describe('AppStore', () => {
appStore = TestBed.inject(AppStore);
store.overrideSelector(selectHasDevices, true);
+ store.overrideSelector(selectHasRiskProfiles, false);
store.overrideSelector(selectHasConnectionSettings, true);
store.overrideSelector(selectMenuOpened, true);
store.overrideSelector(selectInterfaces, {});
@@ -127,6 +137,7 @@ describe('AppStore', () => {
expect(store).toEqual({
consentShown: false,
hasDevices: true,
+ hasRiskProfiles: false,
isStatusLoaded: false,
systemStatus: null,
hasConnectionSettings: true,
@@ -171,6 +182,22 @@ describe('AppStore', () => {
});
});
+ describe('fetchProfiles', () => {
+ const riskProfiles = [PROFILE_MOCK];
+
+ beforeEach(() => {
+ mockService.fetchProfiles.and.returnValue(of(riskProfiles));
+ });
+
+ it('should dispatch action setRiskProfiles', () => {
+ appStore.getRiskProfiles();
+
+ expect(store.dispatch).toHaveBeenCalledWith(
+ setRiskProfiles({ riskProfiles })
+ );
+ });
+ });
+
describe('getSystemStatus', () => {
it('should dispatch fetchSystemStatus', () => {
appStore.getSystemStatus();
diff --git a/modules/ui/src/app/app.store.ts b/modules/ui/src/app/app.store.ts
index 66d4086b3..cf67ffcf1 100644
--- a/modules/ui/src/app/app.store.ts
+++ b/modules/ui/src/app/app.store.ts
@@ -21,6 +21,7 @@ import {
selectError,
selectHasConnectionSettings,
selectHasDevices,
+ selectHasRiskProfiles,
selectInterfaces,
selectMenuOpened,
selectStatus,
@@ -34,8 +35,10 @@ import {
setDevices,
setIsOpenStartTestrun,
fetchSystemStatus,
+ setRiskProfiles,
} from './store/actions';
import { TestrunStatus } from './model/testrun-status';
+import { Profile } from './model/profile';
import { SettingMissedError, SystemInterfaces } from './model/setting';
export const CONSENT_SHOWN_KEY = 'CONSENT_SHOWN';
@@ -49,6 +52,7 @@ export class AppStore extends ComponentStore {
private consentShown$ = this.select(state => state.consentShown);
private isStatusLoaded$ = this.select(state => state.isStatusLoaded);
private hasDevices$ = this.store.select(selectHasDevices);
+ private hasRiskProfiles$ = this.store.select(selectHasRiskProfiles);
private hasConnectionSetting$ = this.store.select(
selectHasConnectionSettings
);
@@ -62,6 +66,7 @@ export class AppStore extends ComponentStore {
viewModel$ = this.select({
consentShown: this.consentShown$,
hasDevices: this.hasDevices$,
+ hasRiskProfiles: this.hasRiskProfiles$,
isStatusLoaded: this.isStatusLoaded$,
systemStatus: this.systemStatus$,
hasConnectionSettings: this.hasConnectionSetting$,
@@ -101,6 +106,18 @@ export class AppStore extends ComponentStore {
);
});
+ getRiskProfiles = this.effect(trigger$ => {
+ return trigger$.pipe(
+ exhaustMap(() => {
+ return this.testRunService.fetchProfiles().pipe(
+ tap((riskProfiles: Profile[]) => {
+ this.store.dispatch(setRiskProfiles({ riskProfiles }));
+ })
+ );
+ })
+ );
+ });
+
statusLoaded = this.effect(() => {
return this.systemStatus$.pipe(
skip(1),
diff --git a/modules/ui/src/app/components/callout/callout.component.scss b/modules/ui/src/app/components/callout/callout.component.scss
index 262552c91..20f30e28f 100644
--- a/modules/ui/src/app/components/callout/callout.component.scss
+++ b/modules/ui/src/app/components/callout/callout.component.scss
@@ -22,7 +22,8 @@
}
:host:has(.callout-container.info),
-:host:has(.callout-container.error) {
+:host:has(.callout-container.error),
+:host:has(.callout-container.check_circle) {
position: absolute;
}
@@ -72,6 +73,15 @@
}
}
+.callout-container.check_circle {
+ margin: 24px 32px;
+ background-color: $green-50;
+
+ .callout-icon {
+ color: $green-800;
+ }
+}
+
.callout-container.error_outline {
display: flex;
align-items: flex-start;
diff --git a/modules/ui/src/app/model/callout-type.ts b/modules/ui/src/app/model/callout-type.ts
index b8fabd0bc..c784b46f6 100644
--- a/modules/ui/src/app/model/callout-type.ts
+++ b/modules/ui/src/app/model/callout-type.ts
@@ -15,6 +15,7 @@
*/
export enum CalloutType {
Info = 'info',
+ Check = 'check_circle',
Warning = 'warning_amber',
Error = 'error',
ErrorOutline = 'error_outline',
diff --git a/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.spec.ts b/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.spec.ts
index 2667388bc..db45e728f 100644
--- a/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.spec.ts
+++ b/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.spec.ts
@@ -33,12 +33,14 @@ import { Profile } from '../../model/profile';
import { MatDialogRef } from '@angular/material/dialog';
import { DeleteFormComponent } from '../../components/delete-form/delete-form.component';
import { FocusManagerService } from '../../services/focus-manager.service';
+import { RiskAssessmentStore } from './risk-assessment.store';
describe('RiskAssessmentComponent', () => {
let component: RiskAssessmentComponent;
let fixture: ComponentFixture;
let mockService: SpyObj;
let mockFocusManagerService: SpyObj;
+ let mockRiskAssessmentStore: SpyObj;
let compiled: HTMLElement;
beforeEach(async () => {
@@ -49,15 +51,25 @@ describe('RiskAssessmentComponent', () => {
'focusFirstElementInContainer',
]);
+ mockRiskAssessmentStore = jasmine.createSpyObj('RiskAssessmentStore', [
+ 'deleteProfile',
+ 'setFocus',
+ ]);
+
await TestBed.configureTestingModule({
declarations: [RiskAssessmentComponent, FakeProfileItemComponent],
imports: [MatToolbarModule, MatSidenavModule, BrowserAnimationsModule],
providers: [
{ provide: TestRunService, useValue: mockService },
{ provide: FocusManagerService, useValue: mockFocusManagerService },
+ { provide: RiskAssessmentStore, useValue: mockRiskAssessmentStore },
],
}).compileComponents();
+ TestBed.overrideProvider(RiskAssessmentStore, {
+ useValue: mockRiskAssessmentStore,
+ });
+
fixture = TestBed.createComponent(RiskAssessmentComponent);
component = fixture.componentInstance;
compiled = fixture.nativeElement as HTMLElement;
@@ -69,6 +81,10 @@ describe('RiskAssessmentComponent', () => {
describe('with no data', () => {
beforeEach(() => {
+ component.viewModel$ = of({
+ profiles: [] as Profile[],
+ });
+ mockRiskAssessmentStore.profiles$ = of([]);
fixture.detectChanges();
});
diff --git a/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.ts b/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.ts
index 6e9bfa54c..ddd9d8b3e 100644
--- a/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.ts
+++ b/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.ts
@@ -32,9 +32,7 @@ export class RiskAssessmentComponent implements OnDestroy {
constructor(
private store: RiskAssessmentStore,
public dialog: MatDialog
- ) {
- this.store.getProfiles();
- }
+ ) {}
ngOnDestroy() {
this.destroy$.next(true);
diff --git a/modules/ui/src/app/pages/risk-assessment/risk-assessment.store.spec.ts b/modules/ui/src/app/pages/risk-assessment/risk-assessment.store.spec.ts
index 7b45ca9a1..a9add3bc4 100644
--- a/modules/ui/src/app/pages/risk-assessment/risk-assessment.store.spec.ts
+++ b/modules/ui/src/app/pages/risk-assessment/risk-assessment.store.spec.ts
@@ -14,17 +14,21 @@
* limitations under the License.
*/
import { TestBed } from '@angular/core/testing';
-import { of, skip, take } from 'rxjs';
-import { provideMockStore } from '@ngrx/store/testing';
+import { of, take } from 'rxjs';
+import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { TestRunService } from '../../services/test-run.service';
import SpyObj = jasmine.SpyObj;
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { RiskAssessmentStore } from './risk-assessment.store';
import { PROFILE_MOCK, PROFILE_MOCK_2 } from '../../mocks/profile.mock';
import { FocusManagerService } from '../../services/focus-manager.service';
+import { AppState } from '../../store/state';
+import { selectRiskProfiles } from '../../store/selectors';
+import { setRiskProfiles } from '../../store/actions';
describe('RiskAssessmentStore', () => {
let riskAssessmentStore: RiskAssessmentStore;
+ let store: MockStore;
let mockService: SpyObj;
let mockFocusManagerService: SpyObj;
@@ -38,35 +42,34 @@ describe('RiskAssessmentStore', () => {
imports: [NoopAnimationsModule],
providers: [
RiskAssessmentStore,
- provideMockStore({}),
+ provideMockStore({
+ selectors: [
+ {
+ selector: selectRiskProfiles,
+ value: [PROFILE_MOCK, PROFILE_MOCK_2],
+ },
+ ],
+ }),
{ provide: TestRunService, useValue: mockService },
{ provide: FocusManagerService, useValue: mockFocusManagerService },
],
});
+ store = TestBed.inject(MockStore);
riskAssessmentStore = TestBed.inject(RiskAssessmentStore);
+
+ spyOn(store, 'dispatch').and.callFake(() => {});
});
it('should be created', () => {
expect(riskAssessmentStore).toBeTruthy();
});
- describe('updaters', () => {
- it('should update profiles', (done: DoneFn) => {
- riskAssessmentStore.viewModel$.pipe(skip(1), take(1)).subscribe(store => {
- expect(store.profiles).toEqual([PROFILE_MOCK]);
- done();
- });
-
- riskAssessmentStore.updateProfiles([PROFILE_MOCK]);
- });
- });
-
describe('selectors', () => {
it('should select state', done => {
riskAssessmentStore.viewModel$.pipe(take(1)).subscribe(store => {
expect(store).toEqual({
- profiles: [],
+ profiles: [PROFILE_MOCK, PROFILE_MOCK_2],
});
done();
});
@@ -74,37 +77,15 @@ describe('RiskAssessmentStore', () => {
});
describe('effects', () => {
- describe('getProfiles', () => {
- beforeEach(() => {
- mockService.fetchProfiles.and.returnValue(of([PROFILE_MOCK]));
- });
-
- it('should update profiles', done => {
- riskAssessmentStore.viewModel$
- .pipe(skip(1), take(1))
- .subscribe(store => {
- expect(store.profiles).toEqual([PROFILE_MOCK]);
- done();
- });
-
- riskAssessmentStore.getProfiles();
- });
- });
-
describe('deleteProfile', () => {
- it('should update store profiles', done => {
+ it('should dispatch setRiskProfiles', () => {
mockService.deleteProfile.and.returnValue(of(true));
- riskAssessmentStore.updateProfiles([PROFILE_MOCK, PROFILE_MOCK_2]);
-
- riskAssessmentStore.viewModel$
- .pipe(skip(1), take(1))
- .subscribe(store => {
- expect(store.profiles).toEqual([PROFILE_MOCK_2]);
- done();
- });
-
riskAssessmentStore.deleteProfile(PROFILE_MOCK.name);
+
+ expect(store.dispatch).toHaveBeenCalledWith(
+ setRiskProfiles({ riskProfiles: [PROFILE_MOCK_2] })
+ );
});
});
@@ -118,7 +99,6 @@ describe('RiskAssessmentStore', () => {
nextItem: mockNextItem,
firstItem: mockFirstItem,
};
- riskAssessmentStore.updateProfiles([PROFILE_MOCK, PROFILE_MOCK_2]);
riskAssessmentStore.setFocus(mockData);
@@ -132,7 +112,6 @@ describe('RiskAssessmentStore', () => {
nextItem: mockNullEL,
firstItem: mockFirstItem,
};
- riskAssessmentStore.updateProfiles([PROFILE_MOCK, PROFILE_MOCK_2]);
riskAssessmentStore.setFocus(mockData);
@@ -146,7 +125,9 @@ describe('RiskAssessmentStore', () => {
nextItem: mockNullEL,
firstItem: mockFirstItem,
};
- riskAssessmentStore.updateProfiles([PROFILE_MOCK]);
+
+ store.overrideSelector(selectRiskProfiles, [PROFILE_MOCK]);
+ store.refreshState();
riskAssessmentStore.setFocus(mockData);
diff --git a/modules/ui/src/app/pages/risk-assessment/risk-assessment.store.ts b/modules/ui/src/app/pages/risk-assessment/risk-assessment.store.ts
index 6b0a348c8..737d8f024 100644
--- a/modules/ui/src/app/pages/risk-assessment/risk-assessment.store.ts
+++ b/modules/ui/src/app/pages/risk-assessment/risk-assessment.store.ts
@@ -21,35 +21,22 @@ import { exhaustMap } from 'rxjs';
import { TestRunService } from '../../services/test-run.service';
import { Profile } from '../../model/profile';
import { FocusManagerService } from '../../services/focus-manager.service';
+import { Store } from '@ngrx/store';
+import { AppState } from '../../store/state';
+import { selectRiskProfiles } from '../../store/selectors';
+import { setRiskProfiles } from '../../store/actions';
export interface AppComponentState {
profiles: Profile[];
}
@Injectable()
export class RiskAssessmentStore extends ComponentStore {
- private profiles$ = this.select(state => state.profiles);
+ profiles$ = this.store.select(selectRiskProfiles);
viewModel$ = this.select({
profiles: this.profiles$,
});
- updateProfiles = this.updater((state, profiles: Profile[]) => ({
- ...state,
- profiles,
- }));
-
- getProfiles = this.effect(trigger$ => {
- return trigger$.pipe(
- exhaustMap(() => {
- return this.testRunService.fetchProfiles().pipe(
- tap((profiles: Profile[]) => {
- this.updateProfiles(profiles);
- })
- );
- })
- );
- });
-
deleteProfile = this.effect(trigger$ => {
return trigger$.pipe(
exhaustMap((name: string) => {
@@ -87,8 +74,13 @@ export class RiskAssessmentStore extends ComponentStore {
this.updateProfiles(profiles);
}
+ private updateProfiles(riskProfiles: Profile[]): void {
+ this.store.dispatch(setRiskProfiles({ riskProfiles }));
+ }
+
constructor(
private testRunService: TestRunService,
+ private store: Store,
private focusManagerService: FocusManagerService
) {
super({
diff --git a/modules/ui/src/app/store/actions.ts b/modules/ui/src/app/store/actions.ts
index 0024ccd9e..f5c0c937e 100644
--- a/modules/ui/src/app/store/actions.ts
+++ b/modules/ui/src/app/store/actions.ts
@@ -23,6 +23,7 @@ import {
import { SystemInterfaces } from '../model/setting';
import { Device } from '../model/device';
import { TestrunStatus } from '../model/testrun-status';
+import { Profile } from '../model/profile';
// App component
export const toggleMenu = createAction('[App Component] Toggle Menu');
@@ -83,6 +84,16 @@ export const setDevices = createAction(
props<{ devices: Device[] }>()
);
+export const setHasRiskProfiles = createAction(
+ '[Shared] Set Has Risk Profiles',
+ props<{ hasRiskProfiles: boolean }>()
+);
+
+export const setRiskProfiles = createAction(
+ '[Shared] Set Risk Profiles',
+ props<{ riskProfiles: Profile[] }>()
+);
+
export const setTestrunStatus = createAction(
'[Shared] Set Testrun Status',
props<{ systemStatus: TestrunStatus }>()
diff --git a/modules/ui/src/app/store/effects.spec.ts b/modules/ui/src/app/store/effects.spec.ts
index dc8ab8620..92cddf9fb 100644
--- a/modules/ui/src/app/store/effects.spec.ts
+++ b/modules/ui/src/app/store/effects.spec.ts
@@ -40,6 +40,8 @@ import {
} from '../mocks/testrun.mock';
import { fetchSystemStatus, setStatus, setTestrunStatus } from './actions';
import { NotificationService } from '../services/notification.service';
+import { PROFILE_MOCK } from '../mocks/profile.mock';
+
describe('Effects', () => {
let actions$ = new Observable();
let effects: AppEffects;
@@ -110,6 +112,17 @@ describe('Effects', () => {
});
});
+ it('onSetRiskProfiles$ should call setHasRiskProfiles', done => {
+ actions$ = of(actions.setRiskProfiles({ riskProfiles: [PROFILE_MOCK] }));
+
+ effects.onSetRiskProfiles$.subscribe(action => {
+ expect(action).toEqual(
+ actions.setHasRiskProfiles({ hasRiskProfiles: true })
+ );
+ done();
+ });
+ });
+
it('onMenuOpened$ should call updateFocusNavigation', done => {
actions$ = of(actions.toggleMenu());
store.overrideSelector(selectMenuOpened, true);
diff --git a/modules/ui/src/app/store/effects.ts b/modules/ui/src/app/store/effects.ts
index e98f96686..ee082a178 100644
--- a/modules/ui/src/app/store/effects.ts
+++ b/modules/ui/src/app/store/effects.ts
@@ -114,6 +114,17 @@ export class AppEffects {
);
});
+ onSetRiskProfiles$ = createEffect(() => {
+ return this.actions$.pipe(
+ ofType(AppActions.setRiskProfiles),
+ map(({ riskProfiles }) =>
+ AppActions.setHasRiskProfiles({
+ hasRiskProfiles: riskProfiles.length > 0,
+ })
+ )
+ );
+ });
+
onSetTestrunStatus$ = createEffect(() => {
return this.actions$.pipe(
ofType(AppActions.setTestrunStatus),
diff --git a/modules/ui/src/app/store/reducers.spec.ts b/modules/ui/src/app/store/reducers.spec.ts
index 7adb63c61..ad611e9f9 100644
--- a/modules/ui/src/app/store/reducers.spec.ts
+++ b/modules/ui/src/app/store/reducers.spec.ts
@@ -21,9 +21,11 @@ import {
setDevices,
setHasConnectionSettings,
setHasDevices,
+ setHasRiskProfiles,
setIsOpenAddDevice,
setIsOpenStartTestrun,
setIsOpenWaitSnackBar,
+ setRiskProfiles,
setStatus,
setTestrunStatus,
toggleMenu,
@@ -32,6 +34,7 @@ import {
} from './actions';
import { device } from '../mocks/device.mock';
import { MOCK_PROGRESS_DATA_CANCELLING } from '../mocks/testrun.mock';
+import { PROFILE_MOCK } from '../mocks/profile.mock';
describe('Reducer', () => {
describe('unknown action', () => {
@@ -169,6 +172,31 @@ describe('Reducer', () => {
});
});
+ describe('setHasRiskProfiles action', () => {
+ it('should update state', () => {
+ const initialState = initialSharedState;
+ const action = setHasRiskProfiles({ hasRiskProfiles: true });
+ const state = fromReducer.sharedReducer(initialState, action);
+ const newState = { ...initialState, ...{ hasRiskProfiles: true } };
+
+ expect(state).toEqual(newState);
+ expect(state).not.toBe(initialState);
+ });
+ });
+
+ describe('setRiskProfiles action', () => {
+ it('should update state', () => {
+ const initialState = initialSharedState;
+ const riskProfiles = [PROFILE_MOCK];
+ const action = setRiskProfiles({ riskProfiles });
+ const state = fromReducer.sharedReducer(initialState, action);
+ const newState = { ...initialState, ...{ riskProfiles } };
+
+ expect(state).toEqual(newState);
+ expect(state).not.toBe(initialState);
+ });
+ });
+
describe('setDeviceInProgress action', () => {
it('should update state', () => {
const initialState = initialSharedState;
diff --git a/modules/ui/src/app/store/reducers.ts b/modules/ui/src/app/store/reducers.ts
index cf8b3a48b..501c231a5 100644
--- a/modules/ui/src/app/store/reducers.ts
+++ b/modules/ui/src/app/store/reducers.ts
@@ -71,6 +71,18 @@ export const sharedReducer = createReducer(
devices,
};
}),
+ on(Actions.setHasRiskProfiles, (state, { hasRiskProfiles }) => {
+ return {
+ ...state,
+ hasRiskProfiles,
+ };
+ }),
+ on(Actions.setRiskProfiles, (state, { riskProfiles }) => {
+ return {
+ ...state,
+ riskProfiles,
+ };
+ }),
on(Actions.setTestrunStatus, (state, { systemStatus }) => {
return {
...state,
diff --git a/modules/ui/src/app/store/selectors.spec.ts b/modules/ui/src/app/store/selectors.spec.ts
index 43843b9dd..e8d31efc8 100644
--- a/modules/ui/src/app/store/selectors.spec.ts
+++ b/modules/ui/src/app/store/selectors.spec.ts
@@ -21,11 +21,13 @@ import {
selectError,
selectHasConnectionSettings,
selectHasDevices,
+ selectHasRiskProfiles,
selectInterfaces,
selectIsOpenAddDevice,
selectIsOpenStartTestrun,
selectIsOpenWaitSnackBar,
selectMenuOpened,
+ selectRiskProfiles,
selectStatus,
selectSystemStatus,
} from './selectors';
@@ -45,6 +47,8 @@ describe('Selectors', () => {
devices: [],
hasDevices: false,
isOpenAddDevice: false,
+ riskProfiles: [],
+ hasRiskProfiles: false,
isStopTestrun: false,
isOpenWaitSnackBar: false,
isOpenStartTestrun: false,
@@ -84,6 +88,16 @@ describe('Selectors', () => {
expect(result).toEqual(false);
});
+ it('should select riskProfiles', () => {
+ const result = selectRiskProfiles.projector(initialState);
+ expect(result).toEqual([]);
+ });
+
+ it('should select hasRiskProfiles', () => {
+ const result = selectHasRiskProfiles.projector(initialState);
+ expect(result).toEqual(false);
+ });
+
it('should select isOpenAddDevice', () => {
const result = selectIsOpenAddDevice.projector(initialState);
expect(result).toEqual(false);
diff --git a/modules/ui/src/app/store/selectors.ts b/modules/ui/src/app/store/selectors.ts
index 7075d4b0d..2f42db3d6 100644
--- a/modules/ui/src/app/store/selectors.ts
+++ b/modules/ui/src/app/store/selectors.ts
@@ -57,6 +57,16 @@ export const selectDeviceInProgress = createSelector(
(state: AppState) => state.shared.deviceInProgress
);
+export const selectHasRiskProfiles = createSelector(
+ selectAppState,
+ (state: AppState) => state.shared.hasRiskProfiles
+);
+
+export const selectRiskProfiles = createSelector(
+ selectAppState,
+ (state: AppState) => state.shared.riskProfiles
+);
+
export const selectError = createSelector(
selectAppState,
(state: AppState) => state.appComponent.settingMissedError
diff --git a/modules/ui/src/app/store/state.ts b/modules/ui/src/app/store/state.ts
index 11f52af2b..e2528c5a0 100644
--- a/modules/ui/src/app/store/state.ts
+++ b/modules/ui/src/app/store/state.ts
@@ -16,6 +16,7 @@
import { TestrunStatus } from '../model/testrun-status';
import { SettingMissedError, SystemInterfaces } from '../model/setting';
import { Device } from '../model/device';
+import { Profile } from '../model/profile';
export interface AppState {
appComponent: AppComponentState;
@@ -38,6 +39,9 @@ export interface SharedState {
devices: Device[];
//used in app, devices, testrun
hasDevices: boolean;
+ //app, risk-assessment, testrun, reports
+ riskProfiles: Profile[];
+ hasRiskProfiles: boolean;
//app, testrun
status: string | null;
systemStatus: TestrunStatus | null;
@@ -69,6 +73,8 @@ export const initialSharedState: SharedState = {
hasDevices: false,
devices: [],
deviceInProgress: null,
+ riskProfiles: [],
+ hasRiskProfiles: false,
isOpenStartTestrun: false,
systemStatus: null,
status: null,
diff --git a/modules/ui/src/styles.scss b/modules/ui/src/styles.scss
index a35b71254..74cb3765a 100644
--- a/modules/ui/src/styles.scss
+++ b/modules/ui/src/styles.scss
@@ -239,6 +239,19 @@ body
#main:has(app-callout .info):not(:has(app-callout .error))
app-risk-assessment
.risk-assessment-container,
+body
+ #main:has(app-callout .check_circle):not(:has(app-callout .error))
+ app-device-repository:not(:has(.device-repository-content-empty)),
+body
+ #main:has(app-callout .check_circle):not(:has(app-callout .error))
+ app-history:not(:has(.results-content-empty)),
+body
+ #main:has(app-callout .check_circle):not(:has(app-callout .error))
+ app-progress:not(:has(.progress-content-empty)),
+body
+ #main:has(app-callout .check_circle):not(:has(app-callout .error))
+ app-risk-assessment
+ .risk-assessment-container,
body
#main:has(app-callout .error):not(:has(app-callout .info))
app-device-repository:not(:has(.device-repository-content-empty)),
@@ -271,6 +284,22 @@ body
margin-top: 156px;
}
+body
+ #main:has(app-callout .check_circle):has(app-callout .error)
+ app-device-repository:not(:has(.device-repository-content-empty)),
+body
+ #main:has(app-callout .check_circle):has(app-callout .error)
+ app-history:not(:has(.results-content-empty)),
+body
+ #main:has(app-callout .check_circle):has(app-callout .error)
+ app-progress:not(:has(.progress-content-empty)),
+body
+ #main:has(app-callout .check_circle):has(app-callout .error)
+ app-risk-assessment
+ .risk-assessment-container {
+ margin-top: 156px;
+}
+
body:has(app-risk-assessment .profiles-drawer) #main app-callout {
width: calc(100% - $profiles-drawer-width);
}