Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minimal Report Version #1349

Merged
merged 7 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions .github/workflows/report-viewer-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,6 @@ jobs:
with:
node-version: "18"

- name: Set version of Report Viewer
shell: bash
run: |
VERSION=$(grep "<revision>" pom.xml | grep -oPm1 "(?<=<revision>)[^-|<]+")
MAJOR=$(echo $VERSION | cut -d '.' -f 1)
MINOR=$(echo $VERSION | cut -d '.' -f 2)
PATCH=$(echo $VERSION | cut -d '.' -f 3)
sed -i "/major/s/.*/ \"major\": $MAJOR,/" report-viewer/src/version.json
sed -i "/minor/s/.*/ \"minor\": $MINOR,/" report-viewer/src/version.json
sed -i "/patch/s/.*/ \"patch\": $PATCH/" report-viewer/src/version.json
echo "Version of Report Viewer:"
cat report-viewer/src/version.json

- name: Install and Build 🔧
working-directory: report-viewer
run: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/report-viewer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ jobs:
MAJOR=$(echo $VERSION | cut -d '.' -f 1)
MINOR=$(echo $VERSION | cut -d '.' -f 2)
PATCH=$(echo $VERSION | cut -d '.' -f 3)
sed -i "/major/s/.*/ \"major\": $MAJOR,/" report-viewer/src/version.json
sed -i "/minor/s/.*/ \"minor\": $MINOR,/" report-viewer/src/version.json
sed -i "/patch/s/.*/ \"patch\": $PATCH/" report-viewer/src/version.json
json=$(cat report-viewer/src/version.json)
json=$(echo "$json" | jq --arg MAJOR "$MAJOR" --arg MINOR "$MINOR" --arg PATCH "$PATCH" '.report_viewer_version |= { "major": $MAJOR | tonumber, "minor": $MINOR | tonumber, "patch": $PATCH | tonumber }')
echo "$json" > report-viewer/src/version.json
echo "Version of Report Viewer:"
cat report-viewer/src/version.json

Expand Down
35 changes: 19 additions & 16 deletions report-viewer/src/components/VersionInfoComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,32 @@
You are using a development version of the JPlag Report Viewer.
</div>

<div v-else-if="newestVersion.compareTo(reportViewerVersion) > 0" class="text-left text-error">
You are using an outdated version of the JPlag Report Viewer ({{
reportViewerVersion.toString()
}}).<br />
Version {{ newestVersion.toString() }} is available on
<a href="https://github.com/jplag/JPlag/releases/latest" class="text-link underline">GitHub</a
>.
</div>
<div v-else>
<div v-if="newestVersion.compareTo(reportViewerVersion) > 0" class="text-left text-error">
You are using an outdated version of the JPlag Report Viewer ({{
reportViewerVersion.toString()
}}).<br />
Version {{ newestVersion.toString() }} is available on
<a href="https://github.com/jplag/JPlag/releases/latest" class="text-link underline"
>GitHub</a
>.
</div>

<div v-else>JPlag v{{ reportViewerVersion.toString() }}</div>

<div v-else>JPlag v{{ reportViewerVersion.toString() }}</div>
<div v-if="!minimalReportVersion.isInvalid()">
The minimal version of JPlag that is supported by the viewer is v{{
minimalReportVersion.toString()
}}.
</div>
</div>
</div>
</template>

<script setup lang="ts">
import { Version } from '@/model/Version'
import versionJson from '@/version.json'
import { ref } from 'vue'
import { OverviewFactory } from '@/model/factories/OverviewFactory'

const reportViewerVersion: Version =
versionJson['report_viewer_version'] !== undefined
? OverviewFactory.extractVersion(versionJson['report_viewer_version'])
: new Version(-1, -1, -1)
import { minimalReportVersion, reportViewerVersion } from '@/model/Version'

const newestVersion = ref(new Version(-1, -1, -1))

Expand Down
12 changes: 12 additions & 0 deletions report-viewer/src/model/Version.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import versionJson from '@/version.json'

/**
* Version of the report viewer.
*/
Expand Down Expand Up @@ -33,4 +35,14 @@ export class Version {
public isInvalid(): boolean {
return this.major < 0 || this.minor < 0 || this.patch < 0
}

public static fromJsonField(versionField: Record<string, number> | undefined): Version {
if (versionField) {
return new Version(versionField.major, versionField.minor, versionField.patch)
}
return new Version(-1, -1, -1)
}
}

export const reportViewerVersion = Version.fromJsonField(versionJson['report_viewer_version'])
export const minimalReportVersion = Version.fromJsonField(versionJson['minimal_report_version'])
67 changes: 34 additions & 33 deletions report-viewer/src/model/factories/OverviewFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { Overview } from '../Overview'
import type { ComparisonListElement } from '../ComparisonListElement'
import type { Cluster } from '@/model/Cluster'
import { store } from '@/stores/store'
import { Version } from '../Version'
import versionJson from '@/version.json'
import { Version, minimalReportVersion, reportViewerVersion } from '../Version'
import { getLanguageParser } from '../Language'
import { Distribution } from '../Distribution'
import { MetricType } from '../MetricType'
Expand All @@ -15,11 +14,6 @@ import { TenValueDistribution } from '../TenValueDistribution'
* Factory class for creating Overview objects
*/
export class OverviewFactory extends BaseFactory {
static reportViewerVersion: Version =
versionJson['report_viewer_version'] !== undefined
? this.extractVersion(versionJson['report_viewer_version'] as Record<string, number>)
: new Version(-1, -1, -1)

/**
* Gets the overview file based on the used mode (zip, local, single).
*/
Expand All @@ -33,9 +27,9 @@ export class OverviewFactory extends BaseFactory {
*/
private static extractOverview(json: Record<string, unknown>): Overview {
const versionField = json.jplag_version as Record<string, number>
const jplagVersion = this.extractVersion(versionField)
const jplagVersion = Version.fromJsonField(versionField)

OverviewFactory.compareVersions(jplagVersion, this.reportViewerVersion)
OverviewFactory.compareVersions(jplagVersion, reportViewerVersion, minimalReportVersion)

const submissionFolder = json.submission_folder_path as Array<string>
const baseCodeFolder = json.base_code_folder_path as string
Expand Down Expand Up @@ -64,10 +58,6 @@ export class OverviewFactory extends BaseFactory {
)
}

public static extractVersion(versionField: Record<string, number>): Version {
return new Version(versionField.major, versionField.minor, versionField.patch)
}

private static extractDistributions(
json: Record<string, unknown>
): Record<MetricType, Distribution> {
Expand Down Expand Up @@ -203,29 +193,40 @@ export class OverviewFactory extends BaseFactory {
* @param jsonVersion the version of the json file
* @param reportViewerVersion the version of the report viewer
*/
static compareVersions(jsonVersion: Version, reportViewerVersion: Version) {
static compareVersions(
jsonVersion: Version,
reportViewerVersion: Version,
minimalVersion: Version = new Version(0, 0, 0)
) {
if (sessionStorage.getItem('versionAlert') === null) {
if (jsonVersion.compareTo(reportViewerVersion) !== 0) {
if (reportViewerVersion.isInvalid()) {
console.warn(
"The report viewer's version cannot be read from version.json file. Please configure it correctly."
)
} else {
console.warn(
"The result's version tag does not fit the report viewer's version. Trying to read it anyhow but be careful."
)
alert(
"The result's version(" +
jsonVersion.toString() +
") tag does not fit the report viewer's version(" +
reportViewerVersion.toString() +
'). ' +
'Trying to read it anyhow but be careful.'
)
}
if (reportViewerVersion.isInvalid()) {
console.warn(
"The report viewer's version cannot be read from version.json file. Please configure it correctly."
)
} else if (
!reportViewerVersion.isDevVersion() &&
jsonVersion.compareTo(reportViewerVersion) > 0
) {
alert(
"The result's version(" +
jsonVersion.toString() +
") is newer than the report viewer's version(" +
reportViewerVersion.toString() +
'). ' +
'Trying to read it anyhow but be careful.'
)
}

sessionStorage.setItem('versionAlert', 'true')
}
if (jsonVersion.compareTo(minimalVersion) < 0) {
throw (
"The result's version(" +
jsonVersion.toString() +
') is older than the minimal support version of the report viewer(' +
reportViewerVersion.toString() +
'). ' +
'Can not read the report.'
)
}
}
}
5 changes: 5 additions & 0 deletions report-viewer/src/version.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@
"major": 0,
"minor": 0,
"patch": 0
},
"minimal_report_version": {
"major": 4,
"minor": 0,
"patch": 0
}
}
31 changes: 19 additions & 12 deletions report-viewer/tests/unit/components/VersionInfoComponent.test.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,50 @@
import VersionInfoComponent from '@/components/VersionInfoComponent.vue'
import { flushPromises, mount } from '@vue/test-utils'
import { describe, it, vi, expect } from 'vitest'
import version from '@/version.json'

vi.mock('@/version.json')
import { describe, it, vi, expect, beforeAll } from 'vitest'

Check warning on line 3 in report-viewer/tests/unit/components/VersionInfoComponent.test.ts

View workflow job for this annotation

GitHub Actions / check

'beforeAll' is defined but never used
import * as versionTsFile from '@/model/Version'
import { Version } from '@/model/Version'

describe('VersionInfoComponent', () => {
it('Render develop version', async () => {
version.report_viewer_version = mockVersionJSON(0, 0, 0)
vi.spyOn(versionTsFile, 'reportViewerVersion', 'get').mockReturnValue(mockVersionJSON(0, 0, 0))
vi.spyOn(versionTsFile, 'minimalReportVersion', 'get').mockReturnValue(mockVersionJSON(4, 0, 0))
global.fetch = vi.fn().mockResolvedValueOnce(mockVersionResponse('v4.3.0'))

const wrapper = mount(VersionInfoComponent)
await flushPromises()

expect(wrapper.text()).toContain('development version')
expect(wrapper.text()).not.toContain(
'The minimal version of JPlag that is supported by the viewer is v4.0.0.'
)
})

it('Render outdated version', async () => {
version.report_viewer_version = mockVersionJSON(4, 3, 0)
vi.spyOn(versionTsFile, 'reportViewerVersion', 'get').mockReturnValue(mockVersionJSON(4, 3, 0))
vi.spyOn(versionTsFile, 'minimalReportVersion', 'get').mockReturnValue(mockVersionJSON(4, 0, 0))
global.fetch = vi.fn().mockResolvedValueOnce(mockVersionResponse('v4.4.0'))

const wrapper = mount(VersionInfoComponent)
await flushPromises()

expect(wrapper.text()).toContain('outdated version')
expect(wrapper.text()).toContain(
'The minimal version of JPlag that is supported by the viewer is v4.0.0.'
)
})

it('Render latest version', async () => {
version.report_viewer_version = mockVersionJSON(4, 3, 0)
vi.spyOn(versionTsFile, 'reportViewerVersion', 'get').mockReturnValue(mockVersionJSON(4, 3, 0))
vi.spyOn(versionTsFile, 'minimalReportVersion', 'get').mockReturnValue(mockVersionJSON(4, 0, 0))
global.fetch = vi.fn().mockResolvedValueOnce(mockVersionResponse('v4.3.0'))

const wrapper = mount(VersionInfoComponent)
await flushPromises()

expect(wrapper.text()).toContain('JPlag v4.3.0')
expect(wrapper.text()).toContain(
'The minimal version of JPlag that is supported by the viewer is v4.0.0.'
)
})
})

Expand All @@ -47,9 +58,5 @@
}

function mockVersionJSON(major: number, minor: number, patch: number) {
return {
major: major,
minor: minor,
patch: patch
}
return new Version(major, minor, patch)
}
73 changes: 73 additions & 0 deletions report-viewer/tests/unit/model/factories/OutdatedOverview.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"jplag_version": { "major": 3, "minor": 0, "patch": 0 },
"submission_folder_path": ["files"],
"base_code_folder_path": "",
"language": "Javac based AST plugin",
"file_extensions": [".java", ".JAVA"],
"submission_id_to_display_name": { "A": "A", "B": "B", "C": "C", "D": "D" },
"submission_ids_to_comparison_file_name": {
"A": { "B": "B-A.json", "C": "A-C.json", "D": "D-A.json" },
"B": { "A": "B-A.json", "C": "B-C.json", "D": "B-D.json" },
"C": { "A": "A-C.json", "B": "B-C.json", "D": "D-C.json" },
"D": { "A": "D-A.json", "B": "B-D.json", "C": "D-C.json" }
},
"failed_submission_names": [],
"excluded_files": [],
"match_sensitivity": 9,
"date_of_execution": "12/07/23",
"execution_time": 12,
"distributions": {
"MAX": [
1, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0
],
"AVG": [
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0
]
},
"top_comparisons": [
{
"first_submission": "A",
"second_submission": "C",
"similarities": { "AVG": 0.9960435212660732, "MAX": 0.9960435212660732 }
},
{
"first_submission": "D",
"second_submission": "A",
"similarities": { "AVG": 0.751044776119403, "MAX": 0.947289156626506 }
},
{
"first_submission": "D",
"second_submission": "C",
"similarities": { "AVG": 0.751044776119403, "MAX": 0.947289156626506 }
},
{
"first_submission": "B",
"second_submission": "D",
"similarities": { "AVG": 0.28322981366459626, "MAX": 0.8085106382978723 }
},
{
"first_submission": "B",
"second_submission": "A",
"similarities": { "AVG": 0.2378472222222222, "MAX": 0.9716312056737588 }
},
{
"first_submission": "B",
"second_submission": "C",
"similarities": { "AVG": 0.2378472222222222, "MAX": 0.9716312056737588 }
}
],
"clusters": [
{
"average_similarity": 94.746956,
"strength": 0.0,
"members": ["C", "A", "B", "D"]
}
],
"total_comparisons": 6
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { HundredValueDistribution } from '@/model/HundredValueDistribution'
import { TenValueDistribution } from '@/model/TenValueDistribution'
import validNew from './ValidNewOverview.json'
import validOld from './ValidOldOverview.json'
import outdated from './OutdatedOverview.json'

const store = {
state: {
Expand Down Expand Up @@ -175,3 +176,10 @@ describe('Test JSON to Overview', () => {
})
})
})

describe('Outdated JSON to Overview', () => {
it('Outdated version', async () => {
store.state.files['overview.json'] = JSON.stringify(outdated)
expect(() => OverviewFactory.getOverview()).rejects.toThrowError()
})
})
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"jplag_version": { "major": 0, "minor": 0, "patch": 0 },
"jplag_version": { "major": 4, "minor": 0, "patch": 0 },
"submission_folder_path": ["files"],
"base_code_folder_path": "",
"language": "Javac based AST plugin",
Expand Down