Showing preview only (620K chars total). Download the full file or copy to clipboard to get everything.
Repository: appium/ruby_lib
Branch: master
Commit: 47ac48a3aaac
Files: 141
Total size: 579.2 KB
Directory structure:
gitextract_9jozq5zh/
├── .github/
│ ├── CODEOWNERS
│ ├── ISSUE_TEMPLATE.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── dependabot.yml
│ └── workflows/
│ ├── functional-test.yml
│ ├── pr-title.yml
│ └── rubocop.yml
├── .gitignore
├── .rubocop.yml
├── CHANGELOG.md
├── Gemfile
├── LICENSE-2.0.txt
├── Rakefile
├── Thorfile
├── android_tests/
│ ├── Gemfile
│ ├── LICENSE-2.0.txt
│ ├── Rakefile
│ ├── appium.txt
│ ├── flaky.txt
│ ├── lib/
│ │ ├── android/
│ │ │ └── specs/
│ │ │ ├── android/
│ │ │ │ ├── element/
│ │ │ │ │ ├── alert.rb
│ │ │ │ │ ├── button.rb
│ │ │ │ │ ├── generic.rb
│ │ │ │ │ ├── text.rb
│ │ │ │ │ └── textfield.rb
│ │ │ │ ├── helper.rb
│ │ │ │ └── patch.rb
│ │ │ ├── common/
│ │ │ │ ├── device.rb
│ │ │ │ ├── device_touchaction.rb
│ │ │ │ ├── element/
│ │ │ │ │ └── window.rb
│ │ │ │ ├── helper.rb
│ │ │ │ ├── patch.rb
│ │ │ │ ├── version.rb
│ │ │ │ └── web_context.rb
│ │ │ ├── driver.rb
│ │ │ ├── install.rb
│ │ │ └── sauce_labs.rb
│ │ ├── format.rb
│ │ └── run.rb
│ └── readme.md
├── appium_lib.gemspec
├── contributing.md
├── docs/
│ ├── android_uiautomator.md
│ ├── docs.md
│ ├── ios_xcuitest.md
│ ├── parallel.md
│ └── w3c.md
├── grid/
│ ├── README.md
│ ├── appium.txt.ios.example
│ ├── config.json
│ ├── hub_config.json
│ └── hub_config_3.json
├── ios_tests/
│ ├── Gemfile
│ ├── LICENSE-2.0.txt
│ ├── Rakefile
│ ├── appium.txt
│ ├── data/
│ │ └── unicode.txt
│ ├── flaky.txt
│ ├── lib/
│ │ ├── common.rb
│ │ ├── format.rb
│ │ ├── ios/
│ │ │ └── specs/
│ │ │ ├── common/
│ │ │ │ ├── element/
│ │ │ │ │ └── window.rb
│ │ │ │ ├── helper.rb
│ │ │ │ ├── patch.rb
│ │ │ │ ├── version.rb
│ │ │ │ └── web_context.rb
│ │ │ ├── device/
│ │ │ │ ├── device.rb
│ │ │ │ └── image_comparison.rb
│ │ │ ├── driver.rb
│ │ │ └── ios/
│ │ │ ├── command/
│ │ │ │ ├── multi_app_handler.rb
│ │ │ │ ├── pasteboard.rb
│ │ │ │ └── source.rb
│ │ │ ├── element/
│ │ │ │ ├── alert.rb
│ │ │ │ ├── button.rb
│ │ │ │ ├── generic.rb
│ │ │ │ ├── text.rb
│ │ │ │ └── textfield.rb
│ │ │ ├── helper.rb
│ │ │ ├── mobile_methods.rb
│ │ │ ├── patch.rb
│ │ │ └── xcuitest_gestures.rb
│ │ └── run.rb
│ ├── parallel/
│ │ └── test.rb
│ └── readme.md
├── lib/
│ ├── appium_lib/
│ │ ├── android/
│ │ │ ├── android.rb
│ │ │ ├── common/
│ │ │ │ ├── command/
│ │ │ │ │ └── command.rb
│ │ │ │ └── helper.rb
│ │ │ ├── element/
│ │ │ │ ├── alert.rb
│ │ │ │ ├── button.rb
│ │ │ │ ├── generic.rb
│ │ │ │ ├── text.rb
│ │ │ │ └── textfield.rb
│ │ │ ├── espresso/
│ │ │ │ ├── bridge.rb
│ │ │ │ ├── element/
│ │ │ │ │ ├── button.rb
│ │ │ │ │ └── generic.rb
│ │ │ │ ├── element.rb
│ │ │ │ └── helper.rb
│ │ │ ├── espresso.rb
│ │ │ ├── uiautomator2/
│ │ │ │ ├── bridge.rb
│ │ │ │ ├── element/
│ │ │ │ │ └── button.rb
│ │ │ │ ├── element.rb
│ │ │ │ └── helper.rb
│ │ │ └── uiautomator2.rb
│ │ ├── appium.rb
│ │ ├── common/
│ │ │ ├── command.rb
│ │ │ ├── device.rb
│ │ │ ├── helper.rb
│ │ │ ├── http_client.rb
│ │ │ ├── log.rb
│ │ │ └── wait.rb
│ │ ├── driver.rb
│ │ ├── error.rb
│ │ ├── ios/
│ │ │ ├── common/
│ │ │ │ ├── errors.rb
│ │ │ │ └── helper.rb
│ │ │ ├── element/
│ │ │ │ ├── alert.rb
│ │ │ │ ├── button.rb
│ │ │ │ ├── generic.rb
│ │ │ │ ├── text.rb
│ │ │ │ └── textfield.rb
│ │ │ ├── ios.rb
│ │ │ ├── xcuitest/
│ │ │ │ ├── bridge.rb
│ │ │ │ ├── command/
│ │ │ │ │ ├── certificate.rb
│ │ │ │ │ ├── gestures.rb
│ │ │ │ │ ├── get_context.rb
│ │ │ │ │ ├── multi_app_handler.rb
│ │ │ │ │ ├── pasteboard.rb
│ │ │ │ │ └── source.rb
│ │ │ │ ├── command.rb
│ │ │ │ ├── element/
│ │ │ │ │ ├── button.rb
│ │ │ │ │ ├── generic.rb
│ │ │ │ │ ├── text.rb
│ │ │ │ │ └── textfield.rb
│ │ │ │ ├── element.rb
│ │ │ │ └── helper.rb
│ │ │ └── xcuitest.rb
│ │ ├── sauce_labs.rb
│ │ └── version.rb
│ └── appium_lib.rb
├── readme.md
├── release_notes.md
├── test/
│ └── first_test.rb
└── test_apps/
├── VodQA.apk
└── api.apk
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/CODEOWNERS
================================================
* @KazuCocoa
================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
## This is a
* [ ] Bug report
* [ ] Question
* [ ] Freature Request
## Summary
## Environment
* Appium version (or git revision):
* `ruby_lib` version:
* Mobile platform/version/device under test:
## Actual behaviour and steps to reproduce
## Expected behaviour
## Link to Appium/Ruby logs
Create a [GIST](https://gist.github.com) which is a paste of your _full_ Appium logs, and link them here.
## Any additional comments
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
# Summary
Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context.
Closes # (issue)
# How Has This Been Tested?
Please describe the tests that you ran to verify your changes. If the change has test code, it can be alternative.
- [ ] Test A
- [ ] Test B
# Checklist
- [ ] `bundle exec rake rubocop`
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: bundler
directory: "/"
schedule:
interval: weekly
time: "11:00"
open-pull-requests-limit: 10
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
time: "11:00"
open-pull-requests-limit: 10
================================================
FILE: .github/workflows/functional-test.yml
================================================
name: Functional Tests
on:
# Run by manual at this time
workflow_dispatch:
push:
branches: [ master ]
pull_request:
branches: [ master ]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
ios_test:
runs-on: macos-15
timeout-minutes: 90
env:
XCODE_VERSION: 16.4
IOS_VERSION: 18.5
IOS_DEVICE_NAME: iPhone 16 Plus
steps:
- uses: actions/checkout@v6
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 'lts/*'
- name: Select Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: ${{ env.XCODE_VERSION }}
- run: defaults write com.apple.iphonesimulator PasteboardAutomaticSync -bool false
- uses: futureware-tech/simulator-action@v5
with:
# https://github.com/actions/runner-images/blob/main/images/macos/macos-14-arm64-Readme.md
model: ${{ env.IOS_DEVICE_NAME }}
os_version: ${{ env.IOS_VERSION }}
- name: Preparing other environment
run: |
brew install ffmpeg
brew tap wix/brew
brew install applesimutils
# Start Appium
- name: Install appium and mjpeg-consumer
run: |
npm install -g appium
npm install -g mjpeg-consumer
- run: |
appium driver install xcuitest
appium plugin install images
appium plugin install execute-driver
nohup appium --use-plugins=images,execute-driver --relaxed-security --log-timestamp --log-no-colors > appium.log &
- run: |
npx appium driver run xcuitest download-wda-sim --platform=ios --outdir=${{ github.workspace }}/wda
name: Downloading prebuilt WDA
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 4.0
- run: |
bundle install
bundle exec rake ios
name: Run tests
timeout-minutes: 60
working-directory: ios_tests
env:
LOCAL_PREBUILT_WDA: ${{ github.workspace }}/wda/WebDriverAgentRunner-Runner.app
- name: Save server output
if: ${{ always() }}
uses: actions/upload-artifact@master
with:
name: appium-ios_test_with_other_deps.log
path: |
appium.log
test/report/
android_test:
runs-on: ubuntu-latest
timeout-minutes: 90
env:
API_LEVEL: 35
ARCH: x86_64
steps:
- uses: actions/checkout@v6
- name: Set up Java
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '17'
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 'lts/*'
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 4.0
- name: Install appium
run: |
npm install -g appium
npm install -g mjpeg-consumer
- name: Start appium
run: |
appium driver install uiautomator2
appium plugin install images
appium plugin install execute-driver
nohup appium --use-plugins=images,execute-driver --relaxed-security --log-timestamp --log-no-colors > appium.log &
- name: Enable KVM group perms
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: AVD cache
uses: actions/cache@v5
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-${{ env.API_LEVEL }}
- name: Create AVD snapshot for cache
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ env.API_LEVEL }}
arch: ${{ env.ARCH }}
target: google_apis
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
script: echo "Generated AVD snapshot for caching."
- name: run tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ env.API_LEVEL }}
arch: ${{ env.ARCH }}
script: cd android_tests;bundle install;bundle exec rake --tasks;bundle exec rake android
target: google_apis
profile: Nexus 5X
disable-spellchecker: true
disable-animations: true
- name: Save server output
if: ${{ always() }}
uses: actions/upload-artifact@master
with:
name: appium-android_test_with_other_deps.log
path: |
appium.log
test/report/
================================================
FILE: .github/workflows/pr-title.yml
================================================
name: Conventional Commits
on:
pull_request:
types: [opened, edited, synchronize, reopened]
jobs:
lint:
uses: appium/appium-workflows/.github/workflows/pr-title.yml@main
with:
config-preset: angular
================================================
FILE: .github/workflows/rubocop.yml
================================================
name: rubocop
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
test:
strategy:
fail-fast: false
matrix:
ruby: [3.1, 3.2, 3.3]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
- name: Install dependencies
run: bundle install
- name: Run rubocop
run: bundle exec rake rubocop
- name: Run tests
run: bundle exec rake test
================================================
FILE: .gitignore
================================================
*.gem
*.lock
.DS_Store
================================================
FILE: .rubocop.yml
================================================
AllCops:
TargetRubyVersion: 3.1
Layout/LineLength:
Max: 128
Metrics/MethodLength:
Enabled: false
Metrics/ModuleLength:
Enabled: false
Metrics/ClassLength:
Enabled: false
Metrics/CyclomaticComplexity:
Enabled: false
Metrics/PerceivedComplexity:
Enabled: false
Metrics/AbcSize:
Enabled: false
Metrics/BlockLength:
Enabled: false
Style/Documentation:
Enabled: false
Style/RegexpLiteral:
Enabled: false
# blocked on https://github.com/appium/ruby_lib/issues/312. Already removed from core part
Style/GlobalVars:
Enabled: false
Style/PercentLiteralDelimiters:
Enabled: false
Style/CommentedKeyword:
Enabled: false
Naming/AccessorMethodName:
Enabled: false
Naming/RescuedExceptionsVariableName:
Enabled: false
Layout/HeredocIndentation:
Enabled: false
Layout/RescueEnsureAlignment:
Enabled: false
Layout/HashAlignment:
Enabled: false
Style/ExplicitBlockArgument:
Enabled: false
Style/OptionalBooleanParameter:
Enabled: false
Naming/MethodParameterName:
Enabled: false
Style/KeywordParametersOrder:
Enabled: false
Style/AccessorGrouping:
Enabled: false
Style/StringConcatenation:
Enabled: false
Lint/NonDeterministicRequireOrder:
Enabled: false
Gemspec/DeprecatedAttributeAssignment:
Enabled: true
Layout/LineEndStringConcatenationIndentation:
Enabled: true
Layout/SpaceBeforeBrackets:
Enabled: true
Lint/AmbiguousAssignment:
Enabled: true
Lint/AmbiguousOperatorPrecedence:
Enabled: false
Lint/AmbiguousRange:
Enabled: true
Lint/DeprecatedConstants:
Enabled: true
Lint/DuplicateBranch:
Enabled: true
Lint/DuplicateRegexpCharacterClassElement:
Enabled: true
Lint/EmptyBlock:
Enabled: true
Lint/EmptyClass:
Enabled: false
Lint/EmptyInPattern:
Enabled: true
Lint/IncompatibleIoSelectWithFiberScheduler:
Enabled: true
Lint/LambdaWithoutLiteralBlock:
Enabled: true
Lint/NoReturnInBeginEndBlocks:
Enabled: true
Lint/NumberedParameterAssignment:
Enabled: true
Lint/OrAssignmentToConstant:
Enabled: true
Lint/RedundantDirGlobSort:
Enabled: true
Lint/RequireRelativeSelfPath:
Enabled: true
Lint/SymbolConversion:
Enabled: true
Lint/ToEnumArguments:
Enabled: true
Lint/TripleQuotes:
Enabled: true
Lint/UnexpectedBlockArity:
Enabled: true
Lint/UnmodifiedReduceAccumulator:
Enabled: true
Security/IoMethods:
Enabled: true
Style/ArgumentsForwarding:
Enabled: true
Style/CollectionCompact:
Enabled: true
Style/DocumentDynamicEvalDefinition:
Enabled: true
Style/EndlessMethod:
Enabled: true
Style/HashConversion:
Enabled: false
Style/HashExcept:
Enabled: true
Style/IfWithBooleanLiteralBranches:
Enabled: true
Style/InPatternThen:
Enabled: true
Style/MultilineInPatternThen:
Enabled: true
Style/NegatedIfElseCondition:
Enabled: true
Style/NilLambda:
Enabled: true
Style/NumberedParameters:
Enabled: true
Style/NumberedParametersLimit:
Enabled: true
Style/QuotedSymbols:
Enabled: true
Style/RedundantArgument:
Enabled: true
Style/RedundantSelfAssignmentBranch:
Enabled: true
Style/SelectByRegexp:
Enabled: true
Style/StringChars:
Enabled: true
Style/SwapValues:
Enabled: true
Gemspec/DevelopmentDependencies: # new in 1.44
Enabled: true
Layout/LineContinuationLeadingSpace: # new in 1.31
Enabled: true
Layout/LineContinuationSpacing: # new in 1.31
Enabled: true
Lint/ConstantOverwrittenInRescue: # new in 1.31
Enabled: true
Lint/DuplicateMagicComment: # new in 1.37
Enabled: true
Lint/NonAtomicFileOperation: # new in 1.31
Enabled: false
Lint/RefinementImportMethods: # new in 1.27
Enabled: true
Lint/RequireRangeParentheses: # new in 1.32
Enabled: true
Lint/UselessRescue: # new in 1.43
Enabled: true
Metrics/CollectionLiteralLength: # new in 1.47
Enabled: true
Naming/BlockForwarding: # new in 1.24
Enabled: true
Security/CompoundHash: # new in 1.28
Enabled: true
Style/ArrayIntersect: # new in 1.40
Enabled: true
Style/ComparableClamp: # new in 1.44
Enabled: true
Style/ConcatArrayLiterals: # new in 1.41
Enabled: true
Style/DirEmpty: # new in 1.48
Enabled: true
Style/EmptyHeredoc: # new in 1.32
Enabled: true
Style/EnvHome: # new in 1.29
Enabled: true
Style/FetchEnvVar: # new in 1.28
Enabled: true
Style/FileEmpty: # new in 1.48
Enabled: true
Style/FileRead: # new in 1.24
Enabled: true
Style/FileWrite: # new in 1.24
Enabled: true
Style/MagicCommentFormat: # new in 1.35
Enabled: true
Style/MapCompactWithConditionalBlock: # new in 1.30
Enabled: true
Style/MapToHash: # new in 1.24
Enabled: true
Style/MapToSet: # new in 1.42
Enabled: true
Style/MinMaxComparison: # new in 1.42
Enabled: true
Style/NestedFileDirname: # new in 1.26
Enabled: true
Style/ObjectThen: # new in 1.28
Enabled: true
Style/OperatorMethodCall: # new in 1.37
Enabled: true
Style/RedundantConstantBase: # new in 1.40
Enabled: false
Style/RedundantDoubleSplatHashBraces: # new in 1.41
Enabled: true
Style/RedundantEach: # new in 1.38
Enabled: true
Style/RedundantHeredocDelimiterQuotes: # new in 1.45
Enabled: true
Style/RedundantInitialize: # new in 1.27
Enabled: true
Style/RedundantStringEscape: # new in 1.37
Enabled: true
Gemspec/RequireMFA: # new in 1.23
Enabled: true
Lint/UselessRuby2Keywords: # new in 1.23
Enabled: true
Style/OpenStructUse: # new in 1.23
Enabled: false
Lint/RedundantStringCoercion:
Enabled: false
Gemspec/AddRuntimeDependency: # new in 1.65
Enabled: true
Lint/ConstantReassignment: # new in 1.70
Enabled: true
Lint/DuplicateMatchPattern: # new in 1.50
Enabled: true
Lint/DuplicateSetElement: # new in 1.67
Enabled: true
Lint/HashNewWithKeywordArgumentsAsDefault: # new in 1.69
Enabled: true
Lint/ItWithoutArgumentsInBlock: # new in 1.59
Enabled: true
Lint/LiteralAssignmentInCondition: # new in 1.58
Enabled: true
Lint/MixedCaseRange: # new in 1.53
Enabled: true
Lint/NumericOperationWithConstantResult: # new in 1.69
Enabled: true
Lint/RedundantRegexpQuantifiers: # new in 1.53
Enabled: true
Lint/SharedMutableDefault: # new in 1.70
Enabled: true
Lint/UnescapedBracketInRegexp: # new in 1.68
Enabled: true
Lint/UselessDefined: # new in 1.69
Enabled: true
Lint/UselessNumericOperation: # new in 1.66
Enabled: true
Style/AmbiguousEndlessMethodDefinition: # new in 1.68
Enabled: true
Style/BitwisePredicate: # new in 1.68
Enabled: true
Style/CombinableDefined: # new in 1.68
Enabled: true
Style/DataInheritance: # new in 1.49
Enabled: true
Style/DigChain: # new in 1.69
Enabled: true
Style/ExactRegexpMatch: # new in 1.51
Enabled: true
Style/FileNull: # new in 1.69
Enabled: true
Style/FileTouch: # new in 1.69
Enabled: true
Style/ItAssignment: # new in 1.70
Enabled: true
Style/KeywordArgumentsMerging: # new in 1.68
Enabled: true
Style/MapIntoArray: # new in 1.63
Enabled: true
Style/RedundantArrayConstructor: # new in 1.52
Enabled: true
Style/RedundantCurrentDirectoryInPath: # new in 1.53
Enabled: true
Style/RedundantFilterChain: # new in 1.52
Enabled: true
Style/RedundantInterpolationUnfreeze: # new in 1.66
Enabled: true
Style/RedundantLineContinuation: # new in 1.49
Enabled: true
Style/RedundantRegexpArgument: # new in 1.53
Enabled: true
Style/RedundantRegexpConstructor: # new in 1.52
Enabled: true
Style/ReturnNilInPredicateMethodDefinition: # new in 1.53
Enabled: true
Style/SafeNavigationChainLength: # new in 1.68
Enabled: false
Style/SendWithLiteralMethodName: # new in 1.64
Enabled: true
Style/SingleLineDoEndBlock: # new in 1.57
Enabled: true
Style/SuperArguments: # new in 1.64
Enabled: true
Style/SuperWithArgsParentheses: # new in 1.58
Enabled: true
Style/YAMLFileRead: # new in 1.53
Enabled: true
================================================
FILE: CHANGELOG.md
================================================
# Changelogs
Commit based release not is [release_notes.md](./release_notes.md)
Release tags are https://github.com/appium/ruby_lib/releases .
## [16.2.0] - 2026-04-19
- Define device methods (`lock`, `unlock`, `hide_keyboard`, `push_file`, `pull_file`, `background_app`, `shake`, etc.) natively on `Appium::Driver` via `def_delegators :driver`, replacing the implicit delegation previously set up by `extend ::Appium::Core::Device`. Paves the way for `ruby_lib_core` to drop its static compatibility list (appium/ruby_lib_core#97).
## 16.1.1 - 2025-12-28
- Add deprecated mark for start_logs_broadcast/stop_logs_broadcast to use BiDi instead
## 16.1.0 - 2025-03-37
- Relaxed usable the appium_lib_core deps version to `> 11`
## 16.0.1 - 2025-03-16
- Update appium_lib_core deps version condition
## 16.0.0 - 2025-02-16
- Use `http://127.0.0.1:4723` as the default url destination instead of `http://127.0.0.1:4723/wd/hub`
- `--base-path` in appium server may need to drop the `/wd/hub` if configured
## 15.2.2 - 2024-08-06
- Fix non `app` capability behavior
## 15.2.1 - 2024-08-03
- Fix client side timeout in the default http client
- Bump appium_lib_core 9.2.1+ to apply the fix
## 15.2.0 - 2024-07-20
- Raise defined errors instead of Ruby general errors by appium_lib's own errors
## 15.1.0 - 2024-05-19
- Use appium_lib_core 9.0.0
## 15.0.1 - 2024-04-26
- Bump release module (internal only)
## 15.0.0 - 2024-04-11
- Breaking
- Use appium_lib_core 8.0.0 and up
- Please refer to [the diff](https://github.com/appium/ruby_lib_core/blob/master/CHANGELOG.md#800---2024-03-08) about the details.
- Remove `Appium::MultiTouch` and `Appium::TouchAction`
- `swipe` could use `mobile:swipe`, or w3c actions. Multi-touch actions such as zoom/pinch can be written in w3c actions.
- Please use [w3c actions](https://github.com/appium/ruby_lib/blob/master/docs/w3c.md) instead. Several resources such as [test code in ruby_lib_core](https://github.com/appium/ruby_lib_core/blob/master/test/functional/common_w3c_actions.rb) also would help to check the syntax.
## 14.0.0 - 2024-01-25
- Use appium_lib_core 7.4.0 and up
- Removed deprecated `export_session` and `export_session_path`
- Please get the session id via `driver.session_id` instead
## 13.0.2 - 2024-01-25
- Allow up to appium_lib_core 7.3
## 13.0.1 - 2023-06-19
- Ruby 3.0+ is required
## 12.3.3 - 2023-04-27
### Bug fixes
- Fix start_driver
## 12.2.1 - 2023-04-24
### 1. Enhancements
### 2. Bug fixes
- fixed the `default_wait` value as zero (regression)
`set_wait` will set `0` if no `appium_lib: {wait: 0}` is not given.
### 3. Deprecations
## 12.2.0 - 2022-12-25
### 1. Enhancements
### 2. Bug fixes
### 3. Deprecations
- Defaults to XCUITest modulefor iOS
## 12.1.3 - 2022-12-13
### 1. Enhancements
- Minor internal update
### 2. Bug fixes
### 3. Deprecations
## 12.1.2 - 2022-11-13
### 1. Enhancements
### 2. Bug fixes
- Fix `app` capability handling in parsing a toml file
### 3. Deprecations
## 12.1.1 - 2022-10-19
### 1. Enhancements
### 2. Bug fixes
- Fix undefined `.warning` method call
### 3. Deprecations
## 12.1.0 - 2022-10-11
### 1. Enhancements
- Bump minimal ruby_lib_core version
### 2. Bug fixes
### 3. Deprecations
- Deprecate `Appium::Driver.absolute_app_path`, instead, please set proper `app` capability
- This aims to reduce client side validation as same as other clients.
## 12.0.1 - 2022-04-02
### 1. Enhancements
### 2. Bug fixes
- Fixes `promote_appium_methods`
### 3. Deprecations
## 12.0.0 - 2021-11-06
### 1. Enhancements
- Update ruby_lib_core version from v4 to v5. The change affects this library.
- [Migration from v4 to v5 in ruby_lib_core client](https://github.com/appium/ruby_lib_core#migration-from-v4-to-v5)
- Base Selenium Ruby binding is now v4
- Support only W3C WebDriver spec (and a few Appium specific commands)
- Support Ruby 2.6+
- `element.id` returns the element id instead of `element.ref`
- `element.ref` now returns an array
- Removed `forceMjsonwp` to send only MJSONWP capabilities since Selenium cleint v4 no longer supports MJSONWP
- No longer set default `timeouts` as `0`
- ruby_lib_core will call `/timeouts` endpoint only when `appium_lib: { wait: 5 }` is provided explicitly
- Raises `::Appium::Core::Error::ArgumentError` instead of `ArgumentError` for this library specific argument errors
### 2. Deprecations
- `TouchAction` and `MultiTouch` are deprecated
- Please use W3C actions instead https://github.com/appium/ruby_lib/blob/master/docs/w3c.md
- Other examples
- https://github.com/appium/ruby_lib/pull/909
- https://github.com/appium/ruby_lib_core/blob/master/CHANGELOG.md#deprecations-1
- `launch_app`, `close_app` and `reset` are deprecated. Please read [issues#15807](https://github.com/appium/appium/issues/15807) for more details.
- `activate_app` or a new session request can be alternatives of `launch_app`
- `terminate_app` or close the session request can be alternatives of `close_app`
- Close current session and creating a new session, or `terminate_app` and `launch_app` can be alternatives of `reset`
- Global driver (`$driver`) is `false` by default. Please provide `true` as `Appium::Driver.new(opts, true)` to enable it as previously logged as a deprecation warning message.
## 11.1.0 - 2020-12-29 (11.2.0 is the same as this version)
Support Ruby 3
### 1. Enhancements
### 2. Bug fixes
### 3. Deprecations
- Rename `Appium::Ios::Xcuitest::Guesture#tap` to `Appium::Ios::Xcuitest::Guesture#one_finger_tap` to prevent conflicts with `tap` in Ruby
## 11.0.0 - 2020-12-19
Bump supported Ruby version to 2.4+
[related changes](https://github.com/appium/ruby_lib_core/blob/master/CHANGELOG.md#400---2020-12-19) in ruby_lib_core.
## 10.6.0
### 1. Enhancements
### 2. Bug fixes
### 3. Deprecations
- Remove auto `Pry.config.pager` off
- Please turn it off if you needed. https://github.com/pry/pry/wiki/Customization-and-configuration#Config_pager
## v10.5.0
### 1. Enhancements
- Added `driver.log_event` to post an event
- Added `driver.log_events` to get the events
### 2. Bug fixes
### 3. Deprecations
## v10.4.1
### 1. Enhancements
### 2. Bug fixes
- Fix iOS `page` in native context
### 3. Deprecations
## v10.4.0
### 1. Enhancements
- Add `execute_driver` support
### 2. Bug fixes
- Fix wrong warning message in create session
### 3. Deprecations
## v10.3.1
### 1. Enhancements
### 2. Bug fixes
- Fix `scroll_to` and `scroll_to_exact` for Android [#859](https://github.com/appium/ruby_lib/pull/859)
### 3. Deprecations
## v10.3.0
### 1. Enhancements
- Add `tvOS` support
- Requires Appium 1.13
### 2. Bug fixes
### 3. Deprecations
## v10.2.0
### 1. Enhancements
### 2. Bug fixes
- **Breaking changes**
- `find_element/s_by_image` no longer need arguments except for a file path
- `find_element/s_by_image(file_to_image)` instead of `find_element/s_by_image(file_to_image, match_threshold:, visualize:)`
### 3. Deprecations
## v10.1.0
### 1. Enhancements
### 2. Bug fixes
- `*_exact` methods handle value as case sensitive
- This might break test cases if it calls `*_exact` as case insensitive
### 3. Deprecations
## v10.0.0
This change has a breaking change about implicit wait.
### 1. Enhancements
- **Breaking changes**
- Set implicit wait zero by default following [WebDriver spec in Selenium](https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp)
- The change potentially break your `find_element/s`
- You can wrap it with `wait` method to avoid the error explicitly
- Or you also can configure `wait: 20` as `appium_lib` capability to keep the behaviour
- [Experimental]
- Add `direct_connect` capability
- How to use: `{ caps: {...}, appium_lib: { direct_connect: true }}`
- Read [here](https://github.com/appium/ruby_lib_core/blob/master/CHANGELOG.md#enhancements-1) for more details
### 2. Bug fixes
### 3. Deprecations
## v9.18.0
### 1. Enhancements
- Enhance Espresso automation name adaptation
- Call `xpath` locator strategy instead of `uiautomator` locator strategy in various wrapper methods like `text/s`, `button/s`, etc
- [#884](https://github.com/appium/ruby_lib/pull/844/)
### 2. Bug fixes
### 3. Deprecations
## v9.17.0
### 1. Enhancements
- Add `action` wrapping _ruby_lib_core_ for [W3C actions](https://github.com/appium/ruby_lib_core/blob/master/lib/appium_lib_core/common/base/bridge/w3c.rb#L39)
- Returns `TouchAction.new` if the driver works as _MJSONWP_
### 2. Bug fixes
### 3. Deprecations
- `:offset_x` and `:offset_y` in `TouchAction#swipe` is deprecated in favor of `:end_x` and `:end_y`
- [internal] Remove `check_server_version_xcuitest`
## v9.16.1
### 1. Enhancements
### 2. Bug fixes
- Fix failing Appium version comparison [#836](https://github.com/appium/ruby_lib/issues/836)
### 3. Deprecations
## v9.16.0
### 1. Enhancements
- Introduce `appium_thor` in order to automate release
### 2. Bug fixes
- `:app` can be non-path capability like [Windows](https://github.com/Microsoft/WinAppDriver)
```ruby
{ caps:
{ platformName: :windows,
app: 'Microsoft.WindowsCalculator_8wekyb3d8bbwe!App'
}
} # `:app` is bundle id.
{ caps:
{ platformName: :windows,
app: 'relative/path/to/app'
}
} # `:app` will be alsolute path to the `:app` if the path exists
```
### 3. Deprecations
## v9.15.2
### 1. Enhancements
- Wrap selenium-webdriver apis via `Appium::Driver` through Appium Core Bridge [#827](https://github.com/appium/ruby_lib/pull/827/files)
### 2. Bug fixes
### 3. Deprecations
## v9.15.1
### 1. Enhancements
- [Internal] Use [ruby_lib_core](https://github.com/appium/ruby_lib_core) 2.0
- The change shouldn't affect this version since the change influence `Core.new`.
### 2. Bug fixes
### 3. Deprecations
## v9.15.0
### 1. Enhancements
- Requires `appium_lib_core` 1.9.0+
- Requires `selenium-webdriver 3.14+`
- Support `find_element :image, image` [appium-base-driver#235](https://github.com/appium/appium-base-driver/pull/235)
- Requires Appium1.8.2
- Read [changelog](https://github.com/appium/ruby_lib_core/blob/master/CHANGELOG.md#190---2018-08-05) for more details
- Add `distance` option in `scroll` for XCUITest [#805](https://github.com/appium/ruby_lib/pull/805). Thanks [@saim80](https://github.com/saim80)
### 2. Bug fixes
### 3. Deprecations
## v9.14.3
### 1. Enhancements
- Add Tizen
- Use [ruby_lib_core](https://github.com/appium/ruby_lib_core) 1.8.0
### 2. Bug fixes
### 3. Deprecations
## v9.14.2
### 1. Enhancements
- add `mobile: installCertificate` shortcut for XCUITest
- add `mobile: getContexts` shortcut for XCUITest
- Add `find_element_by_image` and `find_elements_by_image` to handle `ImageElement`
- Read a [PR](https://github.com/appium/ruby_lib/pull/795/files) and [Core](https://github.com/appium/ruby_lib_core/blob/master/CHANGELOG.md#enhancements-1) for more details
- Experimental feature
### 2. Bug fixes
### 3. Deprecations
## v9.14.1
### 1. Enhancements
### 2. Bug fixes
- Fix an initialisation error for iOS with `appium_lib_core 1.7.0` [#785](https://github.com/appium/ruby_lib/issues/785)
### 3. Deprecations
## v9.14.0
### 1. Enhancements
- Breaking changes for `press_keycode` and `long_press_keycode`
- Detail: https://github.com/appium/ruby_lib_core/blob/master/CHANGELOG.md#170---2018-05-28
### 2. Bug fixes
### 3. Deprecations
## v9.13.0
### 1. Enhancements
- Requires `appium_lib_core` 1.6.0+
- Breaking change for `app_state`: https://github.com/appium/ruby_lib_core/blob/master/CHANGELOG.md#160---2018-05-08
### 2. Bug fixes
### 3. Deprecations
## v9.12.1
### 1. Enhancements
- Support `start_logs_broadcast` and `stop_logs_broadcast` for iOS
### 2. Bug fixes
- Back compatible for `wait(number) {}` and `wait_true(number) {}`
### 3. Deprecations
## v9.12.0
### 1. Enhancements
### 2. Bug fixes
### 3. Deprecations
- Changed the name of arguments
- `swipe(start_x:, start_y:, end_x:, end_y:)` instead of `swipe(start_x:, start_y:, offset_x:, offset_y:)`
## v9.11.1
### 1. Enhancements
- Apply `ruby_lib_core ~> 1.4.2`
- Support image comparison features
- http://www.rubydoc.info/gems/appium_lib_core/Appium/Core/Device/ImageComparison
### 2. Bug fixes
- Fix `wait` compatibility for `ruby_lib_core ~> 1.4.1`
### 3. Deprecations
## v9.11.0
### 1. Enhancements
- Add `start_logs_broadcast` and `stop_logs_broadcast` which use WebSocket to get logcat.
- Include https://github.com/appium/ruby_lib_core/blob/master/CHANGELOG.md#140---2018-04-15
### 2. Bug fixes
### 3. Deprecations
## v9.10.0
### 1. Enhancements
- Some changes for Appium 1.8.0
- Read also:
- https://github.com/appium/ruby_lib_core/blob/master/CHANGELOG.md#131---2018-02-14
- https://github.com/appium/ruby_lib_core/blob/master/CHANGELOG.md#130---2018-01-28
### 2. Bug fixes
### 3. Deprecations
## v9.9.2
### 1. Enhancements
- Fix Security Vulnerability(Nokogiri)[#761](https://github.com/appium/ruby_lib/pull/761)
### 2. Bug fixes
### 3. Deprecations
## v9.9.1
### 1. Enhancements
### 2. Bug fixes
- fix `Minitest`'s revert: [URL](http://docs.seattlerb.org/minitest/History_rdoc.html#label-5.11.2+-2F+2018-01-25)
### 3. Deprecations
## v9.9.0
### 1. Enhancements
- Bump the core library to 1.3.0
- The change have one breaking change for `start_recording_screen`(Android)
### 2. Bug fixes
### 3. Deprecations
## v9.8.5
### 1. Enhancements
### 2. Bug fixes
- Fix _Bug: NameError: uninitialized constant Minitest::VERSION [#750](https://github.com/appium/ruby_lib/issues/750)_
### 3. Deprecations
## v9.8.4
### 1. Enhancements
### 2. Bug fixes
- Fix `TypeError: superclass mismatch for class Test` for minitest `5.11.0`+ [PR](https://github.com/appium/ruby_lib/pull/748)
### 3. Deprecations
## v9.8.3
### 1. Enhancements
- Bump the core library to 1.2.5
- The changelog is [here](https://github.com/appium/ruby_lib_core/blob/master/CHANGELOG.md#124---2018-01-03)
### 2. Bug fixes
### 3. Deprecations
## v9.8.2
### 1. Enhancements
- add `shell` command wrapped `mobile: shell` for Android [#732](https://github.com/appium/ruby_lib/pull/732)
- add handling multiple apps for iOS [#729](https://github.com/appium/ruby_lib/issues/729)
- Adapt W3C commands and make sure to work Appium 1.7.2+
- Which module, msjsonwp or w3c, used depends on server side's response.
### 2. Bug fixes
### 3. Deprecations
## v9.8.1
### 1. Enhancements
### 2. Bug fixes
- Fix creating session for the new W3C createSession
- https://github.com/appium/appium/pull/9791
### 3. Deprecations
## v9.8.0
### 1. Enhancements
- Add start/stop recording screen [#674](https://github.com/appium/ruby_lib/issues/674)
- replace core directory to core library [#665](https://github.com/appium/ruby_lib/issues/665), [#718](https://github.com/appium/ruby_lib/pull/718)
- No change for users
### 2. Bug fixes
### 3. Deprecations
- `ap_` prefixed logging
- `source_window`: use `get_source` instead
- `ios_version`: use `platform_version` instead
- `current_app`: use `current_activity`, for example to know current app.
## v9.7.5
### 1. Enhancements
### 2. Bug fixes
- [fix: take care capybara case #716](https://github.com/appium/ruby_lib/pull/716)
### 3. Deprecations
## v9.7.4
### 1. Enhancements
- Add unlock command: [PR](https://github.com/appium/ruby_lib/pull/710/files)
- Be able to call `source` command from any `automationName`
### 2. Bug fixes
### 3. Deprecations
## v9.7.3
### 1. Enhancements
- Get source from XCUITest with `xcuitest_source format: :json`
- https://github.com/appium/ruby_lib/pull/699
- `:espresso` support
### 2. Bug fixes
### 3. Deprecations
## v9.7.2
### 1. Enhancements
- Raise error if capability is wrong
- [validate `caps` and `appium_lib` #684](https://github.com/appium/ruby_lib/issues/684)
### 2. Bug fixes
- `Bug: NoMethodError: undefined method 'write_session_id' for #<Appium::Core::Driver:0x00007fa69119ce88>` [#686](https://github.com/appium/ruby_lib/issues/686)
- undefined local variable or method `patch_webdriver_element' [#687](https://github.com/appium/ruby_lib/issues/687)
### 3. Deprecations
## v9.7.1
Hot-fix for v9.7.0: [uninitialized constant Appium::VERSION #680](https://github.com/appium/ruby_lib/issues/680)
## v9.7.0
_v9.7.0_ has [a bunch of refactoring](https://github.com/appium/ruby_lib/issues/602#issuecomment-331140219) but the behaviours must be the same as well as previous versions.
I've checked the behaviour and confirmed test cases in this repository. So, please create issues if you have any issues against this version.
### 1. Enhancements
- Refactoring
```
lib/appium_lib # root directory
/core # Minumul driver files for the Appium server and dependencies for Selenium Driver.
/common # Appium related(some methods to make ruby_lib useful)
/android # for Android
/ios # for iOS
```
- The `core` directory will separate as the other gem in [separate core as core ruby gem #665](https://github.com/appium/ruby_lib/issues/665)
- Logs
- `get_available_log_types`: To get a list of available log types
- `get_log(type)`: To get logs associated with `type`
### 2. Bug fixes
### 3. Deprecations
- [refactor: Reduce patch_webdriver_element and some DEPRECATIONs #663](https://github.com/appium/ruby_lib/pull/663)
- Remove deprecated methods:
- Android
- `client_xpath/client_xpaths`
- Please use `xpath` or `find_element/s(:xpath, "xpaths")`
- iOS
- `get_page`
- Please use `source` instead
- Deprecated
- iOS
- `ios_version`, `source_window`, `page_window`
- Please use `source` instead
## v9.6.1
### 1. Enhancements
- Refactor `XCUItest` for iOS and `uiautomator2` for Android a bit
### 2. Bug fixes
- missing extending `button` methods for `uiautomator2`, Android
### 3. Deprecations
## v9.6.0
### 1. Enhancements
- Reduce Global Driver
- We'll stop defining global scope driver by default. So, if you'd like to continue to define global scope, please call `start_driver` as the following.
```ruby
Appium::Driver.new(opts, true).start_driver # $driver is defined.
Appium::Driver.new(opts, false).start_driver # $driver isn't defined.
```
- [link](https://github.com/appium/ruby_lib/blob/master/docs/ios_docs.md#initialize)
- We need to provide `driver` to work `TouchAction` and `MultiAction` without global driver
- `TouchAction`
```ruby
driver = Appium::Driver.new(opts, false).start_driver
action = TouchAction.new.press(x: 45, y: 100).wait(5).release
action.perform(driver)
action = TouchAction.new.swipe(....)
action.perform(driver)
```
- `MultiAction`
```ruby
driver = Appium::Driver.new(opts, false).start_driver
pinch 200, true, driver
```
- Add example to run multiple iOS Simulators [doc](https://github.com/appium/ruby_lib/blob/master/docs/ios_xcuitest.md#run-tests-on-multiple-simulators-with-xcode-9)
- Require Xcode 9 and Appium 1.6.6
### 2. Bug fixes
- `scroll_to` is failed on some Android 5.0 and 5.1 devices
- https://github.com/appium/ruby_lib/pull/638
### 3. Deprecations
### Special Thanks
- Fixing `acroll_to`
- [@emen](https://github.com/emen)
- Add alias `quit_driver`
- [@DylanLacey ](https://github.com/DylanLacey)
## v9.5.0
### 1. Enhancements
- Support `selenium-webdriver3.4.1+`
- Support new `createSession`
### 2. Bug fixes
### 3. Deprecations
- Drop `selenium-webdriver` `3.0 ~ 3.4.0` since some methods depends on `selenium-webdriver3.4.1+`
## v9.4.10
### 1. Enhancements
- some refactoring
- add some documentations
### 2. Bug fixes
### 3. Deprecations
## v9.4.9
### 1. Enhancements
### 2. Bug fixes
- fix handling a tap gesture in xcuitest [#611](https://github.com/appium/ruby_lib/pull/611)
### 3. Deprecations
## v9.4.8
### 1. Enhancements
- within_context swallowing block return value [#311](https://github.com/appium/ruby_lib/issues/311)
- get current_package for Android [#604](https://github.com/appium/ruby_lib/issues/604)
- Show visibility on iOS page command [#609](https://github.com/appium/ruby_lib/pull/609)
- related: allow showing all elements on ios page command [#310](https://github.com/appium/ruby_lib/issues/310)
### 2. Bug fixes
### 3. Deprecations
- Android: mark deprecated for client side xpath strategy [#608](https://github.com/appium/ruby_lib/pull/608)
- iOS: get_page method [#609](https://github.com/appium/ruby_lib/pull/609)
## v9.4.7
### 1. Enhancements
### 2. Bug fixes
- fix raise 500 error by `driver.remote_status` in `appium_server_version` [#599](https://github.com/appium/ruby_lib/issues/599)
### 3. Deprecations
## v9.4.6
### 1. Enhancements
### 2. Bug fixes
- reduce gemfile size [#591](https://github.com/appium/ruby_lib/issues/591)
- Exclude `ios_tests`, `android_tests` and `grid` from gem
### 3. Deprecations
## v9.4.5
### 1. Enhancements
- add `touch_and_hols` for `mobile:` command in XCUITest [#581](https://github.com/appium/ruby_lib/pull/581)
- Driver disables Pry pager without asking [#582](https://github.com/appium/ruby_lib/issues/582)
- add grid environments in this repository.
### 2. Bug fixes
### 3. Deprecations
## v9.4.4
### 1. Enhancements
- add mobile gesture, `mobile: alert`
- Required over https://github.com/appium/appium-xcuitest-driver/releases/tag/v2.28.6
- add travis example for ios [#573](https://github.com/appium/ruby_lib/pull/573)
- remove some redundant code [#572](https://github.com/appium/ruby_lib/pull/572), [#571](https://github.com/appium/ruby_lib/pull/571)
- update api-demos [#569](https://github.com/appium/ruby_lib/issues/569)
### 2. Bug fixes
### 3. Deprecations
## v9.4.3
### 1. Enhancements
- Use uiautomator for uiautomator2 [#561](https://github.com/appium/ruby_lib/pull/561)
- improve stability for some methods
- don't use selenium-webdriver 3.5+ [#559](https://github.com/appium/ruby_lib/pull/559)
- Auto link bug # from release notes [#239](https://github.com/appium/ruby_lib/issues/239)
### 2. Bug fixes
### 3. Deprecations
### Special Thanks
- Thanks for checking uiautomator2
- [@Edouard-chin](https://github.com/Edouard-chin), [@rajdeepv](https://github.com/rajdeepv)
## v9.4.2
### 1. Enhancements
### 2. Bug fixes
- fix drag_from_to_for_duration gets server error [#552](https://github.com/appium/ruby_lib/issues/552)
### 3. Deprecations
## v9.4.1
### 1. Enhancements
### 2. Bug fixes
- fix 9.4.0 release sudden failures [#546](https://github.com/appium/ruby_lib/issues/546)
- XPath strategy for find_element/s sudden fail than uiautomator strategy.
- Use `:xpath` strategy only for uiautomator2
### 3. Deprecations
## v9.4.0
### 1. Enhancements
- update mobile gesture APIs for XCUITest(WDA) [#514](https://github.com/appium/ruby_lib/pull/514)
- For XCUITest(WebDriverAgent)
- Users can call some [`mobile:` methods](https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/ios-xctest-mobile-gestures.md) without `execute_script('mobile: tap', args)`.
- Users can write test code without `.ref` method for elements in `execute_script`.
- Example: https://github.com/appium/ruby_lib/pull/537
- Support UIAutomator2 strategy for Android[#505](https://github.com/appium/ruby_lib/issues/505)
- Fix some find elemenet methods[#544](https://github.com/appium/ruby_lib/pull/544)
### 2. Bug fixes
### 3. Deprecations
## v9.3.8
### 1. Enhancements
- allow using TestObject server [#538](https://github.com/appium/ruby_lib/pull/538)
### 2. Bug fixes
### 3. Deprecations
## v9.3.7
### 1. Enhancements
- Remove appium suffix from find element [#532](https://github.com/appium/ruby_lib/pull/532)
- rename `@driver.find_element/s_with_appium` to `@driver.find_element/s`
- fix documentations
### 2. Bug fixes
### 3. Deprecations
- `@driver.find_element/s_with_appium`
- use `@driver.find_element/s` instead
## v9.3.6
### 1. Enhancements
- Add toggle touch id enrollment [#521](https://github.com/appium/ruby_lib/pull/521)
### 2. Bug fixes
### 3. Deprecations
## v9.3.5
### 1. Enhancements
- add some commands for Android and class chain for iOS [#513](https://github.com/appium/ruby_lib/issues/513)
- iOS
- `find_element :class_chain, 'XCUIElementTypeWindow/*/*/XCUIElementTypeStaticText'`
- Android
- `get_system_bars`
- `get_display_density`
- `is_keyboard_shown`
- add scrollable index parameter into scroll methods [#506](https://github.com/appium/ruby_lib/issues/506)
- `scroll_to(text, scrollable_index = 0)`
- `scroll_to_exact(text, scrollable_index = 0)`
- clear `@actions` in Appium::TouchAction if `perform` is called [#511](https://github.com/appium/ruby_lib/issues/511)
### 2. Bug fixes
### 3. Deprecations
## v9.3.4
### 1. Enhancements
- [remove workaround](https://github.com/appium/ruby_lib/pull/474/commits/57cc95264e83e14862f729683b93c1f020a30ce5) to pass CI
- document uiautomator events logging command [#319](https://github.com/appium/ruby_lib/issues/319)
- use predicate for XCUITest to improve performance [#493](https://github.com/appium/ruby_lib/issues/493)
- `text/s`, `button/s`, `textfield/s`, `tags_exact`, `tags_include`
- new: `find_ele/s_by_predicate`, `find_ele/s_by_predicate_include`
### 2. Bug fixes
### 3. Deprecations
## v9.3.3
### 1. Enhancements
- add tags_include/tags_exact to be able to find elements of arbitrary classes such as XCUIElementTypeTextView [#488](https://github.com/appium/ruby_lib/issues/488)
### 2. Bug fixes
### 3. Deprecations
## v9.3.2
### 1. Enhancements
- allow SAUCE_ENDPOINT env var to override sauce server url/path [#485](https://github.com/appium/ruby_lib/pull/485)
- Read [readme](https://github.com/appium/ruby_lib/blob/89c7c89be058153d119d517eab22ccc318d33649/readme.md#sauce-labs-env-vars)'s `SAUCE_ENDPOINT` section.
### 2. Bug fixes
### 3. Deprecations
## v9.3.1
### 1. Enhancements
- Clarify disabling Sauce Labs. [#471](https://github.com/appium/ruby_lib/pull/471)
- add getting performance [#479](https://github.com/appium/ruby_lib/issues/479)
- **require appium-base-driver@2.1.7**
### 2. Bug fixes
- Fix missed var rename [#481](https://github.com/appium/ruby_lib/pull/481)
### 3. Deprecations
## v9.3.0
### 1. Enhancements
- wait / wait_true need global defaults [#250](https://github.com/appium/ruby_lib/issues/250)
- You can set default value in `appium_lib`
- e.g.: [lib/appium_lib/driver.rb](https://github.com/appium/ruby_lib/blob/34803ef6b7b94df9ef4e147ba8fec5c1d2cfaada/lib/appium_lib/driver.rb#L341-L351)
- Problem with delta_x/delta_y in swipe method [#461](https://github.com/appium/ruby_lib/issues/461)
- Revert _fix arguments for `move_to` in `swipe` method._ in Appium v8.2.1
- `delta_x/delta_y` replace to `offset_*` for iOS
- e.g.: `swipe start_x: start_x, start_y: start_y, end_offset_x: 0, offset_y: -100`
- `delta_x/delta_y` replace to `end_*` for Android
- e.g.: `swipe start_x: start_x, start_y: start_y, end_x: start_x, end_y: start_y - 100`
- The reason why there are two kind of arguments is the following issue.
- [Difference behaviour between iOS and Android regarding with `swipe` action #7702](https://github.com/appium/appium/issues/7702)
- Clarify disabling Sauce Labs. #471
- update documentations
### 2. Bug fixes
- REQUIRED_VERSION_XCUITEST [#463](https://github.com/appium/ruby_lib/issues/463)
- find elements except for name attributes in text/s, button/s [#462](https://github.com/appium/ruby_lib/issues/462)
- Return only **visible** elements
- Previously, these methods return **all** elements.
### 3. Deprecations
- Problem with delta_x/delta_y in swipe method [#461](https://github.com/appium/ruby_lib/issues/461)
- `delta_x/delta_y` are replaced to `offset_*` for iOS and `end_*` for Android.
## v9.2.0
### 1. Enhancements
- update set_wait / no_wait logic #249
- `no_wait` just set `implicit_wait = 0`
- `set_wait` just set `@default_wait` or arbitrary time as `implicit_wait`
- remove `last_waits` attribute
### 2. Bug fixes
- automationName always nil if set automationName in server side #450
### 3. Deprecations
## v9.1.3
Support selenium-webdriver 3.0.4+
### 1. Enhancements
- Improve performance for button/s and text/s #442
- Should use `open_timeout` or `read_timeout` instead of `timeout` #436
- add documentation for alternative long_press method #440
### 2. Bug fixes
### 3. Deprecations
## v9.1.2
### 1. Enhancements
- add `appium_client_version`: https://github.com/appium/ruby_lib/issues/260
- add some tests and fix some rubocop syntax errors
### 2. Bug fixes
- fix `set_immediate_value`: https://github.com/appium/ruby_lib/issues/263
### 3. Deprecations
## v9.1.1
### 1. Enhancements
### 2. Bug fixes
- fix Finds exact in ios does not return an array #423
### 3. Deprecations
Thanks @slipy12
## v9.1.0
### 1. Enhancements
- update dependencies
- Support selenium-webdriver 3.0.2+
- If you'd like to use `selenium-webdriver2.x`, please use `appium_lib9.0.0`
### 2. Bug fixes
### 3. Deprecations
- Drop Ruby 1.9.3, 2.0, 2.1 support
- Because these ruby versions have already stop updating.
## v9.0.0
### 1. Enhancements
- Support `XCUITest` strategy for iOS
- Basically, `XCUITest` strategy is compatible with `Appium` strategy in this library.
- But users who use XPath should be check [this document](https://github.com/appium/ruby_lib/blob/master/docs/ios_xcuitest.md) since XPath has performance issue
- Users who use `find_element/s` should work fine.
- tests for elements are [here](https://github.com/appium/ruby_lib/tree/master/ios_tests/lib/ios/specs/ios/element)
Special thanks to @montdidier
### 2. Bug fixes
### 3. Deprecations
## v8.2.1
- fix arguments for `move_to` in `swipe` method.
- https://github.com/appium/ruby_lib/pull/405
- Please set `:delta_x` and `:delta_y` as the distance from start to move.
================================================
FILE: Gemfile
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
source 'https://rubygems.org'
gemspec
gem 'appium_thor', '~> 2.0'
gem 'hashdiff', '~> 1.2.0'
gem 'minitest', '~> 5.0'
gem 'minitest-reporters', '~> 1.1'
gem 'pry'
gem 'rake', '~> 13.0'
gem 'rubocop', '1.86.1'
gem 'yard', '~> 0.9.11'
================================================
FILE: LICENSE-2.0.txt
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: Rakefile
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'bundler/gem_tasks'
require 'rubocop/rake_task'
require 'rake/testtask'
desc 'Execute RuboCop static code analysis'
RuboCop::RakeTask.new(:rubocop) do |t|
t.patterns = %w(lib ios_tests android_tests)
t.options = %w(-D)
t.fail_on_error = true
end
desc('Run all unit tests in test directory')
Rake::TestTask.new(:test) do |t|
t.libs << 'test'
t.libs << 'lib'
t.test_files = FileList[ENV['TESTS'] ? ENV['TESTS'].split(',') : 'test/**/*_test.rb']
end
================================================
FILE: Thorfile
================================================
require 'appium_thor'
Appium::Thor::Config.set do
gem_name 'appium_lib'
github_name 'ruby_lib'
version_file 'lib/appium_lib/version.rb'
end
================================================
FILE: android_tests/Gemfile
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
source 'https://rubygems.org'
eval_gemfile File.join(File.expand_path('..', __dir__), 'Gemfile')
================================================
FILE: android_tests/LICENSE-2.0.txt
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: android_tests/Rakefile
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'rubygems'
require 'rake'
require 'rubocop/rake_task'
task default: :android
# Run sh and ignore exception
def run_sh(cmd)
sh cmd
rescue StandardError
# ignored
end
# Run cmd. On failure run install and try again.
def bash(cmd)
sh cmd do |successful, result|
# exitstatus 7 means bundle install failed
# non-zero (except 7 retry path) means the test failed
if !successful && result.exitstatus == 7
Rake::Task['install'].execute
sh cmd
elsif !successful
raise "Command failed with status #{result.exitstatus}: #{cmd}"
end
end
end
# rake android['single_text_name']
# rake android
def run_android(test_file = nil)
cmd = 'bundle exec ruby ./lib/run.rb android'
cmd = %(#{cmd} "#{test_file}") if test_file
bash cmd
end
# Run a single test with:
# rake android['android/element/generic']
#
# Run all tests with:
# rake android
desc 'Run the Android tests'
task :android, :args, :test_file do |_args, test_file|
run_android test_file[:args]
end
desc 'Run the Android tests without uninstalling'
task :droid, :args, :test_file do |_args, test_file|
run_android test_file[:args]
end
desc 'Run bundle install'
task :install do
sh 'bundle install'
end
desc 'Execute RuboCop static code analysis'
RuboCop::RakeTask.new(:rubocop) do |t|
t.patterns = %w(**/*.rb)
t.options = %w(-D)
t.fail_on_error = false
end
================================================
FILE: android_tests/appium.txt
================================================
[caps]
automationName = "uiautomator2"
platformName = "android"
deviceName = "Android emulator"
app = "../test_apps/api.apk"
appPackage = "io.appium.android.apis"
appActivity = "io.appium.android.apis.ApiDemos"
some_capability = "some_capability"
[appium_lib]
sauce_username = ""
sauce_access_key = ""
================================================
FILE: android_tests/flaky.txt
================================================
android = "lib/android/specs/"
================================================
FILE: android_tests/lib/android/specs/android/element/alert.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[android/element/alert]"
class AndroidTest
class Element
class Alert < Minitest::Test
def open_alert
# trigger the alert
wait { button('OK Cancel dialog with a message').click }
end
def test_01_alert_click
# nav to alert activity
wait { find('app').click }
wait { find('alert').click }
# test
wait { open_alert }
wait { alert_click('OK') }
end
def test_02_alert_accept
wait { open_alert }
wait { alert_accept }
end
def test_03_alert_accept_text
wait { open_alert }
wait { assert_equal alert_accept_text, 'OK' }
wait { alert_accept }
end
def test_04_alert_dismiss
wait { open_alert }
wait { alert_dismiss }
end
def test_05_alert_dismiss_text
wait { open_alert }
# alert dialog button placement changed:
# 'OK Cancel dialog with a long message'
# Android L: 'Something, Cancel, Ok'
# Android 19: 'Cancel, Something, Ok'
wait { assert_equal alert_dismiss_text.downcase, 'cancel' }
wait { alert_dismiss }
# nav to start activity
2.times { back }
end
end
end
end
================================================
FILE: android_tests/lib/android/specs/android/element/button.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[android/element/button]"
class AndroidTest
class Element
class Button < Minitest::Test
def before_first
# nav to buttons activity
wait { find('App').click }
wait { find('Activity').click }
wait { find('Animation').click }
end
def after_last
# nav back to home activity
3.times { back }
end
def fade_in
'Fade in'
end
def test_01_before_first
before_first
end
def test_02_button
# by index
2.times { wait { assert_equal button(1).text.upcase, fade_in.upcase } }
# by name contains
wait { assert_equal button('ade').text.upcase, fade_in.upcase }
end
def test_03_buttons
exp = ['ZOOM IN', 'MODERN ZOOM IN', 'THUMBNAIL ZOOM']
wait { assert_equal buttons('zoom').map(&:text).map(&:upcase), exp }
wait { assert_equal buttons.length, 6 }
end
def test_04_first_button
wait { assert_equal first_button.text.upcase, fade_in.upcase }
end
def test_05_last_button
wait { assert_equal last_button.text.upcase, 'THUMBNAIL ZOOM' }
end
def test_06_button_exact
wait { assert_equal button_exact(fade_in).text.upcase, fade_in.upcase }
end
def test_07_buttons_exact
2.times { wait { assert_equal buttons_exact(fade_in).first.text.upcase, fade_in.upcase } }
end
def test_08_after_last
after_last
end
end
end
end
================================================
FILE: android_tests/lib/android/specs/android/element/generic.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[android/element/generic]"
class AndroidTest
class Element
class Generic < Minitest::Test
def content
'Content'
end
def partial
'tent'
end
def test_01_find_works_before_and_after_get_source
wait { assert_equal find(partial).text, content }
wait { assert_equal get_source.class, String }
wait { assert_equal find(partial).text, content }
end
def test_01_find
wait { assert_equal find(partial).text, content }
end
def test_01_finds
wait { assert_equal finds(partial).first.text, content }
end
def test_01_find_exact
wait { assert_equal find_exact(content).text, content }
end
def test_01_finds_exact
wait { assert_equal finds_exact(content).first.text, content }
end
# scroll_to is broken
def test_01_scroll_to
wait { scroll_to('Views').click }
wait { assert_equal scroll_to('scrollbars').text, 'ScrollBars' }
wait { find('ScrollBars').click }
wait { text('style').click }
wait { assert scroll_to('Developers', 1).text.include? 'What would it take to build a better mobile phone?' }
back
back
# back to start activity
back
end
def test_01_scroll_to_exact
wait { scroll_to('Views').click }
wait { assert_equal scroll_to_exact('ScrollBars').text, 'ScrollBars' }
wait { find('ScrollBars').click }
wait { text('style').click }
back
back
# back to start activity
back
end
end
end
end
================================================
FILE: android_tests/lib/android/specs/android/element/text.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[android/element/text]"
class AndroidTest
class Element
class Text < Minitest::Test
def must_raise_no_element
assert_raises Selenium::WebDriver::Error::NoSuchElementError do
yield
end
end
def test_01_text
wait { assert ['API Demos', "Access'ibility"].include? text(1).text }
wait { assert_equal text('mos').text, 'API Demos' }
end
def test_02_texts
wait { assert_equal texts('i').length, 7 }
wait { assert_equal texts.length, 13 }
end
def test_03_first_text
wait { assert ['API Demos', "Access'ibility"].include? first_text.text }
end
def test_04_last_text
wait { assert ['API Demos', 'Views'].include? last_text.text }
end
def test_05_text_exact
must_raise_no_element { text_exact 'mos' }
# should pass
wait { assert_equal text_exact('API Demos').text, 'API Demos' }
end
def test_06_texts_exact
wait { assert_equal texts_exact('API Demos').length, 1 }
end
end
end
end
================================================
FILE: android_tests/lib/android/specs/android/element/textfield.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[android/element/textfield]"
class AndroidTest
class Element
class TextField < Minitest::Test
def must_raise_no_element
assert_raises Selenium::WebDriver::Error::NoSuchElementError do
yield
end
end
def left
'Left is best'
end
def right
'Right is always right'
end
def before_first
# nav to activity
wait { find('app').click }
wait { find('activity').click }
wait { find('custom title').click }
end
def after_last
# back to start
3.times { back }
end
def test_01_before_test
before_first
end
def test_02_textfield
wait { assert_equal textfield(1).text, left }
wait { assert_equal textfield('right').text, right }
end
def test_03_textfields
wait { assert_equal textfields('right').first.text, right }
wait { assert_equal textfields.length, 2 }
end
def test_04_first_textfield
wait { assert_equal first_textfield.text, left }
end
def test_05_last_textfield
wait { assert_equal last_textfield.text, right }
end
def test_06_textfield_exact
must_raise_no_element { textfield_exact 'zz' }
wait { assert_equal textfield_exact(left).text, left }
end
def test_07_textfields_exact
wait { assert_equal textfields_exact('zz'), [] }
wait { assert_equal textfields_exact(left).first.text, left }
end
def test_08_hide_keyboard
first_textfield.click
hide_keyboard
end
def test_09_after_last
after_last
end
end
end
end
================================================
FILE: android_tests/lib/android/specs/android/helper.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[android/helper]"
class AndroidTest
class Helper < Minitest::Test
def test_01_tags
wait { assert_equal tags('android.widget.TextView').length, 13 }
end
def test_01_get_page_class
# digit values change based on screen size
# larger screens have more elements
act = get_page_class
assert act.split("\n").length >= 5
assert act.include? '13x android.widget.TextView'
if automation_name_is_espresso?
# 13x android.widget.TextView
# 1x android.widget.ActionMenuView
# 1x android.widget.Toolbar
# 1x com.android.internal.widget.ActionBarContainer
# 1x com.android.internal.widget.ActionBarContextView
# 1x android.widget.ListView
# 1x android.widget.FrameLayout
# 1x com.android.internal.widget.ActionBarOverlayLayout
# 1x com.android.internal.policy.DecorView
assert act.include? '1x android.widget.ActionMenuView'
else
assert act.include? '3x android.widget.FrameLayout'
assert act.include? '2x android.view.ViewGroup'
assert act.include? '1x android.widget.ListView'
assert act.include? '1x hierarchy'
end
end
# def test_01_page_class' do # tested by get_page_c
def test_02_get_android_inspect
# line count changes based on screen size
wait { assert get_android_inspect.split("\n").length >= 40 }
end
# def test_01_get_inspect' do # tested by get_android_ins
# def test_01_page' do # tested by get_android_ins
def id_key
'animation_2_instructions'
end
def id_value
'Select an animation:'
end
def test_03_xml_keys
wait do
id_pair = xml_keys id_key
id_pair = id_pair.to_a[0]
assert_equal id_pair.length, 2
assert_equal id_pair.first, id_key
assert_equal id_pair.last, id_value
end
end
def test_04_resolve_id
wait do
str = resolve_id id_key
assert_equal str, id_value
end
end
def test_05_xml_values
wait do
value = xml_values(id_value).first.last
assert_equal value, id_value
end
end
def test_06_find_by_id
wait { find('accessibility').click }
wait { find('accessibility node provider').click }
if automation_name_is_uiautomator2? || automation_name_is_espresso?
wait { text 'Accessibility/Accessibility Node Provider' }
else
# With string.xml
# Only for uiautomator1
wait { id 'accessibility_node_provider' }
end
2.times { back }
end
def test_07_ids
wait { assert_equal ids('android:id/text1').length, 12 }
end
end
end
================================================
FILE: android_tests/lib/android/specs/android/patch.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[android/patch]"
class AndroidTest
class Patch < Minitest::Test
def test_type
# nav to textfield
wait { find('app').click }
wait { find('Search').click }
wait { find('Invoke Search').click }
wait { first_textfield.type 'ok' }
wait { assert_equal first_textfield.text, 'ok' }
# TODO: how to invoke random am start commands?
# nav to start activity
# io.appium.android.apis/io.appium.android.apis.ApiDemos
# keyboard may exist, if it doesn't then an error will raise
ignore { hide_keyboard }
# return to app start
back
wait { find('Invoke Search') }
back
wait { find_exact('Search') }
back
wait { find('app') }
end
end
end
================================================
FILE: android_tests/lib/android/specs/common/device.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[common/device]"
class AndroidTest
class Common
class Device < Minitest::Test
def test_01_get_performance_data_types
expected = %w(batteryinfo cpuinfo memoryinfo networkinfo)
assert_equal get_performance_data_types.sort, expected
assert_equal get_performance_data(
package_name: 'io.appium.android.apis', data_type: 'cpuinfo'
)[0], %w(user kernel)
end
def test_02_start_activity
wait { assert_equal current_activity, '.ApiDemos' }
start_activity(
app_package: 'io.appium.android.apis',
app_activity: '.accessibility.AccessibilityNodeProviderActivity'
)
wait { assert_equal current_activity.include?('Node'), true }
start_activity(
app_package: 'com.android.settings',
app_activity: '.Settings',
app_wait_package: 'com.android.settings',
app_wait_activity: '.Settings'
)
wait { assert_equal current_activity.include?('Settings'), true }
end
def test_03_current_package
start_activity(
app_package: 'io.appium.android.apis',
app_activity: '.accessibility.AccessibilityNodeProviderActivity'
)
wait { assert_equal current_package, 'io.appium.android.apis' }
end
def test_04_app_strings
wait_true { app_strings.key? 'activity_save_restore' }
end
def test_05_press_keycode
# http://developer.android.com/reference/android/view/KeyEvent.html
press_keycode 176
end
def test_06_long_press_keycode
# http://developer.android.com/reference/android/view/KeyEvent.html
long_press_keycode 176
end
end
end
end
================================================
FILE: android_tests/lib/android/specs/common/device_touchaction.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[common/device_touchaction]"
class AndroidTest
class Common
class DeviceTouchAction < Minitest::Test
def test_01_before_test
wait { text('Accessibility') }
end
def test_02_action_chain_press_release
wait do
e = text('Accessibility')
action.click(e).perform
end
wait { text('Custom View') }
back
wait { text_exact 'NFC' }
end
def test_03_action_chain_tap
wait do
e = text('Accessibility')
action.click(e).perform
end
wait { text('Custom View') }
back
wait { text_exact 'NFC' }
end
def test_04_swipe
wait { text('Animation').click }
wait { text_exact('Bouncing Balls').click }
driver.action
.move_to_location(0.75, 0.25).pointer_down(:left)
.move_to_location(0.75, 50)
.release.perform
3.times { back }
wait { text_exact 'NFC' }
end
def test_05_pinch_zoom
wait { text_exact 'NFC' }
wait { text_exact('Graphics').click }
wait { scroll_to('Touch Paint').click }
# multiple action chains
f1 = driver.action.add_pointer_input(:touch, 'finger1')
f1.create_pointer_move(
duration: 0.5, x: 500, y: 800,
origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT
)
f1.create_pointer_down(:left)
f1.create_pause(0.5)
f1.create_pointer_move(
duration: 3, x: 500, y: 700,
origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT
)
f1.create_pointer_up(:left)
f2 = driver.action.add_pointer_input(:touch, 'finger2')
f2.create_pointer_move(
duration: 0.5, x: 500, y: 800,
origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT
)
f2.create_pointer_down(:left)
f1.create_pause(0.5)
f2.create_pointer_move(
duration: 3, x: 500, y: 900,
origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT
)
f2.create_pointer_up(:left)
driver.perform_actions [f1, f2]
wait { text('Graphics/Touch Paint') }
2.times { back }
wait { text_exact 'NFC' }
end
end
end
end
================================================
FILE: android_tests/lib/android/specs/common/element/window.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[common/element/window]"
class AndroidTest
class Common
class Element
class Window < Minitest::Test
def test_window_size
wait do
size = window_size
assert_equal size.width.class, Integer
assert_equal size.height.class, Integer
end
end
end
end
end
end
================================================
FILE: android_tests/lib/android/specs/common/helper.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[common/helper]"
class AndroidTest
class Common
class Helper < Minitest::Test
def wait_opts
{ timeout: 0.2, interval: 0.2 } # max_wait, interval
end
# There's no `must_not_raise` as the opposite of must_raise
# By default code is expected to not raise exceptions.
# must_not_raise is a no-op.
# wait is a success unless an error is raised
# max_wait=0 is infinity to use 0.1
def test_01_wait
# successful wait should not raise error
wait(wait_opts) { true }
wait(wait_opts) { false }
wait(wait_opts) { nil }
# failed wait should error
assert_raises ::Appium::Core::Wait::TimeoutError do
wait(wait_opts) { raise }
end
# regular rescue will not handle exceptions outside of StandardError hierarchy
# must rescue Exception explicitly to rescue everything
assert_raises ::Appium::Core::Wait::TimeoutError do
wait(wait_opts) { raise NoMemoryError }
end
assert_raises ::Appium::Core::Wait::TimeoutError do
wait(timeout: 0.2, interval: 0.0) { raise NoMemoryError }
end
e = assert_raises ArgumentError do
wait_true(invalidkey: 2) { true }
end
assert_equal 'unknown keyword: :invalidkey', e.message
end
def test_02_ignore
# ignore should rescue all exceptions
ignore { true }
ignore { false }
ignore { nil }
ignore { raise }
ignore { raise NoMemoryError }
end
# wait_true is a success unless the value is not true
def test_03_wait_true
# successful wait should not error
wait_true(wait_opts) { true }
# failed wait should error
assert_raises ::Appium::Core::Wait::TimeoutError do
wait_true(wait_opts) { false }
end
assert_raises ::Appium::Core::Wait::TimeoutError do
wait_true(wait_opts) { nil }
end
# raise should error
assert_raises ::Appium::Core::Wait::TimeoutError do
wait_true(wait_opts) { raise }
end
# regular rescue will not handle exceptions outside of StandardError hierarchy
# must rescue Exception explicitly to rescue everything
assert_raises ::Appium::Core::Wait::TimeoutError do
wait_true(wait_opts) { raise NoMemoryError }
end
assert_raises ::Appium::Core::Wait::TimeoutError do
wait_true(timeout: 0.2, interval: 0.0) { raise NoMemoryError }
end
e = assert_raises ArgumentError do
wait_true(invalidkey: 2) { true }
end
assert_equal 'unknown keyword: :invalidkey', e.message
end
def test_04_back
# start page
wait { assert_equal texts.length, 13 }
# nav to new page.
# ele 0 is the title and can't be clicked.
wait { text(2).click }
wait { assert_equal texts.length, 5 }
# go back
back
# start page
wait { find 'NFC' }
end
def test_05_session_id
wait { assert_match(/\h{8}-\h{4}-\h{4}-\h{4}-\h{12}/, session_id) }
end
def test_06_xpath
# Access'ibility is for Espresso
wait { assert ['API Demos', "Access'ibility"].include? xpath('//android.widget.TextView').text }
end
def test_07_xpaths
wait { assert_equal xpaths('//android.widget.TextView').length, 13 }
end
def test_08_ele_index
# Animation is for Espresso
wait { assert %w(Accessibility Animation).include? ele_index('android.widget.TextView', 3).text }
end
def test_09_tags
wait { assert_equal tags('android.widget.TextView').length, 13 }
end
def test_10_first_ele
wait do
# Access'ibility is for Espresso
assert ['API Demos', "Access'ibility"].include? first_ele('android.widget.TextView').text
end
end
def test_11_last_ele
wait do
# "API Demos" is for Espresso
assert ['API Demos', 'Views'].include? last_ele('android.widget.TextView').text
end
end
# def test_01_source' do # tested by get_so
def test_12_get_source
wait do
assert_equal get_source.class, String
end
end
end
end
end
================================================
FILE: android_tests/lib/android/specs/common/patch.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Skip:
# status # status patches are already tested in driver.rb
# execute # debug output for Pry
# rake "android[common/patch]"
class AndroidTest
class Common
class Patch < Minitest::Test
# Attributes are busted in Android.
# Blocked on https://github.com/appium/appium/issues/628
# Android supports exactly two string Attributes
# .name and .text
# https://github.com/appium/appium/blob/ea3450e7f78d1794bab42fa396a387e7b86fd3b3/android/bootstrap/src/io/appium/android/bootstrap/handler/GetAttribute.java#L43
# def test_01_value' do; end # Doesn't work on And
def test_01_element_method_name
wait { assert_equal first_text.text, 'API Demos' }
end
# def test_01_tag_name' do; end # Doesn't work on And
def test_02_element_method_location_rel
wait do
loc = first_text.location_rel($driver)
assert_equal loc.x.class, String
assert_equal loc.y.class, String
end
end
# By default, the webdriver gem will return message instead of origValue
def test_03_common_patch_id_error_message
value = ''
begin
set_wait 0
find_element(:id, 'ok')
rescue StandardError => e
value = e.message
ensure
set_wait 30
end
exp = 'An element could not be located on the page using the given search parameters.'
assert value.start_with? exp
end
def test_04_id_common_patch_success
if automation_name_is_uiautomator2?
wait do
el = text 'text' # <string name="autocomplete_3_button_7">Text</str
assert_equal el.text, 'Text'
end
else
wait do
el = id 'autocomplete_3_button_7' # <string name="autocomplete_3_button_7">Text</string>
assert_equal el.text, 'Text'
end
end
end
def test_05_find_many_elements_by_resource_id
wait do
value = find_elements(:id, 'android:id/text1').length
assert_equal value, 12
end
end
def test_06_find_single_element_by_resource_id
wait do
value = id('android:id/text1').text
assert_equal value, "Access'ibility"
end
end
end
end
end
================================================
FILE: android_tests/lib/android/specs/common/version.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[common/version]"
class AndroidTest
class Common
class Version < Minitest::Test
def test_appium_version
assert_match(/(\d+)\.(\d+).(\d+)/, ::Appium::VERSION)
end
def test_appium_date
assert_match(/(\d+)-(\d+)-(\d+)/, ::Appium::DATE)
end
end
end
end
================================================
FILE: android_tests/lib/android/specs/common/web_context.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Tests specifically for areas where the web_context differs in behaviour
# rake "android[common/web_context]"
class AndroidTest
class Common
class WebContext < Minitest::Test
# appium's context support is broken on android
def test_01_available_contexts
wait_true { available_contexts.include? 'NATIVE_APP' }
end
def test_02_current_context
wait { assert_equal current_context, 'NATIVE_APP' }
end
def undo_setcontext_nav
back
wait { find('WebView') }
back
wait { find 'Views' }
end
def test_03_set_context
wait { scroll_to('Views').click }
wait { scroll_to('WebView').click }
wait_true { !available_contexts.detect { |e| e.start_with?('WEBVIEW') }.nil? }
webview_context = available_contexts.detect { |e| e.start_with?('WEBVIEW') }
if webview_context.nil?
undo_setcontext_nav
raise "No webview context found. contexts are: #{contexts}"
end
wait { set_context webview_context }
wait { assert_equal current_context, webview_context }
# verify inspect within webview works
assert get_android_inspect.split("\n").length >= 3
wait { set_context 'NATIVE_APP' }
wait { assert_equal current_context, 'NATIVE_APP' }
undo_setcontext_nav
end
end
end
end
================================================
FILE: android_tests/lib/android/specs/driver.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'tmpdir'
# rake "android[driver]"
class AndroidTest
class Driver < Minitest::Test
def sauce?
ENV.fetch('UPLOAD_FILE', nil) && ENV.fetch('SAUCE_USERNAME', nil)
end
def test_01_load_settings
appium_txt = File.join(Dir.pwd, 'appium.txt')
parsed = Appium.load_settings file: appium_txt, verbose: true
apk_name = File.basename parsed[:caps][:app]
assert_equal apk_name, 'api.apk'
end
def test_02_attributes_no_wait
no_wait
assert_raises Selenium::WebDriver::Error::NoSuchElementError do
button('zz')
end
set_wait
end
# attr_reader :default_wait, :app_path, :app_name,
# :app_package, :app_activity, :app_wait_activity,
# :sauce_username, :sauce_access_key, :port, :os, :debug
def test_03_attributes_default_wait_attr
set_wait 1
assert_equal default_wait, 1
set_wait # restore default
end
def test_04_attributes_app_path_attr
apk_name = File.basename driver_attributes[:caps][:app]
assert_equal apk_name, 'api.apk'
end
def test_05_attributes_verify_all_attributes
actual = driver_attributes
expected_app = File.absolute_path('../test_apps/api.apk')
expected = {
automation_name: :uiautomator2,
custom_url: 'http://127.0.0.1:4723',
default_wait: 1,
sauce_username: nil,
sauce_access_key: nil,
sauce_endpoint: 'ondemand.saucelabs.com:443/wd/hub',
port: 4723,
device: :android,
debug: true,
listener: nil,
wait_timeout: 30, # default
wait_interval: 0.5 # default
}
# actual[:caps].to_json send to Appium server
caps_with_json = JSON.parse(actual[:caps].to_json)
assert_equal caps_with_json['platformName'], 'android'
assert_equal caps_with_json['app'], expected_app
assert_equal caps_with_json['appPackage'], 'io.appium.android.apis'
assert_equal caps_with_json['appActivity'], 'io.appium.android.apis.ApiDemos'
assert_equal caps_with_json['deviceName'], 'Android emulator'
assert_equal caps_with_json['someCapability'], 'some_capability'
assert_equal actual[:caps][:platformName], 'android'
assert_equal actual[:caps][:app], expected_app
assert_equal actual[:caps][:appPackage], 'io.appium.android.apis'
assert_equal actual[:caps][:appActivity], 'io.appium.android.apis.ApiDemos'
assert !actual[:caps][:deviceName].nil?
assert_equal actual[:caps][:some_capability], 'some_capability'
dup_actual = actual.dup
dup_actual.delete(:caps)
raise "\n\nactual:\n\n: #{dup_actual}expected:\n\n#{expected}" if dup_actual != expected
end
def test_06_driver_class
assert_equal $driver.class, Appium::Driver
end
def absolute_app_path(path)
$driver.class.absolute_app_path(caps: { app: path })
end
def validate_path(path)
assert_equal absolute_app_path(path), path
end
def test_07_absolute_app_path
validate_path 'sauce-storage:some_storage_suffix'
validate_path 'http://www.saucelabs.com'
Dir.mktmpdir do |tmp_dir|
existing_path = File.join(tmp_dir, 'myapp.app')
FileUtils.mkdir_p existing_path
validate_path existing_path
end
# bundle id test
validate_path 'my.bundle.id'
# relative path test
relative_path = File.join __FILE__, ('..' + File::SEPARATOR) * 5, 'test_apps/api.apk'
expected_path = File.expand_path relative_path
assert_equal absolute_app_path(relative_path), expected_path
# invalid path test
assert_equal absolute_app_path('../../does_not_exist.apk'), '../../does_not_exist.apk'
end
def test_08_methods_status
appium_server_version['build'].keys.sort.include? 'version'
end
def test_09_methods_server_version
server_version = appium_server_version['build']['version']
if sauce?
assert_match 'Sauce OnDemand', server_version
else
assert_match(/(\d+)\.(\d+).(\d+)/, server_version)
end
end
def test_10_methods_client_version
client_version = appium_client_version
expected = { version: ::Appium::VERSION }
assert_equal client_version, expected
end
def test_11_methods_restart
set_wait 1 # ensure wait is 1 before we restart.
restart
assert_equal current_activity, '.ApiDemos'
end
def test_12_methods_driver
assert_equal driver.browser, 'unknown'
end
# Skip:
# screenshot # this is slow and already tested by Appium
# driver_quit # tested by restart
# start_driver # tested by restart
# no_wait # posts value to server, it's not stored locally
# set_wait # posts value to server, it's not stored locally
# execute_script # 'mobile: ' is deprecated and plain execute_script unsupported
def test_13_methods_default_wait
set_wait 1
assert_equal default_wait, 1
end
# returns true unless an error is raised
def test_14_methods_exists
assert_equal exists(0, 0) { true }, true
assert_equal exists(0, 0) { raise 'error' }, false
end
# any elements
def test_15_methods_find_elements
wait do
assert_equal find_elements(:class_name, 'android.widget.TextView').length, 13
end
end
# any element
def test_16_methods_find_element
wait do
assert_equal find_element(:class_name, 'android.widget.TextView').class, ::Appium::Core::Element
end
end
# simple integration sanity test to check for unexpected exceptions
def test_17_methods_set_location
set_location latitude: 55, longitude: -72, altitude: 33
rescue Selenium::WebDriver::Error::UnknownError => e
# on android this method is expected to raise with this message when running
# on a regular device, or on genymotion.
# error could be many messages, including:
# ERROR running Appium command: port should be a number or string
# ERROR running Appium command: port should be > 0 and < 65536
raise unless e.message.include?('ERROR running Appium command: port should be')
end
# settings
def test_18_methods_get_settings
assert !get_settings.nil?
end
def test_19_methods_update_settings
update_settings allowInvisibleElements: true
assert_equal get_settings['allowInvisibleElements'], true
end
# Skip: x # x is only used in Pry
end
end
================================================
FILE: android_tests/lib/android/specs/install.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[install]"
class AndroidTest
class Install < Minitest::Test
# To Do: Blocked on https://github.com/appium/appium/issues/3032
def pkg
'io.appium.android.apis'
end
def installed
assert_equal app_installed?(pkg), true
end
def not_installed
assert_equal app_installed?(pkg), false
end
def test_install_uninstall
installed
remove_app 'io.appium.android.apis'
not_installed
install_app caps[:app]
installed
end
# no way to launch apk after it's uninstalled/installed
# blocked on: https://github.com/appium/appium/issues/2969
# launch_app
end
end
================================================
FILE: android_tests/lib/android/specs/sauce_labs.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "android[sauce_labs]"
class AndroidTest
class SauceLabs < Minitest::Test
def test_sauce_settings
opt = {}
sauce_username = 'sauce_name'
sauce_access_key = 'abcdefghijklmn'
sauce_endpoint = 'ondemand.saucelabs.com:443/wd/hub'
opt[:sauce_username] = sauce_username
opt[:sauce_access_key] = sauce_access_key
opt[:sauce_endpoint] = sauce_endpoint
sauce = Appium::SauceLabs.new(opt)
assert_equal sauce.username, sauce_username
assert_equal sauce.access_key, sauce_access_key
assert_equal sauce.endpoint, sauce_endpoint
assert_equal sauce.sauce_server_url?, true
assert_equal sauce.server_url, 'https://sauce_name:abcdefghijklmn@ondemand.saucelabs.com:443/wd/hub'
end
def test_no_sauce_settings
opt = {}
sauce = Appium::SauceLabs.new(opt)
assert_equal sauce.sauce_server_url?, false
assert_equal sauce.server_url, 'http://127.0.0.1:4723/wd/hub'
end
end
end
================================================
FILE: android_tests/lib/format.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# helper code useful for writing and verifying tests using Pry
list = <<-TXT
find
text
texts
name
names
scroll_to
TXT
list.split("\n").each do |method|
puts "t '#{method}' do"
puts
puts 'end'
puts
end
# --
# Format AndroidElementClassMap from
# https://github.com/appium/appium/blob/master/android/bootstrap/src/io/appium/android/bootstrap/AndroidElementClassMap.java
# for ruby_lib android/helper.rb tag_name_to_android
list = <<TXT
map.put("abslist", "AbsListView");
map.put("button", "Button");
TXT
list.split("\n").each do |method|
pair = method.match(/"([^"]+)"[^"]+"([^"]+)"/)
tag = pair[1]
klass = pair[2]
indent = 6
puts "#{' ' * indent}when '#{tag}'"
line2 = "#{' ' * (indent + 2)}prefix '#{klass}'"
# button must translate to both button and image button
# for ruby_lib to find all buttons
line2.concat(", 'ImageButton'") if klass == 'Button'
puts line2
end
# for Pry
# class Object
# def must_equal b
# raise 'not equal' unless self == b
# end
# end
================================================
FILE: android_tests/lib/run.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'rubygems'
require 'minitest/autorun'
require 'minitest/reporters'
require 'minitest'
require 'hashdiff'
require_relative '../../lib/appium_lib'
Appium::Logger.level = ::Logger::ERROR # Show Logger logs only they are error
Minitest::Test.i_suck_and_my_tests_are_order_dependent!
begin
Minitest::Reporters.use! [Minitest::Reporters::ProgressReporter.new]
rescue Errno::ENOENT
# Ignore since Minitest::Reporters::JUnitReporter.new fails in deleting files, sometimes
end
# Run all Android tests:
# ruby run.rb android
# Run only the view album test:
# ruby run.rb ios view_album
def start_driver(caps)
driver = Appium::Driver.new(caps, true)
# Tests expect methods defined on the minispec object
Appium.promote_appium_methods Minitest::Test, driver
# Use bounded HTTP timeouts in tests to avoid CI hangs on stuck requests.
open_timeout = Integer(ENV.fetch('APPIUM_TEST_OPEN_TIMEOUT', '120'))
read_timeout = Integer(ENV.fetch('APPIUM_TEST_READ_TIMEOUT', '300'))
driver.start_driver(open_timeout: open_timeout, read_timeout: read_timeout)
end
dir = File.expand_path(File.join(Dir.pwd, 'lib'))
appium_txt = File.join(Dir.pwd, 'appium.txt')
device = ARGV[0].downcase.strip
devices = %w(android ios)
raise 'Expected android or ios as first argument' unless devices.include? device
one_test = ARGV[1]
test_dir = "/#{device}/"
caps = Appium.load_settings file: appium_txt, verbose: true
caps = if caps[:appium_lib]
appium_lib = caps[:appium_lib]
appium_lib = appium_lib.merge(debug: true) unless appium_lib[:debug]
appium_lib = appium_lib.merge(wait: 1) unless appium_lib[:wait]
caps.merge(appium_lib: appium_lib)
else
caps.merge(appium_lib: { debug: true, wait: 1 })
end
if ENV['LOCAL_PREBUILT_WDA']
caps[:caps][:usePreinstalledWDA] = true
caps[:caps][:prebuiltWDAPath] = ENV['LOCAL_PREBUILT_WDA']
end
trace_files = []
if one_test
if File.exist? one_test
one_test = File.expand_path one_test
else
# ensure ext is .rb
one_test = File.join(File.dirname(one_test),
"#{File.basename(one_test, '.*')}.rb")
one_test = File.join(dir, "#{test_dir}specs/#{one_test}")
end
raise "\nTest #{one_test} does not exist.\n" unless File.exist?(one_test)
start_driver(caps)
# Ruby 3.0 sorts the Dir.glob order
# require support (common.rb)
file_name = File.join dir, "#{test_dir}/*.rb"
Dir.glob(file_name) do |test|
require test
trace_files << test
end
puts "Loading one test: #{one_test}"
require one_test
trace_files << one_test
else
# require all
file_names = File.join(dir, "#{test_dir}**/*.rb")
Dir.glob(file_names) do |test|
# load all tests
trace_files << test
puts " #{File.basename(test, '.*')}"
require test
end
start_driver(caps)
end
trace_files.map! do |f|
f = File.expand_path f
# ensure all traced files end in .rb
f = File.join(File.dirname(f), "#{File.basename(f, '.*')}.rb")
f
end
# Exit after tests.
Minitest.after_run { $driver&.x }
================================================
FILE: android_tests/readme.md
================================================
ruby_lib_android
=====================
ruby_lib's Android tests. Requires `Ruby 2.2+` or better.
- `rake install` Install gems required to run the tests.
- `rake android` Run all tests.
- `rake android['android/element/generic']` Run a single test.
- `arc` Opens the Appium Ruby Console (arc). Enables interactive testing.
- `gem install appium_console` if it's not installed already.
api.apk is from [appium/android-apidemos](https://github.com/appium/android-apidemos)
The way to generate api.apk is described in the repository.
---
```ruby
Finished in 2 mins 57 secs
106 runs, 144 assertions, 0 failures, 0 errors, 0 skips
```
#### Coverage
- apk
- [emma-build](https://github.com/appium/android-apidemos/blob/a20597cb97238bf43c073500444b9428fab53f50/README.md#emma-build-for-testing-code-coverage)
- `appium.txt`
```
[caps]
platformName = "android"
deviceName = "Nexus 7"
app = "../test_apps/api.apk"
appPackage = "io.appium.android.apis"
appActivity = "io.appium.android.apis.ApiDemos"
some_capability = "some_capability"
androidCoverage = 'io.appium.android.apis/io.appium.android.apis.app.LocalSampleInstrumentation'
[appium_lib]
sauce_username = ""
sauce_access_key = ""
```
================================================
FILE: appium_lib.gemspec
================================================
require_relative 'lib/appium_lib/version'
Gem::Specification.new do |s|
s.required_ruby_version = '>= 3.1'
s.name = 'appium_lib'
s.version = Appium::VERSION
s.license = 'Apache-2.0'
s.description = 'Ruby library for Appium.'
s.summary = 'Ruby library for Appium'
s.authors = ['code@bootstraponline.com', 'Kazuaki Matsuo']
s.email = %w(code@bootstraponline.com fly.49.89.over@gmail.com)
s.homepage = 'https://github.com/appium/ruby_lib' # published as appium_lib
s.require_paths = ['lib']
s.add_dependency 'appium_lib_core', '>= 9.2.1', '< 13.0'
s.add_dependency 'nokogiri', '~> 1.8', '>= 1.8.1'
s.add_dependency 'tomlrb', '>= 1.1', '< 3.0'
s.files = `git ls-files`.split("\n").reject { |v| v.match(/\A^(ios_tests|android_tests|grid|test_apps)\/.+/) }
s.metadata['rubygems_mfa_required'] = 'true'
end
================================================
FILE: contributing.md
================================================
# Contributing
For features or bug fixes, please submit a pull request. Ideally there would be a test as well. The remainder of this doc details how to run the tests.
If you'd like to adding new driver commands, please refer to https://github.com/appium/ruby_lib_core
## Tests
- Tests are run against [appium's master branch](https://github.com/appium/appium/blob/master/docs/en/contributing-to-appium/appium-from-source.md)
- The tests are run using the [flaky gem](https://github.com/appium/flaky) on OS X
- The `arc` command can be run from within the `ios_tests` or `android_tests` folder to open an interactive console
### Run iOS tests
iOS tests are run on the iPhone 6 / iOS 9.3 simulator.
- `cd ios_tests`
- `flake 3 ios` - Run all the iOS tests up to 3 times
### Run Android tests
Android tests require running on physical hardware with Android 5.0 (API 21). The emulator is unreliable.
- `cd android_tests`
- `flake 3 android` - Run all the Android tests up to 3 times
## Publishing
0. Ensure you have `~/.gem/credentials` If not run [the following command](http://guides.rubygems.org/make-your-own-gem/) (replace username with your rubygems user)
> $ curl -u username https://rubygems.org/api/v1/api_key.yaml >
~/.gem/credentials; chmod 0600 ~/.gem/credentials
1. Bump the version number: `thor bump` (`bumpy`, `bumpz`)
2. Update `CHANGELOG.md`
3. Generate release note, publish release gem and push the tag to this repository: `thor release`
================================================
FILE: docs/android_uiautomator.md
================================================
# Help debugging
- `adb shell uiautomator events`
- Prints out accessibility events to the console until the connection to the device is terminated
- [URL](https://stuff.mit.edu/afs/sipb/project/android/docs/tools/help/uiautomator/index.html)
- **notice**
- If Appium is started then it terminates the other `uiautomator` processes
# uiautomator2
## difference between uiautomator1 and uiautomator2
- `find_element/s :id, "ids"`
- uiautomator1
- Find elements with `resource_id`
- Find elements with string id resource(string.xml based)
- uiautomator2
- Find elements with `resource_id`
- from: Does not appium-uiautomator2-server support finding string ids with "id" strategy? [issue](https://github.com/appium/appium/issues/8349)
================================================
FILE: docs/docs.md
================================================
# Documentation
## API Doc of Ruby Client
- This library: http://www.rubydoc.info/github/appium/ruby_lib
- Core: http://www.rubydoc.info/github/appium/ruby_lib_core
- [Ruby selenium-webdriver](https://github.com/SeleniumHQ/selenium/wiki/Ruby-Bindings)
### General
- [Appium](https://github.com/appium/appium/blob/master/README.md)
- [Supported platforms](https://github.com/appium/appium/blob/master/docs/en/about-appium/platform-support.md)
- [All methods supported by Appium](https://github.com/appium/appium-base-driver/blob/master/docs/mjsonwp/protocol-methods.md)
- Fundamental Commands: http://appium.io/docs/en/commands/status/ etc
- [MiniTest Expectations](http://docs.seattlerb.org/minitest/Minitest/Expectations.html)
### Driver types in Ruby Client
```ruby
# Appium specific driver with helpers available extending Standard Appium Driver.
@appium_driver = Appium::Driver.new @options, false
# Standard Appium Driver extends Selenium WebDriver.
@selenium_driver = @appium_driver.start_driver
```
### Example
Example of automating the built in Android settings.
```ruby
# run Pry, and paste the following
apk = {
platformName: 'android',
deviceName: :nexus,
appPackage: 'com.android.settings',
appActivity: '.Settings',
appWaitActivity: '.Settings'
}
Appium::Driver.new({caps: apk}, false).start_driver
```
Example use of Appium's mobile gesture.
Long click on an ImageView in Android.
```
last_image = find_elements(:class, 'ImageView').last
long_press(element: last_image)
```
Rotate examples. The behaviour is depends on devices.
```ruby
driver.rotate :landscape
driver.rotate :portrait
```
- `appium_server_version` Discover the Appium rev running on the server.
- `element.send_keys "msg"` Sends keys to currently active element
### APIs
```ruby
e.name # button, text
e.value # secure, textfield
e.type 'some text' # type text into textfield
e.clear # clear textfield
e.tag_name # calls .type (patch.rb)
e.text
e.size
e.location
e.location_rel
e.click
e.send_keys 'keys to send'
e.displayed? # true or false depending if the element is visible
e.selected? # is the tab selected?
e.attribute('checked') # is the checkbox checked?
# alert example without helper methods
alert = @driver.switch_to.alert
alert.text
alert.accept
alert.dismiss
# Secure textfield example.
#
# Find using default value
s = textfield 'Password'
# Enter password
s.send_keys 'hello'
# Check value
s.value == ios_password('hello'.length)
```
--
#### Driver
- `start_driver` will restart the driver.
- `x` will quit the driver and exit Pry.
- `execute_script` calls `@driver.execute_script`
- `find_element` calls `@driver.find_element`
- `find_elements` calls `@driver.find_elements`
- `no_wait` will set implicit wait to 0. `@driver.manage.timeouts.implicit_wait = 0`
- `set_wait` will set implicit wait to default seconds. `@driver.manage.timeouts.implicit_wait = default`
- `set_wait(timeout_seconds)` will set implicit wait to desired timeout. `@driver.manage.timeouts.implicit_wait = timeout`
- `.click` to tap an element.
- `.send_keys` or `.type` to type on an element.
#### Cucumber Sauce Integration
Reset after each test and when done report the result to Sauce after quiting the driver.
```ruby
require 'rest_client' # https://github.com/archiloque/rest-client
require 'json' # for .to_json
require 'sauce_whisk'
After do |scenario|
# end the test session, ignoring any exceptions.
ignore { $driver.driver_quit }
user = ENV['SAUCE_USERNAME']
key = ENV['SAUCE_ACCESS_KEY']
if user && !user.empty? && key && !key.empty?
passed = ! scenario.failed?
SauceWhisk::Jobs.change_status $driver.driver.session_id, passed
end
end
```
================================================
FILE: docs/ios_xcuitest.md
================================================
## XCUITest
- Over Appium1.6.0 provides `XCUITest` automation name based on WebDriverAgent.
- [appium-xcuitest-driver](https://github.com/appium/appium-xcuitest-driver)
- [WebDriverAgent](https://github.com/facebook/WebDriverAgent)
- How to migrate XCUITest from UIAutomation
- [Migrating your iOS tests from UIAutomation](https://github.com/appium/appium/blob/v1.6.2/docs/en/advanced-concepts/migrating-to-xcuitest.md)
- Mobile gestures for XCUITest
- [ios-xctest-mobile-gestures](https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/ios/ios-xctest-mobile-gestures.md)
- Required Appium1.6.4+
## find elements
- supported elements by find_element are:
- [appium-xcuitest-driver](https://github.com/appium/appium-xcuitest-driver/blob/master/lib/commands/find.js#L17)
- [locatorStrategies](https://github.com/appium/appium-xcuitest-driver/blob/95886f1118d71fe950768f8262179d3608b40fc7/lib/driver.js#L81)
- [WebDriverAgent](https://github.com/facebook/WebDriverAgent/blob/8346199212bffceab24192e81bc0118d65132466/WebDriverAgentLib/Commands/FBFindElementCommands.m#L111)
- Mapping
- https://github.com/facebook/WebDriverAgent/blob/master/WebDriverAgentLib/Utilities/FBElementTypeTransformer.m#L19
### with except for XPath and Predicate
#### examples
- [button_class](https://github.com/appium/ruby_lib/blob/master/lib/appium_lib/ios/element/button.rb#L8), [static_text_class](https://github.com/appium/ruby_lib/blob/master/lib/appium_lib/ios/element/text.rb#L8), [text_field_class](https://github.com/appium/ruby_lib/blob/master/lib/appium_lib/ios/element/textfield.rb#L10) and [secure_text_field_class](https://github.com/appium/ruby_lib/blob/master/lib/appium_lib/ios/element/textfield.rb#L15) provide class name.
- If `automationName` is `Appium` or `nil`, then they provide `UIAxxxx`
- If `automationName` is `XCUITest`, then they provide `XCUIElementTypexxx`
```ruby
find_element(:class, button_class) # Return a element of XCUIElementTypeButton for XCUITest
```
- [tag/s](https://github.com/appium/ruby_lib/blob/ac03116756a72fbd624fa32ea886123b955d7089/lib/appium_lib/android/helper.rb#L238) is alias of `find_element :class, element`
- `accessibility_id`
```ruby
find_element(:accessibility_id, element) # Return a element which has accessibilityIdentifier, `element`.
```
- `button/s(value)`, `button_exact/buttons_exact`, `text/s(value)`, `text_exact/texts_exact`
```ruby
buttons(value) # Return button elements include `value` as its name attributes.
```
### with Predicate
- We recommend to use predicate strategy instead of XPath strategy.
- e.g. `find_ele_by_predicate/find_eles_by_predicate`, `find_ele_by_predicate_include/find_eles_by_predicate_include`
- A helpful cheatsheet for predicate
- https://realm.io/news/nspredicate-cheatsheet/
- For XCUITest(WebDriverAgent), without 'wd' prefixes are supported.
- https://github.com/facebook/WebDriverAgent/wiki/Queries
- For example, `%(name ==[c] "#{value}" || label ==[c] "#{value}" || value ==[c] "#{value}")` is equal to `%(wdName ==[c] "#{value}" || wdLabel ==[c] "#{value}" || wdValue ==[c] "#{value}")` in WebDriverAgent.
#### examples
- `textfield/s(value)`, `find/s`, `find_exact/finds_exact`, `find_ele_by_predicate/find_eles_by_predicate` and `find_ele_by_predicate_include/find_eles_by_predicate_include` use predicate strategy in their method.
```ruby
textfield(value) # Return a XCUIElementTypeSecureTextField or XCUIElementTypeTextField element which has `value` text.
finds_exact(value) # Return any elements include `value` as its name attributes.
```
### with Class Chain
- require Appium 1.6.4+
- https://github.com/appium/appium-xcuitest-driver/pull/391
- https://github.com/appium/java-client/pull/599/files
- WebDriverAgent
- https://github.com/facebook/WebDriverAgent/wiki/Queries
### with XPath
- It is better to avoid XPath strategy.
- https://github.com/appium/appium/blob/v1.6.2/docs/en/advanced-concepts/migrating-to-xcuitest.md#xpath-locator-strategy
- > Try not to use XPath locators unless there are absolutely no other alternatives. In general, XPath locators might be times slower, than other types of locators like accessibility id, class name and predicate (up to 100 times slower in some special cases). They are so slow because XPath location is not natively supported by Apple's XCTest framework.
- Improved performance a bit
- https://github.com/appium/appium/issues/6842
- https://github.com/facebook/WebDriverAgent/issues/306
- XPath in WebDriverAgent
- https://github.com/facebook/WebDriverAgent/blob/2158a8d0f305549532f1338fe1e4628cfbd53cd9/WebDriverAgentLib/Categories/XCElementSnapshot%2BFBHelpers.m#L57
#### examples
```ruby
xpaths("//some xpaths")
```
## Gesture
- `mobile:` commands are provided by WDA.
- Documentations
- https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/ios/ios-xctest-mobile-gestures.md
- Specs by test code
- https://github.com/appium/appium-xcuitest-driver/blob/master/test/functional/basic/gesture-e2e-specs.js
### Workaround
- `mobile:` commands depends on WDA and Apple's framework and the behaviour depends on them.
- Sometimes issues occur such as "doubleTap isn't tapping #548"
- workaround for it:
- with `selenium-webdriver >= 3.4.0`
```ruby
def double_tap(element)
rect = element.rect
execute_script 'mobile: doubleTap', x: rect.x + rect.width / 2, y: rect.y + rect.height / 2
end
```
- with `selenium-webdriver < 3.4.0`
```ruby
def double_tap(element)
size = element.size
location = element.location
execute_script 'mobile: doubleTap', x: location.x + size.width / 2, y: location.y + size.height / 2
end
```
## Other actions
Basically, other actions such as `type` are compatible with `automationName = Appium`.
## Pasteboard
- Simulator only
- https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/ios-xctest-pasteboard.md
================================================
FILE: docs/parallel.md
================================================
Appium 1.7.0+ supports single server and multiple sessions, and it requires Xcode 9 for iOS.
# Example
## Run tests on Multiple Simulators with Xcode 9
- https://github.com/appium/appium-xcuitest-driver/tree/master/test/functional/parallel
- https://github.com/appium/ruby_lib/tree/master/ios_tests/parallel
- Thread programming: TestParallelRunThread
- Process programming: TestParallelRunProcess
================================================
FILE: docs/w3c.md
================================================
Perform touch actions for W3C module. Generate `touch` pointer action here and users can use this via `driver.action`
[Documentation](http://www.rubydoc.info/github/appium/ruby_lib_core/Appium%2FCore%2FBase%2FCoreBridgeW3C:action)
# Example
```ruby
dialect #=> :w3c
# then
el = find_element(:name, 'Pickers')
driver.action.click(el).perform #=> work
# Scroll/Swipe
driver.action
.move_to_location(500, 500).pointer_down(:left)
.move_to_location(0, 700)
.release.perform
# Zoom in
# multiple action chains
f1 = driver.action.add_pointer_input(:touch, 'finger1')
f1.create_pointer_move(duration: 1, x: 200, y: 500,
origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
f1.create_pointer_down(:left)
f1.create_pause(0.5)
f1.create_pointer_move(duration: 1, x: 200, y: 200,
origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
f1.create_pointer_up(:left)
f2 = driver.action.add_pointer_input(:touch, 'finger2')
f2.create_pointer_move(duration: 1, x: 200, y: 500,
origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
f2.create_pointer_down(:left)
f2.create_pause(0.5)
f2.create_pointer_move(duration: 1, x: 200, y: 800,
origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
f2.create_pointer_up(:left)
driver.perform_actions [f1, f2]
```
# Note
## Coordinate points
- jsonwp
- Relative action coordinates are counted relatively to the **top left point** of element's rectangle
- W3C
- Relative action coordinates are counted relatively to the **center** of element's rectangle
## Limitations
- WebDriverAgent support only `touch` as a `pointer type`.
- By default, [ruby_lib_core](https://github.com/appium/ruby_lib_core/blob/ab5d7c5ed31f318a9395e5aeafe1d0d655d3cff4/lib/appium_lib_core/common/base/w3c_bridge.rb#L26) generate `touch` based actions.
- About `pointer type` => [W3C](https://www.w3.org/TR/webdriver/#perform-actions) and [Simple WD Spec](https://github.com/jlipps/simple-wd-spec#perform-actions)
================================================
FILE: grid/README.md
================================================
# Run Grid
```bash
$ java -jar selenium-server-standalone-2.53.1.jar -role hub -hubConfig hub_config.json
```
**note**
Selenium Grid 3.4.0 is failed to establish sessions:
# Run Appium
```bash
$ node . --nodeconfig ~/GitHub/ruby_lib/grid/config.json
# or
$ appium --nodeconfig ~/GitHub/ruby_lib/grid/config.json
```
# Run Ruby Script
```bash
$ rake ios # for example
```
================================================
FILE: grid/appium.txt.ios.example
================================================
[caps]
platformName = "ios"
platformVersion = "11.4"
deviceName ="iPhone 11"
automationName = 'XCUITest'
app = "/absolute/path/to/UICatalog.app.zip"
some_capability = "some_capability"
[appium_lib]
server_url = "http://localhost:4444/wd/hub"
sauce_username = ""
sauce_access_key = ""
sauce_endpoint = ""
wait = 30
wait_timeout = 20
wait_interval = 1
================================================
FILE: grid/config.json
================================================
{
"capabilities":
[
{
"browserName": "iPhone 11",
"version":"11.4",
"platform":"ios",
"maxInstances": 1
}
],
"configuration":
{
"cleanUpCycle": 2000,
"timeout": 60000,
"proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
"url": "http://localhost:4723",
"host": "localhost",
"port": 4723,
"maxSession": 1,
"register": true,
"registerCycle": 5000,
"hubPort": 4444,
"hubHost": "localhost"
}
}
================================================
FILE: grid/hub_config.json
================================================
{
"port": 4444,
"newSessionWaitTimeout": -1,
"servlets" : [],
"withoutServlets": [],
"custom": {},
"capabilityMatcher": "org.openqa.grid.internal.utils.DefaultCapabilityMatcher",
"throwOnCapabilityNotPresent": true,
"cleanUpCycle": 5000,
"role": "hub",
"debug": false,
"browserTimeout": 0,
"timeout": 1800
}
================================================
FILE: grid/hub_config_3.json
================================================
{
"capabilities":
[
{
"browserName": "iPhone 11",
"version":"11.4",
"maxInstances": 1,
"seleniumProtocol": "WebDriver"
}
],
"proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
"maxSession": 5,
"port": 4444,
"register": true,
"registerCycle": 5000,
"hub": "http://localhost:4444",
"nodeStatusCheckTimeout": 5000,
"nodePolling": 5000,
"role": "hub",
"unregisterIfStillDownAfter": 60000,
"downPollingLimit": 2,
"debug": true,
"servlets" : [],
"withoutServlets": [],
"custom": {}
}
================================================
FILE: ios_tests/Gemfile
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
source 'https://rubygems.org'
eval_gemfile File.join(File.expand_path('..', __dir__), 'Gemfile')
gem 'parallel_tests'
================================================
FILE: ios_tests/LICENSE-2.0.txt
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: ios_tests/Rakefile
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'rubygems'
require 'rake'
require 'rubocop/rake_task'
task default: :ios
# Run sh and ignore exception
def run_sh(cmd)
sh cmd
rescue StandardError
# Ignored
end
# Run cmd. On failure run install and try again.
def bash(cmd)
sh cmd do |successful, result|
# exitstatus 7 means bundle install failed
# non-zero (except 7 retry path) means the test failed
if !successful && result.exitstatus == 7
Rake::Task['install'].execute
sh cmd
elsif !successful
raise "Command failed with status #{result.exitstatus}: #{cmd}"
end
end
end
# Run a single test with:
# rake ios['ios/element/generic']
#
# rake ios['driver']
#
# Run all tests with:
# rake ios
desc 'Run the iOS tests'
task :ios, :args, :test_file do |_args, test_file|
# rake android['ok']
# args = android
# test_file = {:args=>"ok"}
test_file = test_file[:args]
cmd = 'bundle exec ruby ./lib/run.rb ios'
cmd = %(#{cmd} "#{test_file}") if test_file
bash cmd
end
desc 'Run bundle install'
task :install do
sh 'bundle install'
end
desc 'Execute RuboCop static code analysis'
RuboCop::RakeTask.new(:rubocop) do |t|
t.patterns = %w(**/*.rb)
t.options = %w(-D)
t.fail_on_error = false
end
class Device
def self.one
{
automationName: 'xcuitest',
platformName: 'ios',
platformVersion: '11.0',
deviceName: 'iPhone 6',
app: "#{Dir.pwd}/../test_apps/UICatalog.app.zip",
wdaLocalPort: 8100,
isCommandsQueueEnabled: false
}
end
def self.two
{
automationName: 'xcuitest',
platformName: 'ios',
platformVersion: '11.0',
deviceName: 'iPhone 6s',
app: "#{Dir.pwd}/../test_apps/UICatalog.app.zip",
wdaLocalPort: 8200,
isCommandsQueueEnabled: false
}
end
end
desc 'Run tests with parallel thread'
task :run_parallel_t do
require_relative 'parallel/test'
threads = []
[Device.one, Device.two].map do |capability|
threads << Thread.new do
TestParallelRunThread.new(capability).test_run
end
end
threads.each(&:join)
end
desc 'Run tests with parallel processes'
task :run_parallel_p do
require_relative 'parallel/test'
[Device.one, Device.two].each do |capability|
fork do
TestParallelRunProcess.new(capability).test_run
end
end
Process.waitall
end
================================================
FILE: ios_tests/appium.txt
================================================
[caps]
platformName = "ios"
platformVersion = "18.5"
deviceName ="iPhone 16 Plus"
automationName = 'XCUITest'
app = "../test_apps/UICatalog.app.zip"
someCapability = "some_capability"
simulatorStartupTimeout = 600000
wdaLaunchTimeout = 600000
[appium_lib]
wait = 30
wait_timeout = 20
wait_interval = 1
================================================
FILE: ios_tests/data/unicode.txt
================================================
®
================================================
FILE: ios_tests/flaky.txt
================================================
ios = "lib/ios/specs/"
================================================
FILE: ios_tests/lib/common.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# common methods
def back_click
back
end
def leave_textfields
back_click
assert screen == catalog
end
def go_to_textfields
assert screen == catalog
wait_true do
find_element(:name, 'Text Fields').click
screen == 'Text Fields' # wait for screen transition
end
end
def screen
$driver.find_element(:class, ui_ios.navbar).name
end
def catalog
'UICatalog'
end
def target_bundle_id
'com.example.apple-samplecode.UICatalog'
end
def ui_ios
UI.new($driver)
end
class UI
def initialize(driver)
@driver = driver
end
def navbar
'XCUIElementTypeNavigationBar'
end
def button
'XCUIElementTypeButton'
end
def static_text
'XCUIElementTypeStaticText'
end
def text_field
'XCUIElementTypeTextField'
end
def secure_text_field
'XCUIElementTypeSecureTextField'
end
def picker
'XCUIElementTypePicker'
end
def picker_wheel
'XCUIElementTypePickerWheel'
end
def action_sheet
'XCUIElementTypeActionSheet'
end
def table
'XCUIElementTypeTable'
end
def table_cell
'XCUIElementTypeCell'
end
def other
'XCUIElementTypeOther'
end
def status_bar
'XCUIElementTypeStatusBar'
end
end
================================================
FILE: ios_tests/lib/format.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# helper code useful for writing and verifying tests using Pry
list = <<TXT
alert_click
alert_text
alert_accept
alert_accept_text
alert_dismiss
alert_dismiss_text
TXT
list.split("\n").each do |method|
puts "t '#{method}' do"
puts
puts 'end'
puts
end
# for Pry
# class Object
# def must_equal b
# raise 'not equal' unless self == b
# end
# end
================================================
FILE: ios_tests/lib/ios/specs/common/element/window.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "ios[common/element/window]"
class IosTest
class Common
class Element
class Window < Minitest::Test
def before_first
driver.terminate_app target_bundle_id
driver.activate_app target_bundle_id
assert_equal screen, catalog
end
def test_01_before_first
before_first
end
def test_02_window_size
size = window_size
assert_equal size.width.class, Integer
assert_equal size.height.class, Integer
end
end
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/common/helper.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "ios[common/helper]"
class IosTest
class Common
class Helper < Minitest::Test
def setup
@wait_opts = { timeout: 0.2, interval: 0.2 } # max_wait, interval
end
def test_01_before_first
driver.terminate_app target_bundle_id
driver.activate_app target_bundle_id
assert_equal screen, catalog
end
# There's no `must_not_raise` as the opposite of must_raise
#
# By default code is expected to not raise exceptions.
# must_not_raise is a no-op.
# wait is a success unless an error is raised
# max_wait=0 is infinity to use 0.1
def test_02_wait
# successful wait should not raise error
wait(@wait_opts) { true }
wait(@wait_opts) { false }
wait(@wait_opts) { nil }
# failed wait should error
assert_raises ::Appium::Core::Wait::TimeoutError do
wait(@wait_opts) { raise }
end
# regular rescue will not handle exceptions outside of StandardError hierarchy
# must rescue Exception explicitly to rescue everything
assert_raises ::Appium::Core::Wait::TimeoutError do
wait(@wait_opts) { raise NoMemoryError }
end
assert_raises ::Appium::Core::Wait::TimeoutError do
wait(timeout: 0.2, interval: 0.0) { raise NoMemoryError }
end
e = assert_raises ArgumentError do
wait(invalidkey: 2) { true }
end
assert_equal 'unknown keyword: :invalidkey', e.message
end
def test_03_ignore
# ignore should rescue all exceptions
ignore { true }
ignore { false }
ignore { nil }
ignore { raise }
ignore { raise NoMemoryError }
end
# wait_true is a success unless the value is not true
def test_04_wait_true
# successful wait should not error
wait_true(@wait_opts) { true }
# failed wait should error
assert_raises ::Appium::Core::Wait::TimeoutError do
wait_true(@wait_opts) { false }
end
assert_raises ::Appium::Core::Wait::TimeoutError do
wait_true(@wait_opts) { nil }
end
# raise should error
assert_raises ::Appium::Core::Wait::TimeoutError do
wait_true(@wait_opts) { raise }
end
# regular rescue will not handle exceptions outside of StandardError hierarchy
# must rescue Exception explicitly to rescue everything
assert_raises ::Appium::Core::Wait::TimeoutError do
wait_true(@wait_opts) { raise NoMemoryError }
end
assert_raises ::Appium::Core::Wait::TimeoutError do
wait_true(timeout: 0.2, interval: 0.0) { raise NoMemoryError }
end
e = assert_raises ArgumentError do
wait_true(invalidkey: 2) { true }
end
assert_equal 'unknown keyword: :invalidkey', e.message
end
def test_06_back
# start page
assert_equal tag(ui_ios.navbar).name, 'UICatalog'
# nav to new page.
wait_true do
text('buttons').click
tag(ui_ios.navbar).name == 'Buttons'
end
assert_equal tag(ui_ios.navbar).name, 'Buttons'
# go back
back_click
# start page
assert_equal tag(ui_ios.navbar).name, 'UICatalog'
end
def test_07_session_id
# Sauce doesn't return '-' so make them optional.
assert_match(/\h{8}-?\h{4}-?\h{4}-?\h{4}-?\h{12}/, session_id)
end
def test_08_xpath
assert_equal xpath("//#{ui_ios.static_text}").name, 'UICatalog'
end
def test_09_xpaths
assert_equal xpaths("//#{ui_ios.static_text}").length, 35
end
def uibutton_text
'Buttons'
end
def action_sheets
'Action Sheets'
end
def test_10_ele_index
assert_equal ele_index(ui_ios.static_text, 2).name, action_sheets
end
# TODO: 'string_attr_exact'
def test_11_find_ele_by_attr
el_id = find_ele_by_attr(ui_ios.static_text, 'name', uibutton_text).instance_variable_get :@id
assert_match(/\d+/, el_id)
end
def test_12_find_eles_by_attr
# '!' clears the input buffer in Pry so make sure there's
# no space after the !
set_wait 1
# empty array returned when no match
found = !find_eles_by_attr(ui_ios.static_text, 'name', uibutton_text).empty?
assert_equal found, true
found = !find_eles_by_attr(ui_ios.static_text, 'name', 'zz').empty?
assert_equal found, false
set_wait
end
def test_13_find_ele_by_predicate
el_text = find_ele_by_predicate(value: uibutton_text).text
assert_equal el_text, uibutton_text
el_name = find_ele_by_predicate(value: uibutton_text).name
assert_equal el_name, uibutton_text
end
def test_14_find_eles_by_predicate
ele_count = find_eles_by_predicate(value: uibutton_text).length
assert_equal ele_count, 1
ele_count = find_eles_by_predicate(value: 'zz').length
assert_equal ele_count, 0
end
# TODO: 'string_attr_include'
def test_15_find_ele_by_attr_include
el_text = find_ele_by_attr_include(ui_ios.static_text, :name, 'button').text
assert_equal el_text, uibutton_text
el_name = find_ele_by_attr_include(ui_ios.static_text, :name, 'button').name
assert_equal el_name, uibutton_text
end
def test_16_find_eles_by_attr_include
ele_count = find_eles_by_attr_include(ui_ios.static_text, :name, 'e').length
assert_equal ele_count, 31
end
def test_17_find_ele_by_predicate_include
el_text = find_ele_by_predicate_include(value: 'button').text
assert_equal el_text, uibutton_text
el_name = find_ele_by_predicate_include(value: 'button').name
assert_equal el_name, uibutton_text
end
def test_18_find_eles_by_predicate_include
assert_equal find_eles_by_predicate_include(value: 'e').length, 51
end
def test_19_first_ele
assert_equal first_ele(ui_ios.static_text).name, 'UICatalog'
end
def test_20_last_ele
expected = 'Steppers'
el = last_ele(ui_ios.static_text)
assert_equal el.text, expected
assert_equal el.name, expected
end
# t 'source' do # tested by get_source
def test_21_get_source
assert_equal get_source.class, String
end
def test_22_invalid_id_should_error
assert_raises Selenium::WebDriver::Error::NoSuchElementError do
id 'does not exist'
end
assert_raises Selenium::WebDriver::Error::NoSuchElementError do
id 'android:id/text1'
end
end
def test_23_tag
assert_equal tag(ui_ios.navbar).name, 'UICatalog'
end
def test_24_tags
assert_equal tags(ui_ios.table_cell).length, 12
end
def test_25_find_eles_by_attr_include_length
assert_equal find_eles_by_attr_include(ui_ios.static_text, 'name', 'AAPL').length, 16
end
def test_26_get_page_class
act = get_page_class
assert(act.split("\n").length >= 7)
assert_includes act, '25x XCUIElementTypeOther'
assert_includes act, '24x XCUIElementTypeStaticText'
assert_includes act, '12x XCUIElementTypeCell'
assert_includes act, '1x XCUIElementTypeTable'
assert_includes act, '1x XCUIElementTypeNavigationBar'
assert_includes act, '1x XCUIElementTypeWindow'
assert_includes act, '1x XCUIElementTypeApplication'
end
# TODO: write tests
# page_class
# px_to_window_rel
# lazy_load_strings
# xml_keys
# xml_values
# resolve_id
# string_visible_contains
# xpath_visible_contains
# xpaths_visible_contains
# string_visible_exact
# xpath_visible_exact
# xpaths_visible_exact
# raise_no_element_error
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/common/patch.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Skip:
# status # status patches are already tested in driver.rb
# execute # debug output for Pry
#
# bundle exec rake "ios[common/patch]"
class IosTest
class Common
class Patch < Minitest::Test
def test_01_before_first
driver.terminate_app target_bundle_id
driver.activate_app target_bundle_id
assert_equal screen, catalog
end
def test_02_appium_core_element_method_name
assert_equal first_text.name, 'UICatalog'
end
def test_03_appium_core_element_method_location_rel
loc = first_text.location_rel($driver)
assert_equal loc.x.class, String
assert_equal loc.y.class, String
end
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/common/version.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
class IosTest
class Common
class Version < Minitest::Test
def test_01_before_first
assert_equal screen, catalog
end
def test_02_appium_version
assert_match(/(\d+)\.(\d+).(\d+)/, ::Appium::VERSION)
end
def test_03_appium_date
assert_match(/(\d+)-(\d+)-(\d+)/, ::Appium::DATE)
end
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/common/web_context.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Tests specifically for areas where the web_context differs in behaviour
# rake "ios[common/web_context]"
class IosTest
class Common
class WebContext < Minitest::Test
def test_01_before_first
driver.terminate_app target_bundle_id
driver.activate_app target_bundle_id
assert_equal screen, catalog
end
def test_02_get_ios_inspect
find_eles_by_predicate_include(value: 'Web').first.click
wait_true { available_contexts.size >= 2 }
web_view_context = available_contexts.find { |c| c.start_with? 'WEBVIEW' } # Get WEBVIEW_59153.1 for example.
set_context web_view_context
assert_equal current_context, web_view_context
sleep 1 # Give a chance to load
assert_equal page.start_with?("\nhtml\n"), true
end
def test_03_xcuitest_get_contexts
context = xcuitest_get_contexts
assert_equal({ 'id' => 'NATIVE_APP' }, context.first)
assert context[1]['id'].include?('WEBVIEW_')
end
def test_04_after_last
set_context 'NATIVE_APP'
back_click
end
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/device/device.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# $ rake "ios[device/device]"
class IosTest
class Device
class Device < Minitest::Test
# go back to the main page
def go_back
back
wait { find_ele_by_predicate_include(class_name: ui_ios.navbar, value: 'UICatalog') }
end
def test_01_before_first
driver.terminate_app target_bundle_id
driver.activate_app target_bundle_id
assert_equal screen, catalog
end
def test_02_app_installed
installed = app_installed? 'Derrp'
assert_equal installed, false
end
def test_03_background_app_homescreen
bundle_id = 'com.example.apple-samplecode.UICatalog'
background_app(-1) # background_app(nil) should work as same.
# The app goes to background and never come back
wait do
assert_equal driver.app_state(bundle_id), :running_in_background_suspended
end
driver.activate_app bundle_id
end
def test_04_app_strings
assert_includes app_strings, 'A Short Title Is Best'
assert_includes app_strings('en'), 'A Short Title Is Best'
end
def test_05_action_chain
element = text('Buttons')
one_finger_tap x: 0, y: 0, element: element
wait { button 'UICatalog' } # successfully transitioned to buttons page
go_back
end
def test_06_swipe
action.move_to_location(75, 500).pointer_down(:left)
.move_to_location(75, 20).release.perform
end
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/device/image_comparison.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# $ rake ios[device/image_comparison]
class IosTest
class Device
class ImageComparison < Minitest::Test
def test_image_comparison
image1 = File.read './data/test_normal.png'
image2 = File.read './data/test_has_blue.png'
# Equal to `$driver.driver.find_image_occurrence`
# Equal to `driver.find_image_occurrence`
find_result = find_image_occurrence full_image: image1, partial_image: image2
rect = find_result['rect']
assert_equal({ 'x' => 0, 'y' => 0, 'width' => 750, 'height' => 1334 }, rect)
end
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/driver.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# bundle exec rake "ios[driver]"
class IosTest
class Driver < Minitest::Test
def test_01_before_first
driver.terminate_app target_bundle_id
driver.activate_app target_bundle_id
assert_equal screen, catalog
end
def test_02_unicode_defaults
data = File.read File.expand_path('../../../data/unicode.txt', __dir__)
assert_equal data.strip, 174.chr('UTF-8')
end
def test_03_load_settings
appium_txt = File.join(Dir.pwd, 'appium.txt')
opts = Appium.load_settings file: appium_txt, verbose: true
actual = ''
actual = File.basename opts[:caps][:app] if opts && opts[:caps]
expected = 'UICatalog.app.zip'
assert_equal expected, actual
end
def test_04_verify_all_attributes
actual = driver_attributes
caps_app_for_teardown = actual[:caps][:app]
expected_app = File.absolute_path('../test_apps/UICatalog.app.zip')
# actual[:caps].to_json send to Appium server
caps_with_json = JSON.parse(actual[:caps].to_json)
assert_equal caps_with_json['platformName'], 'ios'
assert !caps_with_json['platformVersion'].nil?
assert_equal caps_with_json['app'], expected_app
assert_equal caps_with_json['automationName'], 'XCUITest'
assert !caps_with_json['deviceName'].nil?
assert_equal caps_with_json['someCapability'], 'some_capability'
assert_equal actual[:caps][:platformName], 'ios'
assert !actual[:caps][:platformVersion].nil?
assert_equal actual[:caps][:app], expected_app
assert_equal actual[:caps][:automationName], 'XCUITest'
assert !actual[:caps][:deviceName].nil?
assert_equal actual[:caps][:someCapability], 'some_capability'
actual_selenium_caps = actual[:caps][:automationName]
assert_equal actual_selenium_caps, 'XCUITest'
actual[:caps][:app] = caps_app_for_teardown
end
def test_05_verify_attributes_are_immutable
assert_equal driver_attributes[:custom_url], 'http://127.0.0.1:4723'
driver_attributes[:custom_url] = true
assert_equal driver_attributes[:custom_url], 'http://127.0.0.1:4723'
end
def test_06_verify_attribute_of_caps_are_not_immutable_because_it_depends_on_selenium
# immutability depends on Selenium
for_clean_up = driver_attributes[:caps][:app].dup
driver_attributes[:caps][:app] = 'fake'
expected = 'fake'
assert_equal driver_attributes[:caps][:app], expected
# clean up
driver_attributes[:caps][:app] = for_clean_up
end
def test_07_no_wait
no_wait
assert_raises Selenium::WebDriver::Error::NoSuchElementError do
find_element(:accessibility_id, 'zz')
end
set_wait
end
def test_08_app_path_attr
apk_name = File.basename driver_attributes[:caps][:app]
assert_equal apk_name, 'UICatalog.app.zip'
end
def test_09_driver_class
assert_equal $driver.class, Appium::Driver
end
def test_10_status
assert appium_server_version['build'].keys.member?('version')
end
def test_11_server_version
server_version = appium_server_version['build']['version']
assert_match(/(\d+)\.(\d+).(\d+)/, server_version)
end
def test_12_client_version
client_version = appium_client_version
expected = { version: ::Appium::VERSION }
assert_equal client_version, expected
end
def test_13_restart
restart
text 'buttons'
end
def test_14_driver
assert driver.browser.empty?
end
def test_15_automation_name_is_xcuitest?
assert_equal automation_name_is_xcuitest?, true
end
#
# Skip:
# screenshot # this is slow and already tested by Appium
# driver_quit # tested by restart
# start_driver # tested by restart
#
def test_16_set_wait
# fill the @last_waits array with: [30, 30]
assert_equal set_wait(30), 30
assert_equal set_wait(30), 30
# verify set_wait with no args works correctly
assert_equal set_wait, 30
assert_equal set_wait(30), 30
assert_equal set_wait, 30
assert_equal set_wait(2), 2
assert_equal set_wait, 30
assert_equal set_wait(3), 3
assert_equal set_wait, 30
assert_equal set_wait(2), 2
assert_equal set_wait(3), 3
assert_equal set_wait, 30
end
def test_17_default_wait
set_wait 30
assert_equal default_wait, 30 # set in run.rb
end
# returns true unless an error is raised
def test_18_exists
assert_equal exists(0, 0) { true }, true
assert_equal exists(0, 0) { raise 'error' }, false
end
# simple integration sanity test to check for unexpected exceptions
def test_19_set_location
set_location latitude: 55, longitude: -72, altitude: 33
end
# any elements
def test_20_find_elements
assert_equal find_elements(:class, ui_ios.table_cell).length, 18
end
# any element
def test_21_find_element
assert_equal find_element(:class, ui_ios.static_text).class, ::Appium::Core::Element
end
# settings
def test_22_get_settings
assert !get_settings.nil?
end
def test_23_update_settings
update_settings allowInvisibleElements: true
assert_equal get_settings['allowInvisibleElements'], true
end
def test_24_events
log_event vendor: 'appium', event: 'funEvent'
log_events
end
def test_25_device_is_ios
assert_equal device_is_ios?, true
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/ios/command/multi_app_handler.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "ios[ios/command/multi_app_handler]"
class IosTest
class Ios
class Command
class MultiAppHandler < Minitest::Test
# Only for Xcode 9+
def test_multip_app_handler
driver.terminate_app target_bundle_id
driver.activate_app target_bundle_id
test_app_bundle = target_bundle_id
assert_equal xcuitest_query_app_status(bundle_id: test_app_bundle), :running_in_foreground
assert_equal xcuitest_terminate_app(bundle_id: test_app_bundle), true
assert_equal xcuitest_query_app_status(bundle_id: test_app_bundle), :not_running
assert xcuitest_activate_app(bundle_id: test_app_bundle).nil?
assert_equal xcuitest_query_app_status(bundle_id: test_app_bundle), :running_in_foreground
assert xcuitest_activate_app(bundle_id: 'com.apple.Preferences').nil?
wait(timeout: 5) do
assert_equal xcuitest_query_app_status(bundle_id: test_app_bundle), :running_in_background_suspended
end
assert xcuitest_activate_app(bundle_id: test_app_bundle).nil?
wait(timeout: 5) do
assert_equal xcuitest_query_app_status(bundle_id: test_app_bundle), :running_in_foreground
end
end
end
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/ios/command/pasteboard.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "ios[ios/command/pasteboard]"
class IosTest
class Ios
class Command
class Pasteboard < Minitest::Test
def test_pasteboard
driver.terminate_app target_bundle_id
driver.activate_app target_bundle_id
# set blank before testing because pasteboard is remaining during launching simulators
set_pasteboard content: 'before'
assert_equal get_pasteboard, 'before'
set_pasteboard content: 'sample content'
assert_equal get_pasteboard, 'sample content'
end
end
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/ios/command/source.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake ios[ios/command/source]
class IosTest
class Ios
class Command
class Source < Minitest::Test
def test_source
assert_equal xcuitest_source(format: :json).is_a?(Hash), true
assert_equal xcuitest_source(format: :xml).is_a?(String), true
end
end
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/ios/element/alert.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "ios[ios/element/alert]"
class IosTest
class Ios
class Element
class Alert < Minitest::Test
def open_alert
wait_true do
find_element(:name, 'Okay / Cancel').click
find_element(:name, 'A Short Title Is Best').displayed?
end
end
def test_01_before
driver.terminate_app target_bundle_id
driver.activate_app target_bundle_id
assert_equal screen, catalog
wait_true do
find_element(:name, 'Alert Views').click
tag(ui_ios.navbar).name == 'Alert Views' # wait for true
end
end
def test_02_alert_accept
open_alert
alert_accept
end
def test_03_alert_dismiss
open_alert
alert_dismiss
end
def test_04_after_last
back_click
assert screen == catalog
sleep 1
end
end
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/ios/element/button.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# FIXME: The order is broken in Ruby 3.
# rake "ios[ios/element/button]"
class IosTest
class Ios
class Element
class Button < Minitest::Test
def before_first
assert_equal screen, catalog
# nav to buttons activity
wait { find_element(:name, 'Buttons').click }
end
def after_last
# nav back to start
back_click
end
def test_01_before_first
driver.terminate_app target_bundle_id
driver.activate_app target_bundle_id
before_first
end
def test_02_button
# by index
assert_equal button(3).name, 'UIAccessoryButtonPlus'
# by name contains
assert_equal button('Plus').name, 'UIAccessoryButtonPlus'
end
def test_03_buttons
exp = %w(UICatalog UIAccessoryButtonPlus)
target_buttons = buttons('a')
assert_equal target_buttons.map(&:name), exp
assert_equal target_buttons.length, exp.length
end
def test_04_first_button
assert_equal first_button.name, 'UICatalog'
end
def test_05_last_button
expected = 'Button'
assert_equal last_button.name, expected
end
def test_06_button_exact
assert_equal button_exact('UIAccessoryButtonPlus').name, 'UIAccessoryButtonPlus'
end
def test_07_buttons_exact
assert_equal buttons_exact('UIAccessoryButtonPlus').first.name, 'UIAccessoryButtonPlus'
end
def test_08_after_last
after_last
end
end
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/ios/element/generic.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "ios[ios/element/generic]"
class IosTest
class Ios
class Element
class Generic < Minitest::Test
def uibutton_text
'Buttons'
end
def verify(element)
element = element.first if element.is_a? Array
assert_equal element.name, uibutton_text
end
def test_01_before_first
driver.terminate_app target_bundle_id
driver.activate_app target_bundle_id
assert_equal screen, catalog
end
def test_02_find
verify find 'tons'
end
def test_03_finds
verify finds 'tons'
end
def test_04_find_exact
verify find_exact uibutton_text
end
def test_05_finds_exact
elements = finds_exact uibutton_text
assert_equal elements.is_a?(Array), true
verify elements
end
end
end
end
end
================================================
FILE: ios_tests/lib/ios/specs/ios/element/text.rb
================================================
# frozen_string_literal: true
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# rake "ios[ios/element/text]"
class IosTest
class Ios
class Element
class Text < Minitest::Test
def ui_catalog
'UICatalog'
end
def uiview_steppers
'Steppers'
end
def test_01_before_first
driver.terminate_app target_bundle_id
driver.activate_app target_bundle_id
assert_equal screen, catalog
end
def test_02_first_text
assert_equal first_text.text, ui_catalog
end
def test_03_last_text
expected = 'Steppers'
assert_equal last_text.text, expected
assert_equal last_text.name, expected
end
def test_04_
gitextract_9jozq5zh/
├── .github/
│ ├── CODEOWNERS
│ ├── ISSUE_TEMPLATE.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── dependabot.yml
│ └── workflows/
│ ├── functional-test.yml
│ ├── pr-title.yml
│ └── rubocop.yml
├── .gitignore
├── .rubocop.yml
├── CHANGELOG.md
├── Gemfile
├── LICENSE-2.0.txt
├── Rakefile
├── Thorfile
├── android_tests/
│ ├── Gemfile
│ ├── LICENSE-2.0.txt
│ ├── Rakefile
│ ├── appium.txt
│ ├── flaky.txt
│ ├── lib/
│ │ ├── android/
│ │ │ └── specs/
│ │ │ ├── android/
│ │ │ │ ├── element/
│ │ │ │ │ ├── alert.rb
│ │ │ │ │ ├── button.rb
│ │ │ │ │ ├── generic.rb
│ │ │ │ │ ├── text.rb
│ │ │ │ │ └── textfield.rb
│ │ │ │ ├── helper.rb
│ │ │ │ └── patch.rb
│ │ │ ├── common/
│ │ │ │ ├── device.rb
│ │ │ │ ├── device_touchaction.rb
│ │ │ │ ├── element/
│ │ │ │ │ └── window.rb
│ │ │ │ ├── helper.rb
│ │ │ │ ├── patch.rb
│ │ │ │ ├── version.rb
│ │ │ │ └── web_context.rb
│ │ │ ├── driver.rb
│ │ │ ├── install.rb
│ │ │ └── sauce_labs.rb
│ │ ├── format.rb
│ │ └── run.rb
│ └── readme.md
├── appium_lib.gemspec
├── contributing.md
├── docs/
│ ├── android_uiautomator.md
│ ├── docs.md
│ ├── ios_xcuitest.md
│ ├── parallel.md
│ └── w3c.md
├── grid/
│ ├── README.md
│ ├── appium.txt.ios.example
│ ├── config.json
│ ├── hub_config.json
│ └── hub_config_3.json
├── ios_tests/
│ ├── Gemfile
│ ├── LICENSE-2.0.txt
│ ├── Rakefile
│ ├── appium.txt
│ ├── data/
│ │ └── unicode.txt
│ ├── flaky.txt
│ ├── lib/
│ │ ├── common.rb
│ │ ├── format.rb
│ │ ├── ios/
│ │ │ └── specs/
│ │ │ ├── common/
│ │ │ │ ├── element/
│ │ │ │ │ └── window.rb
│ │ │ │ ├── helper.rb
│ │ │ │ ├── patch.rb
│ │ │ │ ├── version.rb
│ │ │ │ └── web_context.rb
│ │ │ ├── device/
│ │ │ │ ├── device.rb
│ │ │ │ └── image_comparison.rb
│ │ │ ├── driver.rb
│ │ │ └── ios/
│ │ │ ├── command/
│ │ │ │ ├── multi_app_handler.rb
│ │ │ │ ├── pasteboard.rb
│ │ │ │ └── source.rb
│ │ │ ├── element/
│ │ │ │ ├── alert.rb
│ │ │ │ ├── button.rb
│ │ │ │ ├── generic.rb
│ │ │ │ ├── text.rb
│ │ │ │ └── textfield.rb
│ │ │ ├── helper.rb
│ │ │ ├── mobile_methods.rb
│ │ │ ├── patch.rb
│ │ │ └── xcuitest_gestures.rb
│ │ └── run.rb
│ ├── parallel/
│ │ └── test.rb
│ └── readme.md
├── lib/
│ ├── appium_lib/
│ │ ├── android/
│ │ │ ├── android.rb
│ │ │ ├── common/
│ │ │ │ ├── command/
│ │ │ │ │ └── command.rb
│ │ │ │ └── helper.rb
│ │ │ ├── element/
│ │ │ │ ├── alert.rb
│ │ │ │ ├── button.rb
│ │ │ │ ├── generic.rb
│ │ │ │ ├── text.rb
│ │ │ │ └── textfield.rb
│ │ │ ├── espresso/
│ │ │ │ ├── bridge.rb
│ │ │ │ ├── element/
│ │ │ │ │ ├── button.rb
│ │ │ │ │ └── generic.rb
│ │ │ │ ├── element.rb
│ │ │ │ └── helper.rb
│ │ │ ├── espresso.rb
│ │ │ ├── uiautomator2/
│ │ │ │ ├── bridge.rb
│ │ │ │ ├── element/
│ │ │ │ │ └── button.rb
│ │ │ │ ├── element.rb
│ │ │ │ └── helper.rb
│ │ │ └── uiautomator2.rb
│ │ ├── appium.rb
│ │ ├── common/
│ │ │ ├── command.rb
│ │ │ ├── device.rb
│ │ │ ├── helper.rb
│ │ │ ├── http_client.rb
│ │ │ ├── log.rb
│ │ │ └── wait.rb
│ │ ├── driver.rb
│ │ ├── error.rb
│ │ ├── ios/
│ │ │ ├── common/
│ │ │ │ ├── errors.rb
│ │ │ │ └── helper.rb
│ │ │ ├── element/
│ │ │ │ ├── alert.rb
│ │ │ │ ├── button.rb
│ │ │ │ ├── generic.rb
│ │ │ │ ├── text.rb
│ │ │ │ └── textfield.rb
│ │ │ ├── ios.rb
│ │ │ ├── xcuitest/
│ │ │ │ ├── bridge.rb
│ │ │ │ ├── command/
│ │ │ │ │ ├── certificate.rb
│ │ │ │ │ ├── gestures.rb
│ │ │ │ │ ├── get_context.rb
│ │ │ │ │ ├── multi_app_handler.rb
│ │ │ │ │ ├── pasteboard.rb
│ │ │ │ │ └── source.rb
│ │ │ │ ├── command.rb
│ │ │ │ ├── element/
│ │ │ │ │ ├── button.rb
│ │ │ │ │ ├── generic.rb
│ │ │ │ │ ├── text.rb
│ │ │ │ │ └── textfield.rb
│ │ │ │ ├── element.rb
│ │ │ │ └── helper.rb
│ │ │ └── xcuitest.rb
│ │ ├── sauce_labs.rb
│ │ └── version.rb
│ └── appium_lib.rb
├── readme.md
├── release_notes.md
├── test/
│ └── first_test.rb
└── test_apps/
├── VodQA.apk
└── api.apk
SYMBOL INDEX (904 symbols across 93 files)
FILE: android_tests/lib/android/specs/android/element/alert.rb
class AndroidTest (line 16) | class AndroidTest
class Element (line 17) | class Element
class Alert (line 18) | class Alert < Minitest::Test
method open_alert (line 19) | def open_alert
method test_01_alert_click (line 24) | def test_01_alert_click
method test_02_alert_accept (line 34) | def test_02_alert_accept
method test_03_alert_accept_text (line 39) | def test_03_alert_accept_text
method test_04_alert_dismiss (line 45) | def test_04_alert_dismiss
method test_05_alert_dismiss_text (line 50) | def test_05_alert_dismiss_text
FILE: android_tests/lib/android/specs/android/element/button.rb
class AndroidTest (line 16) | class AndroidTest
class Element (line 17) | class Element
class Button (line 18) | class Button < Minitest::Test
method before_first (line 19) | def before_first
method after_last (line 26) | def after_last
method fade_in (line 31) | def fade_in
method test_01_before_first (line 35) | def test_01_before_first
method test_02_button (line 39) | def test_02_button
method test_03_buttons (line 47) | def test_03_buttons
method test_04_first_button (line 53) | def test_04_first_button
method test_05_last_button (line 57) | def test_05_last_button
method test_06_button_exact (line 61) | def test_06_button_exact
method test_07_buttons_exact (line 65) | def test_07_buttons_exact
method test_08_after_last (line 69) | def test_08_after_last
FILE: android_tests/lib/android/specs/android/element/generic.rb
class AndroidTest (line 16) | class AndroidTest
class Element (line 17) | class Element
class Generic (line 18) | class Generic < Minitest::Test
method content (line 19) | def content
method partial (line 23) | def partial
method test_01_find_works_before_and_after_get_source (line 27) | def test_01_find_works_before_and_after_get_source
method test_01_find (line 33) | def test_01_find
method test_01_finds (line 37) | def test_01_finds
method test_01_find_exact (line 41) | def test_01_find_exact
method test_01_finds_exact (line 45) | def test_01_finds_exact
method test_01_scroll_to (line 50) | def test_01_scroll_to
method test_01_scroll_to_exact (line 63) | def test_01_scroll_to_exact
FILE: android_tests/lib/android/specs/android/element/text.rb
class AndroidTest (line 16) | class AndroidTest
class Element (line 17) | class Element
class Text (line 18) | class Text < Minitest::Test
method must_raise_no_element (line 19) | def must_raise_no_element
method test_01_text (line 25) | def test_01_text
method test_02_texts (line 30) | def test_02_texts
method test_03_first_text (line 35) | def test_03_first_text
method test_04_last_text (line 39) | def test_04_last_text
method test_05_text_exact (line 43) | def test_05_text_exact
method test_06_texts_exact (line 50) | def test_06_texts_exact
FILE: android_tests/lib/android/specs/android/element/textfield.rb
class AndroidTest (line 16) | class AndroidTest
class Element (line 17) | class Element
class TextField (line 18) | class TextField < Minitest::Test
method must_raise_no_element (line 19) | def must_raise_no_element
method left (line 25) | def left
method right (line 29) | def right
method before_first (line 33) | def before_first
method after_last (line 40) | def after_last
method test_01_before_test (line 45) | def test_01_before_test
method test_02_textfield (line 49) | def test_02_textfield
method test_03_textfields (line 54) | def test_03_textfields
method test_04_first_textfield (line 59) | def test_04_first_textfield
method test_05_last_textfield (line 63) | def test_05_last_textfield
method test_06_textfield_exact (line 67) | def test_06_textfield_exact
method test_07_textfields_exact (line 72) | def test_07_textfields_exact
method test_08_hide_keyboard (line 77) | def test_08_hide_keyboard
method test_09_after_last (line 82) | def test_09_after_last
FILE: android_tests/lib/android/specs/android/helper.rb
class AndroidTest (line 16) | class AndroidTest
class Helper (line 17) | class Helper < Minitest::Test
method test_01_tags (line 18) | def test_01_tags
method test_01_get_page_class (line 22) | def test_01_get_page_class
method test_02_get_android_inspect (line 51) | def test_02_get_android_inspect
method id_key (line 59) | def id_key
method id_value (line 63) | def id_value
method test_03_xml_keys (line 67) | def test_03_xml_keys
method test_04_resolve_id (line 77) | def test_04_resolve_id
method test_05_xml_values (line 84) | def test_05_xml_values
method test_06_find_by_id (line 91) | def test_06_find_by_id
method test_07_ids (line 106) | def test_07_ids
FILE: android_tests/lib/android/specs/android/patch.rb
class AndroidTest (line 16) | class AndroidTest
class Patch (line 17) | class Patch < Minitest::Test
method test_type (line 18) | def test_type
FILE: android_tests/lib/android/specs/common/device.rb
class AndroidTest (line 16) | class AndroidTest
class Common (line 17) | class Common
class Device (line 18) | class Device < Minitest::Test
method test_01_get_performance_data_types (line 19) | def test_01_get_performance_data_types
method test_02_start_activity (line 28) | def test_02_start_activity
method test_03_current_package (line 44) | def test_03_current_package
method test_04_app_strings (line 52) | def test_04_app_strings
method test_05_press_keycode (line 56) | def test_05_press_keycode
method test_06_long_press_keycode (line 61) | def test_06_long_press_keycode
FILE: android_tests/lib/android/specs/common/device_touchaction.rb
class AndroidTest (line 16) | class AndroidTest
class Common (line 17) | class Common
class DeviceTouchAction (line 18) | class DeviceTouchAction < Minitest::Test
method test_01_before_test (line 19) | def test_01_before_test
method test_02_action_chain_press_release (line 23) | def test_02_action_chain_press_release
method test_03_action_chain_tap (line 33) | def test_03_action_chain_tap
method test_04_swipe (line 43) | def test_04_swipe
method test_05_pinch_zoom (line 56) | def test_05_pinch_zoom
FILE: android_tests/lib/android/specs/common/element/window.rb
class AndroidTest (line 16) | class AndroidTest
class Common (line 17) | class Common
class Element (line 18) | class Element
class Window (line 19) | class Window < Minitest::Test
method test_window_size (line 20) | def test_window_size
FILE: android_tests/lib/android/specs/common/helper.rb
class AndroidTest (line 16) | class AndroidTest
class Common (line 17) | class Common
class Helper (line 18) | class Helper < Minitest::Test
method wait_opts (line 19) | def wait_opts
method test_01_wait (line 30) | def test_01_wait
method test_02_ignore (line 57) | def test_02_ignore
method test_03_wait_true (line 67) | def test_03_wait_true
method test_04_back (line 101) | def test_04_back
method test_05_session_id (line 114) | def test_05_session_id
method test_06_xpath (line 118) | def test_06_xpath
method test_07_xpaths (line 123) | def test_07_xpaths
method test_08_ele_index (line 127) | def test_08_ele_index
method test_09_tags (line 132) | def test_09_tags
method test_10_first_ele (line 136) | def test_10_first_ele
method test_11_last_ele (line 143) | def test_11_last_ele
method test_12_get_source (line 152) | def test_12_get_source
FILE: android_tests/lib/android/specs/common/patch.rb
class AndroidTest (line 20) | class AndroidTest
class Common (line 21) | class Common
class Patch (line 22) | class Patch < Minitest::Test
method test_01_element_method_name (line 31) | def test_01_element_method_name
method test_02_element_method_location_rel (line 37) | def test_02_element_method_location_rel
method test_03_common_patch_id_error_message (line 46) | def test_03_common_patch_id_error_message
method test_04_id_common_patch_success (line 60) | def test_04_id_common_patch_success
method test_05_find_many_elements_by_resource_id (line 74) | def test_05_find_many_elements_by_resource_id
method test_06_find_single_element_by_resource_id (line 81) | def test_06_find_single_element_by_resource_id
FILE: android_tests/lib/android/specs/common/version.rb
class AndroidTest (line 16) | class AndroidTest
class Common (line 17) | class Common
class Version (line 18) | class Version < Minitest::Test
method test_appium_version (line 19) | def test_appium_version
method test_appium_date (line 23) | def test_appium_date
FILE: android_tests/lib/android/specs/common/web_context.rb
class AndroidTest (line 17) | class AndroidTest
class Common (line 18) | class Common
class WebContext (line 19) | class WebContext < Minitest::Test
method test_01_available_contexts (line 22) | def test_01_available_contexts
method test_02_current_context (line 26) | def test_02_current_context
method undo_setcontext_nav (line 30) | def undo_setcontext_nav
method test_03_set_context (line 37) | def test_03_set_context
FILE: android_tests/lib/android/specs/driver.rb
class AndroidTest (line 18) | class AndroidTest
class Driver (line 19) | class Driver < Minitest::Test
method sauce? (line 20) | def sauce?
method test_01_load_settings (line 24) | def test_01_load_settings
method test_02_attributes_no_wait (line 31) | def test_02_attributes_no_wait
method test_03_attributes_default_wait_attr (line 42) | def test_03_attributes_default_wait_attr
method test_04_attributes_app_path_attr (line 48) | def test_04_attributes_app_path_attr
method test_05_attributes_verify_all_attributes (line 53) | def test_05_attributes_verify_all_attributes
method test_06_driver_class (line 94) | def test_06_driver_class
method absolute_app_path (line 98) | def absolute_app_path(path)
method validate_path (line 102) | def validate_path(path)
method test_07_absolute_app_path (line 106) | def test_07_absolute_app_path
method test_08_methods_status (line 130) | def test_08_methods_status
method test_09_methods_server_version (line 134) | def test_09_methods_server_version
method test_10_methods_client_version (line 143) | def test_10_methods_client_version
method test_11_methods_restart (line 149) | def test_11_methods_restart
method test_12_methods_driver (line 155) | def test_12_methods_driver
method test_13_methods_default_wait (line 167) | def test_13_methods_default_wait
method test_14_methods_exists (line 173) | def test_14_methods_exists
method test_15_methods_find_elements (line 179) | def test_15_methods_find_elements
method test_16_methods_find_element (line 186) | def test_16_methods_find_element
method test_17_methods_set_location (line 193) | def test_17_methods_set_location
method test_18_methods_get_settings (line 205) | def test_18_methods_get_settings
method test_19_methods_update_settings (line 209) | def test_19_methods_update_settings
FILE: android_tests/lib/android/specs/install.rb
class AndroidTest (line 16) | class AndroidTest
class Install (line 17) | class Install < Minitest::Test
method pkg (line 19) | def pkg
method installed (line 23) | def installed
method not_installed (line 27) | def not_installed
method test_install_uninstall (line 31) | def test_install_uninstall
FILE: android_tests/lib/android/specs/sauce_labs.rb
class AndroidTest (line 16) | class AndroidTest
class SauceLabs (line 17) | class SauceLabs < Minitest::Test
method test_sauce_settings (line 18) | def test_sauce_settings
method test_no_sauce_settings (line 37) | def test_no_sauce_settings
FILE: android_tests/lib/run.rb
function start_driver (line 38) | def start_driver(caps)
FILE: ios_tests/lib/common.rb
function back_click (line 16) | def back_click
function leave_textfields (line 20) | def leave_textfields
function go_to_textfields (line 25) | def go_to_textfields
function screen (line 33) | def screen
function catalog (line 37) | def catalog
function target_bundle_id (line 41) | def target_bundle_id
function ui_ios (line 45) | def ui_ios
class UI (line 49) | class UI
method initialize (line 50) | def initialize(driver)
method navbar (line 54) | def navbar
method button (line 58) | def button
method static_text (line 62) | def static_text
method text_field (line 66) | def text_field
method secure_text_field (line 70) | def secure_text_field
method picker (line 74) | def picker
method picker_wheel (line 78) | def picker_wheel
method action_sheet (line 82) | def action_sheet
method table (line 86) | def table
method table_cell (line 90) | def table_cell
method other (line 94) | def other
method status_bar (line 98) | def status_bar
FILE: ios_tests/lib/ios/specs/common/element/window.rb
class IosTest (line 17) | class IosTest
class Common (line 18) | class Common
class Element (line 19) | class Element
class Window (line 20) | class Window < Minitest::Test
method before_first (line 21) | def before_first
method test_01_before_first (line 27) | def test_01_before_first
method test_02_window_size (line 31) | def test_02_window_size
FILE: ios_tests/lib/ios/specs/common/helper.rb
class IosTest (line 16) | class IosTest
class Common (line 17) | class Common
class Helper (line 18) | class Helper < Minitest::Test
method setup (line 19) | def setup
method test_01_before_first (line 23) | def test_01_before_first
method test_02_wait (line 36) | def test_02_wait
method test_03_ignore (line 62) | def test_03_ignore
method test_04_wait_true (line 72) | def test_04_wait_true
method test_06_back (line 104) | def test_06_back
method test_07_session_id (line 120) | def test_07_session_id
method test_08_xpath (line 125) | def test_08_xpath
method test_09_xpaths (line 129) | def test_09_xpaths
method uibutton_text (line 133) | def uibutton_text
method action_sheets (line 137) | def action_sheets
method test_10_ele_index (line 141) | def test_10_ele_index
method test_11_find_ele_by_attr (line 147) | def test_11_find_ele_by_attr
method test_12_find_eles_by_attr (line 152) | def test_12_find_eles_by_attr
method test_13_find_ele_by_predicate (line 165) | def test_13_find_ele_by_predicate
method test_14_find_eles_by_predicate (line 173) | def test_14_find_eles_by_predicate
method test_15_find_ele_by_attr_include (line 183) | def test_15_find_ele_by_attr_include
method test_16_find_eles_by_attr_include (line 191) | def test_16_find_eles_by_attr_include
method test_17_find_ele_by_predicate_include (line 196) | def test_17_find_ele_by_predicate_include
method test_18_find_eles_by_predicate_include (line 204) | def test_18_find_eles_by_predicate_include
method test_19_first_ele (line 208) | def test_19_first_ele
method test_20_last_ele (line 212) | def test_20_last_ele
method test_21_get_source (line 222) | def test_21_get_source
method test_22_invalid_id_should_error (line 226) | def test_22_invalid_id_should_error
method test_23_tag (line 236) | def test_23_tag
method test_24_tags (line 240) | def test_24_tags
method test_25_find_eles_by_attr_include_length (line 244) | def test_25_find_eles_by_attr_include_length
method test_26_get_page_class (line 248) | def test_26_get_page_class
FILE: ios_tests/lib/ios/specs/common/patch.rb
class IosTest (line 21) | class IosTest
class Common (line 22) | class Common
class Patch (line 23) | class Patch < Minitest::Test
method test_01_before_first (line 24) | def test_01_before_first
method test_02_appium_core_element_method_name (line 30) | def test_02_appium_core_element_method_name
method test_03_appium_core_element_method_location_rel (line 34) | def test_03_appium_core_element_method_location_rel
FILE: ios_tests/lib/ios/specs/common/version.rb
class IosTest (line 15) | class IosTest
class Common (line 16) | class Common
class Version (line 17) | class Version < Minitest::Test
method test_01_before_first (line 18) | def test_01_before_first
method test_02_appium_version (line 22) | def test_02_appium_version
method test_03_appium_date (line 26) | def test_03_appium_date
FILE: ios_tests/lib/ios/specs/common/web_context.rb
class IosTest (line 18) | class IosTest
class Common (line 19) | class Common
class WebContext (line 20) | class WebContext < Minitest::Test
method test_01_before_first (line 21) | def test_01_before_first
method test_02_get_ios_inspect (line 27) | def test_02_get_ios_inspect
method test_03_xcuitest_get_contexts (line 39) | def test_03_xcuitest_get_contexts
method test_04_after_last (line 45) | def test_04_after_last
FILE: ios_tests/lib/ios/specs/device/device.rb
class IosTest (line 17) | class IosTest
class Device (line 18) | class Device
class Device (line 19) | class Device < Minitest::Test
method go_back (line 21) | def go_back
method test_01_before_first (line 26) | def test_01_before_first
method test_02_app_installed (line 32) | def test_02_app_installed
method test_03_background_app_homescreen (line 37) | def test_03_background_app_homescreen
method test_04_app_strings (line 50) | def test_04_app_strings
method test_05_action_chain (line 55) | def test_05_action_chain
method test_06_swipe (line 63) | def test_06_swipe
FILE: ios_tests/lib/ios/specs/device/image_comparison.rb
class IosTest (line 17) | class IosTest
class Device (line 18) | class Device
class ImageComparison (line 19) | class ImageComparison < Minitest::Test
method test_image_comparison (line 20) | def test_image_comparison
FILE: ios_tests/lib/ios/specs/driver.rb
class IosTest (line 16) | class IosTest
class Driver (line 17) | class Driver < Minitest::Test
method test_01_before_first (line 18) | def test_01_before_first
method test_02_unicode_defaults (line 24) | def test_02_unicode_defaults
method test_03_load_settings (line 29) | def test_03_load_settings
method test_04_verify_all_attributes (line 39) | def test_04_verify_all_attributes
method test_05_verify_attributes_are_immutable (line 65) | def test_05_verify_attributes_are_immutable
method test_06_verify_attribute_of_caps_are_not_immutable_because_it_depends_on_selenium (line 71) | def test_06_verify_attribute_of_caps_are_not_immutable_because_it_de...
method test_07_no_wait (line 82) | def test_07_no_wait
method test_08_app_path_attr (line 90) | def test_08_app_path_attr
method test_09_driver_class (line 95) | def test_09_driver_class
method test_10_status (line 99) | def test_10_status
method test_11_server_version (line 103) | def test_11_server_version
method test_12_client_version (line 108) | def test_12_client_version
method test_13_restart (line 114) | def test_13_restart
method test_14_driver (line 119) | def test_14_driver
method test_15_automation_name_is_xcuitest? (line 123) | def test_15_automation_name_is_xcuitest?
method test_16_set_wait (line 134) | def test_16_set_wait
method test_17_default_wait (line 154) | def test_17_default_wait
method test_18_exists (line 160) | def test_18_exists
method test_19_set_location (line 166) | def test_19_set_location
method test_20_find_elements (line 171) | def test_20_find_elements
method test_21_find_element (line 176) | def test_21_find_element
method test_22_get_settings (line 181) | def test_22_get_settings
method test_23_update_settings (line 185) | def test_23_update_settings
method test_24_events (line 190) | def test_24_events
method test_25_device_is_ios (line 195) | def test_25_device_is_ios
FILE: ios_tests/lib/ios/specs/ios/command/multi_app_handler.rb
class IosTest (line 16) | class IosTest
class Ios (line 17) | class Ios
class Command (line 18) | class Command
class MultiAppHandler (line 19) | class MultiAppHandler < Minitest::Test
method test_multip_app_handler (line 21) | def test_multip_app_handler
FILE: ios_tests/lib/ios/specs/ios/command/pasteboard.rb
class IosTest (line 16) | class IosTest
class Ios (line 17) | class Ios
class Command (line 18) | class Command
class Pasteboard (line 19) | class Pasteboard < Minitest::Test
method test_pasteboard (line 20) | def test_pasteboard
FILE: ios_tests/lib/ios/specs/ios/command/source.rb
class IosTest (line 16) | class IosTest
class Ios (line 17) | class Ios
class Command (line 18) | class Command
class Source (line 19) | class Source < Minitest::Test
method test_source (line 20) | def test_source
FILE: ios_tests/lib/ios/specs/ios/element/alert.rb
class IosTest (line 16) | class IosTest
class Ios (line 17) | class Ios
class Element (line 18) | class Element
class Alert (line 19) | class Alert < Minitest::Test
method open_alert (line 20) | def open_alert
method test_01_before (line 27) | def test_01_before
method test_02_alert_accept (line 38) | def test_02_alert_accept
method test_03_alert_dismiss (line 43) | def test_03_alert_dismiss
method test_04_after_last (line 48) | def test_04_after_last
FILE: ios_tests/lib/ios/specs/ios/element/button.rb
class IosTest (line 18) | class IosTest
class Ios (line 19) | class Ios
class Element (line 20) | class Element
class Button (line 21) | class Button < Minitest::Test
method before_first (line 22) | def before_first
method after_last (line 28) | def after_last
method test_01_before_first (line 33) | def test_01_before_first
method test_02_button (line 40) | def test_02_button
method test_03_buttons (line 48) | def test_03_buttons
method test_04_first_button (line 56) | def test_04_first_button
method test_05_last_button (line 60) | def test_05_last_button
method test_06_button_exact (line 65) | def test_06_button_exact
method test_07_buttons_exact (line 69) | def test_07_buttons_exact
method test_08_after_last (line 73) | def test_08_after_last
FILE: ios_tests/lib/ios/specs/ios/element/generic.rb
class IosTest (line 16) | class IosTest
class Ios (line 17) | class Ios
class Element (line 18) | class Element
class Generic (line 19) | class Generic < Minitest::Test
method uibutton_text (line 20) | def uibutton_text
method verify (line 24) | def verify(element)
method test_01_before_first (line 29) | def test_01_before_first
method test_02_find (line 36) | def test_02_find
method test_03_finds (line 40) | def test_03_finds
method test_04_find_exact (line 44) | def test_04_find_exact
method test_05_finds_exact (line 48) | def test_05_finds_exact
FILE: ios_tests/lib/ios/specs/ios/element/text.rb
class IosTest (line 16) | class IosTest
class Ios (line 17) | class Ios
class Element (line 18) | class Element
class Text (line 19) | class Text < Minitest::Test
method ui_catalog (line 20) | def ui_catalog
method uiview_steppers (line 24) | def uiview_steppers
method test_01_before_first (line 28) | def test_01_before_first
method test_02_first_text (line 35) | def test_02_first_text
method test_03_last_text (line 39) | def test_03_last_text
method test_04_text (line 46) | def test_04_text
method test_05_texts (line 52) | def test_05_texts
method test_06_text_exact (line 59) | def test_06_text_exact
method test_07_texts_exact (line 74) | def test_07_texts_exact
FILE: ios_tests/lib/ios/specs/ios/element/textfield.rb
class IosTest (line 16) | class IosTest
class Element (line 17) | class Element
class Textfield (line 18) | class Textfield < Minitest::Test
method enter_text (line 19) | def enter_text
method enter_password (line 23) | def enter_password
method test_01_before_first (line 27) | def test_01_before_first
method test_02_textfield (line 34) | def test_02_textfield
method test_03_textfields (line 40) | def test_03_textfields
method test_04_predicate_textfields (line 47) | def test_04_predicate_textfields
method test_05_first_textfield (line 52) | def test_05_first_textfield
method test_06_last_textfield (line 56) | def test_06_last_textfield
method test_07_textfield_exact (line 60) | def test_07_textfield_exact
method test_08_textfields_exact (line 64) | def test_08_textfields_exact
method test_09_textfield_type (line 68) | def test_09_textfield_type
method test_10_hide_keyboard (line 74) | def test_10_hide_keyboard
method test_11_leave_textfields (line 81) | def test_11_leave_textfields
method test_12_no_textfield (line 86) | def test_12_no_textfield
method test_13_no_textfields (line 91) | def test_13_no_textfields
method test_14_no_first_textfield (line 95) | def test_14_no_first_textfield
method test_15_no_last_textfield (line 99) | def test_15_no_last_textfield
method test_16_no_textfield_exact (line 103) | def test_16_no_textfield_exact
method test_17_no_textfields_exact (line 107) | def test_17_no_textfields_exact
method test_18_after_last (line 111) | def test_18_after_last
FILE: ios_tests/lib/ios/specs/ios/helper.rb
class IosTest (line 16) | class IosTest
class Ios (line 17) | class Ios
class Helper (line 18) | class Helper < Minitest::Test
method test_01_before_first (line 19) | def test_01_before_first
method test_02_ios_password (line 26) | def test_02_ios_password
method test_03_page (line 31) | def test_03_page
method test_04_id (line 35) | def test_04_id
method test_05_platform_version (line 39) | def test_05_platform_version
method test_06_tags_include (line 43) | def test_06_tags_include
method test_07_tags_exact (line 54) | def test_07_tags_exact
FILE: ios_tests/lib/ios/specs/ios/mobile_methods.rb
class IosTest (line 16) | class IosTest
class Ios (line 17) | class Ios
class MobileMethods (line 18) | class MobileMethods < Minitest::Test
method test_01_before_first (line 19) | def test_01_before_first
method test_02_an_element_with_class_chain (line 25) | def test_02_an_element_with_class_chain
method test_03_elements_with_class_chain (line 31) | def test_03_elements_with_class_chain
FILE: ios_tests/lib/ios/specs/ios/patch.rb
class IosTest (line 16) | class IosTest
class Ios (line 17) | class Ios
class Patch (line 18) | class Patch < Minitest::Test
method test_01_before_first (line 19) | def test_01_before_first
method test_02_label (line 26) | def test_02_label
method test_03_type (line 30) | def test_03_type
method test_04_after_last (line 40) | def test_04_after_last
FILE: ios_tests/lib/ios/specs/ios/xcuitest_gestures.rb
class IosTest (line 16) | class IosTest
class Ios (line 17) | class Ios
class XcuitestGestures (line 18) | class XcuitestGestures < Minitest::Test
method open_alert_ok_cancel (line 19) | def open_alert_ok_cancel
method open_alert_custom (line 26) | def open_alert_custom
method test_01_before_first (line 33) | def test_01_before_first
method test_02_tap (line 39) | def test_02_tap
method test_03_double_tap (line 50) | def test_03_double_tap
method test_04_touch_and_hold (line 55) | def test_04_touch_and_hold
method test_05_swipe (line 61) | def test_05_swipe
method test_06_drag_from_to_for_duration (line 70) | def test_06_drag_from_to_for_duration
method test_07_pinch (line 74) | def test_07_pinch
method test_08_back_to_top (line 78) | def test_08_back_to_top
method test_09_select_picker_wheel (line 82) | def test_09_select_picker_wheel
method test_10_back_to_top (line 95) | def test_10_back_to_top
method test_11_alert (line 99) | def test_11_alert
method test_12_back_to_top (line 117) | def test_12_back_to_top
method test_13_after_last (line 121) | def test_13_after_last
FILE: ios_tests/parallel/test.rb
function des_server_caps (line 17) | def des_server_caps
class TestParallelRunThread (line 27) | class TestParallelRunThread
method initialize (line 28) | def initialize(capability)
method setup (line 32) | def setup
method teardown (line 37) | def teardown
method test_run (line 42) | def test_run
class TestParallelRunProcess (line 65) | class TestParallelRunProcess
method initialize (line 66) | def initialize(capability)
method setup (line 70) | def setup
method teardown (line 76) | def teardown
method test_run (line 81) | def test_run
FILE: lib/appium_lib/android/android.rb
type Appium (line 30) | module Appium
type Android (line 31) | module Android
class Bridge (line 32) | class Bridge
method for (line 33) | def self.for(target)
FILE: lib/appium_lib/android/common/command/command.rb
type Appium (line 15) | module Appium
type Android (line 16) | module Android
type Command (line 17) | module Command
function shell (line 28) | def shell(command, arguments)
FILE: lib/appium_lib/android/common/helper.rb
type Appium (line 15) | module Appium
type Android (line 16) | module Android
class AndroidElements (line 19) | class AndroidElements < Nokogiri::XML::SAX::Document
method filter= (line 23) | def filter=(value)
method initialize (line 30) | def initialize # rubocop:disable Lint/MissingSuper
method reset (line 35) | def reset
method start_element (line 41) | def start_element(name, attrs = [], driver = $driver)
function get_android_inspect (line 95) | def get_android_inspect(class_name = false)
function page (line 121) | def page(opts = {})
function id (line 130) | def id(id)
function ids (line 138) | def ids(id)
function ele_index (line 147) | def ele_index(class_name, index)
function first_ele (line 166) | def first_ele(class_name)
function last_ele (line 173) | def last_ele(class_name)
function tag (line 181) | def tag(class_name)
function tags (line 189) | def tags(class_name)
function resource_id (line 202) | def resource_id(string, on_match)
function string_visible_contains_xpath (line 232) | def string_visible_contains_xpath(class_name, value)
function string_visible_contains (line 252) | def string_visible_contains(class_name, value)
function complex_find_contains (line 270) | def complex_find_contains(class_name, value)
function complex_finds_contains (line 278) | def complex_finds_contains(class_name, value)
function string_visible_exact_xpath (line 288) | def string_visible_exact_xpath(class_name, value)
function string_visible_exact (line 301) | def string_visible_exact(class_name, value)
function complex_find_exact (line 320) | def complex_find_exact(class_name, value)
function complex_finds_exact (line 328) | def complex_finds_exact(class_name, value)
FILE: lib/appium_lib/android/element/alert.rb
type Appium (line 15) | module Appium
type Android (line 16) | module Android
function alert_click (line 20) | def alert_click(value)
function alert_accept (line 27) | def alert_accept
function alert_accept_text (line 34) | def alert_accept_text
function alert_dismiss (line 41) | def alert_dismiss
function alert_dismiss_text (line 48) | def alert_dismiss_text
FILE: lib/appium_lib/android/element/button.rb
type Appium (line 15) | module Appium
type Android (line 16) | module Android
function button (line 27) | def button(value)
function buttons (line 45) | def buttons(value = false)
function first_button (line 53) | def first_button
function last_button (line 59) | def last_button
function button_exact (line 75) | def button_exact(value)
function buttons_exact (line 82) | def buttons_exact(value)
function raise_no_such_element_if_empty (line 89) | def raise_no_such_element_if_empty(elements)
function _button_visible_selectors (line 95) | def _button_visible_selectors(opts = {})
function _button_exact_string (line 108) | def _button_exact_string(value)
function _button_contains_string (line 114) | def _button_contains_string(value)
FILE: lib/appium_lib/android/element/generic.rb
type Appium (line 15) | module Appium
type Android (line 16) | module Android
function find (line 20) | def find(value)
function finds (line 27) | def finds(value)
function find_exact (line 34) | def find_exact(value)
function finds_exact (line 41) | def finds_exact(value)
function scroll_uiselector (line 46) | def scroll_uiselector(content, index = 0)
function scroll_to (line 54) | def scroll_to(text, scrollable_index = 0)
function scroll_to_exact (line 70) | def scroll_to_exact(text, scrollable_index = 0)
FILE: lib/appium_lib/android/element/text.rb
type Appium (line 16) | module Appium
type Android (line 17) | module Android
function text (line 25) | def text(value)
function texts (line 35) | def texts(value = false)
function first_text (line 43) | def first_text
function last_text (line 49) | def last_text
function text_exact (line 56) | def text_exact(value)
function texts_exact (line 63) | def texts_exact(value)
FILE: lib/appium_lib/android/element/textfield.rb
type Appium (line 15) | module Appium
type Android (line 16) | module Android
function textfield (line 24) | def textfield(value)
function textfields (line 34) | def textfields(value = false)
function first_textfield (line 42) | def first_textfield
function last_textfield (line 48) | def last_textfield
function textfield_exact (line 55) | def textfield_exact(value)
function textfields_exact (line 62) | def textfields_exact(value)
FILE: lib/appium_lib/android/espresso.rb
type Appium (line 19) | module Appium
type Android (line 20) | module Android
type Espresso (line 21) | module Espresso
FILE: lib/appium_lib/android/espresso/bridge.rb
type Appium (line 17) | module Appium
type Android (line 18) | module Android
type Espresso (line 19) | module Espresso
class Bridge (line 20) | class Bridge
method for (line 21) | def self.for(target)
FILE: lib/appium_lib/android/espresso/element.rb
type Appium (line 18) | module Appium
type Android (line 19) | module Android
type Espresso (line 20) | module Espresso
type Element (line 21) | module Element
FILE: lib/appium_lib/android/espresso/element/button.rb
type Appium (line 15) | module Appium
type Android (line 16) | module Android
type Espresso (line 17) | module Espresso
type Element (line 18) | module Element
function button (line 23) | def button(value)
function buttons (line 46) | def buttons(value = false)
function first_button (line 56) | def first_button
function last_button (line 62) | def last_button
function button_exact (line 77) | def button_exact(value)
function buttons_exact (line 89) | def buttons_exact(value)
function raise_no_such_element_if_empty (line 98) | def raise_no_such_element_if_empty(elements)
function _button_visible_selectors_xpath (line 104) | def _button_visible_selectors_xpath(opts = {})
function _button_exact_string_xpath (line 125) | def _button_exact_string_xpath(class_name, value)
function _button_contains_string_xpath (line 130) | def _button_contains_string_xpath(class_name, value)
FILE: lib/appium_lib/android/espresso/element/generic.rb
type Appium (line 15) | module Appium
type Android (line 16) | module Android
type Espresso (line 17) | module Espresso
type Element (line 18) | module Element
function scroll_to (line 23) | def scroll_to(text)
function scroll_to_exact (line 48) | def scroll_to_exact(text)
FILE: lib/appium_lib/android/espresso/helper.rb
type Appium (line 15) | module Appium
type Android (line 16) | module Android
type Espresso (line 17) | module Espresso
type Helper (line 18) | module Helper
function complex_find_contains (line 23) | def complex_find_contains(class_name, value)
function complex_finds_contains (line 31) | def complex_finds_contains(class_name, value)
function complex_find_exact (line 39) | def complex_find_exact(class_name, value)
function complex_finds_exact (line 47) | def complex_finds_exact(class_name, value)
FILE: lib/appium_lib/android/uiautomator2.rb
type Appium (line 19) | module Appium
type Android (line 20) | module Android
type Uiautomator2 (line 21) | module Uiautomator2
FILE: lib/appium_lib/android/uiautomator2/bridge.rb
type Appium (line 17) | module Appium
type Android (line 18) | module Android
type Uiautomator2 (line 19) | module Uiautomator2
class Bridge (line 20) | class Bridge
method for (line 21) | def self.for(target)
FILE: lib/appium_lib/android/uiautomator2/element.rb
type Appium (line 17) | module Appium
type Android (line 18) | module Android
type Uiautomator2 (line 19) | module Uiautomator2
type Element (line 20) | module Element
FILE: lib/appium_lib/android/uiautomator2/element/button.rb
type Appium (line 15) | module Appium
type Android (line 16) | module Android
type Uiautomator2 (line 17) | module Uiautomator2
type Element (line 18) | module Element
function button (line 23) | def button(value)
function buttons (line 44) | def buttons(value = false)
function first_button (line 52) | def first_button
function last_button (line 59) | def last_button
function button_exact (line 76) | def button_exact(value)
function buttons_exact (line 84) | def buttons_exact(value)
function raise_no_such_element_if_empty (line 91) | def raise_no_such_element_if_empty(elements)
function _button_visible_selectors (line 98) | def _button_visible_selectors(opts = {})
function _button_exact_string (line 112) | def _button_exact_string(value)
function _button_contains_string (line 119) | def _button_contains_string(value)
FILE: lib/appium_lib/android/uiautomator2/helper.rb
type Appium (line 15) | module Appium
type Android (line 16) | module Android
type Uiautomator2 (line 17) | module Uiautomator2
type Helper (line 18) | module Helper
function string_visible_contains (line 27) | def string_visible_contains(class_name, value)
function complex_find_contains (line 45) | def complex_find_contains(class_name, value)
function complex_finds_contains (line 56) | def complex_finds_contains(class_name, value)
function string_visible_exact (line 65) | def string_visible_exact(class_name, value)
function complex_find_exact (line 84) | def complex_find_exact(class_name, value)
function complex_finds_exact (line 95) | def complex_finds_exact(class_name, value)
FILE: lib/appium_lib/appium.rb
type Appium (line 39) | module Appium
function load_settings (line 58) | def load_settings(opts = {})
function expand_required_files (line 111) | def expand_required_files(base_dir, file_paths)
function promote_singleton_appium_methods (line 153) | def promote_singleton_appium_methods(modules, driver = $driver)
function promote_appium_methods (line 207) | def promote_appium_methods(class_array, driver = $driver)
FILE: lib/appium_lib/common/command.rb
type Appium (line 15) | module Appium
type Common (line 16) | module Common
type Command (line 17) | module Command
FILE: lib/appium_lib/common/device.rb
type Appium (line 15) | module Appium
type Device (line 16) | module Device
FILE: lib/appium_lib/common/helper.rb
type Appium (line 16) | module Appium
type Common (line 17) | module Common
function ignore (line 30) | def ignore
function back (line 38) | def back
function session_id (line 49) | def session_id
function xpath (line 57) | def xpath(xpath_str)
function xpaths (line 65) | def xpaths(xpath_str)
class CountElements (line 74) | class CountElements < Nokogiri::XML::SAX::Document
method initialize (line 77) | def initialize(platform) # rubocop:disable Lint/MissingSuper
method reset (line 82) | def reset
method start_element (line 87) | def start_element(name, attrs = [])
method formatted_result (line 98) | def formatted_result
function get_page_class (line 116) | def get_page_class
function page_class (line 141) | def page_class
function source (line 148) | def source
function get_source (line 155) | def get_source
function px_to_window_rel (line 165) | def px_to_window_rel(opts = {}, driver = $driver)
function lazy_load_strings (line 175) | def lazy_load_strings
function xml_keys (line 184) | def xml_keys(target)
function xml_values (line 192) | def xml_values(target)
function resolve_id (line 200) | def resolve_id(id)
class HTMLElements (line 206) | class HTMLElements < Nokogiri::XML::SAX::Document
method filter= (line 210) | def filter=(value)
method initialize (line 217) | def initialize # rubocop:disable Lint/MissingSuper
method reset (line 222) | def reset
method result (line 228) | def result
method start_element (line 242) | def start_element(name, attrs = [])
method end_element (line 252) | def end_element(name)
method characters (line 259) | def characters(chars)
function _no_such_element (line 268) | def _no_such_element
function _print_source (line 274) | def _print_source(source)
FILE: lib/appium_lib/common/http_client.rb
type Appium (line 18) | module Appium
type Http (line 19) | module Http
class Default (line 20) | class Default < ::Appium::Core::Base::Http::Default
FILE: lib/appium_lib/common/log.rb
type Appium (line 15) | module Appium
type Common (line 16) | module Common
function get_log (line 25) | def get_log(type)
function get_available_log_types (line 37) | def get_available_log_types
FILE: lib/appium_lib/common/wait.rb
type Appium (line 17) | module Appium
type Common (line 18) | module Common
class Wait (line 19) | class Wait
function wait_true (line 44) | def wait_true(opts = {})
function wait (line 73) | def wait(opts = {})
FILE: lib/appium_lib/driver.rb
type Minitest (line 18) | module Minitest
class Runnable (line 20) | class Runnable
class Test (line 24) | class Test < Runnable
class Test (line 32) | class Test < Result
type Appium (line 41) | module Appium
class Driver (line 42) | class Driver
method convert_to_symbol (line 72) | def convert_to_symbol(value)
method get_cap (line 81) | def get_cap(caps, name)
method initialize (line 200) | def initialize(opts = {}, global_driver = false)
method extend_for (line 255) | def extend_for(device:, automation_name:)
method set_app_path (line 294) | def set_app_path(opts)
method set_sauce_related_values (line 306) | def set_sauce_related_values(appium_lib_opts)
method driver_attributes (line 316) | def driver_attributes
method device_is_android? (line 334) | def device_is_android?
method device_is_ios? (line 338) | def device_is_ios?
method device_is_windows? (line 342) | def device_is_windows?
method automation_name_is_uiautomator2? (line 348) | def automation_name_is_uiautomator2?
method automation_name_is_espresso? (line 354) | def automation_name_is_espresso?
method automation_name_is_xcuitest? (line 360) | def automation_name_is_xcuitest?
method action (line 374) | def action
method appium_server_version (line 389) | def appium_server_version
method platform_version (line 401) | def platform_version
method appium_client_version (line 417) | def appium_client_version
method absolute_app_path (line 429) | def self.absolute_app_path(opts)
method server_url (line 453) | def server_url
method restart (line 462) | def restart
method screenshot (line 475) | def screenshot(png_save_path)
method element_screenshot (line 489) | def element_screenshot(element, png_save_path)
method driver_quit (line 496) | def driver_quit
method window_size (line 513) | def window_size
method window_rect (line 531) | def window_rect
method start_driver (line 566) | def start_driver(http_client_ops = { http_client: nil, open_timeout:...
method set_implicit_wait (line 601) | def set_implicit_wait(wait)
method no_wait (line 612) | def no_wait
method set_wait (line 626) | def set_wait(timeout = nil)
method exists (line 643) | def exists(pre_check = 0, post_check = @default_wait)
method execute_script (line 667) | def execute_script(script, *args)
method execute_async_script (line 677) | def execute_async_script(script, *args)
method execute_driver (line 711) | def execute_driver(script: '', type: 'webdriverio', timeout_ms: nil)
method window_handles (line 717) | def window_handles
method window_handle (line 724) | def window_handle
method navigate (line 730) | def navigate
method manage (line 736) | def manage
method get (line 742) | def get(url)
method current_url (line 748) | def current_url
method title (line 754) | def title
method switch_to (line 762) | def switch_to
method find_elements (line 791) | def find_elements(*args)
method find_element (line 809) | def find_element(*args)
method find_element_by_image (line 826) | def find_element_by_image(png_img_path)
method find_elements_by_image (line 843) | def find_elements_by_image(png_img_paths)
method set_location (line 858) | def set_location(opts = {})
method log_event (line 883) | def log_event(vendor:, event:)
method log_event= (line 889) | def log_event=(log_event)
method log_events (line 909) | def log_events(type = nil)
method x (line 918) | def x
FILE: lib/appium_lib/error.rb
type Appium (line 15) | module Appium
class Error (line 16) | class Error < StandardError; end
class NoDriverInstanceError (line 19) | class NoDriverInstanceError < Appium::Error; end
class ArgumentError (line 21) | class ArgumentError < ArgumentError; end
FILE: lib/appium_lib/ios/common/errors.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
class CommandError (line 17) | class CommandError < RuntimeError
FILE: lib/appium_lib/ios/common/helper.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
class UITestElementsPrinter (line 18) | class UITestElementsPrinter < Nokogiri::XML::SAX::Document
method start_element (line 21) | def start_element(type, attrs = [])
method _print_attr (line 32) | def _print_attr(type, name, label, value, hint, visible) # rubocop...
function ios_password (line 58) | def ios_password(length = 1)
function page (line 74) | def page(opts = {})
function id (line 101) | def id(id)
function ele_index (line 109) | def ele_index(class_name, index)
function string_attr_exact (line 128) | def string_attr_exact(class_name, attr, value)
function find_ele_by_attr (line 139) | def find_ele_by_attr(class_name, attr, value)
function find_eles_by_attr (line 150) | def find_eles_by_attr(class_name, attr, value)
function string_attr_include (line 155) | def string_attr_include(class_name, attr, value)
function find_ele_by_predicate (line 163) | def find_ele_by_predicate(class_name: '*', value:)
function find_eles_by_predicate (line 175) | def find_eles_by_predicate(class_name: '*', value:)
function find_ele_by_attr_include (line 191) | def find_ele_by_attr_include(class_name, attr, value)
function find_eles_by_attr_include (line 201) | def find_eles_by_attr_include(class_name, attr, value)
function find_ele_by_predicate_include (line 209) | def find_ele_by_predicate_include(class_name: '*', value:)
function find_eles_by_predicate_include (line 221) | def find_eles_by_predicate_include(class_name: '*', value:)
function first_ele (line 234) | def first_ele(class_name)
function last_ele (line 241) | def last_ele(class_name)
function tag (line 249) | def tag(class_name)
function tags (line 257) | def tags(class_name)
function tags_include (line 268) | def tags_include(class_names:, value: nil)
function tags_exact (line 283) | def tags_exact(class_names:, value: nil)
function string_visible_contains (line 299) | def string_visible_contains(element, value)
function ele_by_json_visible_contains (line 320) | def ele_by_json_visible_contains(element, value)
function eles_by_json_visible_contains (line 329) | def eles_by_json_visible_contains(element, value)
function string_visible_exact (line 338) | def string_visible_exact(element, value)
function ele_by_json_visible_exact (line 359) | def ele_by_json_visible_exact(element, value)
function eles_by_json_visible_exact (line 368) | def eles_by_json_visible_exact(element, value)
function _all_pred (line 377) | def _all_pred(opts)
function ele_with_pred (line 391) | def ele_with_pred(opts)
function eles_with_pred (line 402) | def eles_with_pred(opts)
function _validate_object (line 406) | def _validate_object(*objects)
function _by_json (line 456) | def _by_json(opts)
function eles_by_json (line 506) | def eles_by_json(opts)
function ele_by_json (line 512) | def ele_by_json(opts)
FILE: lib/appium_lib/ios/element/alert.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
function alert_accept (line 19) | def alert_accept
function alert_dismiss (line 27) | def alert_dismiss
FILE: lib/appium_lib/ios/element/button.rb
type Appium (line 16) | module Appium
type Ios (line 17) | module Ios
function button_class (line 25) | def button_class
function button (line 33) | def button(value)
function buttons (line 44) | def buttons(value = false)
function first_button (line 52) | def first_button
function last_button (line 60) | def last_button
function button_exact (line 67) | def button_exact(value)
function buttons_exact (line 74) | def buttons_exact(value)
FILE: lib/appium_lib/ios/element/generic.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
function find (line 20) | def find(value)
function finds (line 27) | def finds(value)
function find_exact (line 34) | def find_exact(value)
function finds_exact (line 41) | def finds_exact(value)
function raise_error_if_no_element (line 47) | def raise_error_if_no_element(element)
function select_visible_elements (line 55) | def select_visible_elements(elements)
FILE: lib/appium_lib/ios/element/text.rb
type Appium (line 16) | module Appium
type Ios (line 17) | module Ios
function static_text_class (line 25) | def static_text_class
function text (line 33) | def text(value)
function texts (line 43) | def texts(value = false)
function first_text (line 51) | def first_text
function last_text (line 57) | def last_text
function text_exact (line 64) | def text_exact(value)
function texts_exact (line 71) | def texts_exact(value)
FILE: lib/appium_lib/ios/element/textfield.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
function text_field_class (line 28) | def text_field_class
function secure_text_field_class (line 33) | def secure_text_field_class
function textfield (line 42) | def textfield(value)
function textfields (line 61) | def textfields(value = false)
function first_textfield (line 69) | def first_textfield
function last_textfield (line 75) | def last_textfield
function textfield_exact (line 85) | def textfield_exact(value)
function textfields_exact (line 92) | def textfields_exact(value)
function _textfield_visible (line 99) | def _textfield_visible
function _textfield_exact_string (line 104) | def _textfield_exact_string(value)
function _textfield_contains_string (line 111) | def _textfield_contains_string(value)
FILE: lib/appium_lib/ios/ios.rb
type Appium (line 26) | module Appium
type Ios (line 27) | module Ios
class Bridge (line 28) | class Bridge
method for (line 29) | def self.for(target)
FILE: lib/appium_lib/ios/xcuitest.rb
type Appium (line 20) | module Appium
type Ios (line 21) | module Ios
type Xcuitest (line 22) | module Xcuitest
FILE: lib/appium_lib/ios/xcuitest/bridge.rb
type Appium (line 17) | module Appium
type Ios (line 18) | module Ios
type Xcuitest (line 19) | module Xcuitest
class Bridge (line 20) | class Bridge
method for (line 21) | def self.for(target)
FILE: lib/appium_lib/ios/xcuitest/command/certificate.rb
type Appium (line 17) | module Appium
type Ios (line 18) | module Ios
type Xcuitest (line 19) | module Xcuitest
type Certificate (line 20) | module Certificate
function install_certificate (line 32) | def install_certificate(cer_file:)
FILE: lib/appium_lib/ios/xcuitest/command/gestures.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
type Xcuitest (line 17) | module Xcuitest
type Gesture (line 18) | module Gesture
function swipe (line 25) | def swipe(direction:, element: nil)
function scroll (line 46) | def scroll(direction:, distance: nil, name: nil, element: nil, t...
function pinch (line 67) | def pinch(scale:, velocity: 1.0, element: nil)
function double_tap (line 82) | def double_tap(x: nil, y: nil, element: nil)
function touch_and_hold (line 99) | def touch_and_hold(x: nil, y: nil, element: nil, duration: 1.0)
function two_finger_tap (line 112) | def two_finger_tap(element:)
function one_finger_tap (line 127) | def one_finger_tap(x:, y:, element: nil)
function drag_from_to_for_duration (line 147) | def drag_from_to_for_duration(from_x:, from_y:, to_x:, to_y:, du...
function select_picker_wheel (line 164) | def select_picker_wheel(element:, order:, offset: nil)
function alert (line 182) | def alert(action:, button_label: nil)
FILE: lib/appium_lib/ios/xcuitest/command/get_context.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
type Xcuitest (line 17) | module Xcuitest
type GetContext (line 19) | module GetContext
function xcuitest_get_contexts (line 28) | def xcuitest_get_contexts
FILE: lib/appium_lib/ios/xcuitest/command/multi_app_handler.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
type Xcuitest (line 17) | module Xcuitest
type MultiAppHandler (line 21) | module MultiAppHandler
function xcuitest_install_app (line 35) | def xcuitest_install_app(app:)
function xcuitest_app_installed? (line 48) | def xcuitest_app_installed?(bundle_id:)
function xcuitest_remove_app (line 62) | def xcuitest_remove_app(bundle_id:)
function xcuitest_launch_app (line 76) | def xcuitest_launch_app(bundle_id:)
function xcuitest_terminate_app (line 91) | def xcuitest_terminate_app(bundle_id:)
function xcuitest_query_app_status (line 112) | def xcuitest_query_app_status(bundle_id:)
function xcuitest_activate_app (line 127) | def xcuitest_activate_app(bundle_id:)
FILE: lib/appium_lib/ios/xcuitest/command/pasteboard.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
type Xcuitest (line 17) | module Xcuitest
type PasteBoard (line 18) | module PasteBoard
function set_pasteboard (line 26) | def set_pasteboard(content:, encoding: nil)
function get_pasteboard (line 38) | def get_pasteboard(encoding: nil)
FILE: lib/appium_lib/ios/xcuitest/command/source.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
type Xcuitest (line 17) | module Xcuitest
type Source (line 19) | module Source
function xcuitest_source (line 25) | def xcuitest_source(format: :xml)
FILE: lib/appium_lib/ios/xcuitest/element.rb
type Appium (line 20) | module Appium
type Ios (line 21) | module Ios
type Xcuitest (line 22) | module Xcuitest
type Element (line 23) | module Element
FILE: lib/appium_lib/ios/xcuitest/element/button.rb
type Appium (line 16) | module Appium
type Ios (line 17) | module Ios
type Xcuitest (line 18) | module Xcuitest
type Element (line 19) | module Element
function button_class (line 23) | def button_class
function button (line 31) | def button(value)
function buttons (line 42) | def buttons(value = false)
function first_button (line 51) | def first_button
function last_button (line 59) | def last_button
function button_exact (line 66) | def button_exact(value)
function buttons_exact (line 73) | def buttons_exact(value)
FILE: lib/appium_lib/ios/xcuitest/element/generic.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
type Xcuitest (line 17) | module Xcuitest
type Element (line 18) | module Element
function find (line 22) | def find(value)
function finds (line 29) | def finds(value)
function find_exact (line 37) | def find_exact(value)
function finds_exact (line 44) | def finds_exact(value)
function raise_error_if_no_element (line 51) | def raise_error_if_no_element(element)
function select_visible_elements (line 59) | def select_visible_elements(elements)
FILE: lib/appium_lib/ios/xcuitest/element/text.rb
type Appium (line 16) | module Appium
type Ios (line 17) | module Ios
type Xcuitest (line 18) | module Xcuitest
type Element (line 19) | module Element
function static_text_class (line 23) | def static_text_class
function text (line 31) | def text(value)
function texts (line 41) | def texts(value = false)
function first_text (line 50) | def first_text
function last_text (line 56) | def last_text
function text_exact (line 63) | def text_exact(value)
function texts_exact (line 70) | def texts_exact(value)
FILE: lib/appium_lib/ios/xcuitest/element/textfield.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
type Xcuitest (line 17) | module Xcuitest
type Element (line 18) | module Element
function text_field_class (line 23) | def text_field_class
function secure_text_field_class (line 28) | def secure_text_field_class
function textfield (line 37) | def textfield(value)
function textfields (line 57) | def textfields(value = false)
function first_textfield (line 66) | def first_textfield
function last_textfield (line 72) | def last_textfield
function textfield_exact (line 82) | def textfield_exact(value)
function textfields_exact (line 89) | def textfields_exact(value)
function _textfield_with_predicate (line 98) | def _textfield_with_predicate
function _textfields_with_predicate (line 104) | def _textfields_with_predicate
FILE: lib/appium_lib/ios/xcuitest/helper.rb
type Appium (line 15) | module Appium
type Ios (line 16) | module Ios
type Xcuitest (line 17) | module Xcuitest
type Helper (line 18) | module Helper
function string_attr_exact (line 20) | def string_attr_exact(class_name, attr, value)
function string_attr_include (line 29) | def string_attr_include(class_name, attr, value)
function last_ele (line 40) | def last_ele(class_name)
function tag (line 51) | def tag(class_name)
function tags (line 59) | def tags(class_name)
function tags_include (line 71) | def tags_include(class_names:, value: nil)
function tags_exact (line 93) | def tags_exact(class_names:, value: nil)
FILE: lib/appium_lib/sauce_labs.rb
type Appium (line 15) | module Appium
class SauceLabs (line 16) | class SauceLabs
method initialize (line 47) | def initialize(appium_lib_opts)
method sauce_server_url? (line 67) | def sauce_server_url?
method server_url (line 80) | def server_url
FILE: lib/appium_lib/version.rb
type Appium (line 15) | module Appium
FILE: test/first_test.rb
class SampleTest (line 25) | class SampleTest < Minitest::Test
method test_test (line 26) | def test_test
Condensed preview — 141 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (617K chars).
[
{
"path": ".github/CODEOWNERS",
"chars": 13,
"preview": "* @KazuCocoa\n"
},
{
"path": ".github/ISSUE_TEMPLATE.md",
"chars": 431,
"preview": "## This is a\n* [ ] Bug report\n* [ ] Question\n* [ ] Freature Request\n\n## Summary\n\n## Environment\n* Appium version (or git"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 366,
"preview": "# Summary\n\nPlease include a summary of the change and which issue is fixed.\nPlease also include relevant motivation and "
},
{
"path": ".github/dependabot.yml",
"chars": 283,
"preview": "version: 2\nupdates:\n- package-ecosystem: bundler\n directory: \"/\"\n schedule:\n interval: weekly\n time: \"11:00\"\n o"
},
{
"path": ".github/workflows/functional-test.yml",
"chars": 4772,
"preview": "name: Functional Tests\n\non:\n # Run by manual at this time\n workflow_dispatch:\n push:\n branches: [ master ]\n pull_"
},
{
"path": ".github/workflows/pr-title.yml",
"chars": 222,
"preview": "name: Conventional Commits\non:\n pull_request:\n types: [opened, edited, synchronize, reopened]\n\njobs:\n lint:\n use"
},
{
"path": ".github/workflows/rubocop.yml",
"chars": 543,
"preview": "name: rubocop\n\non:\n push:\n branches: [ master ]\n pull_request:\n branches: [ master ]\n\njobs:\n test:\n strategy"
},
{
"path": ".gitignore",
"chars": 24,
"preview": "*.gem\n*.lock\n.DS_Store\n\n"
},
{
"path": ".rubocop.yml",
"chars": 7599,
"preview": "AllCops:\n TargetRubyVersion: 3.1\nLayout/LineLength:\n Max: 128\nMetrics/MethodLength:\n Enabled: false\nMetrics/ModuleLen"
},
{
"path": "CHANGELOG.md",
"chars": 30478,
"preview": "# Changelogs\nCommit based release not is [release_notes.md](./release_notes.md)\n\nRelease tags are https://github.com/app"
},
{
"path": "Gemfile",
"chars": 810,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "LICENSE-2.0.txt",
"chars": 11358,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "Rakefile",
"chars": 1045,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "Thorfile",
"chars": 152,
"preview": "require 'appium_thor'\n\nAppium::Thor::Config.set do\n gem_name 'appium_lib'\n github_name 'ruby_lib'\n version_file "
},
{
"path": "android_tests/Gemfile",
"chars": 673,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/LICENSE-2.0.txt",
"chars": 11358,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "android_tests/Rakefile",
"chars": 1953,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/appium.txt",
"chars": 304,
"preview": "[caps]\nautomationName = \"uiautomator2\"\nplatformName = \"android\"\ndeviceName = \"Android emulator\"\napp = \"../test_apps/api."
},
{
"path": "android_tests/flaky.txt",
"chars": 30,
"preview": "android = \"lib/android/specs/\""
},
{
"path": "android_tests/lib/android/specs/android/element/alert.rb",
"chars": 1834,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/android/element/button.rb",
"chars": 2097,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/android/element/generic.rb",
"chars": 2212,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/android/element/text.rb",
"chars": 1669,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/android/element/textfield.rb",
"chars": 2287,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/android/helper.rb",
"chars": 3288,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/android/patch.rb",
"chars": 1336,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/common/device.rb",
"chars": 2318,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/common/device_touchaction.rb",
"chars": 2929,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/common/element/window.rb",
"chars": 938,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/common/helper.rb",
"chars": 4945,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/common/patch.rb",
"chars": 2884,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/common/version.rb",
"chars": 893,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/common/web_context.rb",
"chars": 1969,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/driver.rb",
"chars": 7209,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/install.rb",
"chars": 1236,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/android/specs/sauce_labs.rb",
"chars": 1561,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/format.rb",
"chars": 1590,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/lib/run.rb",
"chars": 3624,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "android_tests/readme.md",
"chars": 1254,
"preview": "ruby_lib_android\n=====================\n\nruby_lib's Android tests. Requires `Ruby 2.2+` or better.\n\n- `rake install` Inst"
},
{
"path": "appium_lib.gemspec",
"chars": 882,
"preview": "require_relative 'lib/appium_lib/version'\n\nGem::Specification.new do |s|\n s.required_ruby_version = '>= 3.1'\n\n s.name "
},
{
"path": "contributing.md",
"chars": 1467,
"preview": "# Contributing\n\nFor features or bug fixes, please submit a pull request. Ideally there would be a test as well. The rema"
},
{
"path": "docs/android_uiautomator.md",
"chars": 791,
"preview": "# Help debugging\n\n- `adb shell uiautomator events` \n - Prints out accessibility events to the console until the conne"
},
{
"path": "docs/docs.md",
"chars": 3726,
"preview": "# Documentation\n## API Doc of Ruby Client\n- This library: http://www.rubydoc.info/github/appium/ruby_lib\n- Core: http://"
},
{
"path": "docs/ios_xcuitest.md",
"chars": 6184,
"preview": "## XCUITest\n- Over Appium1.6.0 provides `XCUITest` automation name based on WebDriverAgent.\n - [appium-xcuitest-drive"
},
{
"path": "docs/parallel.md",
"chars": 407,
"preview": "Appium 1.7.0+ supports single server and multiple sessions, and it requires Xcode 9 for iOS.\n\n# Example\n## Run tests on "
},
{
"path": "docs/w3c.md",
"chars": 2086,
"preview": "Perform touch actions for W3C module. Generate `touch` pointer action here and users can use this via `driver.action`\n\n["
},
{
"path": "grid/README.md",
"chars": 380,
"preview": "# Run Grid\n\n```bash\n$ java -jar selenium-server-standalone-2.53.1.jar -role hub -hubConfig hub_config.json\n```\n\n**note**"
},
{
"path": "grid/appium.txt.ios.example",
"chars": 351,
"preview": "[caps]\nplatformName = \"ios\"\nplatformVersion = \"11.4\"\ndeviceName =\"iPhone 11\"\nautomationName = 'XCUITest'\napp = \"/absolut"
},
{
"path": "grid/config.json",
"chars": 487,
"preview": "{\n \"capabilities\":\n [\n {\n \"browserName\": \"iPhone 11\",\n \"version\":\"11.4\",\n \"platform\":\"ios\",\n \"m"
},
{
"path": "grid/hub_config.json",
"chars": 332,
"preview": "{\n \"port\": 4444,\n \"newSessionWaitTimeout\": -1,\n \"servlets\" : [],\n \"withoutServlets\": [],\n \"custom\": {},\n \"capabili"
},
{
"path": "grid/hub_config_3.json",
"chars": 556,
"preview": "{\n \"capabilities\":\n [\n {\n \"browserName\": \"iPhone 11\",\n \"version\":\"11.4\",\n \"maxInstances\": 1,\n \""
},
{
"path": "ios_tests/Gemfile",
"chars": 695,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/LICENSE-2.0.txt",
"chars": 11358,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "ios_tests/Rakefile",
"chars": 2897,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/appium.txt",
"chars": 303,
"preview": "[caps]\nplatformName = \"ios\"\nplatformVersion = \"18.5\"\ndeviceName =\"iPhone 16 Plus\"\nautomationName = 'XCUITest'\napp = \"../"
},
{
"path": "ios_tests/data/unicode.txt",
"chars": 1,
"preview": "®"
},
{
"path": "ios_tests/flaky.txt",
"chars": 22,
"preview": "ios = \"lib/ios/specs/\""
},
{
"path": "ios_tests/lib/common.rb",
"chars": 1774,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/format.rb",
"chars": 937,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/common/element/window.rb",
"chars": 1139,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/common/helper.rb",
"chars": 8634,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/common/patch.rb",
"chars": 1282,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/common/version.rb",
"chars": 941,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/common/web_context.rb",
"chars": 1705,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/device/device.rb",
"chars": 2093,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/device/image_comparison.rb",
"chars": 1168,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/driver.rb",
"chars": 6169,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/ios/command/multi_app_handler.rb",
"chars": 1860,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/ios/command/pasteboard.rb",
"chars": 1158,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/ios/command/source.rb",
"chars": 896,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/ios/element/alert.rb",
"chars": 1544,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/ios/element/button.rb",
"chars": 2218,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/ios/element/generic.rb",
"chars": 1498,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/ios/element/text.rb",
"chars": 2204,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/ios/element/textfield.rb",
"chars": 3411,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/ios/helper.rb",
"chars": 2278,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/ios/mobile_methods.rb",
"chars": 1291,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/ios/patch.rb",
"chars": 1192,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/ios/specs/ios/xcuitest_gestures.rb",
"chars": 3437,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/lib/run.rb",
"chars": 730,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/parallel/test.rb",
"chars": 2390,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "ios_tests/readme.md",
"chars": 1243,
"preview": "ruby_lib_ios\n=====================\n\nruby_lib's iOS tests. Requires `Ruby 2.2+` or better.\n\n- `rake install` Install gems"
},
{
"path": "lib/appium_lib/android/android.rb",
"chars": 1120,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/common/command/command.rb",
"chars": 1185,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/common/helper.rb",
"chars": 12290,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/element/alert.rb",
"chars": 1548,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/element/button.rb",
"chars": 4161,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/element/generic.rb",
"chars": 3232,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/element/text.rb",
"chars": 2034,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/element/textfield.rb",
"chars": 2058,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/espresso/bridge.rb",
"chars": 1002,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/espresso/element/button.rb",
"chars": 5124,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/espresso/element/generic.rb",
"chars": 2465,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/espresso/element.rb",
"chars": 814,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/espresso/helper.rb",
"chars": 2137,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/espresso.rb",
"chars": 818,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/uiautomator2/bridge.rb",
"chars": 1018,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/uiautomator2/element/button.rb",
"chars": 4982,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/uiautomator2/element.rb",
"chars": 787,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/uiautomator2/helper.rb",
"chars": 4282,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/android/uiautomator2.rb",
"chars": 838,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/appium.rb",
"chars": 8451,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/common/command.rb",
"chars": 658,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/common/device.rb",
"chars": 671,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/common/helper.rb",
"chars": 8408,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/common/http_client.rb",
"chars": 956,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/common/log.rb",
"chars": 1310,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/common/wait.rb",
"chars": 3577,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/driver.rb",
"chars": 29176,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/error.rb",
"chars": 770,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/common/errors.rb",
"chars": 659,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/common/helper.rb",
"chars": 18665,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/element/alert.rb",
"chars": 1087,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/element/button.rb",
"chars": 2843,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/element/generic.rb",
"chars": 1849,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/element/text.rb",
"chars": 2840,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/element/textfield.rb",
"chars": 3738,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/ios.rb",
"chars": 977,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/bridge.rb",
"chars": 1217,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/command/certificate.rb",
"chars": 1479,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/command/gestures.rb",
"chars": 9532,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/command/get_context.rb",
"chars": 1209,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/command/multi_app_handler.rb",
"chars": 5472,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/command/pasteboard.rb",
"chars": 1689,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/command/source.rb",
"chars": 1187,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/command.rb",
"chars": 768,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/element/button.rb",
"chars": 3190,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/element/generic.rb",
"chars": 2207,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/element/text.rb",
"chars": 3139,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/element/textfield.rb",
"chars": 3825,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/element.rb",
"chars": 888,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest/helper.rb",
"chars": 4201,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/ios/xcuitest.rb",
"chars": 846,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/sauce_labs.rb",
"chars": 3368,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib/version.rb",
"chars": 783,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "lib/appium_lib.rb",
"chars": 814,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": "readme.md",
"chars": 4103,
"preview": "# appium_lib\n\n[](http://badge.fury.io/rb/appium_lib)\n\n["
},
{
"path": "test/first_test.rb",
"chars": 923,
"preview": "# frozen_string_literal: true\n\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
}
]
// ... and 2 more files (download for full content)
About this extraction
This page contains the full source code of the appium/ruby_lib GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 141 files (579.2 KB), approximately 183.9k tokens, and a symbol index with 904 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.