Appium Example
The following Appium example is written in Kotlin and assumes the use of Appium's java-client. The logic is transferable to other clients.
important
Before running the Appium test, ensure the application.app being passed into Appium runs axe DevTools on the screens you want to test with axe?.showA11yFab()
and is connected to the dashboard with AxeDevTools.login(...)
.
Setup
build.gradle
plugins {
id 'java'
id 'org.jetbrains.kotlin.jvm' version '1.5.0'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
maven { url "https://maven.google.com" }
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "junit:junit:4.13.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2"
testImplementation "junit:junit:4.13.1"
implementation "com.github.appium:java-client:8.1.1"
implementation "org.seleniumhq.selenium:selenium-java:4.2.1"
implementation "com.google.code.gson:gson:2.9.0"
implementation "com.squareup.okhttp3:okhttp:4.10.0"
}
Full Example
import com.google.gson.Gson
import io.appium.java_client.AppiumBy
import io.appium.java_client.ios.IOSDriver
import io.appium.java_client.remote.MobileCapabilityType
import io.appium.java_client.remote.MobilePlatform
import okhttp3.OkHttpClient
import okhttp3.Request
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.openqa.selenium.WebDriver
import org.openqa.selenium.remote.DesiredCapabilities
import org.openqa.selenium.support.ui.ExpectedCondition
import org.openqa.selenium.support.ui.WebDriverWait
import java.io.BufferedReader
import java.io.File
import java.net.URL
import java.time.Duration
@RunWith(JUnit4::class)
class DemoWithAPIRequest {
private val client = OkHttpClient()
private lateinit var driver: IOSDriver
val appFilePath = "path/to/your/application.app"
@Before
fun setup() {
val capabilities = DesiredCapabilities()
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone 14")
capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.IOS)
capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "16.0")
capabilities.setCapability(MobileCapabilityType.APP, File(appFilePath).absolutePath)
driver = IOSDriver(URL("http://127.0.0.1:4723/wd/hub"), capabilities)
}
@Test
fun runA11y() {
// Navigate and Click the FAB
driver.findElement(
AppiumBy.accessibilityId("com.deque.axeDevTools.accessibilityFab")
).click()
val webDriverWait = WebDriverWait(driver, Duration.ofSeconds(10))
webDriverWait.until(ExpectedCondition { input: WebDriver? ->
input?.findElement(AppiumBy.accessibilityId("com.deque.axeDevTools.accessibilityFab"))
true
})
// Getting Result Key from the FAB
val resultKey: String = driver.findElement(
AppiumBy.accessibilityId("com.deque.axeDevTools.accessibilityFab")
).getAttribute("label")
// Fetch Rule Results from API
val apiKey = "your-api-key-here"
val url = "https://sauron.dequecloud.com/attest/result/axe/$resultKey"
val request = Request.Builder()
.url(url)
.addHeader("X-Api-Key", apiKey)
.addHeader("Content-Type", "application/json")
.build()
try {
val response = client.newCall(request).execute()
if (response.code == 200) {
val content = response.body?.string()
// Parse JSON and output the result
val axeResult = Gson().fromJson(content, AxeResult::class.java)
axeResult.axeRuleResults.forEach {
if (it.status == "FAIL") {
println("rule: ${it.ruleId}")
}
}
} else {
println("httpCode: ${response.code}")
}
} catch (t: Throwable) {
println("error: ${t.message}")
}
}
}
data class AxeRuleResult(
val ruleId: String?,
val ruleSummary: String?,
val axeViewId: String?,
val status: String?, // "PASS", "FAIL", "INCOMPLETE"
val impact: Int?,
val props: HashMap<String, Any?>,
val isVisibileToUser: Boolean = true
)
data class AxeResult(
val axeRuleResults: List<AxeRuleResult>,
val userName: String?,
val scanName: String?,
val tags: List<String>?
)