diff --git a/report-viewer/src/components/ComparisonsTable.vue b/report-viewer/src/components/ComparisonsTable.vue index 67545cc4e..c22f40f70 100644 --- a/report-viewer/src/components/ComparisonsTable.vue +++ b/report-viewer/src/components/ComparisonsTable.vue @@ -11,8 +11,27 @@
Similarity
-
Average
-
Maximum
+ + + + + + + + +
Cluster
@@ -102,21 +121,23 @@ }" class="tect-center flex w-full justify-center" > -
- {{ clusters?.[index].members?.length }} - - {{ ((clusters?.[index].averageSimilarity as number) * 100).toFixed(2) }}% -
@@ -137,7 +158,8 @@ import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' import { library } from '@fortawesome/fontawesome-svg-core' import { faUserGroup } from '@fortawesome/free-solid-svg-icons' import { generateColors } from '@/utils/ColorUtils' -import { MetricType } from '@/model/MetricType' +import ToolTipComponent from './ToolTipComponent.vue' +import { MetricType, metricToolTips } from '@/model/MetricType' library.add(faUserGroup) diff --git a/report-viewer/src/components/MatchList.vue b/report-viewer/src/components/MatchList.vue index aeb218112..17e5bee28 100644 --- a/report-viewer/src/components/MatchList.vue +++ b/report-viewer/src/components/MatchList.vue @@ -3,26 +3,33 @@ --> diff --git a/report-viewer/src/components/ToolTipComponent.vue b/report-viewer/src/components/ToolTipComponent.vue new file mode 100644 index 000000000..48212c0f5 --- /dev/null +++ b/report-viewer/src/components/ToolTipComponent.vue @@ -0,0 +1,73 @@ + + + diff --git a/report-viewer/src/components/optionsSelectors/MetricSelector.vue b/report-viewer/src/components/optionsSelectors/MetricSelector.vue new file mode 100644 index 000000000..345d4ed68 --- /dev/null +++ b/report-viewer/src/components/optionsSelectors/MetricSelector.vue @@ -0,0 +1,40 @@ + + + diff --git a/report-viewer/src/components/optionsSelectors/OptionComponent.vue b/report-viewer/src/components/optionsSelectors/OptionComponent.vue new file mode 100644 index 000000000..443940a84 --- /dev/null +++ b/report-viewer/src/components/optionsSelectors/OptionComponent.vue @@ -0,0 +1,27 @@ + + + diff --git a/report-viewer/src/components/optionsSelectors/OptionsSelectorComponent.vue b/report-viewer/src/components/optionsSelectors/OptionsSelectorComponent.vue new file mode 100644 index 000000000..94397decd --- /dev/null +++ b/report-viewer/src/components/optionsSelectors/OptionsSelectorComponent.vue @@ -0,0 +1,76 @@ + + + + diff --git a/report-viewer/src/model/MetricType.ts b/report-viewer/src/model/MetricType.ts index c0b53fcf9..08c81d072 100644 --- a/report-viewer/src/model/MetricType.ts +++ b/report-viewer/src/model/MetricType.ts @@ -5,3 +5,24 @@ export enum MetricType { AVERAGE = 'AVG', MAXIMUM = 'MAX' } + +type MetricToolTipData = { + longName: string + shortName: string + tooltip: string +} + +export const metricToolTips: Record = { + [MetricType.AVERAGE]: { + longName: 'Average Similarity', + shortName: 'AVG', + tooltip: + 'The average similarity of the two files.\nA high similarity indicates that the programms work in a similar way.' + }, + [MetricType.MAXIMUM]: { + longName: 'Maximum Similarity', + shortName: 'MAX', + tooltip: + 'The maximum similarity of the two files.\nUsefull if programms are very dfferent in size.' + } +} diff --git a/report-viewer/src/views/ClusterView.vue b/report-viewer/src/views/ClusterView.vue index d8e254631..62c94d50e 100644 --- a/report-viewer/src/views/ClusterView.vue +++ b/report-viewer/src/views/ClusterView.vue @@ -15,7 +15,7 @@ - +

Comparisons of Cluster Members:

diff --git a/report-viewer/src/views/OverviewView.vue b/report-viewer/src/views/OverviewView.vue index 456409075..36161c346 100644 --- a/report-viewer/src/views/OverviewView.vue +++ b/report-viewer/src/views/OverviewView.vue @@ -17,7 +17,15 @@ {{ overview.matchSensitivity }} - + + + + +
@@ -32,17 +40,17 @@ />

Options:

- - +

Top Comparisons:

- + + + + +
- 1 const submissionPathValue = hasMoreSubmissionPaths ? 'Click More to see all paths' diff --git a/report-viewer/tests/unit/components/optionsSelectors/MetricSelector.test.ts b/report-viewer/tests/unit/components/optionsSelectors/MetricSelector.test.ts new file mode 100644 index 000000000..304100bf1 --- /dev/null +++ b/report-viewer/tests/unit/components/optionsSelectors/MetricSelector.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, it } from 'vitest' +import { mount } from '@vue/test-utils' +import MetricSelector from '@/components/optionsSelectors/MetricSelector.vue' +import { MetricType } from '@/model/MetricType' + +describe('OptionSelectorComponent', () => { + it('renders all options', async () => { + const wrapper = mount(MetricSelector, { + props: { + title: 'Test:' + } + }) + + expect(wrapper.text()).toContain('Test:') + expect(wrapper.text()).toContain('Average Similarity') + expect(wrapper.text()).toContain('Maximum Similarity') + }) + + it('renders given metrics only', async () => { + const wrapper = mount(MetricSelector, { + props: { + title: 'Test:', + metrics: [MetricType.AVERAGE] + } + }) + + expect(wrapper.text()).toContain('Test:') + expect(wrapper.text()).toContain('Average Similarity') + expect(wrapper.text()).not.toContain('Maximum Similarity') + }) + + it('switch selection', async () => { + const wrapper = mount(MetricSelector, { + props: { + title: 'Test:' + } + }) + + await wrapper.findAllComponents({ name: 'OptionComponent' })[1].trigger('click') + + expect(wrapper.emitted('selectionChanged')).toBeTruthy() + expect(wrapper.emitted('selectionChanged')?.length).toBe(1) + expect(wrapper.emitted('selectionChanged')?.[0]).toEqual([MetricType.MAXIMUM]) + }) +}) diff --git a/report-viewer/tests/unit/components/optionsSelectors/OptionSelectorComponent.test.ts b/report-viewer/tests/unit/components/optionsSelectors/OptionSelectorComponent.test.ts new file mode 100644 index 000000000..8947c8050 --- /dev/null +++ b/report-viewer/tests/unit/components/optionsSelectors/OptionSelectorComponent.test.ts @@ -0,0 +1,70 @@ +import { describe, expect, it } from 'vitest' +import { mount } from '@vue/test-utils' +import OptionsSelectorComponent from '@/components/optionsSelectors/OptionsSelectorComponent.vue' +import OptionComponent from '@/components/optionsSelectors/OptionComponent.vue' + +describe('OptionSelectorComponent', () => { + it('renders all options', async () => { + const wrapper = mount(OptionsSelectorComponent, { + props: { + title: 'Test:', + labels: ['Option 1', 'Option 2', 'Option 3'], + defaultSelected: 1 + } + }) + + expect(wrapper.text()).toContain('Test:') + expect(wrapper.text()).toContain('Option 1') + expect(wrapper.text()).toContain('Option 2') + expect(wrapper.text()).toContain('Option 3') + + expect( + wrapper + .findAllComponents(OptionComponent) + .find((e) => e.text() === 'Option 2') + ?.classes() + ).toContain('!bg-accent') + }) + + it('switch selection', async () => { + const wrapper = mount(OptionsSelectorComponent, { + props: { + title: 'Test:', + labels: ['Option 1', 'Option 2'], + defaultSelected: 0 + } + }) + + expect( + wrapper + .findAllComponents(OptionComponent) + .find((e) => e.text() === 'Option 1') + ?.classes() + ).toContain('!bg-accent') + expect( + wrapper + .findAllComponents(OptionComponent) + .find((e) => e.text() === 'Option 2') + ?.classes() + ).not.toContain('!bg-accent') + + await wrapper.findAllComponents({ name: 'OptionComponent' })[1].trigger('click') + + expect(wrapper.emitted('selectionChanged')).toBeTruthy() + expect(wrapper.emitted('selectionChanged')?.length).toBe(1) + expect(wrapper.emitted('selectionChanged')?.[0]).toEqual([1]) + + expect( + wrapper + .findAllComponents(OptionComponent) + .find((e) => e.text() === 'Option 1') + ?.classes() + ).not.toContain('!bg-accent') + expect( + wrapper + .findAll('.cursor-pointer') + .find((e) => e.text() === 'Option 2') + ?.classes() + ).toContain('!bg-accent') + }) +})