From 2afcde99db06011d30ba5630e9626f8a815fcf48 Mon Sep 17 00:00:00 2001 From: kurilova Date: Tue, 30 Jun 2026 07:28:26 +0000 Subject: [PATCH 1/4] The "Discard changes" popup is not shown on navigating from changed outdated device --- .../device-qualification-from.component.ts | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/modules/ui/src/app/pages/devices/components/device-qualification-from/device-qualification-from.component.ts b/modules/ui/src/app/pages/devices/components/device-qualification-from/device-qualification-from.component.ts index a34b96493..d256d50d8 100644 --- a/modules/ui/src/app/pages/devices/components/device-qualification-from/device-qualification-from.component.ts +++ b/modules/ui/src/app/pages/devices/components/device-qualification-from/device-qualification-from.component.ts @@ -363,13 +363,33 @@ export class DeviceQualificationFromComponent implements OnInit, AfterViewInit { } } - if (device1.additional_info) { - for (const question of device1.additional_info) { - if ( - question.answer !== - device2.additional_info?.find( - question2 => question2.question === question.question - )?.answer + // the 2nd device has the newest version of risk assessment + if (device2.additional_info) { + for (const question of device2.additional_info) { + const answer2 = device1.additional_info?.find( + question1 => question1.question === question.question + )?.answer; + const answer1 = question.answer; + if (!this.isEmptyAnswer(answer1) && !this.isEmptyAnswer(answer2)) { + if (typeof question.answer === 'string') { + if (answer1 !== answer2) { + return false; + } + } else { + //the type of answer is array + if (answer1?.length !== answer2?.length) { + return false; + } + if ( + (answer1 as number[]).some( + answer => !(answer2 as number[]).includes(answer) + ) + ) + return false; + } + } else if ( + this.isEmptyAnswer(answer2) && + !this.isEmptyAnswer(answer1) ) { return false; } @@ -380,6 +400,12 @@ export class DeviceQualificationFromComponent implements OnInit, AfterViewInit { return true; } + private isEmptyAnswer(answer: unknown): boolean { + if (answer === undefined || answer === null || answer === '') return true; + if (Array.isArray(answer) && answer.length === 0) return true; + return false; + } + private fillDeviceForm(format: QuestionFormat[], device: Device): void { format.forEach((question, index) => { const answer = device.additional_info?.find( From dfb75a5234de9a68e946f90543995bd59c04aff2 Mon Sep 17 00:00:00 2001 From: kurilova Date: Tue, 30 Jun 2026 08:06:14 +0000 Subject: [PATCH 2/4] Update tests --- modules/ui/src/app/mocks/profile.mock.ts | 23 ++++++++++ .../profile-form.component.spec.ts | 43 +++++++++++++++++++ .../profile-form/profile-form.component.ts | 8 +++- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/modules/ui/src/app/mocks/profile.mock.ts b/modules/ui/src/app/mocks/profile.mock.ts index a380d49ee..d56919c74 100644 --- a/modules/ui/src/app/mocks/profile.mock.ts +++ b/modules/ui/src/app/mocks/profile.mock.ts @@ -149,6 +149,29 @@ export const NEW_PROFILE_MOCK_DRAFT = { ], }; +export const NEW_PROFILE_MOCK_CHANGED = { + ...NEW_PROFILE_MOCK, + questions: [ + { + question: 'What is the email of the device owner(s)?', + answer: 'a@test.te;b@test.te, c@test.te, d@test.te', + }, + { + question: 'What type of device do you need reviewed?', + answer: 'new', + }, + { + question: 'Are any of the following statements true about your device?', + answer: 'new', + }, + { + question: 'What features does the device have?', + answer: [0, 1, 2, 4], + }, + { question: 'Comments', answer: 'no' }, + ], +}; + export const RENAME_PROFILE_MOCK = { ...NEW_PROFILE_MOCK, name: 'Primary profile', diff --git a/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.spec.ts b/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.spec.ts index d7d595273..20c2ee718 100644 --- a/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.spec.ts +++ b/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.spec.ts @@ -21,6 +21,7 @@ import { COPY_PROFILE_MOCK, EXPIRED_PROFILE_MOCK, NEW_PROFILE_MOCK, + NEW_PROFILE_MOCK_CHANGED, NEW_PROFILE_MOCK_DRAFT, OUTDATED_DRAFT_PROFILE_MOCK, PROFILE_FORM, @@ -489,6 +490,48 @@ describe('ProfileFormComponent', () => { done(); }); }); + + describe('compareProfiles', () => { + it('should return false if the name is different', () => { + const res = component.compareProfiles(PROFILE_MOCK, PROFILE_MOCK_2); + + expect(res).toBeFalse(); + }); + + it('should return false for copy of profile', () => { + const res = component.compareProfiles( + PROFILE_MOCK, + PROFILE_MOCK, + PROFILE_MOCK_2 + ); + + expect(res).toBeFalse(); + }); + + it('should return false is profile status is different', () => { + const res = component.compareProfiles( + NEW_PROFILE_MOCK, + NEW_PROFILE_MOCK_DRAFT + ); + + expect(res).toBeFalse(); + }); + + it('should return false is profile has changes', () => { + const res = component.compareProfiles( + NEW_PROFILE_MOCK, + NEW_PROFILE_MOCK_CHANGED + ); + + expect(res).toBeFalse(); + }); + + it('should return true is profile has no changes', () => { + const res = component.compareProfiles(PROFILE_MOCK, PROFILE_MOCK); + + expect(res).toBeTrue(); + }); + }); }); }); diff --git a/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.ts b/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.ts index 1da440c16..8c428dc2f 100644 --- a/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.ts +++ b/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.ts @@ -237,8 +237,12 @@ export class ProfileFormComponent implements OnInit, AfterViewInit { return true; } - private compareProfiles(profile1: Profile, profile2: Profile) { - if (profile1.name !== profile2.name || this.copyProfile) { + compareProfiles( + profile1: Profile, + profile2: Profile, + copyProfile = this.copyProfile + ) { + if (profile1.name !== profile2.name || copyProfile) { return false; } if ( From a96e4bce911d136d3259848140a22c4d99d81cb0 Mon Sep 17 00:00:00 2001 From: kurilova Date: Tue, 30 Jun 2026 08:53:29 +0000 Subject: [PATCH 3/4] Update tests --- ...evice-qualification-from.component.spec.ts | 99 +++++++++++++++++++ .../device-qualification-from.component.ts | 80 +++++++-------- 2 files changed, 139 insertions(+), 40 deletions(-) diff --git a/modules/ui/src/app/pages/devices/components/device-qualification-from/device-qualification-from.component.spec.ts b/modules/ui/src/app/pages/devices/components/device-qualification-from/device-qualification-from.component.spec.ts index 253d4eccb..d05795036 100644 --- a/modules/ui/src/app/pages/devices/components/device-qualification-from/device-qualification-from.component.spec.ts +++ b/modules/ui/src/app/pages/devices/components/device-qualification-from/device-qualification-from.component.spec.ts @@ -499,6 +499,105 @@ describe('DeviceQualificationFromComponent', () => { expect(saveSpy).toHaveBeenCalledWith(MOCK_DEVICE); }); }); + + describe('compareDevices', () => { + it('should return false if manufacturer has changes', () => { + const updated_device = { + ...device, + manufacturer: 'new manufacturer', + }; + + expect(component.compareDevices(device, updated_device)).toBeFalse(); + }); + }); + + it('should return false if model has changes', () => { + const updated_device = { + ...device, + model: 'new model', + }; + + expect(component.compareDevices(device, updated_device)).toBeFalse(); + }); + + it('should return false if mac_addr has changes', () => { + const updated_device = { + ...device, + mac_addr: 'new mac_addr', + }; + + expect(component.compareDevices(device, updated_device)).toBeFalse(); + }); + + it('should return false if type has changes', () => { + const updated_device = { + ...device, + type: 'new type', + }; + + expect(component.compareDevices(device, updated_device)).toBeFalse(); + }); + + it('should return false if technology has changes', () => { + const updated_device = { + ...device, + technology: 'new technology', + }; + + expect(component.compareDevices(device, updated_device)).toBeFalse(); + }); + + it('should return false if test_pack has changes', () => { + const updated_device = { + ...device, + test_pack: TestingType.Qualification, + }; + + expect(component.compareDevices(device, updated_device)).toBeFalse(); + }); + + it('should return false if test modules has changes', () => { + const updated_device = { + ...device, + test_modules: { + dns: { + enabled: true, + }, + connection: { + enabled: true, + }, + }, + }; + + expect(component.compareDevices(device, updated_device)).toBeFalse(); + }); + + it('should return false if additional info has changes', () => { + const updated_device = { + ...device, + additional_info: [ + { + question: 'Please select the technology this device falls into', + answer: 'Building Automation', + }, + ], + }; + + expect(component.compareDevices(device, updated_device)).toBeFalse(); + }); + + it('should return true if device has no changes', () => { + const new_device = { + ...device, + additional_info: [ + { + question: 'Please select the technology this device falls into', + answer: 'Building Automation', + }, + ], + }; + expect(component.compareDevices(new_device, new_device)).toBeTrue(); + }); }); @Component({ diff --git a/modules/ui/src/app/pages/devices/components/device-qualification-from/device-qualification-from.component.ts b/modules/ui/src/app/pages/devices/components/device-qualification-from/device-qualification-from.component.ts index d256d50d8..338529da3 100644 --- a/modules/ui/src/app/pages/devices/components/device-qualification-from/device-qualification-from.component.ts +++ b/modules/ui/src/app/pages/devices/components/device-qualification-from/device-qualification-from.component.ts @@ -295,46 +295,7 @@ export class DeviceQualificationFromComponent implements OnInit, AfterViewInit { ); } - private deviceIsEmpty(device: Device) { - if (device.manufacturer && device.manufacturer !== '') { - return false; - } - if (device.model && device.model !== '') { - return false; - } - if (device.mac_addr && device.mac_addr !== '') { - return false; - } - if (device.type && device.type !== '') { - return false; - } - if (device.technology && device.technology !== '') { - return false; - } - if (device.test_pack !== TestingType.Qualification) { - return false; - } - const keys1 = Object.keys(device.test_modules!); - - for (const key of keys1) { - const val1 = device.test_modules![key]; - if (!val1.enabled) { - return false; - } - } - if (device.additional_info) { - for (const question of device.additional_info) { - if (question.answer && question.answer !== '') { - return false; - } - } - } else { - return false; - } - return true; - } - - private compareDevices(device1: Device, device2: Device) { + compareDevices(device1: Device, device2: Device) { if (device1.manufacturer !== device2.manufacturer) { return false; } @@ -400,6 +361,45 @@ export class DeviceQualificationFromComponent implements OnInit, AfterViewInit { return true; } + private deviceIsEmpty(device: Device) { + if (device.manufacturer && device.manufacturer !== '') { + return false; + } + if (device.model && device.model !== '') { + return false; + } + if (device.mac_addr && device.mac_addr !== '') { + return false; + } + if (device.type && device.type !== '') { + return false; + } + if (device.technology && device.technology !== '') { + return false; + } + if (device.test_pack !== TestingType.Qualification) { + return false; + } + const keys1 = Object.keys(device.test_modules!); + + for (const key of keys1) { + const val1 = device.test_modules![key]; + if (!val1.enabled) { + return false; + } + } + if (device.additional_info) { + for (const question of device.additional_info) { + if (question.answer && question.answer !== '') { + return false; + } + } + } else { + return false; + } + return true; + } + private isEmptyAnswer(answer: unknown): boolean { if (answer === undefined || answer === null || answer === '') return true; if (Array.isArray(answer) && answer.length === 0) return true; From c4af54788f2461b8147cb1ac40463a4a4dc62dc7 Mon Sep 17 00:00:00 2001 From: kurilova Date: Tue, 30 Jun 2026 09:28:28 +0000 Subject: [PATCH 4/4] Update version --- make/DEBIAN/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/DEBIAN/control b/make/DEBIAN/control index 439f0c1bc..6b7ea9f7c 100644 --- a/make/DEBIAN/control +++ b/make/DEBIAN/control @@ -1,5 +1,5 @@ Package: Testrun -Version: 2.4.0-beta.5 +Version: 2.4.0-beta.6 Architecture: amd64 Maintainer: Google Homepage: https://github.com/google/testrun