Skip to content

Commit

Permalink
Disable device item if device in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
sofyakurilova committed Apr 4, 2024
1 parent cbf9328 commit 5d34823
Show file tree
Hide file tree
Showing 16 changed files with 137 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
*ngIf="deviceView === DeviceView.WithActions"
class="device-item-with-actions">
<button
[disabled]="disabled"
[tabIndex]="tabIndex"
(click)="itemClick()"
attr.aria-label="Edit device {{ label }}"
Expand All @@ -57,6 +58,7 @@
</div>
</button>
<button
[disabled]="disabled"
(click)="startTestrunClick()"
attr.aria-label="Start new testrun for device {{ label }}"
class="button-start"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ $border-radius: 12px;
width: 24px;
}
}

&:disabled {
pointer-events: none;
opacity: 0.5;
}
}

.item-manufacturer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,27 @@ describe('DeviceItemComponent', () => {

expect(clickSpy).toHaveBeenCalledWith(component.device);
});

it('should disable buttons if disable set to true', () => {
component.disabled = true;
fixture.detectChanges();

const startBtn = compiled.querySelector('.button-start') as HTMLElement;
const editBtn = compiled.querySelector('.button-edit') as HTMLElement;

expect(editBtn.getAttribute('disabled')).not.toBeNull();
expect(startBtn.getAttribute('disabled')).toBeTruthy();
});

it('should not disable buttons if disable set to false', () => {
component.disabled = false;
fixture.detectChanges();

const startBtn = compiled.querySelector('.button-start') as HTMLElement;
const editBtn = compiled.querySelector('.button-edit') as HTMLElement;

expect(editBtn.getAttribute('disabled')).toBeNull();
expect(startBtn.getAttribute('disabled')).toBeFalsy();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export class DeviceItemComponent {
@Input() device!: Device;
@Input() tabIndex = 0;
@Input() deviceView!: string;
@Input() disabled = false;
@Output() itemClicked = new EventEmitter<Device>();
@Output() startTestrunClicked = new EventEmitter<Device>();
readonly DeviceView = DeviceView;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ <h2 class="title">Devices</h2>
(startTestrunClicked)="openStartTestrun($event, vm.devices)"
[deviceView]="DeviceView.WithActions"
[class.device-item-selected]="device === vm.selectedDevice"
[device]="device"></app-device-item>
[device]="device"
[disabled]="
device?.mac_addr === vm.deviceInProgress?.mac_addr
"></app-device-item>
</ng-container>
</div>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ describe('DeviceRepositoryComponent', () => {
component.viewModel$ = of({
devices: [] as Device[],
selectedDevice: null,
deviceInProgress: null,
});
mockDevicesStore.devices$ = of([]);
mockDevicesStore.isOpenAddDevice$ = of(true);
Expand Down Expand Up @@ -102,6 +103,7 @@ describe('DeviceRepositoryComponent', () => {
component.viewModel$ = of({
devices: [device, device, device],
selectedDevice: device,
deviceInProgress: device,
});
fixture.detectChanges();
});
Expand Down Expand Up @@ -199,6 +201,12 @@ describe('DeviceRepositoryComponent', () => {
openSpy.calls.reset();
});
});

it('should disable device if deviceInProgress is exist', () => {
const item = compiled.querySelector('app-device-item');

expect(item?.getAttribute('ng-reflect-disabled')).toBeTruthy();
});
});

it('should call setIsOpenAddDevice if dialog closes with null', () => {
Expand Down Expand Up @@ -230,6 +238,7 @@ describe('DeviceRepositoryComponent', () => {
component.viewModel$ = of({
devices: [device, device, device],
selectedDevice: device,
deviceInProgress: null,
});
fixture.detectChanges();
});
Expand Down
7 changes: 6 additions & 1 deletion modules/ui/src/app/pages/devices/devices.store.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import { TestBed } from '@angular/core/testing';
import { of, skip, take } from 'rxjs';
import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { AppState } from '../../store/state';
import { selectHasDevices } from '../../store/selectors';
import {
selectDeviceInProgress,
selectHasDevices,
} from '../../store/selectors';
import { TestRunService } from '../../services/test-run.service';
import SpyObj = jasmine.SpyObj;
import { device, updated_device } from '../../mocks/device.mock';
Expand Down Expand Up @@ -45,6 +48,7 @@ describe('DevicesStore', () => {
selectors: [
{ selector: selectDevices, value: [device] },
{ selector: selectIsOpenAddDevice, value: true },
{ selector: selectDeviceInProgress, value: device },
],
}),
{ provide: TestRunService, useValue: mockService },
Expand Down Expand Up @@ -79,6 +83,7 @@ describe('DevicesStore', () => {
expect(store).toEqual({
devices: [device],
selectedDevice: null,
deviceInProgress: device,
});
done();
});
Expand Down
8 changes: 7 additions & 1 deletion modules/ui/src/app/pages/devices/devices.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ import { tap, withLatestFrom } from 'rxjs/operators';
import { Device } from '../../model/device';
import { AppState } from '../../store/state';
import { Store } from '@ngrx/store';
import { selectDevices, selectIsOpenAddDevice } from '../../store/selectors';
import {
selectDeviceInProgress,
selectDevices,
selectIsOpenAddDevice,
} from '../../store/selectors';
import { setDevices, setIsOpenAddDevice } from '../../store/actions';

export interface DevicesComponentState {
Expand All @@ -34,12 +38,14 @@ export interface DevicesComponentState {
export class DevicesStore extends ComponentStore<DevicesComponentState> {
devices$ = this.store.select(selectDevices);
isOpenAddDevice$ = this.store.select(selectIsOpenAddDevice);
private deviceInProgress$ = this.store.select(selectDeviceInProgress);
private selectedDevice$ = this.select(state => state.selectedDevice);

testModules = this.testRunService.getTestModules();
viewModel$ = this.select({
devices: this.devices$,
selectedDevice: this.selectedDevice$,
deviceInProgress: this.deviceInProgress$,
});

selectDevice = this.updater((state, device: Device | null) => ({
Expand Down
23 changes: 22 additions & 1 deletion modules/ui/src/app/services/test-run.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import {
import { StatusOfTestResult, TestrunStatus } from '../model/testrun-status';
import { device } from '../mocks/device.mock';
import { NEW_VERSION, VERSION } from '../mocks/version.mock';
import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { AppState } from '../store/state';
import { setDeviceInProgress } from '../store/actions';

const MOCK_SYSTEM_CONFIG: SystemConfig = {
network: {
Expand All @@ -41,15 +44,18 @@ describe('TestRunService', () => {
let injector: TestBed;
let httpTestingController: HttpTestingController;
let service: TestRunService;
let store: MockStore<AppState>;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [TestRunService],
providers: [TestRunService, provideMockStore({})],
});
injector = getTestBed();
httpTestingController = injector.get(HttpTestingController);
service = injector.get(TestRunService);
store = TestBed.inject(MockStore);
spyOn(store, 'dispatch').and.callFake(() => {});
});

afterEach(() => {
Expand Down Expand Up @@ -171,6 +177,21 @@ describe('TestRunService', () => {
req.flush(result);
});

it('should dispatch setDeviceInProgress when testrun is in progress', () => {
const result = { ...MOCK_PROGRESS_DATA_IN_PROGRESS };

service.getSystemStatus();
const req = httpTestingController.expectOne(
'http://localhost:8000/system/status'
);

req.flush(result);

expect(store.dispatch).toHaveBeenCalledWith(
setDeviceInProgress({ device: result.device })
);
});

it('should get cancelling data if status is cancelling', () => {
const result = { ...MOCK_PROGRESS_DATA_IN_PROGRESS };

Expand Down
18 changes: 17 additions & 1 deletion modules/ui/src/app/services/test-run.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import {
TestrunStatus,
} from '../model/testrun-status';
import { Version } from '../model/version';
import { Store } from '@ngrx/store';
import { AppState } from '../store/state';
import { setDeviceInProgress } from '../store/actions';

const API_URL = `http://${window.location.hostname}:8000`;
export const SYSTEM_STOP = '/system/stop';
Expand Down Expand Up @@ -83,7 +86,10 @@ export class TestRunService {
public isTestrunStarted$ = this.isTestrunStartedSub$.asObservable();
private version = new BehaviorSubject<Version | null>(null);

constructor(private http: HttpClient) {}
constructor(
private http: HttpClient,
private store: Store<AppState>
) {}

setIsOpenStartTestrun(isOpen: boolean): void {
this.isOpenStartTestrunSub$.next(isOpen);
Expand Down Expand Up @@ -125,6 +131,16 @@ export class TestRunService {
res.status = StatusOfTestrun.Cancelling;
}
this.setSystemStatus(res);
this.store.dispatch(
setDeviceInProgress({
device:
res.status === StatusOfTestrun.Monitoring ||
res.status === StatusOfTestrun.InProgress ||
res.status === StatusOfTestrun.WaitingForDevice
? res.device
: null,
})
);
});
}

Expand Down
5 changes: 5 additions & 0 deletions modules/ui/src/app/store/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,8 @@ export const setDevices = createAction(
'[Shared] Set Devices',
props<{ devices: Device[] }>()
);

export const setDeviceInProgress = createAction(
'[Shared] Set Device In Progress',
props<{ device: Device | null }>()
);
17 changes: 17 additions & 0 deletions modules/ui/src/app/store/reducers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import * as fromReducer from './reducers';
import { initialAppComponentState, initialSharedState } from './state';
import {
fetchInterfacesSuccess,
setDeviceInProgress,
setDevices,
setHasConnectionSettings,
setHasDevices,
Expand Down Expand Up @@ -150,4 +151,20 @@ describe('Reducer', () => {
expect(state).not.toBe(initialState);
});
});

describe('setDeviceInProgress action', () => {
it('should update state', () => {
const initialState = initialSharedState;
const deviceInProgress = device;
const action = setDeviceInProgress({ device: deviceInProgress });
const state = fromReducer.sharedReducer(initialState, action);
const newState = {
...initialState,
...{ deviceInProgress: deviceInProgress },
};

expect(state).toEqual(newState);
expect(state).not.toBe(initialState);
});
});
});
6 changes: 6 additions & 0 deletions modules/ui/src/app/store/reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ export const sharedReducer = createReducer(
...state,
devices,
};
}),
on(Actions.setDeviceInProgress, (state, { device }) => {
return {
...state,
deviceInProgress: device,
};
})
);

Expand Down
7 changes: 7 additions & 0 deletions modules/ui/src/app/store/selectors.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import { AppState } from './state';
import {
selectDeviceInProgress,
selectDevices,
selectError,
selectHasConnectionSettings,
Expand All @@ -40,6 +41,7 @@ describe('Selectors', () => {
devices: [],
hasDevices: false,
isOpenAddDevice: false,
deviceInProgress: null,
},
};

Expand Down Expand Up @@ -77,4 +79,9 @@ describe('Selectors', () => {
const result = selectIsOpenAddDevice.projector(initialState);
expect(result).toEqual(false);
});

it('should select deviceInProgress', () => {
const result = selectDeviceInProgress.projector(initialState);
expect(result).toEqual(null);
});
});
5 changes: 5 additions & 0 deletions modules/ui/src/app/store/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ export const selectDevices = createSelector(
(state: AppState) => state.shared.devices
);

export const selectDeviceInProgress = createSelector(
selectAppState,
(state: AppState) => state.shared.deviceInProgress
);

export const selectError = createSelector(
selectAppState,
(state: AppState) => state.appComponent.settingMissedError
Expand Down
2 changes: 2 additions & 0 deletions modules/ui/src/app/store/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface SharedState {
hasConnectionSettings: boolean | null;
// app, devices
isOpenAddDevice: boolean;
deviceInProgress: Device | null;
}

export const initialAppComponentState: AppComponentState = {
Expand All @@ -62,4 +63,5 @@ export const initialSharedState: SharedState = {
isOpenAddDevice: false,
hasDevices: false,
devices: [],
deviceInProgress: null,
};

0 comments on commit 5d34823

Please sign in to comment.