diff --git a/CHANGELOG.md b/CHANGELOG.md index f46ba1721..abbec6f48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Support PURLs in affected components (`OSIDB-3412`) * Increase step value for affects and trackers per page (`OSIDB-3508`) * Support showing all trackers/affects in single page (`OSIDB-3506`) +* Add suggestions on CWE Field (`OSIDB-3743`) ### Fixed diff --git a/src/assets/main.css b/src/assets/main.css index 09cf2b54d..666b3ede3 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -76,3 +76,15 @@ table { pointer-events: none; opacity: 0.5; } + +.flex-1 { + flex: 1; +} + +.flex-2 { + flex: 2; +} + +.flex-3 { + flex: 3; +} diff --git a/src/components/CweSelector/CweSelector.vue b/src/components/CweSelector/CweSelector.vue new file mode 100644 index 000000000..a5ce64208 --- /dev/null +++ b/src/components/CweSelector/CweSelector.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/src/components/FlawForm/FlawForm.vue b/src/components/FlawForm/FlawForm.vue index bcb8a7eaa..aca4655b5 100644 --- a/src/components/FlawForm/FlawForm.vue +++ b/src/components/FlawForm/FlawForm.vue @@ -17,6 +17,7 @@ import FlawHistory from '@/components/FlawHistory/FlawHistory.vue'; import FlawContributors from '@/components/FlawContributors/FlawContributors.vue'; import CvssExplainForm from '@/components/CvssExplainForm/CvssExplainForm.vue'; import FlawAffects from '@/components/FlawAffects/FlawAffects.vue'; +import CweSelector from '@/components/CweSelector/CweSelector.vue'; import { useFlawModel } from '@/composables/useFlawModel'; @@ -244,10 +245,9 @@ const createdDate = computed(() => { :allCvss="flaw.cvss_scores" :nistCvss="nvdCvss3String" /> - { + let wrapper: VueWrapper; + + beforeEach(() => { + wrapper = mountWithConfig(CweSelector); + vi.useFakeTimers(); + }); + + it('renders correctly', () => { + expect(wrapper.exists()).toBe(true); + expect(wrapper.html()).toMatchSnapshot(); + }); + + it('loads CWE data on component mount', async () => { + const data = JSON.stringify([{ id: '123', name: 'Test CWE', status: 'Draft', summary: '', usage: '' }]); + localStorage.setItem(DATA_KEY, data); + wrapper = mountWithConfig(CweSelector); + expect(wrapper.vm.cweData).toEqual([{ id: '123', name: 'Test CWE', status: 'Draft', summary: '', usage: '' }]); + }); + + it('filters suggestions correctly and updates model on suggestion click', async () => { + wrapper.vm.cweData = [ + { id: '123', name: 'Test CWE', status: 'Draft', summary: '', usage: '' }, + { id: '456', name: 'Another CWE', status: 'Draft', summary: '', usage: '' }, + ]; + const input = wrapper.find('input'); + await input.setValue('123'); + + vi.runAllTimers(); + await flushPromises(); + expect(wrapper.text()).toContain('CWE-123'); + + const suggestionRow = wrapper.findAll('.dropdown-menu .item'); + await suggestionRow[0].trigger('click'); + expect(wrapper.vm.modelValue).toBe('CWE-123'); + expect(wrapper.vm.queryRef).toBe('CWE-123'); + expect(wrapper.vm.suggestions).toEqual([]); + }); +}); diff --git a/src/components/__tests__/FlawForm.spec.ts b/src/components/__tests__/FlawForm.spec.ts index d08cc2b2d..1307d298b 100644 --- a/src/components/__tests__/FlawForm.spec.ts +++ b/src/components/__tests__/FlawForm.spec.ts @@ -8,6 +8,7 @@ import FlawForm from '@/components/FlawForm/FlawForm.vue'; import CvssCalculator from '@/components/CvssCalculator/CvssCalculator.vue'; import FlawFormOwner from '@/components/FlawFormOwner/FlawFormOwner.vue'; import IssueFieldEmbargo from '@/components/IssueFieldEmbargo/IssueFieldEmbargo.vue'; +import CweSelector from '@/components/CweSelector/CweSelector.vue'; import { blankFlaw } from '@/composables/useFlaw'; @@ -106,7 +107,7 @@ describe('flawForm', () => { expect(nvdCvssField?.exists()).toBe(true); const cweIdField = subject - .findAllComponents(LabelEditable) + .findAllComponents(CweSelector) .find(component => component.props().label === 'CWE ID'); expect(cweIdField?.exists()).toBe(true); @@ -187,7 +188,7 @@ describe('flawForm', () => { expect(nvdCvssField?.exists()).toBe(true); const cweIdField = subject - .findAllComponents(LabelEditable) + .findAllComponents(CweSelector) .find(component => component.props().label === 'CWE ID'); expect(cweIdField?.exists()).toBe(true); diff --git a/src/components/__tests__/__snapshots__/CweSelector.spec.ts.snap b/src/components/__tests__/__snapshots__/CweSelector.spec.ts.snap new file mode 100644 index 000000000..94a45f4f4 --- /dev/null +++ b/src/components/__tests__/__snapshots__/CweSelector.spec.ts.snap @@ -0,0 +1,23 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`cweSelector.vue > renders correctly 1`] = ` +"
+
+
+ +
+ + +
+ +
+
+ + +
+
+
+
" +`; diff --git a/src/components/__tests__/__snapshots__/FlawForm.spec.ts.snap b/src/components/__tests__/__snapshots__/FlawForm.spec.ts.snap index 05e418793..ba7479c70 100644 --- a/src/components/__tests__/__snapshots__/FlawForm.spec.ts.snap +++ b/src/components/__tests__/__snapshots__/FlawForm.spec.ts.snap @@ -196,22 +196,26 @@ exports[`flawForm > mounts and renders 1`] = ` -