diff --git a/modules/ui/src/app/app.component.html b/modules/ui/src/app/app.component.html
index d52e04772..f47583973 100644
--- a/modules/ui/src/app/app.component.html
+++ b/modules/ui/src/app/app.component.html
@@ -98,7 +98,7 @@
@@ -207,6 +207,7 @@
Testrun
class="settings-drawer">
diff --git a/modules/ui/src/app/app.component.spec.ts b/modules/ui/src/app/app.component.spec.ts
index 6f3f1b3ea..b6b577984 100644
--- a/modules/ui/src/app/app.component.spec.ts
+++ b/modules/ui/src/app/app.component.spec.ts
@@ -62,6 +62,7 @@ import {
} from './store/selectors';
import { MatIconTestingModule } from '@angular/material/icon/testing';
import { CertificatesComponent } from './pages/certificates/certificates.component';
+import { of } from 'rxjs';
describe('AppComponent', () => {
let component: AppComponent;
@@ -96,8 +97,10 @@ describe('AppComponent', () => {
'getTestModules',
'testrunInProgress',
'fetchCertificates',
+ 'deleteCertificate',
]);
+ mockService.deleteCertificate.and.returnValue(of(true));
mockFocusManagerService = jasmine.createSpyObj('mockFocusManagerService', [
'focusFirstElementInContainer',
]);
@@ -673,6 +676,12 @@ describe('AppComponent', () => {
expect(component.certDrawer.open).toHaveBeenCalledTimes(1);
});
+
+ it('should call delete certificate', () => {
+ component.deleteCertificate('name');
+
+ expect(mockService.deleteCertificate).toHaveBeenCalledWith('name');
+ });
});
@Component({
diff --git a/modules/ui/src/app/app.component.ts b/modules/ui/src/app/app.component.ts
index 4334662b3..91a0ddd13 100644
--- a/modules/ui/src/app/app.component.ts
+++ b/modules/ui/src/app/app.component.ts
@@ -165,4 +165,8 @@ export class AppComponent {
isTestrunInProgress(status?: string) {
return this.testRunService.testrunInProgress(status);
}
+
+ deleteCertificate(name: string) {
+ this.appStore.deleteCertificate(name);
+ }
}
diff --git a/modules/ui/src/app/app.store.spec.ts b/modules/ui/src/app/app.store.spec.ts
index a11f85943..ffdb18921 100644
--- a/modules/ui/src/app/app.store.spec.ts
+++ b/modules/ui/src/app/app.store.spec.ts
@@ -32,7 +32,7 @@ import SpyObj = jasmine.SpyObj;
import { device } from './mocks/device.mock';
import { setDevices, setTestrunStatus } from './store/actions';
import { MOCK_PROGRESS_DATA_IN_PROGRESS } from './mocks/progress.mock';
-import { certificate } from './mocks/certificate.mock';
+import { certificate, certificate2 } from './mocks/certificate.mock';
const mock = (() => {
let store: { [key: string]: string } = {};
@@ -62,6 +62,7 @@ describe('AppStore', () => {
'fetchDevices',
'fetchSystemStatus',
'fetchCertificates',
+ 'deleteCertificate',
]);
TestBed.configureTestingModule({
@@ -216,5 +217,20 @@ describe('AppStore', () => {
appStore.getCertificates();
});
});
+
+ describe('deleteCertificate', () => {
+ it('should update store', done => {
+ mockService.deleteCertificate.and.returnValue(of(true));
+
+ appStore.updateCertificates([certificate, certificate2]);
+
+ appStore.viewModel$.pipe(skip(1), take(1)).subscribe(store => {
+ expect(store.certificates).toEqual([certificate2]);
+ done();
+ });
+
+ appStore.deleteCertificate('iot.bms.google.com');
+ });
+ });
});
});
diff --git a/modules/ui/src/app/app.store.ts b/modules/ui/src/app/app.store.ts
index ee5c952fe..46d42bd3f 100644
--- a/modules/ui/src/app/app.store.ts
+++ b/modules/ui/src/app/app.store.ts
@@ -16,7 +16,7 @@
import { Injectable } from '@angular/core';
import { ComponentStore } from '@ngrx/component-store';
-import { tap } from 'rxjs/operators';
+import { tap, withLatestFrom } from 'rxjs/operators';
import {
selectError,
selectHasConnectionSettings,
@@ -148,6 +148,26 @@ export class AppStore extends ComponentStore
{
})
);
});
+
+ deleteCertificate = this.effect(trigger$ => {
+ return trigger$.pipe(
+ exhaustMap((name: string) => {
+ return this.testRunService.deleteCertificate(name).pipe(
+ withLatestFrom(this.certificates$),
+ tap(([, current]) => {
+ this.removeCertificate(name, current);
+ })
+ );
+ })
+ );
+ });
+
+ private removeCertificate(name: string, current: Certificate[]) {
+ const certificates = current.filter(
+ certificate => certificate.name !== name
+ );
+ this.updateCertificates(certificates);
+ }
constructor(
private store: Store,
private testRunService: TestRunService
diff --git a/modules/ui/src/app/mocks/certificate.mock.ts b/modules/ui/src/app/mocks/certificate.mock.ts
index b2a38847b..f563d7d43 100644
--- a/modules/ui/src/app/mocks/certificate.mock.ts
+++ b/modules/ui/src/app/mocks/certificate.mock.ts
@@ -20,3 +20,9 @@ export const certificate = {
organisation: 'Google, Inc.',
expires: '2024-09-01T09:00:12Z',
} as Certificate;
+
+export const certificate2 = {
+ name: 'sensor.bms.google.com',
+ organisation: 'Google, Inc.',
+ expires: '2024-09-01T09:00:12Z',
+} as Certificate;
diff --git a/modules/ui/src/app/pages/certificates/certificate-item/certificate-item.component.html b/modules/ui/src/app/pages/certificates/certificate-item/certificate-item.component.html
index 2f1a4c778..d1a1b2189 100644
--- a/modules/ui/src/app/pages/certificates/certificate-item/certificate-item.component.html
+++ b/modules/ui/src/app/pages/certificates/certificate-item/certificate-item.component.html
@@ -13,7 +13,8 @@
diff --git a/modules/ui/src/app/pages/certificates/certificate-item/certificate-item.component.spec.ts b/modules/ui/src/app/pages/certificates/certificate-item/certificate-item.component.spec.ts
index 7705605e3..b39876501 100644
--- a/modules/ui/src/app/pages/certificates/certificate-item/certificate-item.component.spec.ts
+++ b/modules/ui/src/app/pages/certificates/certificate-item/certificate-item.component.spec.ts
@@ -45,12 +45,24 @@ describe('CertificateItemComponent', () => {
expect(date?.textContent?.trim()).toEqual('01 Sep 2024');
});
- it('should have delete button', () => {
- const deleteButton = fixture.nativeElement.querySelector(
- '#main .test-button'
- ) as HTMLButtonElement;
+ describe('delete button', () => {
+ let deleteButton: HTMLButtonElement;
+ beforeEach(() => {
+ deleteButton = fixture.nativeElement.querySelector(
+ '.certificate-item-delete'
+ ) as HTMLButtonElement;
+ });
- expect(deleteButton).toBeDefined();
+ it('should be present', () => {
+ expect(deleteButton).toBeDefined();
+ });
+
+ it('should emit delete event on delete button clicked', () => {
+ const deleteSpy = spyOn(component.deleteButtonClicked, 'emit');
+ deleteButton.click();
+
+ expect(deleteSpy).toHaveBeenCalledWith('iot.bms.google.com');
+ });
});
});
});
diff --git a/modules/ui/src/app/pages/certificates/certificate-item/certificate-item.component.ts b/modules/ui/src/app/pages/certificates/certificate-item/certificate-item.component.ts
index ccdbf43cc..9e653d111 100644
--- a/modules/ui/src/app/pages/certificates/certificate-item/certificate-item.component.ts
+++ b/modules/ui/src/app/pages/certificates/certificate-item/certificate-item.component.ts
@@ -1,4 +1,4 @@
-import { Component, Input } from '@angular/core';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Certificate } from '../../../model/certificate';
import { MatIcon } from '@angular/material/icon';
import { DatePipe } from '@angular/common';
@@ -13,4 +13,5 @@ import { MatButtonModule } from '@angular/material/button';
})
export class CertificateItemComponent {
@Input() certificate!: Certificate;
+ @Output() deleteButtonClicked = new EventEmitter