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 @@
+
+
+
+
+
+
+
+
+
{{ `CWE-${cwe.id} ` }}
+
{{ `${cwe.name}. ` }}
+
{{ `${cwe.usage}` }}
+
+
+
+
+
+
+
+
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`] = `
-