Skip to content

Commit

Permalink
Merge pull request #1631 from jplag/feature/complete-e2e
Browse files Browse the repository at this point in the history
Complete system e2e test
  • Loading branch information
sebinside authored Mar 6, 2024
2 parents eb71247 + 0064cbe commit 1b0c11d
Show file tree
Hide file tree
Showing 12 changed files with 275 additions and 99 deletions.
157 changes: 157 additions & 0 deletions .github/workflows/complete-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Builds JPlag and then runs Datasets and Report Viewer e2e tests on multiple OS
name: Complete e2e Test

on:
workflow_dispatch:
pull_request:
types: [opened, synchronize, reopened]
paths:
- ".github/workflows/complete-e2e.yml"
- "report-viewer/**"
- "**/pom.xml"
- "**.java"
- "**.g4"

jobs:
pre_job:
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
steps:
- id: skip_check
uses: fkirc/skip-duplicate-actions@master
with:
concurrent_skipping: 'same_content_newer'
skip_after_successful_duplicate: 'true'

build_jar:
needs: pre_job
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: 21
distribution: 'temurin'

- uses: actions/setup-node@v4
with:
node-version: "18"

- name: Build Assembly
run: mvn -Pwith-report-viewer -DskipTests clean package assembly:single

- name: Rename Jar
run: mv cli/target/jplag-*-jar-with-dependencies.jar cli/target/jplag.jar

- name: Upload Assembly
uses: actions/upload-artifact@v4
with:
name: "JPlag"
path: "cli/target/jplag.jar"
retention-days: 30

run_jplag:
needs: build_jar
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
dataset: [
{zip: "progpedia.zip", name: "progpedia", folder: "ACCEPTED", language: "java", cliArgs: "-bc base"},
{zip: "fileSingleRoot.zip", name: "fileSingleRoot", folder: "fileSingleRoot", language: "java", cliArgs: ""},
{zip: "folderSingleRoot.zip", name: "folderSingleRoot", folder: "folderSingleRoot", language: "java", cliArgs: ""},
{zip: "fileMultiRoot.zip", name: "fileMultiRoot", folder: "f0", language: "java", cliArgs: "--new f1"},
{zip: "folderMultiRoot.zip", name: "folderMultiRoot", folder: "f0", language: "java", cliArgs: "--new f1"},
{zip: "mixedMultiRoot.zip", name: "mixedBaseFile", folder: "f0", language: "java", cliArgs: "--new f1"},
{zip: "mixedMultiRoot.zip", name: "mixedBaseFolder", folder: "f1", language: "java", cliArgs: "--new f0"}
]

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: 21
distribution: 'temurin'

- name: Get JAR
uses: actions/download-artifact@v4
with:
name: JPlag

- name: Copy and unzip dataset windows
if: ${{ matrix.os == 'windows-latest' }}
run: |
Expand-Archive -LiteralPath .github/workflows/files/${{ matrix.dataset.zip }} -DestinationPath ./
- name: Copy and unzip dataset macos and ubuntu
if: ${{ matrix.os == 'macos-latest' || matrix.os == 'ubuntu-latest'}}
run: |
unzip .github/workflows/files/${{ matrix.dataset.zip }}
- name: Run JPlag
run: |
java -jar jplag.jar ${{ matrix.dataset.folder }} -l ${{ matrix.dataset.language }} -r ${{ matrix.dataset.name }}-report ${{ matrix.dataset.cliArgs }}
- name: Upload result
uses: actions/upload-artifact@v4
with:
name: "${{ matrix.dataset.name }}-${{ matrix.os }}"
path: "${{ matrix.dataset.name }}-report.zip"
retention-days: 30

e2e_test:
needs: run_jplag
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]

steps:
- name: Checkout
uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "18"

- name: Install and Build
working-directory: report-viewer
run: |
npm install
npm run build
- name: Install playwright
working-directory: report-viewer
run: npx playwright install --with-deps

- name: Download JPlag Reports
uses: actions/download-artifact@v4
with:
pattern: "*-${{ matrix.os }}"
path: "report-viewer/tests/e2e/assets"
merge-multiple: true

- name: Run tests
working-directory: report-viewer
run: |
npm run test:e2e
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: "test-results-${{ matrix.os }}"
path: |
report-viewer/test-results
report-viewer/playwright-report
retention-days: 30
Binary file added .github/workflows/files/fileMultiRoot.zip
Binary file not shown.
Binary file added .github/workflows/files/fileSingleRoot.zip
Binary file not shown.
Binary file added .github/workflows/files/folderMultiRoot.zip
Binary file not shown.
Binary file added .github/workflows/files/folderSingleRoot.zip
Binary file not shown.
Binary file added .github/workflows/files/mixedMultiRoot.zip
Binary file not shown.
58 changes: 0 additions & 58 deletions .github/workflows/report-viewer-e2e.yml

This file was deleted.

1 change: 1 addition & 0 deletions report-viewer/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ coverage

test-results/
playwright-report/
tests/e2e/assets
59 changes: 36 additions & 23 deletions report-viewer/tests/e2e/Comparison.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,33 @@ import { uploadFile } from './TestUtils'
test('Test comparison table and comparsion view', async ({ page }) => {
await page.goto('/')

await uploadFile('result_small_cluster.zip', page)
await uploadFile('progpedia-report.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 page.getByPlaceholder('Filter/Unhide Comparisons').fill('Purple')
const comparisonTableAverageSorted = await page.getByText(/Cluster[0-9]/).textContent()
expect(comparisonTableAverageSorted).toContain('100Purple FishBeige Dog')

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.getByPlaceholder('Filter/Unhide Comparisons').fill('Blue')
const comparisonTableMaxSorted = await page.getByText(/Cluster[0-9]/).textContent()
expect(comparisonTableMaxSorted).toContain('100Blue AntelopeLime Lynx')

await page.getByPlaceholder('Filter/Unhide Comparisons').fill('')
await page.getByText('Hide All').click()
// check for elements being hidden
const comparisonTableOverviewHidden = await page.getByText('Cluster1').textContent()
expect(comparisonTableOverviewHidden).toMatch(/1anon[0-9]+anon[0-9]+/)
expect(comparisonTableOverviewHidden).toMatch(/3anon[0-9]+anon[0-9]+/)
expect(comparisonTableOverviewHidden).toMatch(/4anon[0-9]+anon[0-9]+/)

await page.getByPlaceholder('Filter/Unhide Comparisons').fill('A')
// Temporarily disabled due to https://github.com/jplag/JPlag/issues/1629
/*await page.getByPlaceholder('Filter/Unhide Comparisons').fill('A')
// check for elements being unhidden and filtered
const comparisonTableOverviewFilteredA = await page.getByText('Cluster1').textContent()
expect(comparisonTableOverviewFilteredA).toMatch(/1anon[0-9]+A/) //toContain('1HiddenA')
Expand All @@ -40,32 +42,43 @@ test('Test comparison table and comparsion view', async ({ page }) => {
const comparisonTableOverviewFilteredAC = await page.getByText('Cluster1').textContent()
expect(comparisonTableOverviewFilteredAC).toContain('1CA')
expect(comparisonTableOverviewFilteredAC).toMatch(/3anon[0-9]+A/)
expect(comparisonTableOverviewFilteredAC).toMatch(/4anon[0-9]+C/)
expect(comparisonTableOverviewFilteredAC).toMatch(/4anon[0-9]+C/)+/*/

await page.getByText('Show All').click()
await page.getByPlaceholder('Filter/Unhide Comparisons').fill('Lazy')
// go to comparison page
await page.getByText('1C').click()
await page.getByText('102Gray WolfLazy Bobcat').click()
await page.waitForURL(/\/comparison\/.*/)

// check for elements in comparison page
const submissionName1 = 'Gray Wolf'
const submissionName2 = 'Lazy Bobcat'
const fileName1 = 'Sociologia.java'
const fileName2 = 'Daa_sociologia.java'
const content1 = 'class Aluno'
const content2 = 'class Node'

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')
expect(bodyComparison).toMatch(/Average Similarity: [0-9]{2}.[0-9]{2}%/)
expect(bodyComparison).toMatch(new RegExp(`Similarity ${submissionName1}: [0-9]{2}.[0-9]{2}%`))
expect(bodyComparison).toMatch(new RegExp(`Similarity ${submissionName2}: [0-9]{2}.[0-9]{2}%`))

expect(bodyComparison).toMatch(new RegExp(`${fileName1} - ${fileName2}: [0-9]+`))
expect(bodyComparison).toContain(`${submissionName1}/${fileName1}`)
expect(bodyComparison).toContain(`${submissionName2}/${fileName2}`)

// check for being able to hide and unhide elements
expect(await isCodeVisible(page, 'public class Match {')).toBe(false)
await page.getByText('A/Match.java').click()
expect(await isCodeVisible(page, 'public class Match {')).toBe(true)
await page.getByText('A/Match.java').click()
expect(await isCodeVisible(page, 'public class Match {')).toBe(false)
expect(await isCodeVisible(page, content1)).toBe(false)
await page.getByText(`${submissionName1}/${fileName1}`).click()
expect(await isCodeVisible(page, content1)).toBe(true)
await page.getByText(`${submissionName1}/${fileName1}`).click()
expect(await isCodeVisible(page, content1)).toBe(false)

// unhide elements by clicking match list
expect(await isCodeVisible(page, 'public class GSTiling')).toBe(false)
await page.getByText('GSTiling.java - GSTiling.java: 308').click()
expect(await isCodeVisible(page, content2)).toBe(false)
await page.getByText(`${fileName1} - ${fileName2}:`).first().click()
await page.waitForTimeout(1000)
expect(await isCodeVisible(page, 'public class GSTiling')).toBe(true)
expect(await isCodeVisible(page, content2)).toBe(true)
})

async function isCodeVisible(page: Page, codePart: string) {
Expand Down
2 changes: 1 addition & 1 deletion report-viewer/tests/e2e/Distribution.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { uploadFile } from './TestUtils'
test('Test distribution diagram', async ({ page }) => {
await page.goto('/')

await uploadFile('result_small_cluster.zip', page)
await uploadFile('progpedia-report.zip', page)

const options = getTestCombinations()
selectOptions(page, options[0])
Expand Down
34 changes: 17 additions & 17 deletions report-viewer/tests/e2e/Information.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,32 @@ import { uploadFile } from './TestUtils'

test('Test information page', async ({ page }) => {
await page.goto('/')
await uploadFile('result_small_cluster.zip', page)
await uploadFile('progpedia-report.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 Token Match: 9')
expect(bodyOverview).toContain('Directory: ')
expect(bodyOverview).toMatch(/Total Submissions: [0-9]+/)
expect(bodyOverview).toMatch(/Total Comparisons: [0-9]+/)
expect(bodyOverview).toMatch(/Min Token Match: [0-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 Directory:').textContent()
expect(runOptions).toContain('Submission Directory: files')
expect(runOptions).toContain('Basecode Directory:')
expect(runOptions).toContain('Language: Javac based AST plugin')
expect(runOptions).toContain('File Extensions: .java, .JAVA')
expect(runOptions).toContain('Min Token Match: 9')
const runOptions = await page.getByText('Run Options:Language:').textContent()
expect(runOptions).toContain('Submission Directories: ')
expect(runOptions).toContain('Base Directory: ')
expect(runOptions).toContain('Language: ')
expect(runOptions).toContain('File Suffixes: ')
expect(runOptions).toMatch(/Min Token Match: [0-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('Total Submissions: 4')
expect(runData).toContain('Total Comparisons: 6')
expect(runData).toContain('Shown Comparisons: 6')
expect(runData).toContain('Missing Comparisons: 0')
expect(runData).toMatch(/Date of Execution: [0-9]{2}\/[0-9]{2}\/[0-9]{2}/)
expect(runData).toMatch(/Execution Duration: [0-9]+ ms/)
expect(runData).toMatch(/Total Submissions: [0-9]+/)
expect(runData).toMatch(/Total Comparisons: [0-9]+/)
expect(runData).toMatch(/Shown Comparisons: [0-9]+/)
expect(runData).toMatch(/Missing Comparisons: [0-9]+/)
})
Loading

0 comments on commit 1b0c11d

Please sign in to comment.