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

Some small e2e tests for report viewer #1280

Merged
merged 28 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
097d11e
update config
Kr0nox Sep 2, 2023
9ac3acf
small test for comparisons
Kr0nox Sep 2, 2023
105e480
extract fle upload
Kr0nox Sep 3, 2023
0ee9e75
information view test
Kr0nox Sep 3, 2023
e5cf414
cluster view test
Kr0nox Sep 4, 2023
e1167b3
distribution diagramm test
Kr0nox Sep 4, 2023
d1afc38
Merge remote-tracking branch 'origin/develop' into report-viewer/simp…
Kr0nox Sep 6, 2023
9de538a
generate pictures
Kr0nox Sep 6, 2023
28d09c3
fix workflow file
Kr0nox Sep 9, 2023
9a13500
Merge branch 'develop' into report-viewer/simple-e2e
dfuchss Sep 13, 2023
af64505
linux files
Kr0nox Sep 19, 2023
f8a033d
undo tests on push
Kr0nox Sep 19, 2023
c034fcc
add new linux files
Kr0nox Oct 3, 2023
4717d0c
Merge remote-tracking branch 'origin/develop' into report-viewer/simp…
Kr0nox Oct 3, 2023
f0ec71a
fix tests
Kr0nox Oct 3, 2023
ed9b929
windows files
Kr0nox Oct 3, 2023
47b2cec
delta value for visual comparison
Kr0nox Oct 5, 2023
d5ba1bc
test results as artifacts
Kr0nox Oct 6, 2023
4d80ee3
Merge branch 'report-viewer/simple-e2e' of https://github.com/jplag/J…
Kr0nox Oct 6, 2023
342ea7b
new generated images
Kr0nox Oct 6, 2023
bb8f3a1
Merge remote-tracking branch 'origin/develop' into report-viewer/simp…
Kr0nox Dec 7, 2023
915955d
fix information page test
Kr0nox Dec 7, 2023
a68bef3
fix distrion diagram test
Kr0nox Dec 8, 2023
bfbba42
fix cluster view
Kr0nox Dec 8, 2023
1690527
Merge remote-tracking branch 'origin/develop' into report-viewer/simp…
Kr0nox Dec 8, 2023
967550b
fix comparison tests
Kr0nox Dec 8, 2023
4589a9e
Merge remote-tracking branch 'origin/develop' into report-viewer/simp…
Kr0nox Jan 22, 2024
3483eaa
fix table and comparison view
Kr0nox Jan 22, 2024
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
24 changes: 21 additions & 3 deletions .github/workflows/report-viewer-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,27 @@ jobs:
with:
node-version: "18"

- name: Install and Test 🧪
- name: Install and Build 🔧
working-directory: report-viewer
run: |
npm install
npx playwright install --with-deps
npm run test:e2e
npm run build

- name: Install playwright 🔧
working-directory: report-viewer
run: npx playwright install --with-deps

- name: Run tests 🧪
working-directory: report-viewer
run: |
npm run test:e2e

- name: Upload test results 📤
uses: actions/upload-artifact@v3
if: always()
with:
name: test-results
path: |
report-viewer/test-results
report-viewer/playwright-report
retention-days: 30
13 changes: 8 additions & 5 deletions report-viewer/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ const config: PlaywrightTestConfig = {
* Maximum time expect() should wait for the condition to be met.
* For example in `await expect(locator).toHaveText();`
*/
timeout: 5000
timeout: 5000,
toMatchSnapshot: {
maxDiffPixelRatio: 0.01
}
},
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
Expand All @@ -34,13 +37,13 @@ const config: PlaywrightTestConfig = {
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
actionTimeout: 0,
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://localhost:5173',
baseURL: 'http://localhost:8080',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',

/* Only on CI systems run the tests headless */
headless: !!process.env.CI
headless: true
},

/* Configure projects for major browsers */
Expand Down Expand Up @@ -103,8 +106,8 @@ const config: PlaywrightTestConfig = {
* Use the preview server on CI for more realistic testing.
Playwright will re-use the local server if there is already a dev-server running.
*/
command: process.env.CI ? 'vite preview --port 5173' : 'vite dev',
port: 5173,
command: 'vite preview --port 8080',
port: 8080,
reuseExistingServer: !process.env.CI
}
}
Expand Down
56 changes: 56 additions & 0 deletions report-viewer/tests/e2e/Cluster.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { test, expect, Page } from '@playwright/test'
import { uploadFile } from './TestUtils'

test('Test cluster view', async ({ page }) => {
await page.goto('/')

await uploadFile('result_small_cluster.zip', page)

// check for all clusters being shown
expect(await page.getByText('submissions in cluster').all()).toHaveLength(6)

await page.getByText('4 94.75%').first().click()
await page.waitForURL(/\/cluster\/.*/)

// Check cluster diagramm
await compareClusterDiagramm(page, 'C')
await page.getByRole('combobox').selectOption('B')
await compareClusterDiagramm(page, 'B')

// Check comparison table
const comparisonTable = await page
.getByText('Comparisons of Cluster Members:Submissions in Comparison')
.textContent()
compareTableRow(comparisonTable, 1, 'C', 'A', 99.6, 99.6)
compareTableRow(comparisonTable, 2, 'D', 'C', 76.06, 95.93)
compareTableRow(comparisonTable, 3, 'D', 'A', 76.06, 95.93)
compareTableRow(comparisonTable, 4, 'B', 'D', 28.32, 80.85)
compareTableRow(comparisonTable, 5, 'B', 'C', 23.78, 97.16)
compareTableRow(comparisonTable, 6, 'B', 'A', 23.78, 97.16)
})

/**
*
* @param page Page currently tested on
* @param submissionId Id of the selected submission
*/
async function compareClusterDiagramm(page: Page, submissionId: string) {
expect(page.getByRole('combobox').first()).toHaveValue(submissionId)
// This timeout is so that the screenshot is taken after the animation is finished
await page.waitForTimeout(3000)
const radarChart = await page.locator('canvas').first().screenshot()
expect(radarChart).toMatchSnapshot(`cluster_${submissionId}.png`)
}

function compareTableRow(
table: string,
row: number,
id1: string,
id2: string,
similarityAVG: number,
similarityMAX: number
) {
expect(table).toContain(
`${row}${id1}${id2}${similarityAVG.toFixed(2)}% ${similarityMAX.toFixed(2)}%`
)
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 71 additions & 0 deletions report-viewer/tests/e2e/Comparison.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { test, expect } from '@playwright/test'
import { uploadFile } from './TestUtils'

test('Test comparison table and comparsion view', async ({ page }) => {
await page.goto('/')

await uploadFile('result_small_cluster.zip', page)

const comparisonContainer = page.getByText(
'Top Comparisons: Type in the name of a submission to only show comparisons that contain this submission. Fully written out names get unhidden.Hide AllSort By'
)

// check for elements in average similarity table
const comparisonTableAverageSorted = await page.getByText('Cluster1').textContent()
expect(comparisonTableAverageSorted).toContain('1CA')
expect(comparisonTableAverageSorted).toContain('2DC')

await comparisonContainer.getByText('Maximum Similarity', { exact: true }).click()
// check for elements in maximum similarity table
const comparisonTableMaxSorted = await page.getByText('Cluster1').textContent()
expect(comparisonTableMaxSorted).toContain('1CA')
expect(comparisonTableMaxSorted).toContain('2BC')

await page.getByText('Hide All').click()
// check for elements being hidden
const comparisonTableOverviewHidden = await page.getByText('Cluster1').textContent()
expect(comparisonTableOverviewHidden).toContain('1HiddenHidden')
expect(comparisonTableOverviewHidden).toContain('3HiddenHidden')
expect(comparisonTableOverviewHidden).toContain('4HiddenHidden')

await page.getByPlaceholder('Filter/Unhide Comparisons').fill('A')
// check for elements being unhidden and filtered
const comparisonTableOverviewFilteredA = await page.getByText('Cluster1').textContent()
expect(comparisonTableOverviewFilteredA).toContain('1HiddenA')
expect(comparisonTableOverviewFilteredA).toContain('3HiddenA')
// we cant check for 4Hidden because the dynamic scroller just moves it of screen, so the text is still there but not visible

await page.getByPlaceholder('Filter/Unhide Comparisons').fill('A C')
// check for elements being unhidden and filtered
const comparisonTableOverviewFilteredAC = await page.getByText('Cluster1').textContent()
expect(comparisonTableOverviewFilteredAC).toContain('1CA')
expect(comparisonTableOverviewFilteredAC).toContain('3HiddenA')
expect(comparisonTableOverviewFilteredAC).toContain('4HiddenC')

// go to comparison page
await page.getByRole('link', { name: '1 C A 99.60% 99.60%' }).click()
await page.waitForURL(/\/comparison\/.*/)

// check for elements in comparison page
const bodyComparison = await page.locator('body').textContent()
expect(bodyComparison).toContain('Average Similarity: 99.59%')
expect(bodyComparison).toContain('GSTiling.java - GSTiling.java: 308')
expect(bodyComparison).toContain('Matches.java - Matches.java: 58')
expect(bodyComparison).toContain('A/Match.java')
expect(bodyComparison).toContain('C/Match.java')

// check for being able to hide and unhide elements
expect(bodyComparison).not.toContain('public class Match')
await page.getByText('A/Match.java').click()
const bodyComparisonShowMatch = await page.locator('body').textContent()
expect(bodyComparisonShowMatch).toContain('public class Match')
await page.getByText('A/Match.java').click()
const bodyComparisonHideMatch = await page.locator('body').textContent()
expect(bodyComparisonHideMatch).not.toContain('public class Match')

// unhide elements by clicking match list
expect(bodyComparisonHideMatch).not.toContain('public class GSTiling')
await page.getByText('GSTiling.java - GSTiling.java: 308').click()
const bodyComparisonShowGSTiling = await page.locator('body').textContent()
expect(bodyComparisonShowGSTiling).toContain('public class GSTiling')
})
56 changes: 56 additions & 0 deletions report-viewer/tests/e2e/Distribution.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { test, expect, Page } from '@playwright/test'
import { uploadFile } from './TestUtils'

test('Test all distribution combinations', async ({ page }) => {
await page.goto('/')

await uploadFile('result_small_cluster.zip', page)

const options = getAllOptionCombinations()
for (const option of options) {
await compareDistributionDiagramm(page, option)
}
})

/**
* Checks if the distribution diagramm is correct for the given options
* @param page Page currently tested on
* @param options Options to be selected
*/
async function compareDistributionDiagramm(page: Page, options: string[]) {
const distributionDiagrammContainer = page.getByText('Distribution of Comparisons:Options:')
for (const option of options) {
await distributionDiagrammContainer.getByText(option).first().click()
}
// This timeout is so that the screenshot is taken after the animation is finished
await page.waitForTimeout(3000)
const distributionDiagramm = await page.locator('canvas').first().screenshot()
expect(distributionDiagramm).toMatchSnapshot(`distribution_${options.join('_')}.png`)
}

function getAllOptionCombinations() {
const options = [
['Average', 'Maximum'],
['Linear', 'Logarithmic']
]

function combine(a: string[][], b: string[]) {
const combinations: string[][] = []
for (let i = 0; i < a.length; i++) {
for (let j = 0; j < b.length; j++) {
combinations.push(a[i].concat(b[j]))
}
}
return combinations
}

let combinations: string[][] = []
for (let i = 0; i < options[0].length; i++) {
combinations.push([options[0][i]])
}

for (let i = 1; i < options.length; i++) {
combinations = combine(combinations, options[i])
}
return combinations
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions report-viewer/tests/e2e/Information.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { expect, test } from '@playwright/test'
import { uploadFile } from './TestUtils'

test('Test information page', async ({ page }) => {
await page.goto('/')
await uploadFile('result_small_cluster.zip', page)

// check displayed information on overview page
const bodyOverview = await page.locator('body').textContent()
expect(bodyOverview).toContain('Directory: files')
expect(bodyOverview).toContain('Total Submissions: 4')
expect(bodyOverview).toContain('Total Comparisons: 6')
expect(bodyOverview).toContain('Min Match Length: 9')

// go to information page
await page.getByText('More', { exact: true }).click()
await page.waitForURL('/info')

// check displayed run options on information page
const runOptions = await page.getByText('Run Options:Submission Folder:').textContent()
expect(runOptions).toContain('Submission Folder: files')
expect(runOptions).toContain('Basecode Folder:')
expect(runOptions).toContain('Language: Javac based AST plugin')
expect(runOptions).toContain('File Extentions: .java, .JAVA')
expect(runOptions).toContain('Minimum Token Match:: 9')

const runData = await page.getByText('Run Data:Date of Execution:').textContent()
expect(runData).toContain('Date of Execution: 02/09/23')
expect(runData).toContain('Execution Duration: 12 ms')
expect(runData).toContain('Submission Count: 4')
expect(runData).toContain('Total Comparisons: 6')
expect(runData).toContain('Shown Comparisons: 6')
expect(runData).toContain('Missing Comparisons: 0')
})
19 changes: 19 additions & 0 deletions report-viewer/tests/e2e/TestUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Page, expect } from '@playwright/test'

/**
* Selects a file in the file chooser and uploads it.
* Expects the file to be in the tests/e2e/assets folder.
* Expects to be on the file upload page.
* @param fileName
*/
export async function uploadFile(fileName: string, page: Page) {
expect(page).toHaveURL('/')

// upload file through file chooser
const fileChooserPromise = page.waitForEvent('filechooser')
await page.getByText('Drag and Drop zip/Json file on this page').click()
const fileChooser = await fileChooserPromise
await fileChooser.setFiles(`tests/e2e/assets/${fileName}`)

await page.waitForURL('/overview')
}
Binary file not shown.
5 changes: 0 additions & 5 deletions report-viewer/tests/e2e/boilerplate.spec.ts

This file was deleted.