Test Example in Ruby

This page is not available in the language you requested. You have been redirected to the English version of the page.
Link to this page copied to clipboard
Not for use with personal data

Be sure to check out the full Appium setup guide with axe DevTools Mobile if you're just getting started, or more examples of axe DevTools Mobile for Appium in other languages.

Full Example with UIAutomator2

require 'appium_lib'
require 'rspec'

describe 'DebugTest' do
  before(:all) do
    # The axeSettings object still accepts apiKey and axeAccountURL but is not required
    # if you are going to make one time before(:all) call to 'mobile: axeStartSession'
    @axe_settings = {
      tags: ['appium', 'qa'],
      uploadToDashboard: true,
      ignoreRules: ['ScreenOrientation']
    }
    @api_key = '<YOUR_API_KEY>'
    @project_id = '<YOUR_DEV_HUB_PROJECT_ID>'

    caps = {
      platformName: 'Android',
      deviceName: 'Android',
      appPackage: '<YOUR_APP_PACKAGE_NAME>',
      appActivity: '.MainActivity',
      automationName: 'AxeUiAutomator2',
      uiautomator2ServerLaunchTimeout: 60000,
      uiautomator2ServerInstallTimeout: 60000,
      adbExecTimeout: 60000,
      ignoreHiddenApiPolicyError: true,
      disableWindowAnimation: true,
      waitForIdle: true,
      commandTimeout: 300,
      noReset: false,
      fullReset: false
    }

    appium_opts = {
      caps: caps,
      appium_lib: {
        server_url: 'http://localhost:4723/'
      }
    }

    @driver = Appium::Driver.new(appium_opts, true)
    @driver.start_driver

    # Make one time call to setup your session for posting to Dev Hub.
    # This also accepts axeAccountURL in case of private instance.
    axe_auth_settings = {
      apiKey: @api_key,
      projectId: @project_id
    }
    @driver.execute_script('mobile: axeStartSession', axe_auth_settings)
  end

  after(:all) do
    if @driver
      # Generate an HTML report from all accumulated scans before quitting.
      # The report aggregates every 'mobile: axeScan' call made during this session.
      begin
        report_settings = {
          scanName: 'My Accessibility Report',
          axeHtmlReportPath: 'build/AxeDevToolsMobileResults'
        }

        report_result = @driver.execute_script(
          'mobile: axeGenerateHtmlReportAndSummary', report_settings
        )

        if report_result.key?('axeError')
          puts "Report generation failed: #{report_result['axeError']}"
        else
          puts "HTML report saved to: #{report_result['localDirectory']}"
        end
      rescue StandardError => e
        puts "Failed to generate HTML report: #{e.message}"
      end

      @driver.driver_quit
    end
  end

  def dismiss_system_ui_error
    begin
      system_popup = @driver.find_element(:xpath, '//*[contains(@text, "System UI")]')
      wait = Selenium::WebDriver::Wait.new(timeout: 5)
      wait.until { system_popup.displayed? }

      if system_popup.displayed?
        wait_button = @driver.find_element(:xpath, '//*[contains(@text, "Wait")]')
        wait = Selenium::WebDriver::Wait.new(timeout: 5)
        wait.until { wait_button.displayed? }
        wait_button.click
        puts "Dismissed the System UI error popup by clicking 'Wait'."
      end
    rescue Selenium::WebDriver::Error::TimeoutError, Selenium::WebDriver::Error::NoSuchElementError => e
      puts 'No System UI error popup appeared.'
    end
  end

  def launch_app
    begin
      @driver.terminate_app('<YOUR_APP_PACKAGE_NAME>')
      sleep(1) # Give the app time to fully terminate
    rescue StandardError => e
      puts "App was not running or failed to terminate: #{e.message}"
    end

    @driver.activate_app('<YOUR_APP_PACKAGE_NAME>')

    begin
      element = @driver.find_element(:xpath, '//*[contains(@text, "Screen Name")]')
      wait = Selenium::WebDriver::Wait.new(timeout: 30)
      wait.until { element.displayed? }
    rescue Selenium::WebDriver::Error::TimeoutError => e
      dismiss_system_ui_error
      # Try again after dismissing the error (if not, then fail)
      element = @driver.find_element(:xpath, '//*[contains(@text, "Screen Name")]')
      wait = Selenium::WebDriver::Wait.new(timeout: 30)
      wait.until { element.displayed? }
    end
  end

  before(:each) do
    launch_app
  end

  # Now since your session is authenticated you can keep making 'mobile: axeScan' call
  # like below in test1 and test2. The scans will be uploaded to the dashboard and also grouped in Developer Hub.
  it 'test1' do
    element = @driver.find_element(:xpath, '//*[contains(@text, "Screen Name")]')
    wait = Selenium::WebDriver::Wait.new(timeout: 10)
    wait.until { element.displayed? }
    puts element.text

    appium_scan_result = @driver.execute_script('mobile: axeScan', @axe_settings)
    results = appium_scan_result['axeRuleResults']
    puts "debug: Total results: #{results.length}"
  end

  it 'test2' do
    element = @driver.find_element(:xpath, '//*[contains(@text, "Screen Name")]')
    wait = Selenium::WebDriver::Wait.new(timeout: 10)
    wait.until { element.displayed? }
    element.click
    @driver.find_element(:xpath, '//*[contains(@text, "announced by a screen")]')

    appium_scan_result = @driver.execute_script('mobile: axeScan', @axe_settings)
    results = appium_scan_result['axeRuleResults']
    puts "debug: Total results: #{results.length}"
  end
end

Full Example with XCUITest

require 'appium_lib'
require 'rspec'

describe 'iOS Maps DebugTest' do
  before(:all) do
    # The axeSettings object still accepts apiKey and axeAccountURL but is not required
    # if you are going to make one time before(:all) call to 'mobile: axeStartSession'
    @axe_settings = {
      tags: ['appium', 'qa', 'ios'],
      uploadToDashboard: true,
      ignoreRules: ['ScreenOrientation']
    }
    @api_key = '<YOUR_API_KEY>'
    @project_id = '<YOUR_DEV_HUB_PROJECT_ID>'

    # Matching the working sample - minimal capabilities
    caps = {
      platformName: 'iOS',
      automationName: 'AxeXCUITest',
      udid: '<YOUR_DEVICE_OR_SIMULATOR_UDID>',
      bundleId: 'com.apple.Maps',
      wdaLaunchTimeout: 960000 # 16 minutes like the working sample
      # NOT specifying platformVersion - let it auto-detect
    }

    appium_opts = {
      caps: caps,
      appium_lib: {
        server_url: 'http://127.0.0.1:4723/'
      }
    }

    @driver = Appium::Driver.new(appium_opts, true)
    @driver.start_driver

    # Make one time call to setup your session for posting to Dev Hub.
    # This also accepts axeAccountURL in case of private instance.
    axe_auth_settings = {
      apiKey: @api_key,
      projectId: @project_id,
      axeAccountURL: 'https://mobile-qa.dequelabs.com'
    }
    @driver.execute_script('mobile: axeStartSession', axe_auth_settings)
  end

  after(:all) do
    if @driver
      # Generate HTML reports before quitting the driver
      @driver.execute_script('mobile: axeGenerateHtmlReportAndSummary', {})

      # Alternative: Generate HTML reports to a custom path
      # @driver.execute_script('mobile: axeGenerateHtmlReportAndSummary', {
      #   outputPath: '/Users/me/MyReports'
      # })

      sleep(1)
      @driver.driver_quit
    end
  end

  def launch_app
    @driver.activate_app('com.apple.Maps')
  end

  before(:each) do
    launch_app
  end

  # Now since your session is authenticated you can keep making 'mobile: axeScan' call
  # like below in test1 and test2. The scans will be uploaded to the dashboard and also grouped in Dev Hub.
  it 'test1 - scan main screen' do
    appium_scan_result = @driver.execute_script('mobile: axeScan', @axe_settings)
    results = appium_scan_result['axeRuleResults']
    puts "debug: Total results: #{results.length}"
  end

  it 'test2 - click search and scan' do
    appium_scan_result = @driver.execute_script('mobile: axeScan', @axe_settings)
    results = appium_scan_result['axeRuleResults']
    puts "debug: Total results: #{results.length}"
  end
end