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

Complete system e2e test #1631

Merged
merged 12 commits into from
Mar 6, 2024
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
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