From 4d9eea1b65ff4c1af913ce29025a28a34419c407 Mon Sep 17 00:00:00 2001 From: JamsonChan Date: Thu, 13 Jul 2023 23:48:12 +0800 Subject: [PATCH] ZK-5437: Upgrade WCAG with the lighthouse 10.x detection tools --- zkdoc/release-note | 1 + zktest/build.gradle | 437 +++++++++--------- zktest/src/main/webapp/wcag/listbox.zul | 7 +- .../zkoss/zktest/zats/wcag/CascaderTest.java | 1 - .../zkoss/zktest/zats/wcag/FreezeTest.java | 1 - .../org/zkoss/zktest/zats/wcag/TreeTest.java | 1 - .../zkoss/zktest/zats/wcag/WcagTestCase.java | 62 ++- 7 files changed, 269 insertions(+), 241 deletions(-) diff --git a/zkdoc/release-note b/zkdoc/release-note index 409f635fd3e..07669ecf638 100644 --- a/zkdoc/release-note +++ b/zkdoc/release-note @@ -12,6 +12,7 @@ ZK 10.0.0 ZK-5502: Allow users to customize tooltip on the icon ZK-5503: Allow users to set multiple icons and tooltips on the same LabelImageElement ZK-5213: Improve accessibility by add tooltips on icons + ZK-5437: Upgrade WCAG with the lighthouse 10.x detection tools * Bugs ZK-5089: AfterSizeEvent doesn't return a correct size of a Window component diff --git a/zktest/build.gradle b/zktest/build.gradle index 91c9bf54e15..2c0887ffbf5 100644 --- a/zktest/build.gradle +++ b/zktest/build.gradle @@ -1,226 +1,225 @@ plugins { - id 'war' - id "org.gretty" version "3.0.6" - id 'idea' - id 'com.github.psxpaul.execfork' version '0.2.2' + id 'war' + id "org.gretty" version "3.0.6" + id 'idea' + id 'com.github.psxpaul.execfork' version '0.2.2' } idea { - module { - outputDir file("$buildDir/classes/main") - testOutputDir file("$buildDir/classes/test") - } + module { + outputDir file("$buildDir/classes/main") + testOutputDir file("$buildDir/classes/test") + } } // TODO: don't use gretty since gretty not supporting jetty 10.0.5 and gretty 4.0.0 only support jetty11+ java.sourceCompatibility = JavaVersion.VERSION_11 tasks.withType(JavaCompile) { - options.encoding = 'UTF-8' + options.encoding = 'UTF-8' } repositories { - mavenLocal() { - content { - excludeGroupByRegex "io\\.netty\\.*" - } - } - - maven { - url = uri('https://mavensync.zkoss.org/maven2') - } - - maven { - url = uri('https://mavensync.zkoss.org/eval') - } - - maven { - url = uri('https://repo.maven.apache.org/maven2/') - } - - maven { - url = uri('https://maven.seasar.org/maven2') - } - - maven { - url = uri('https://maven.nuxeo.org/nexus/content/groups/public/') - } - - maven { - url = uri('https://maven.java.net/content/groups/public/') - } - - maven { - url = uri('https://jaspersoft.jfrog.io/jaspersoft/third-party-ce-artifacts/') - } + mavenLocal() { + content { + excludeGroupByRegex "io\\.netty\\.*" + } + } + + maven { + url = uri('https://mavensync.zkoss.org/maven2') + } + + maven { + url = uri('https://mavensync.zkoss.org/eval') + } + + maven { + url = uri('https://repo.maven.apache.org/maven2/') + } + + maven { + url = uri('https://maven.seasar.org/maven2') + } + + maven { + url = uri('https://maven.nuxeo.org/nexus/content/groups/public/') + } + + maven { + url = uri('https://maven.java.net/content/groups/public/') + } + + maven { + url = uri('https://jaspersoft.jfrog.io/jaspersoft/third-party-ce-artifacts/') + } } dependencies { - implementation "org.zkoss.theme:breeze:${version}" - implementation "org.zkoss.theme:silvertail:${version}" - implementation "org.zkoss.theme:sapphire:${version}" - implementation "org.zkoss.theme:atlantic:${version}" - implementation 'commons-logging:commons-logging:1.1.1' - implementation 'commons-fileupload:commons-fileupload:1.5' - implementation 'commons-io:commons-io:2.8.0' - implementation "org.zkoss.zk:zk:${version}" - implementation "org.zkoss.zk:zkplus:${version}" - implementation "org.zkoss.zk:zkplus-legacy:${version}" - implementation "org.zkoss.zk:zkbind:${version}" - implementation "org.zkoss.zk:zul:${version}" - implementation "org.zkoss.zk:zhtml:${version}" - implementation "org.zkoss.zk:zkwebfragment:${version}" - implementation "org.zkoss.common:zcommon:${version}" - implementation "org.zkoss.common:zweb:${version}" - implementation "org.zkoss.common:zweb-dsp:${version}" - implementation "org.zkoss.common:zel:${version}" - implementation "org.zkoss.zk:zkex:${version}" - implementation "org.zkoss.zk:zkmax:${version}" - implementation "org.zkoss.zk:zuti:${version}" - if (project.ext['zktestWithoutA11y'] == 'false') { - implementation "org.zkoss.zk:za11y:${version}" - } - implementation 'org.zkoss.zkforge.el:zcommons-el:1.1.0' - implementation 'org.zkoss.addon:flashchart:1.0' - implementation 'commons-lang:commons-lang:2.6' - implementation 'commons-beanutils:commons-beanutils:1.9.4' - implementation 'com.google.javascript:closure-compiler-unshaded:v20200426' - implementation 'net.sf.jasperreports:jasperreports:6.17.0' - implementation 'org.jfree:jfreechart:1.0.19' - implementation 'com.jhlabs:filters:2.0.235-1' - implementation 'org.zkoss.zkforge:ckez:4.17.1.0' - implementation 'org.zkoss.zkforge:timelinez:2.3.1_50' - implementation 'org.zkoss.zkforge:timeplotz:1.1_50' - implementation 'org.zkoss.zkforge:gmapsz:3.1.0' - implementation 'org.hibernate:hibernate-validator:5.3.6.Final' - implementation 'javax.validation:validation-api:1.1.0.Final' - - // fix for DestroyTest.java that org.eclipse.jetty:apache-jsp:10.0.5 depends on slf4j-api 2.0.0-alpha1 - implementation 'org.slf4j:slf4j-jdk14:2.0.3' - implementation 'javax.inject:javax.inject:1' - implementation 'javax.enterprise:cdi-api:1.0' - implementation 'org.javassist:javassist:3.28.0-GA' - implementation 'org.easymock:easymock:3.4' - implementation 'de.odysseus.juel:juel-spi:2.2.7' - implementation 'de.odysseus.juel:juel-impl:2.2.7' - runtimeOnly 'org.apache-extras.beanshell:bsh:2.0b6' - runtimeOnly 'org.codehaus.groovy:groovy-all:1.5.6' - runtimeOnly 'org.mozilla:rhino:1.7R4' + implementation "org.zkoss.theme:breeze:${version}" + implementation "org.zkoss.theme:silvertail:${version}" + implementation "org.zkoss.theme:sapphire:${version}" + implementation "org.zkoss.theme:atlantic:${version}" + implementation 'commons-logging:commons-logging:1.1.1' + implementation 'commons-fileupload:commons-fileupload:1.5' + implementation 'commons-io:commons-io:2.8.0' + implementation "org.zkoss.zk:zk:${version}" + implementation "org.zkoss.zk:zkplus:${version}" + implementation "org.zkoss.zk:zkplus-legacy:${version}" + implementation "org.zkoss.zk:zkbind:${version}" + implementation "org.zkoss.zk:zul:${version}" + implementation "org.zkoss.zk:zhtml:${version}" + implementation "org.zkoss.zk:zkwebfragment:${version}" + implementation "org.zkoss.common:zcommon:${version}" + implementation "org.zkoss.common:zweb:${version}" + implementation "org.zkoss.common:zweb-dsp:${version}" + implementation "org.zkoss.common:zel:${version}" + implementation "org.zkoss.zk:zkex:${version}" + implementation "org.zkoss.zk:zkmax:${version}" + implementation "org.zkoss.zk:zuti:${version}" + if (project.ext['zktestWithoutA11y'] == 'false') { + implementation "org.zkoss.zk:za11y:${version}" + } + implementation 'org.zkoss.zkforge.el:zcommons-el:1.1.0' + implementation 'org.zkoss.addon:flashchart:1.0' + implementation 'commons-lang:commons-lang:2.6' + implementation 'commons-beanutils:commons-beanutils:1.9.4' + implementation 'com.google.javascript:closure-compiler-unshaded:v20200426' + implementation 'net.sf.jasperreports:jasperreports:6.17.0' + implementation 'org.jfree:jfreechart:1.0.19' + implementation 'com.jhlabs:filters:2.0.235-1' + implementation 'org.zkoss.zkforge:ckez:4.17.1.0' + implementation 'org.zkoss.zkforge:timelinez:2.3.1_50' + implementation 'org.zkoss.zkforge:timeplotz:1.1_50' + implementation 'org.zkoss.zkforge:gmapsz:3.1.0' + implementation 'org.hibernate:hibernate-validator:5.3.6.Final' + implementation 'javax.validation:validation-api:1.1.0.Final' + + // fix for DestroyTest.java that org.eclipse.jetty:apache-jsp:10.0.5 depends on slf4j-api 2.0.0-alpha1 + implementation 'org.slf4j:slf4j-jdk14:2.0.3' + implementation 'javax.inject:javax.inject:1' + implementation 'javax.enterprise:cdi-api:1.0' + implementation 'org.javassist:javassist:3.28.0-GA' + implementation 'org.easymock:easymock:3.4' + implementation 'de.odysseus.juel:juel-spi:2.2.7' + implementation 'de.odysseus.juel:juel-impl:2.2.7' + runtimeOnly 'org.apache-extras.beanshell:bsh:2.0b6' + runtimeOnly 'org.codehaus.groovy:groovy-all:1.5.6' + runtimeOnly 'org.mozilla:rhino:1.7R4' // testImplementation 'org.jruby:jruby-core:1.7.27' // testImplementation 'org.python:jython:2.2.1' - testImplementation 'org.zkoss.zats:zats-mimic-ext:10.0.0-FL-2022070817' - testImplementation 'net.jcip:jcip-annotations:1.0' - testImplementation 'com.deque.html.axe-core:selenium:4.2.2' - testImplementation 'org.springframework.session:spring-session-core:2.1.6.RELEASE' - testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion" - testImplementation "org.mockito:mockito-inline:4.7.0" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" - testImplementation 'org.eclipse.jetty.websocket:websocket-javax-server:10.0.11' - testImplementation 'org.eclipse.jetty:apache-jsp:10.0.11' - testImplementation 'org.junit.platform:junit-platform-launcher:1.9.0' - testImplementation 'xml-apis:xml-apis:1.4.01' - testImplementation 'org.zkoss.test:zk-webdriver:1.0.9.2' - - // For B96_ZK_4194Test to use a specific Chrome driver version (this will change to match latest chrome) - testImplementation 'org.seleniumhq.selenium:selenium-devtools-v112:4.9.0' - testImplementation "org.seleniumhq.selenium:selenium-java:4.9.0" - testImplementation 'com.google.javascript:closure-compiler-unshaded:v20230411' - - providedCompile 'javax.el:javax.el-api:2.2.5' - providedCompile 'javax.servlet:javax.servlet-api:3.1.0' - providedCompile 'javax.websocket:javax.websocket-api:1.1' - // workaround for running Mockito under Java 11 - providedCompile "net.bytebuddy:byte-buddy:1.8.22" - providedCompile "net.bytebuddy:byte-buddy-agent:1.8.22" + testImplementation 'org.zkoss.zats:zats-mimic-ext:10.0.0-FL-2022070817' + testImplementation 'net.jcip:jcip-annotations:1.0' + testImplementation 'org.springframework.session:spring-session-core:2.1.6.RELEASE' + testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion" + testImplementation "org.mockito:mockito-inline:4.7.0" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion" + testImplementation 'org.eclipse.jetty.websocket:websocket-javax-server:10.0.11' + testImplementation 'org.eclipse.jetty:apache-jsp:10.0.11' + testImplementation 'org.junit.platform:junit-platform-launcher:1.9.0' + testImplementation 'xml-apis:xml-apis:1.4.01' + testImplementation 'org.zkoss.test:zk-webdriver:1.0.9.2' + + // For B96_ZK_4194Test to use a specific Chrome driver version (this will change to match latest chrome) + testImplementation 'org.seleniumhq.selenium:selenium-devtools-v112:4.9.0' + testImplementation "org.seleniumhq.selenium:selenium-java:4.9.0" + testImplementation 'com.google.javascript:closure-compiler-unshaded:v20230411' + + providedCompile 'javax.el:javax.el-api:2.2.5' + providedCompile 'javax.servlet:javax.servlet-api:3.1.0' + providedCompile 'javax.websocket:javax.websocket-api:1.1' + // workaround for running Mockito under Java 11 + providedCompile "net.bytebuddy:byte-buddy:1.8.22" + providedCompile "net.bytebuddy:byte-buddy-agent:1.8.22" } sourceSets { - main { - resources { - // some test will try to get content from resources - srcDirs += "src/main/webapp" - } - } + main { + resources { + // some test will try to get content from resources + srcDirs += "src/main/webapp" + } + } } task testGroupForkJVMTestOnly(type: Test) { - forkEvery = 1 // a new test process is started for every test class - maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 - if (project.ext['zktestWithoutA11y'] != 'false') { - reports.junitXml.destination = file("$buildDir/test-results/no-A11Y/testGroupForkJVMTestOnly") - filter { - excludeTestsMatching('*.wcag.*') - } - useJUnitPlatform { - includeTags 'ForkJVMTestOnly' - excludeTags 'WcagTestOnly' - } - } else { - useJUnitPlatform { - includeTags 'ForkJVMTestOnly' - } - } - systemProperty "zkWebdriverContextPath", "/zktest" - systemProperty "zkWebdriverTestURLPackage", "org.zkoss.zktest.zats" - - // a way to pass -Dtags=... - options { - systemProperties(System.getProperties()) - } + forkEvery = 1 // a new test process is started for every test class + maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 + if (project.ext['zktestWithoutA11y'] != 'false') { + reports.junitXml.destination = file("$buildDir/test-results/no-A11Y/testGroupForkJVMTestOnly") + filter { + excludeTestsMatching('*.wcag.*') + } + useJUnitPlatform { + includeTags 'ForkJVMTestOnly' + excludeTags 'WcagTestOnly' + } + } else { + useJUnitPlatform { + includeTags 'ForkJVMTestOnly' + } + } + systemProperty "zkWebdriverContextPath", "/zktest" + systemProperty "zkWebdriverTestURLPackage", "org.zkoss.zktest.zats" + + // a way to pass -Dtags=... + options { + systemProperties(System.getProperties()) + } } test { - forkEvery = 0 // reuse the test process for all test classes - maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 - if (project.ext['zktestWithoutA11y'] != 'false') { - reports.junitXml.destination = file("$buildDir/test-results/no-A11Y/test") - filter { - excludeTestsMatching('*.wcag.*') - } - useJUnitPlatform { - excludeTags 'WcagTestOnly', 'ForkJVMTestOnly' - } - } else { - useJUnitPlatform { - excludeTags 'ForkJVMTestOnly' - } - } - systemProperty "zkWebdriverContextPath", "/zktest" - systemProperty "zkWebdriverTestURLPackage", "org.zkoss.zktest.zats" - - // a way to pass -Dtags=... - options { - systemProperties(System.getProperties()) - } + forkEvery = 0 // reuse the test process for all test classes + maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 + if (project.ext['zktestWithoutA11y'] != 'false') { + reports.junitXml.destination = file("$buildDir/test-results/no-A11Y/test") + filter { + excludeTestsMatching('*.wcag.*') + } + useJUnitPlatform { + excludeTags 'WcagTestOnly', 'ForkJVMTestOnly' + } + } else { + useJUnitPlatform { + excludeTags 'ForkJVMTestOnly' + } + } + systemProperty "zkWebdriverContextPath", "/zktest" + systemProperty "zkWebdriverTestURLPackage", "org.zkoss.zktest.zats" + + // a way to pass -Dtags=... + options { + systemProperties(System.getProperties()) + } } task clearNoA11Y(type: Delete) { - delete "$buildDir/test-results/no-A11Y/" + delete "$buildDir/test-results/no-A11Y/" } task renameNoA11yTestResult (type: Copy) { // mustRunAfter test // mustRunAfter 'testGroupForkJVMTestOnly' // setOnlyIf { project.ext['zktestWithoutA11y'] != 'false' } - destinationDir = file("$buildDir/test-results/no-A11Y0") - from ("$buildDir/test-results/no-A11Y") - includeEmptyDirs false - include '**/*Test.xml' - filter { - String line -> line.replaceAll("testsuite name=\"(.[^\"]*)\"", - "testsuite name=\"\$1(NO_A11Y)\"") - } - rename '(.*).xml', '$1NO_A11Y.xml' - - finalizedBy clearNoA11Y + destinationDir = file("$buildDir/test-results/no-A11Y0") + from ("$buildDir/test-results/no-A11Y") + includeEmptyDirs false + include '**/*Test.xml' + filter { + String line -> line.replaceAll("testsuite name=\"(.[^\"]*)\"", + "testsuite name=\"\$1(NO_A11Y)\"") + } + rename '(.*).xml', '$1NO_A11Y.xml' + + finalizedBy clearNoA11Y } description = 'ZK Test' gretty { - httpPort = 8080 + httpPort = 8080 } // Start browsersync in the background. @@ -248,53 +247,53 @@ task browsersync(type: com.github.psxpaul.task.ExecFork) { // WARNING: Do NOT move this task before the "dependencies" declaration; otherwise, // `configurations.implementation.dependencies` will not work. task devMode { - if (project.gradle.startParameter.taskNames.stream().filter { - it.endsWith('Dev') - }.findFirst().isPresent()) { - dependsOn browsersync - gretty { - httpPort = gretty.httpPort - beforeClassPath = [] - def allowedWorkspace = [] - configurations.implementation.dependencies.each { - allowedWorkspace << it.group + ":" + it.name - } - def subprojectsWithJS = [] - addClassPath(gradle, beforeClassPath, [], allowedWorkspace, subprojectsWithJS) - - println "Watching the following subprojects with browsersync:" - println subprojectsWithJS - browsersync.args << '--subprojectPaths' << subprojectsWithJS.join(',') - } - } + if (project.gradle.startParameter.taskNames.stream().filter { + it.endsWith('Dev') + }.findFirst().isPresent()) { + dependsOn browsersync + gretty { + httpPort = gretty.httpPort + beforeClassPath = [] + def allowedWorkspace = [] + configurations.implementation.dependencies.each { + allowedWorkspace << it.group + ":" + it.name + } + def subprojectsWithJS = [] + addClassPath(gradle, beforeClassPath, [], allowedWorkspace, subprojectsWithJS) + + println "Watching the following subprojects with browsersync:" + println subprojectsWithJS + browsersync.args << '--subprojectPaths' << subprojectsWithJS.join(',') + } + } } task appRunDev { - dependsOn devMode + dependsOn devMode } task appRunDebugDev { - dependsOn devMode + dependsOn devMode } def addClassPath(gradle, beforeClassPath, visitedBuilds, allowedWorkspace, subprojectsWithJS) { - gradle.includedBuilds.each { - if (visitedBuilds.contains(it.name)) return - visitedBuilds << it.name - def rootGradle = it.properties['gradle'] - it.properties['availableModules'].each { - - def prj = rootGradle.rootProject.findProject(it.right.identityPath.toString()) - if (!prj) { - prj = rootGradle.rootProject.findProject(it.right.projectPath.toString()) - } - if (prj && allowedWorkspace.contains(prj.group + ":" + prj.name)) { - beforeClassPath << prj.sourceSets.main.output.resourcesDir - println "add to classPath: " + prj.sourceSets.main.output.resourcesDir - subprojectsWithJS << prj.projectDir - } - } - addClassPath(rootGradle, beforeClassPath, visitedBuilds, allowedWorkspace, subprojectsWithJS); - } + gradle.includedBuilds.each { + if (visitedBuilds.contains(it.name)) return + visitedBuilds << it.name + def rootGradle = it.properties['gradle'] + it.properties['availableModules'].each { + + def prj = rootGradle.rootProject.findProject(it.right.identityPath.toString()) + if (!prj) { + prj = rootGradle.rootProject.findProject(it.right.projectPath.toString()) + } + if (prj && allowedWorkspace.contains(prj.group + ":" + prj.name)) { + beforeClassPath << prj.sourceSets.main.output.resourcesDir + println "add to classPath: " + prj.sourceSets.main.output.resourcesDir + subprojectsWithJS << prj.projectDir + } + } + addClassPath(rootGradle, beforeClassPath, visitedBuilds, allowedWorkspace, subprojectsWithJS); + } } appRunDev.dependsOn 'appRun' diff --git a/zktest/src/main/webapp/wcag/listbox.zul b/zktest/src/main/webapp/wcag/listbox.zul index b4717778bcb..a151477dcf5 100644 --- a/zktest/src/main/webapp/wcag/listbox.zul +++ b/zktest/src/main/webapp/wcag/listbox.zul @@ -142,8 +142,9 @@ Copyright (C) 2020 Potix Corporation. All Rights Reserved. - - - + + + + \ No newline at end of file diff --git a/zktest/src/test/java/org/zkoss/zktest/zats/wcag/CascaderTest.java b/zktest/src/test/java/org/zkoss/zktest/zats/wcag/CascaderTest.java index ceebdaf953e..c97313fe770 100644 --- a/zktest/src/test/java/org/zkoss/zktest/zats/wcag/CascaderTest.java +++ b/zktest/src/test/java/org/zkoss/zktest/zats/wcag/CascaderTest.java @@ -17,7 +17,6 @@ /** * @author jameschu */ -@Disabled("Needs aXe fix this issue, https://github.com/dequelabs/axe-core/issues/2897") public class CascaderTest extends WcagTestCase { @Test public void test() { diff --git a/zktest/src/test/java/org/zkoss/zktest/zats/wcag/FreezeTest.java b/zktest/src/test/java/org/zkoss/zktest/zats/wcag/FreezeTest.java index 2c043acdf1a..0854b60348d 100644 --- a/zktest/src/test/java/org/zkoss/zktest/zats/wcag/FreezeTest.java +++ b/zktest/src/test/java/org/zkoss/zktest/zats/wcag/FreezeTest.java @@ -14,7 +14,6 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -@Disabled("Needs aXe fix this issue, https://github.com/dequelabs/axe-core/issues/2720") public class FreezeTest extends WcagTestCase { @Test public void test() { diff --git a/zktest/src/test/java/org/zkoss/zktest/zats/wcag/TreeTest.java b/zktest/src/test/java/org/zkoss/zktest/zats/wcag/TreeTest.java index 6dccf94b80e..62c3dbb51fe 100644 --- a/zktest/src/test/java/org/zkoss/zktest/zats/wcag/TreeTest.java +++ b/zktest/src/test/java/org/zkoss/zktest/zats/wcag/TreeTest.java @@ -17,7 +17,6 @@ /** * @author jameschu */ -@Disabled("Needs aXe fix this issue, https://github.com/dequelabs/axe-core/issues/2720") public class TreeTest extends WcagTestCase { @Test public void test() { diff --git a/zktest/src/test/java/org/zkoss/zktest/zats/wcag/WcagTestCase.java b/zktest/src/test/java/org/zkoss/zktest/zats/wcag/WcagTestCase.java index 42390d3fe3b..98ad4062dd2 100644 --- a/zktest/src/test/java/org/zkoss/zktest/zats/wcag/WcagTestCase.java +++ b/zktest/src/test/java/org/zkoss/zktest/zats/wcag/WcagTestCase.java @@ -11,13 +11,12 @@ */ package org.zkoss.zktest.zats.wcag; -import java.util.Arrays; - -import com.deque.html.axecore.results.Results; -import com.deque.html.axecore.selenium.AxeBuilder; -import com.deque.html.axecore.selenium.AxeReporter; import org.junit.jupiter.api.Assertions; - +import org.junit.jupiter.api.BeforeAll; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import org.json.JSONObject; import org.zkoss.test.webdriver.WebDriverTestCase; /** @@ -25,6 +24,23 @@ * @author rudyhuang */ public abstract class WcagTestCase extends WebDriverTestCase { + + @BeforeAll + public static void installLighthouse() throws IOException { + try { + String version = "@10.4.0"; + Process process = Runtime.getRuntime().exec("npm -g list lighthouse"); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + reader.readLine(); + if (!reader.readLine().contains("lighthouse" + version)) { + Runtime.getRuntime().exec("npm uninstall -g lighthouse"); + Runtime.getRuntime().exec("npm install -g lighthouse" + version); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + @Override protected String getFileLocation() { String simple = getClass().getSimpleName(); @@ -38,15 +54,29 @@ protected String getFileLocation() { * If there is any issue, test will fail. */ protected void verifyA11y() { - // FIXME: Temporary disabled color-contrast - AxeBuilder builder = new AxeBuilder() - .withTags(Arrays.asList("wcag2a", "wcag2aa")) - .disableRules(Arrays.asList("color-contrast")); - Results results = builder.analyze(driver); - if (!results.violationFree()) { - Assertions.fail(AxeReporter.getReadableAxeResults("WCAG", driver, results.getViolations()) - ? AxeReporter.getAxeResultString() - : null); + + try { + String url = getAddress() + getFileLocation(), failmsg = "", data = "", line = ""; + boolean pass = true; + int count = 1; + Process process = Runtime.getRuntime().exec("lighthouse " + url + " --output=json --chrome-flags=\"--headless\" --only-categories=\"accessibility\""); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + while ((line = reader.readLine()) != null) data += line; + JSONObject audits = (new JSONObject(data)).getJSONObject("audits"); + for (String key : audits.keySet()) { + JSONObject audit = audits.getJSONObject(key); + // Disable color-contrast because it only passes when using wcag theme, general theme does not need to pass + if (audit.get("score").toString().equals("0") && !audit.get("id").toString().equals("color-contrast")) { + pass = false; + failmsg += "\n================== " + (count++) + " ==================\n" + + ">>> id : " + audit.get("id") + "\n" + + ">>> title : " + audit.get("title") + "\n" + + ">>> description : " + audit.get("description") + "\n"; + } + } + if (!pass) Assertions.fail(failmsg); + } catch (IOException e) { + Assertions.fail("\n================== Exception ==================\n" + e.getMessage() + "\n"); } } -} +} \ No newline at end of file