diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index a324a9b7..eca3f55c 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -1,19 +1,19 @@ # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops&tabs=yaml variables: - MIN_VM_IMAGE: macOS-12 - MIN_XCODE_VERSION: 13.1 - MIN_PLATFORM_VERSION: 15.0 - MIN_TV_PLATFORM_VERSION: 15.0 - MIN_TV_DEVICE_NAME: Apple TV 4K (2nd generation) - MIN_IPHONE_DEVICE_NAME: iPhone 11 - MIN_IPAD_DEVICE_NAME: iPad Pro (11-inch) (3rd generation) - MAX_VM_IMAGE: macOS-12 - MAX_XCODE_VERSION: 14.2 - MAX_PLATFORM_VERSION: 16.2 - MAX_PLATFORM_VERSION_TV: 16.1 - MAX_IPHONE_DEVICE_NAME: iPhone 13 - MAX_TV_DEVICE_NAME: Apple TV 4K (2nd generation) - MAX_IPAD_DEVICE_NAME: iPad Pro (11-inch) (3rd generation) + MIN_VM_IMAGE: macOS-13 + MIN_XCODE_VERSION: 14.3.1 + MIN_PLATFORM_VERSION: 16.4 + MIN_TV_PLATFORM_VERSION: 16.4 + MIN_TV_DEVICE_NAME: Apple TV 4K (3rd generation) + MIN_IPHONE_DEVICE_NAME: iPhone 14 Plus + MIN_IPAD_DEVICE_NAME: iPad Pro (11-inch) (4th generation) + MAX_VM_IMAGE: macOS-14 + MAX_XCODE_VERSION: 15.4 + MAX_PLATFORM_VERSION: 17.5 + MAX_PLATFORM_VERSION_TV: 17.5 + MAX_IPHONE_DEVICE_NAME: iPhone 15 Plus + MAX_TV_DEVICE_NAME: Apple TV 4K (3rd generation) + MAX_IPAD_DEVICE_NAME: iPad Air 11-inch (M2) DEFAULT_NODE_VERSION: "18.x" trigger: diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 84930aea..00000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -Resources -coverage -build diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 3d7db084..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "extends": ["@appium/eslint-config-appium-ts"], - "overrides": [ - { - "files": "test/**/*.js", - "rules": { - "func-names": "off", - "@typescript-eslint/no-var-requires": "off" - } - }, - { - "files": "Scripts/**/*.js", - "parserOptions": {"sourceType": "script"}, - "rules": { - "@typescript-eslint/no-var-requires": "off" - } - }, - { - "files": "ci-jobs/scripts/*.js", - "parserOptions": {"sourceType": "script"}, - "rules": { - "@typescript-eslint/no-var-requires": "off" - } - } - ], - "rules": { - "require-await": "error" - } -} diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index e5c1ebad..49785ee2 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -2,17 +2,31 @@ name: Functional Tests on: [pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: test: - env: - CI: true - _FORCE_LOGS: 1 - XCODE_VERSION: 13.4 - DEVICE_NAME: iPhone 11 - PLATFORM_VERSION: 15.5 - # https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md - runs-on: macos-12 + strategy: + fail-fast: false + matrix: + test_targets: + - HOST_OS: 'macos-15' + XCODE_VERSION: '26.0' + IOS_VERSION: '26.0' + IOS_MODEL: iPhone 17 + - HOST_OS: 'macos-15' + XCODE_VERSION: '16.4' + IOS_VERSION: '18.4' + IOS_MODEL: iPhone 16 Plus + - HOST_OS: 'macos-14' + XCODE_VERSION: '15.4' + IOS_VERSION: '17.5' + IOS_MODEL: iPhone 15 Plus + + # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md + runs-on: ${{matrix.test_targets.HOST_OS}} steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 @@ -20,17 +34,28 @@ jobs: node-version: lts/* - uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: "${{ env.XCODE_VERSION }}" + xcode-version: ${{matrix.test_targets.XCODE_VERSION}} - run: | npm install mkdir -p ./Resources/WebDriverAgent.bundle name: Install dev dependencies - - run: | - target_sim_id=$(xcrun simctl list devices available | grep "$DEVICE_NAME (" | cut -d "(" -f2 | cut -d ")" -f1) + - name: Prepare iOS simulator + env: + DEVICE_NAME: ${{matrix.test_targets.IOS_MODEL}} + PLATFORM_VERSION: ${{matrix.test_targets.IOS_VERSION}} + run: | open -Fn "$(xcode-select -p)/Applications/Simulator.app" - xcrun simctl bootstatus $target_sim_id -b - name: Preboot Simulator + udid=$(xcrun simctl list devices available -j | \ + node -p "Object.entries(JSON.parse(fs.readFileSync(0)).devices).filter((x) => x[0].includes('$PLATFORM_VERSION'.replace('.', '-'))).reduce((acc, x) => [...acc, ...x[1]], []).find(({name}) => name === '$DEVICE_NAME').udid") + xcrun simctl bootstatus $udid -b + xcrun simctl shutdown $udid - run: npm run e2e-test name: Run functional tests + env: + CI: true + _FORCE_LOGS: 1 + _LOG_TIMESTAMP: 1 + DEVICE_NAME: ${{matrix.test_targets.IOS_MODEL}} + PLATFORM_VERSION: ${{matrix.test_targets.IOS_VERSION}} diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index 9a192aec..0ff687ca 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -8,7 +8,7 @@ jobs: name: https://www.conventionalcommits.org runs-on: ubuntu-latest steps: - - uses: beemojs/conventional-pr-action@v2 + - uses: beemojs/conventional-pr-action@v3 with: config-preset: angular env: diff --git a/.github/workflows/publish.js.yml b/.github/workflows/publish.js.yml index 92299e7a..38dc80e0 100644 --- a/.github/workflows/publish.js.yml +++ b/.github/workflows/publish.js.yml @@ -8,16 +8,21 @@ on: push: branches: [ master ] +permissions: + contents: write + pull-requests: write + issues: write + id-token: write # to enable use of OIDC for trusted publishing and npm provenance + jobs: build: - runs-on: macos-13 + runs-on: macos-15 env: - XCODE_VERSION: 14.3.1 - ZIP_PKG_NAME_IOS: "WebDriverAgentRunner-Runner.zip" - PKG_PATH_IOS: "appium_wda_ios" - ZIP_PKG_NAME_TVOS: "WebDriverAgentRunner_tvOS-Runner.zip" - PKG_PATH_TVOS: "appium_wda_tvos" + XCODE_VERSION: 16.3 + # Available destination for simulators depend on Xcode version. + DESTINATION_SIM: platform=iOS Simulator,name=iPhone 16 Plus + DESTINATION_SIM_TVOS: platform=tvOS Simulator,name=Apple TV 4K (3rd generation) steps: - uses: actions/checkout@v2 @@ -36,41 +41,62 @@ jobs: name: Run test # building WDA packages - - name: Build iOS - run: | - xcodebuild clean build-for-testing \ - -project WebDriverAgent.xcodeproj \ - -derivedDataPath $PKG_PATH_IOS \ - -scheme WebDriverAgentRunner \ - -destination generic/platform=iOS \ - CODE_SIGNING_ALLOWED=NO ARCHS=arm64 - - name: Creating a zip of WebDriverAgentRunner-Runner.app for iOS after removing test frameworks - run: | - pushd appium_wda_ios/Build/Products/Debug-iphoneos - rm -rf WebDriverAgentRunner-Runner.app/Frameworks/XC*.framework - zip -r $ZIP_PKG_NAME_IOS WebDriverAgentRunner-Runner.app - popd - mv $PKG_PATH_IOS/Build/Products/Debug-iphoneos/$ZIP_PKG_NAME_IOS ./ - - name: Build tvOS - run: | - xcodebuild clean build-for-testing \ - -project WebDriverAgent.xcodeproj \ - -derivedDataPath $PKG_PATH_TVOS \ - -scheme WebDriverAgentRunner_tvOS \ - -destination generic/platform=tvOS \ - CODE_SIGNING_ALLOWED=NO ARCHS=arm64 - - name: Creating a zip of WebDriverAgentRunner-Runner.app for tvOS after removing test frameworks - run: | - pushd appium_wda_tvos/Build/Products/Debug-appletvos - rm -rf WebDriverAgentRunner_tvOS-Runner.app/Frameworks/XC*.framework - zip -r $ZIP_PKG_NAME_TVOS WebDriverAgentRunner_tvOS-Runner.app - popd - mv $PKG_PATH_TVOS/Build/Products/Debug-appletvos/$ZIP_PKG_NAME_TVOS ./ + - name: Building iOS + run: sh $GITHUB_WORKSPACE/Scripts/ci/build-real.sh + env: + DERIVED_DATA_PATH: appium_wda_ios + SCHEME: WebDriverAgentRunner + DESTINATION: generic/platform=iOS + WD: appium_wda_ios/Build/Products/Debug-iphoneos + ZIP_PKG_NAME: WebDriverAgentRunner-Runner.zip + - name: Building tvOS + run: sh $GITHUB_WORKSPACE/Scripts/ci/build-real.sh + env: + DERIVED_DATA_PATH: appium_wda_tvos + SCHEME: WebDriverAgentRunner_tvOS + DESTINATION: generic/platform=tvOS + WD: appium_wda_tvos/Build/Products/Debug-appletvos + ZIP_PKG_NAME: WebDriverAgentRunner_tvOS-Runner.zip + - name: Building iOS sim arm64 + run: sh $GITHUB_WORKSPACE/Scripts/ci/build-sim.sh + env: + DERIVED_DATA_PATH: appium_wda_ios_sim_arm64 + SCHEME: WebDriverAgentRunner + DESTINATION: ${{ env.DESTINATION_SIM }} + WD: appium_wda_ios_sim_arm64/Build/Products/Debug-iphonesimulator + ZIP_PKG_NAME: WebDriverAgentRunner-Build-Sim-arm64.zip + ARCHS: arm64 + - name: Building iOS sim x86_64 + run: sh $GITHUB_WORKSPACE/Scripts/ci/build-sim.sh + env: + DERIVED_DATA_PATH: appium_wda_ios_sim_x86_64 + SCHEME: WebDriverAgentRunner + DESTINATION: ${{ env.DESTINATION_SIM }} + WD: appium_wda_ios_sim_x86_64/Build/Products/Debug-iphonesimulator + ZIP_PKG_NAME: WebDriverAgentRunner-Build-Sim-x86_64.zip + ARCHS: x86_64 + - name: Building tvOS sim arm64 + run: sh $GITHUB_WORKSPACE/Scripts/ci/build-sim.sh + env: + DERIVED_DATA_PATH: appium_wda_tvos_sim_arm64 + SCHEME: WebDriverAgentRunner_tvOS + DESTINATION: ${{ env.DESTINATION_SIM_TVOS }} + WD: appium_wda_tvos_sim_arm64/Build/Products/Debug-appletvsimulator + ZIP_PKG_NAME: WebDriverAgentRunner_tvOS-Build-Sim-arm64.zip + ARCHS: arm64 + - name: Building tvOS sim x86_64 + run: sh $GITHUB_WORKSPACE/Scripts/ci/build-sim.sh + env: + DERIVED_DATA_PATH: appium_wda_tvos_sim_x86_64 + SCHEME: WebDriverAgentRunner_tvOS + DESTINATION: ${{ env.DESTINATION_SIM_TVOS }} + WD: appium_wda_tvos_sim_x86_64/Build/Products/Debug-appletvsimulator + ZIP_PKG_NAME: WebDriverAgentRunner_tvOS-Build-Sim-x86_64.zip + ARCHS: x86_64 # release tasks - run: npx semantic-release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} name: Release diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index ef98e4ca..6ff82176 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -7,11 +7,11 @@ jobs: prepare_matrix: runs-on: ubuntu-latest outputs: - versions: ${{ steps.generate-matrix.outputs.versions }} + versions: ${{ steps.generate-matrix.outputs.lts }} steps: - - name: Select 3 most recent LTS versions of Node.js + - name: Select all current LTS versions of Node.js id: generate-matrix - run: echo "versions=$(curl -s https://endoflife.date/api/nodejs.json | jq -c '[[.[] | select(.lts != false)][:3] | .[].cycle | tonumber]')" >> "$GITHUB_OUTPUT" + uses: msimerson/node-lts-versions@v1 test: needs: diff --git a/.github/workflows/wda-package.yml b/.github/workflows/wda-package.yml index b4b4223f..37794e76 100644 --- a/.github/workflows/wda-package.yml +++ b/.github/workflows/wda-package.yml @@ -8,10 +8,10 @@ on: - completed env: - HOST: macos-13 - XCODE_VERSION: 14.3.1 - DESTINATION_SIM: platform=iOS Simulator,name=iPhone 14 Pro - DESTINATION_SIM_tvOS: platform=tvOS Simulator,name=Apple TV + HOST: macos-15 + XCODE_VERSION: 16.3 + DESTINATION_SIM: platform=iOS Simulator,name=iPhone 16 Plus + DESTINATION_SIM_tvOS: platform=tvOS Simulator,name=Apple TV 4K (3rd generation) jobs: host_machine: @@ -29,12 +29,14 @@ jobs: runs-on: ${{ needs.host_machine.outputs.host }} env: + PKG_NAME_IOS: "WebDriverAgentRunner-Runner" ZIP_PKG_NAME_IOS: "WebDriverAgentRunner-Runner.zip" + PKG_NAME_TVOS: "WebDriverAgentRunner_tvOS-Runner" ZIP_PKG_NAME_TVOS: "WebDriverAgentRunner_tvOS-Runner.zip" steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: "${{ env.XCODE_VERSION }}" @@ -57,12 +59,14 @@ jobs: ZIP_PKG_NAME: "${{ env.ZIP_PKG_NAME_TVOS }}" - name: Upload the built generic app package for iOS - uses: actions/upload-artifact@v3.1.0 + uses: actions/upload-artifact@master with: + name: "${{ env.PKG_NAME_IOS }}" path: "${{ env.ZIP_PKG_NAME_IOS }}" - name: Upload the built generic app package for tvOS - uses: actions/upload-artifact@v3.1.0 + uses: actions/upload-artifact@master with: + name: "${{ env.PKG_NAME_TVOS }}" path: "${{ env.ZIP_PKG_NAME_TVOS }}" for_simulator_devices: @@ -72,9 +76,19 @@ jobs: strategy: matrix: - # '' is for iOS - target: ['', '_tvOS'] - arch: [x86_64, arm64] + include: + - target: '' + arch: x86_64 + simulator_name: Debug-iphonesimulator + - target: '' + arch: arm64 + simulator_name: Debug-iphonesimulator + - target: '_tvOS' + arch: x86_64 + simulator_name: Debug-appletvsimulator + - target: '_tvOS' + arch: arm64 + simulator_name: Debug-appletvsimulator steps: - name: Checkout uses: actions/checkout@v3 @@ -85,11 +99,13 @@ jobs: run: | DESTINATION=$DESTINATION_SIM${{ matrix.target }} sh $GITHUB_WORKSPACE/Scripts/ci/build-sim.sh env: - TARGET: ${{ matrix.target }} SCHEME: WebDriverAgentRunner${{ matrix.target }} ARCHS: ${{ matrix.arch }} ZIP_PKG_NAME: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" + DERIVED_DATA_PATH: wda_build + WD: wda_build/Build/Products/${{ matrix.simulator_name }} - name: Upload the built generic app package for WebDriverAgentRunner${{ matrix.target }} with ${{ matrix.arch }} - uses: actions/upload-artifact@v3.1.0 + uses: actions/upload-artifact@master with: + name: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}" path: "WebDriverAgentRunner${{ matrix.target }}-Build-Sim-${{ matrix.arch }}.zip" diff --git a/.releaserc b/.releaserc index 0cb17f22..3987c1e9 100644 --- a/.releaserc +++ b/.releaserc @@ -35,7 +35,11 @@ ["@semantic-release/github", { "assets": [ "WebDriverAgentRunner-Runner.zip", - "WebDriverAgentRunner_tvOS-Runner.zip" + "WebDriverAgentRunner_tvOS-Runner.zip", + "WebDriverAgentRunner-Build-Sim-arm64.zip", + "WebDriverAgentRunner-Build-Sim-x86_64.zip", + "WebDriverAgentRunner_tvOS-Build-Sim-arm64.zip", + "WebDriverAgentRunner_tvOS-Build-Sim-x86_64.zip" ]}] ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 36307b7a..2bb19e7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,615 @@ +## [10.2.2](https://github.com/appium/WebDriverAgent/compare/v10.2.1...v10.2.2) (2025-11-15) + +### Miscellaneous Chores + +* publish via trusted publisher ([#1068](https://github.com/appium/WebDriverAgent/issues/1068)) ([6321379](https://github.com/appium/WebDriverAgent/commit/6321379d3e97dfa846bf0ff6f0b8e8b9ef85ba1c)) + +## [10.2.1](https://github.com/appium/WebDriverAgent/compare/v10.2.0...v10.2.1) (2025-11-01) + +### Miscellaneous Chores + +* update xcodebuild commands for the new binding ip capability ([#1067](https://github.com/appium/WebDriverAgent/issues/1067)) ([d12f421](https://github.com/appium/WebDriverAgent/commit/d12f4214b958855022c21b4d700b6726740294c1)) + +## [10.2.0](https://github.com/appium/WebDriverAgent/compare/v10.1.4...v10.2.0) (2025-10-31) + +### Features + +* Let binding IP address to be configurable via USE_IP environment variable ([#1066](https://github.com/appium/WebDriverAgent/issues/1066)) ([70ed7cf](https://github.com/appium/WebDriverAgent/commit/70ed7cf0a74e0df3763b99f6155a7923dde17c9d)) + +## [10.1.4](https://github.com/appium/WebDriverAgent/compare/v10.1.3...v10.1.4) (2025-10-31) + +### Miscellaneous Chores + +* Improve type declarations ([#1065](https://github.com/appium/WebDriverAgent/issues/1065)) ([5aadcb8](https://github.com/appium/WebDriverAgent/commit/5aadcb8fa99459e7f8852f75d2549a76f3e55b07)) + +## [10.1.3](https://github.com/appium/WebDriverAgent/compare/v10.1.2...v10.1.3) (2025-10-17) + +### Miscellaneous Chores + +* **deps-dev:** bump semantic-release from 24.2.9 to 25.0.0 ([#1064](https://github.com/appium/WebDriverAgent/issues/1064)) ([6c2cffa](https://github.com/appium/WebDriverAgent/commit/6c2cffa4ee6fcd0c86ae7aa171f25cb800908932)) + +## [10.1.2](https://github.com/appium/WebDriverAgent/compare/v10.1.1...v10.1.2) (2025-10-08) + +### Miscellaneous Chores + +* Skip staleness checks for subelement lookups ([#1063](https://github.com/appium/WebDriverAgent/issues/1063)) ([ada7760](https://github.com/appium/WebDriverAgent/commit/ada77604f9fa9bfc85c61cabbd2a9f4de00aceb9)) + +## [10.1.1](https://github.com/appium/WebDriverAgent/compare/v10.1.0...v10.1.1) (2025-09-12) + +### Miscellaneous Chores + +* remove patents file ([#1061](https://github.com/appium/WebDriverAgent/issues/1061)) ([b001c4e](https://github.com/appium/WebDriverAgent/commit/b001c4e39ef71cb8b91ef7391b418f32a7ebe21c)) + +## [10.1.0](https://github.com/appium/WebDriverAgent/compare/v10.0.1...v10.1.0) (2025-09-03) + +### Features + +* Add process and bundle identifiers to the application node in the XML source ([#1055](https://github.com/appium/WebDriverAgent/issues/1055)) ([088cff2](https://github.com/appium/WebDriverAgent/commit/088cff2b2bc19ddde698ec06f1db37c6989cf392)) + +## [10.0.1](https://github.com/appium/WebDriverAgent/compare/v10.0.0...v10.0.1) (2025-08-23) + +### Miscellaneous Chores + +* **deps-dev:** bump chai from 5.3.2 to 6.0.0 ([#1053](https://github.com/appium/WebDriverAgent/issues/1053)) ([9e9ec38](https://github.com/appium/WebDriverAgent/commit/9e9ec381bd6695e1c8b89f2a9c304b12385c0134)) + +## [10.0.0](https://github.com/appium/WebDriverAgent/compare/v9.15.3...v10.0.0) (2025-08-17) + +### ⚠ BREAKING CHANGES + +* Required Node.js version has been bumped to ^20.19.0 || ^22.12.0 || >=24.0.0 +* Required npm version has been bumped to >=10 +* Required base driver version has been bumped to >=10.0.0-rc.1 + +### Features + +* Update server compatibility ([#1051](https://github.com/appium/WebDriverAgent/issues/1051)) ([f9ea1e5](https://github.com/appium/WebDriverAgent/commit/f9ea1e5e2f5306030387d5293f073b2a6fe658e7)) + +## [9.15.3](https://github.com/appium/WebDriverAgent/compare/v9.15.2...v9.15.3) (2025-08-12) + +### Miscellaneous Chores + +* Cache application instances for their PIDs ([#1049](https://github.com/appium/WebDriverAgent/issues/1049)) ([e9cbf64](https://github.com/appium/WebDriverAgent/commit/e9cbf640c21243c304b476a497f33802e0501a7d)) + +## [9.15.2](https://github.com/appium/WebDriverAgent/compare/v9.15.1...v9.15.2) (2025-08-04) + +### Miscellaneous Chores + +* bump appium-ios-device to 2.9.0 ([#1047](https://github.com/appium/WebDriverAgent/issues/1047)) ([305019d](https://github.com/appium/WebDriverAgent/commit/305019d4dde89853e44c58170e17ec23c89de2f3)) + +## [9.15.1](https://github.com/appium/WebDriverAgent/compare/v9.15.0...v9.15.1) (2025-07-17) + +### Miscellaneous Chores + +* Remove the redundant check after activating the system app ([#1043](https://github.com/appium/WebDriverAgent/issues/1043)) ([33ccba1](https://github.com/appium/WebDriverAgent/commit/33ccba1ab3bc2980349f8553fd30aa5b08141b6b)) + +## [9.15.0](https://github.com/appium/WebDriverAgent/compare/v9.14.6...v9.15.0) (2025-07-10) + +### Features + +* HTTPS support for wda-client if webDriverAgentUrl is set ([#1042](https://github.com/appium/WebDriverAgent/issues/1042)) ([f7c4193](https://github.com/appium/WebDriverAgent/commit/f7c41939c793cdbc62e9c14d8eb91e06957bb566)) + +## [9.14.6](https://github.com/appium/WebDriverAgent/compare/v9.14.5...v9.14.6) (2025-06-24) + +### Miscellaneous Chores + +* add missing arch ([#1039](https://github.com/appium/WebDriverAgent/issues/1039)) ([a8dd958](https://github.com/appium/WebDriverAgent/commit/a8dd958bd92ef685bc1798ec04e92080b798d7d2)) + +## [9.14.5](https://github.com/appium/WebDriverAgent/compare/v9.14.4...v9.14.5) (2025-06-24) + +### Miscellaneous Chores + +* keep entire app for simulators ([d2bbcc6](https://github.com/appium/WebDriverAgent/commit/d2bbcc6d7af6b8eea076e24cd18429b74eeaffd6)) + +## [9.14.4](https://github.com/appium/WebDriverAgent/compare/v9.14.3...v9.14.4) (2025-06-23) + +### Miscellaneous Chores + +* include wda sim prebuilt for gh release ([#1038](https://github.com/appium/WebDriverAgent/issues/1038)) ([4423ecb](https://github.com/appium/WebDriverAgent/commit/4423ecb4f23c50343d8ffbf56a7753b985cbab81)) + +## [9.14.3](https://github.com/appium/WebDriverAgent/compare/v9.14.2...v9.14.3) (2025-06-13) + +### Miscellaneous Chores + +* **deps-dev:** bump sinon from 20.0.0 to 21.0.0 ([#1034](https://github.com/appium/WebDriverAgent/issues/1034)) ([5b205f4](https://github.com/appium/WebDriverAgent/commit/5b205f493f35cd1744cf9e33bce21e0f9e7c3bea)) + +## [9.14.2](https://github.com/appium/WebDriverAgent/compare/v9.14.1...v9.14.2) (2025-06-10) + +### Miscellaneous Chores + +* **deps-dev:** bump @types/node from 22.15.31 to 24.0.0 ([#1033](https://github.com/appium/WebDriverAgent/issues/1033)) ([e9705d9](https://github.com/appium/WebDriverAgent/commit/e9705d964e63222daaf0710bd3b860ca2ba6850f)) + +## [9.14.1](https://github.com/appium/WebDriverAgent/compare/v9.14.0...v9.14.1) (2025-06-09) + +### Miscellaneous Chores + +* add -Wno-reserved-identifier option ([#1032](https://github.com/appium/WebDriverAgent/issues/1032)) ([005dc21](https://github.com/appium/WebDriverAgent/commit/005dc216d9f41757763fe5b1714b68697fa8ee30)) + +## [9.14.0](https://github.com/appium/WebDriverAgent/compare/v9.13.0...v9.14.0) (2025-06-09) + +### Features + +* add minimum and maximum value attributes to page source ([#1031](https://github.com/appium/WebDriverAgent/issues/1031)) ([0e4e7e7](https://github.com/appium/WebDriverAgent/commit/0e4e7e7c483b9196edae576481f4e37f99fc8705)) + +## [9.13.0](https://github.com/appium/WebDriverAgent/compare/v9.12.0...v9.13.0) (2025-06-05) + +### Features + +* expose nativeFrame attribute in XML page source ([#1029](https://github.com/appium/WebDriverAgent/issues/1029)) ([5b56a45](https://github.com/appium/WebDriverAgent/commit/5b56a453f836cbc4358ce24ae43032658467c35c)) + +## [9.12.0](https://github.com/appium/WebDriverAgent/compare/v9.11.0...v9.12.0) (2025-06-04) + +### Features + +* add accessibility traits to XML page source ([#1028](https://github.com/appium/WebDriverAgent/issues/1028)) ([2df6649](https://github.com/appium/WebDriverAgent/commit/2df6649cb532d65a8c14633591b76c90185644cb)) + +## [9.11.0](https://github.com/appium/WebDriverAgent/compare/v9.10.1...v9.11.0) (2025-06-03) + +### Features + +* Add includeHittableInSource setting for including real hittable attribute in XML source ([#1026](https://github.com/appium/WebDriverAgent/issues/1026)) ([0fa4e74](https://github.com/appium/WebDriverAgent/commit/0fa4e7417404b5975445d381d111753fe681edd4)) + +## [9.10.1](https://github.com/appium/WebDriverAgent/compare/v9.10.0...v9.10.1) (2025-05-30) + +### Miscellaneous Chores + +* Make sure the same import style is used everywhere ([#1024](https://github.com/appium/WebDriverAgent/issues/1024)) ([1c50072](https://github.com/appium/WebDriverAgent/commit/1c50072457a8b82eec3684029386ccfa9432eccc)) + +## [9.10.0](https://github.com/appium/WebDriverAgent/compare/v9.9.0...v9.10.0) (2025-05-27) + +### Features + +* Add accessibility traits of the element ([#1020](https://github.com/appium/WebDriverAgent/issues/1020)) ([9465aaf](https://github.com/appium/WebDriverAgent/commit/9465aafd5e81ef57be7f78e9f2e188d3c1ba1bee)) + +### Bug Fixes + +* Use native snapshots if hittable attribute is requested in xPath ([#1023](https://github.com/appium/WebDriverAgent/issues/1023)) ([49d26cb](https://github.com/appium/WebDriverAgent/commit/49d26cb02a8515d1a1b52b65b7cb65512dfd749b)) + +## [9.9.0](https://github.com/appium/WebDriverAgent/compare/v9.8.0...v9.9.0) (2025-05-26) + +### Features + +* Use another snapshotting mechanism for the hittable attribute calculation ([#1022](https://github.com/appium/WebDriverAgent/issues/1022)) ([13c9f45](https://github.com/appium/WebDriverAgent/commit/13c9f453d890ad9b78fa7c47728ebae33880966a)) + +## [9.8.0](https://github.com/appium/WebDriverAgent/compare/v9.7.1...v9.8.0) (2025-05-21) + +### Features + +* Add a native frame property of the element ([#1017](https://github.com/appium/WebDriverAgent/issues/1017)) ([09214c4](https://github.com/appium/WebDriverAgent/commit/09214c4228ed5a49c02adead452cb0bb8dd83b6d)) + +## [9.7.1](https://github.com/appium/WebDriverAgent/compare/v9.7.0...v9.7.1) (2025-05-21) + +### Miscellaneous Chores + +* **deps-dev:** bump conventional-changelog-conventionalcommits ([#1019](https://github.com/appium/WebDriverAgent/issues/1019)) ([7108f7f](https://github.com/appium/WebDriverAgent/commit/7108f7f79575a1758bc7f05bd4ef790fd7694784)) + +## [9.7.0](https://github.com/appium/WebDriverAgent/compare/v9.6.3...v9.7.0) (2025-05-20) + +### Features + +* add placeholderValue to page source tree ([#1016](https://github.com/appium/WebDriverAgent/issues/1016)) ([509c207](https://github.com/appium/WebDriverAgent/commit/509c207b1366dd8582ba273edcdf77bfb30f53c9)) + +## [9.6.3](https://github.com/appium/WebDriverAgent/compare/v9.6.2...v9.6.3) (2025-05-18) + +### Miscellaneous Chores + +* Move the FBDoesElementSupportInnerText helper to a separate utility file ([#1018](https://github.com/appium/WebDriverAgent/issues/1018)) ([f17b07d](https://github.com/appium/WebDriverAgent/commit/f17b07d03abb6c2100405fda04326b7c35bfb48b)) + +## [9.6.2](https://github.com/appium/WebDriverAgent/compare/v9.6.1...v9.6.2) (2025-05-01) + +### Bug Fixes + +* release element screenshot data ([#1013](https://github.com/appium/WebDriverAgent/issues/1013)) ([a85f327](https://github.com/appium/WebDriverAgent/commit/a85f3271991556941234fbc888528051b1569db1)) + +## [9.6.1](https://github.com/appium/WebDriverAgent/compare/v9.6.0...v9.6.1) (2025-04-22) + +### Bug Fixes + +* allow setting precise resolution for the MJPEG stream ([#1009](https://github.com/appium/WebDriverAgent/issues/1009)) ([3f86eda](https://github.com/appium/WebDriverAgent/commit/3f86edafda42d955929f7cca870e2b8da54ae930)) + +## [9.6.0](https://github.com/appium/WebDriverAgent/compare/v9.5.2...v9.6.0) (2025-04-20) + +### Features + +* Split custom and standard snapshotting methods ([#1008](https://github.com/appium/WebDriverAgent/issues/1008)) ([8358856](https://github.com/appium/WebDriverAgent/commit/8358856f5968977b13d5cbdafac97f3053dae56e)) + +## [9.5.2](https://github.com/appium/WebDriverAgent/compare/v9.5.1...v9.5.2) (2025-04-19) + +### Bug Fixes + +* Missing text in long text for get text/value ([#1007](https://github.com/appium/WebDriverAgent/issues/1007)) ([6603a0b](https://github.com/appium/WebDriverAgent/commit/6603a0ba384917d39389509958ccac03ad174610)) + +## [9.5.1](https://github.com/appium/WebDriverAgent/compare/v9.5.0...v9.5.1) (2025-04-10) + +### Bug Fixes + +* Make sure we don't store element snapshot in the cache ([#1001](https://github.com/appium/WebDriverAgent/issues/1001)) ([cfe052b](https://github.com/appium/WebDriverAgent/commit/cfe052bb3adb3f3b24d0a34f386c60cf1516b308)) + +## [9.5.0](https://github.com/appium/WebDriverAgent/compare/v9.4.1...v9.5.0) (2025-04-10) + +### Features + +* Add support for the autoClickAlertSelector setting ([#1002](https://github.com/appium/WebDriverAgent/issues/1002)) ([fd31b95](https://github.com/appium/WebDriverAgent/commit/fd31b9589199d0a7bc76919f6aa7c7c74c498b90)) + +## [9.4.1](https://github.com/appium/WebDriverAgent/compare/v9.4.0...v9.4.1) (2025-04-05) + +### Miscellaneous Chores + +* bump appium-ios-simulator ([445741d](https://github.com/appium/WebDriverAgent/commit/445741d03313019016d4232f49e656d50f673f16)) + +## [9.4.0](https://github.com/appium/WebDriverAgent/compare/v9.3.3...v9.4.0) (2025-04-02) + +### Features + +* Always apply the native snapshotting strategy for XCUIApplication instances ([#998](https://github.com/appium/WebDriverAgent/issues/998)) ([60f5aef](https://github.com/appium/WebDriverAgent/commit/60f5aeffdda85faffd60aba416dc9d92987f19ac)) + +## [9.3.3](https://github.com/appium/WebDriverAgent/compare/v9.3.2...v9.3.3) (2025-03-27) + +### Bug Fixes + +* Properly set snapshot lookup scope if limitXpathContextScope is disabled ([#996](https://github.com/appium/WebDriverAgent/issues/996)) ([03ca7cd](https://github.com/appium/WebDriverAgent/commit/03ca7cd27b7cd92a45b344eb661db973c5dde809)) + +## [9.3.2](https://github.com/appium/WebDriverAgent/compare/v9.3.1...v9.3.2) (2025-03-26) + +### Bug Fixes + +* Adjust limitXPathContextScope setting name ([#995](https://github.com/appium/WebDriverAgent/issues/995)) ([9789e39](https://github.com/appium/WebDriverAgent/commit/9789e393b55bc682a9a8ef5a65fba5e4dbf752ce)) + +## [9.3.1](https://github.com/appium/WebDriverAgent/compare/v9.3.0...v9.3.1) (2025-03-25) + +### Miscellaneous Chores + +* **deps-dev:** bump sinon from 19.0.5 to 20.0.0 ([#994](https://github.com/appium/WebDriverAgent/issues/994)) ([f55462f](https://github.com/appium/WebDriverAgent/commit/f55462f4fa63314dfea48670d17ee54dc5fe2d96)) + +## [9.3.0](https://github.com/appium/WebDriverAgent/compare/v9.2.0...v9.3.0) (2025-03-21) + +### Features + +* Add /window/rect W3C endpoint ([#991](https://github.com/appium/WebDriverAgent/issues/991)) ([34f9510](https://github.com/appium/WebDriverAgent/commit/34f95107997bdec63219a2fd917de899de3e198c)) + +## [9.2.0](https://github.com/appium/WebDriverAgent/compare/v9.1.0...v9.2.0) (2025-03-13) + +### Features + +* Add 'limitXpathContextScope' setting ([#988](https://github.com/appium/WebDriverAgent/issues/988)) ([9c9d8af](https://github.com/appium/WebDriverAgent/commit/9c9d8af9c98ba7b2843a42f54354b78e126d2d27)) + +## [9.1.0](https://github.com/appium/WebDriverAgent/compare/v9.0.6...v9.1.0) (2025-03-09) + +### Features + +* add placeholderValue ([#987](https://github.com/appium/WebDriverAgent/issues/987)) ([8c3a1cb](https://github.com/appium/WebDriverAgent/commit/8c3a1cb30655ed8d1a77d25bbeca71ee48c2ec3e)) + +## [9.0.6](https://github.com/appium/WebDriverAgent/compare/v9.0.5...v9.0.6) (2025-02-28) + +### Bug Fixes + +* optimize LRU cache ([#985](https://github.com/appium/WebDriverAgent/issues/985)) ([46dc417](https://github.com/appium/WebDriverAgent/commit/46dc417da9f4a843838b414c0b154d6f478dbc0b)) + +## [9.0.5](https://github.com/appium/WebDriverAgent/compare/v9.0.4...v9.0.5) (2025-02-26) + +### Bug Fixes + +* add autorelease pool to drain temporary objects ([#983](https://github.com/appium/WebDriverAgent/issues/983)) ([f92f1cd](https://github.com/appium/WebDriverAgent/commit/f92f1cde0fe914086103a110844bbe3bc0e3c4a6)) + +## [9.0.4](https://github.com/appium/WebDriverAgent/compare/v9.0.3...v9.0.4) (2025-02-21) + +### Bug Fixes + +* Accept reqBasePath proxy option ([#982](https://github.com/appium/WebDriverAgent/issues/982)) ([19efbdd](https://github.com/appium/WebDriverAgent/commit/19efbdd69ff9edff20c0c318bd39c29963d4d51d)) + +## [9.0.3](https://github.com/appium/WebDriverAgent/compare/v9.0.2...v9.0.3) (2025-02-05) + +### Bug Fixes + +* add nullable signature ([#979](https://github.com/appium/WebDriverAgent/issues/979)) ([34b303c](https://github.com/appium/WebDriverAgent/commit/34b303c4e226d6a75a45a14eee7ca5e253e67737)) + +## [9.0.2](https://github.com/appium/WebDriverAgent/compare/v9.0.1...v9.0.2) (2025-02-03) + +### Bug Fixes + +* update docs link in xcodebuild error message ([#978](https://github.com/appium/WebDriverAgent/issues/978)) ([ea3863a](https://github.com/appium/WebDriverAgent/commit/ea3863a67d5cfa8bc2e48a1dc2c59052acd47937)) + +## [9.0.1](https://github.com/appium/WebDriverAgent/compare/v9.0.0...v9.0.1) (2025-01-17) + +### Miscellaneous Chores + +* Optimize stable instance retrieval ([#973](https://github.com/appium/WebDriverAgent/issues/973)) ([f2c752d](https://github.com/appium/WebDriverAgent/commit/f2c752db4707b3864efb62b95b64abb487d28e4b)) + +## [9.0.0](https://github.com/appium/WebDriverAgent/compare/v8.12.2...v9.0.0) (2025-01-16) + +### ⚠ BREAKING CHANGES + +* snapshotTimeout and customSnapshotTimeout settings have been removed as a result of the custom snapshotting logic removal + +### Features + +* Refactor snapshotting mechanism ([#970](https://github.com/appium/WebDriverAgent/issues/970)) ([08f1306](https://github.com/appium/WebDriverAgent/commit/08f13060119c710f53b34a98c95683287c0365a0)) + +## [8.12.2](https://github.com/appium/WebDriverAgent/compare/v8.12.1...v8.12.2) (2025-01-13) + +### Miscellaneous Chores + +* Exclude element visibility and accessibility info from the accessibility audit details ([#968](https://github.com/appium/WebDriverAgent/issues/968)) ([f62afc3](https://github.com/appium/WebDriverAgent/commit/f62afc372c123bdd8dd7bb493f653bb128144d24)) + +## [8.12.1](https://github.com/appium/WebDriverAgent/compare/v8.12.0...v8.12.1) (2025-01-03) + +### Miscellaneous Chores + +* Bump eslint ([#965](https://github.com/appium/WebDriverAgent/issues/965)) ([17f49ec](https://github.com/appium/WebDriverAgent/commit/17f49ec5a54e97b0ef0d20a3e39fc96b32575e43)) + +## [8.12.0](https://github.com/appium/WebDriverAgent/compare/v8.11.3...v8.12.0) (2024-12-13) + +### Features + +* look for critical notification in respectSystemAlerts ([#962](https://github.com/appium/WebDriverAgent/issues/962)) ([916c8c5](https://github.com/appium/WebDriverAgent/commit/916c8c557a9366608df211f33b5b7fbb0354dad3)) + +## [8.11.3](https://github.com/appium/WebDriverAgent/compare/v8.11.2...v8.11.3) (2024-12-06) + +### Miscellaneous Chores + +* **deps:** bump @appium/support from 5.1.8 to 6.0.0 ([#960](https://github.com/appium/WebDriverAgent/issues/960)) ([dbeb09c](https://github.com/appium/WebDriverAgent/commit/dbeb09c89f8c02e00a7bdffe7899650d435f3575)) + +## [8.11.2](https://github.com/appium/WebDriverAgent/compare/v8.11.1...v8.11.2) (2024-12-03) + +### Miscellaneous Chores + +* **deps-dev:** bump mocha from 10.8.2 to 11.0.1 ([#959](https://github.com/appium/WebDriverAgent/issues/959)) ([55b49c8](https://github.com/appium/WebDriverAgent/commit/55b49c83581c9e88f70806d98015238de3104f19)) + +## [8.11.1](https://github.com/appium/WebDriverAgent/compare/v8.11.0...v8.11.1) (2024-11-11) + +### Miscellaneous Chores + +* bump appium-ios-device ([#955](https://github.com/appium/WebDriverAgent/issues/955)) ([021f349](https://github.com/appium/WebDriverAgent/commit/021f34901866f4a7870914c00781b83bd0cbddc4)) + +## [8.11.0](https://github.com/appium/WebDriverAgent/compare/v8.10.1...v8.11.0) (2024-11-11) + +### Features + +* Add support for excluded_attributes in JSON source hierarchy ([#953](https://github.com/appium/WebDriverAgent/issues/953)) ([6112223](https://github.com/appium/WebDriverAgent/commit/6112223b21026fae5545fe1b1433a09c67ff524b)) + +## [8.10.1](https://github.com/appium/WebDriverAgent/compare/v8.10.0...v8.10.1) (2024-11-10) + +### Miscellaneous Chores + +* remove unnecessary lines ([#954](https://github.com/appium/WebDriverAgent/issues/954)) ([940df80](https://github.com/appium/WebDriverAgent/commit/940df80937381b481a2762fbf86b6249804591bd)) + +## [8.10.0](https://github.com/appium/WebDriverAgent/compare/v8.9.4...v8.10.0) (2024-11-07) + +### Features + +* add useClearTextShortcut setting ([#952](https://github.com/appium/WebDriverAgent/issues/952)) ([61bc051](https://github.com/appium/WebDriverAgent/commit/61bc051180d691d26233c66a5a76ed20b7fa09d2)) + +## [8.9.4](https://github.com/appium/WebDriverAgent/compare/v8.9.3...v8.9.4) (2024-10-17) + +### Bug Fixes + +* Consider transient overlay windows when respectSystemAlerts is enabled ([#946](https://github.com/appium/WebDriverAgent/issues/946)) ([f0bdce7](https://github.com/appium/WebDriverAgent/commit/f0bdce7eb8fdb13d2309d28e936950c77f006b20)) + +## [8.9.3](https://github.com/appium/WebDriverAgent/compare/v8.9.2...v8.9.3) (2024-10-07) + +### Miscellaneous Chores + +* remove unused FBBaseActionsParser and cleanup imports in FBConfiguration ([#943](https://github.com/appium/WebDriverAgent/issues/943)) ([a2173d0](https://github.com/appium/WebDriverAgent/commit/a2173d05df8ef831310e805a8e6a8a8d17725201)) + +## [8.9.2](https://github.com/appium/WebDriverAgent/compare/v8.9.1...v8.9.2) (2024-09-13) + +### Miscellaneous Chores + +* **deps-dev:** bump sinon from 18.0.1 to 19.0.1 ([#938](https://github.com/appium/WebDriverAgent/issues/938)) ([3ef0093](https://github.com/appium/WebDriverAgent/commit/3ef009317801dca47efe34bd048d3cab2e644ee2)) + +## [8.9.1](https://github.com/appium/WebDriverAgent/compare/v8.9.0...v8.9.1) (2024-08-09) + +### Bug Fixes + +* Update swizzling of waitForQuiescenceIncludingAnimationsIdle: API for Xcode16-beta5 ([#935](https://github.com/appium/WebDriverAgent/issues/935)) ([2ccc436](https://github.com/appium/WebDriverAgent/commit/2ccc436991ca880a1dfdec688dc8167008fe382d)) + +## [8.9.0](https://github.com/appium/WebDriverAgent/compare/v8.8.0...v8.9.0) (2024-08-07) + +### Features + +* Add idleTimeoutMs param to the openUrl call ([#933](https://github.com/appium/WebDriverAgent/issues/933)) ([5e98841](https://github.com/appium/WebDriverAgent/commit/5e98841f56eda6454d67d813b921bfcf98f1ff78)) + +### Bug Fixes + +* Revert the logic to open the default URL in Safari via deeplink ([#932](https://github.com/appium/WebDriverAgent/issues/932)) ([7c51145](https://github.com/appium/WebDriverAgent/commit/7c5114518509c9a399845283eca7708248fb838f)) + +## [8.8.0](https://github.com/appium/WebDriverAgent/compare/v8.7.12...v8.8.0) (2024-08-06) + +### Features + +* Open the default URL in Safari upon session startup ([#929](https://github.com/appium/WebDriverAgent/issues/929)) ([97cf91d](https://github.com/appium/WebDriverAgent/commit/97cf91de34dc53e5f75f91829dc43224101c1b45)) + +## [8.7.12](https://github.com/appium/WebDriverAgent/compare/v8.7.11...v8.7.12) (2024-08-02) + +### Miscellaneous Chores + +* Replace fancy-log dependency with appium logger ([#928](https://github.com/appium/WebDriverAgent/issues/928)) ([5d2ec24](https://github.com/appium/WebDriverAgent/commit/5d2ec249488655451e2d46384e560fee7e08e840)) + +## [8.7.11](https://github.com/appium/WebDriverAgent/compare/v8.7.10...v8.7.11) (2024-07-29) + +### Bug Fixes + +* Respond to /health with a proper HTML ([#925](https://github.com/appium/WebDriverAgent/issues/925)) ([42c519f](https://github.com/appium/WebDriverAgent/commit/42c519f9df7beec81175fd38af388975d6f6b800)) + +## [8.7.10](https://github.com/appium/WebDriverAgent/compare/v8.7.9...v8.7.10) (2024-07-29) + +### Miscellaneous Chores + +* **deps-dev:** bump @types/node from 20.14.13 to 22.0.0 ([#926](https://github.com/appium/WebDriverAgent/issues/926)) ([1699023](https://github.com/appium/WebDriverAgent/commit/1699023086a243c3d86ddae4da8342c6beda3f48)) + +## [8.7.9](https://github.com/appium/WebDriverAgent/compare/v8.7.8...v8.7.9) (2024-07-21) + +### Miscellaneous Chores + +* keep error handling for the future possible usage ([#921](https://github.com/appium/WebDriverAgent/issues/921)) ([2f90739](https://github.com/appium/WebDriverAgent/commit/2f90739340d70073b48c703b36b9a313d3618972)) + +## [8.7.8](https://github.com/appium/WebDriverAgent/compare/v8.7.7...v8.7.8) (2024-07-18) + +### Bug Fixes + +* do nothing for an empty array in w3c actions ([#919](https://github.com/appium/WebDriverAgent/issues/919)) ([9e70ec1](https://github.com/appium/WebDriverAgent/commit/9e70ec1dbec1d1844278a58297a5b956ebaeb7fc)) + +## [8.7.7](https://github.com/appium/WebDriverAgent/compare/v8.7.6...v8.7.7) (2024-07-18) + +### Bug Fixes + +* Pass-through modifier keys ([#918](https://github.com/appium/WebDriverAgent/issues/918)) ([29d0e5c](https://github.com/appium/WebDriverAgent/commit/29d0e5cb2a19809e1babb06e5adaa49b43c754a5)) + +## [8.7.6](https://github.com/appium/WebDriverAgent/compare/v8.7.5...v8.7.6) (2024-07-02) + +### Miscellaneous Chores + +* Simplify xcodebuild lines monitoring ([#916](https://github.com/appium/WebDriverAgent/issues/916)) ([87678f2](https://github.com/appium/WebDriverAgent/commit/87678f260c98b3a3bc3d37017e9ef39098ccb3c4)) + +## [8.7.5](https://github.com/appium/WebDriverAgent/compare/v8.7.4...v8.7.5) (2024-06-26) + +### Bug Fixes + +* Respect wdaRemotePort capability for real devices ([#915](https://github.com/appium/WebDriverAgent/issues/915)) ([03ea143](https://github.com/appium/WebDriverAgent/commit/03ea1439a9cc5b6495be60707bc474e3ae9bdb06)) + +## [8.7.4](https://github.com/appium/WebDriverAgent/compare/v8.7.3...v8.7.4) (2024-06-20) + +### Miscellaneous Chores + +* Bump chai and chai-as-promised ([#913](https://github.com/appium/WebDriverAgent/issues/913)) ([9086783](https://github.com/appium/WebDriverAgent/commit/90867832ec3077f0036938aa68a168a5702fc90a)) + +## [8.7.3](https://github.com/appium/WebDriverAgent/compare/v8.7.2...v8.7.3) (2024-06-12) + +### Miscellaneous Chores + +* **deps:** bump @appium/support from 4.5.0 to 5.0.3 ([#910](https://github.com/appium/WebDriverAgent/issues/910)) ([936005b](https://github.com/appium/WebDriverAgent/commit/936005b458e7b5b64b60d9bda37d45bb5a90e615)) + +## [8.7.2](https://github.com/appium/WebDriverAgent/compare/v8.7.1...v8.7.2) (2024-06-04) + +### Miscellaneous Chores + +* **deps-dev:** bump sinon from 17.0.2 to 18.0.0 ([#903](https://github.com/appium/WebDriverAgent/issues/903)) ([87e4ba5](https://github.com/appium/WebDriverAgent/commit/87e4ba5ce3868d99ac889795039936be119ef87a)) + +## [8.7.1](https://github.com/appium/WebDriverAgent/compare/v8.7.0...v8.7.1) (2024-06-04) + +### Miscellaneous Chores + +* **deps-dev:** bump semantic-release from 23.1.1 to 24.0.0 and conventional-changelog-conventionalcommits to 8.0.0 ([#908](https://github.com/appium/WebDriverAgent/issues/908)) ([26019ec](https://github.com/appium/WebDriverAgent/commit/26019eca9b7331353e26a1014bc4afcecc0450f3)) + +## [8.7.0](https://github.com/appium/WebDriverAgent/compare/v8.6.0...v8.7.0) (2024-06-01) + + +### Features + +* Add a setting to respect system alerts while detecting active apps ([#907](https://github.com/appium/WebDriverAgent/issues/907)) ([5c82d66](https://github.com/appium/WebDriverAgent/commit/5c82d66890b1a74f9b6f698c87590b2154a6c1bd)) + +## [8.6.0](https://github.com/appium/WebDriverAgent/compare/v8.5.7...v8.6.0) (2024-05-17) + + +### Features + +* support maxTypingFrequency in settings api ([#904](https://github.com/appium/WebDriverAgent/issues/904)) ([fa4776a](https://github.com/appium/WebDriverAgent/commit/fa4776a2bfa15cbec8bba35d8ed11318d9629934)) + +## [8.5.7](https://github.com/appium/WebDriverAgent/compare/v8.5.6...v8.5.7) (2024-05-16) + + +### Miscellaneous Chores + +* Update dev dependencies ([e49dcf2](https://github.com/appium/WebDriverAgent/commit/e49dcf2afb0a10edc7085ac56d297234c00d57b0)) + +## [8.5.6](https://github.com/appium/WebDriverAgent/compare/v8.5.5...v8.5.6) (2024-04-20) + + +### Bug Fixes + +* unit test for linux ([#894](https://github.com/appium/WebDriverAgent/issues/894)) ([3a90158](https://github.com/appium/WebDriverAgent/commit/3a9015898d70b177cb6cbfcaf412dfa3c4ec3865)) + +## [8.5.5](https://github.com/appium/WebDriverAgent/compare/v8.5.4...v8.5.5) (2024-04-20) + + +### Bug Fixes + +* xcode warning about com.facebook.wda.lib ([#892](https://github.com/appium/WebDriverAgent/issues/892)) ([6398079](https://github.com/appium/WebDriverAgent/commit/63980796d8f40bd68ffb5af4b085a2348e544a13)) + +## [8.5.4](https://github.com/appium/WebDriverAgent/compare/v8.5.3...v8.5.4) (2024-04-20) + + +### Miscellaneous Chores + +* remove old iOS/Xcode related test code and errors ([#890](https://github.com/appium/WebDriverAgent/issues/890)) ([2fd0dea](https://github.com/appium/WebDriverAgent/commit/2fd0dead0c86d6be08e040360dec9ea085ba0392)) + +## [8.5.3](https://github.com/appium/WebDriverAgent/compare/v8.5.2...v8.5.3) (2024-04-19) + + +### Miscellaneous Chores + +* update integerationapp for newer OS env ([#891](https://github.com/appium/WebDriverAgent/issues/891)) ([2c78348](https://github.com/appium/WebDriverAgent/commit/2c7834842afeb1aec77e953ce11ac3c43c839431)) + +## [8.5.2](https://github.com/appium/WebDriverAgent/compare/v8.5.1...v8.5.2) (2024-04-09) + + +### Miscellaneous Chores + +* **deps-dev:** bump @typescript-eslint/parser from 6.21.0 to 7.6.0 ([#888](https://github.com/appium/WebDriverAgent/issues/888)) ([ead75eb](https://github.com/appium/WebDriverAgent/commit/ead75eb87a5c8e94088bace8f372ab137dcf57ad)) +* Remove extra imports ([fb25742](https://github.com/appium/WebDriverAgent/commit/fb25742a07a2fbcb0365a48d54117267c7c916df)) + +## [8.5.1](https://github.com/appium/WebDriverAgent/compare/v8.5.0...v8.5.1) (2024-04-08) + + +### Miscellaneous Chores + +* Add more type declarations ([#886](https://github.com/appium/WebDriverAgent/issues/886)) ([9ca7632](https://github.com/appium/WebDriverAgent/commit/9ca7632faf999931e7f5edf47267fcce6d6392b2)) + +## [8.5.0](https://github.com/appium/WebDriverAgent/compare/v8.4.0...v8.5.0) (2024-04-07) + + +### Features + +* Add types for WDA caps and settings ([#885](https://github.com/appium/WebDriverAgent/issues/885)) ([4b3c220](https://github.com/appium/WebDriverAgent/commit/4b3c220c0c609802924b7b6ff9a4dfa7a98eb5f4)) + +## [8.4.0](https://github.com/appium/WebDriverAgent/compare/v8.3.1...v8.4.0) (2024-04-01) + + +### Features + +* add system screen size/width in the system info endpoint ([#881](https://github.com/appium/WebDriverAgent/issues/881)) ([5ebc71c](https://github.com/appium/WebDriverAgent/commit/5ebc71c6ca2b364d44a44716e794885f8d3b6d9c)) + +## [8.3.1](https://github.com/appium/WebDriverAgent/compare/v8.3.0...v8.3.1) (2024-03-31) + + +### Miscellaneous Chores + +* do not cleanup with this.usePrebuiltWDA ([#882](https://github.com/appium/WebDriverAgent/issues/882)) ([0436e95](https://github.com/appium/WebDriverAgent/commit/0436e95752826bee7786577ac1bc0d056af11bc8)) + +## [8.3.0](https://github.com/appium/WebDriverAgent/compare/v8.2.1...v8.3.0) (2024-03-29) + + +### Features + +* Add module version to the /status output ([#878](https://github.com/appium/WebDriverAgent/issues/878)) ([a9603f8](https://github.com/appium/WebDriverAgent/commit/a9603f82acbdacdeb7a55b857512ba35353a4bc3)) + +## [8.2.1](https://github.com/appium/WebDriverAgent/compare/v8.2.0...v8.2.1) (2024-03-28) + + +### Miscellaneous Chores + +* wait for wda start in sim as well for preinstalled wda start ([#876](https://github.com/appium/WebDriverAgent/issues/876)) ([6c8920a](https://github.com/appium/WebDriverAgent/commit/6c8920adddb373b463259c3e6c14cb3c49ecbf2b)) + +## [8.2.0](https://github.com/appium/WebDriverAgent/compare/v8.1.0...v8.2.0) (2024-03-28) + + +### Features + +* Add a capability to customize the default state change timeout on app startup ([#877](https://github.com/appium/WebDriverAgent/issues/877)) ([98351c3](https://github.com/appium/WebDriverAgent/commit/98351c358367e67e63701612fd3702d53437e12e)) + +## [8.1.0](https://github.com/appium/WebDriverAgent/compare/v8.0.2...v8.1.0) (2024-03-26) + + +### Features + +* add updatedWDABundleIdSuffix to handle bundle id for updatedWDABundleId with usePreinstalledWDA ([#871](https://github.com/appium/WebDriverAgent/issues/871)) ([d79b624](https://github.com/appium/WebDriverAgent/commit/d79b6245966baaa57f7a1f785d7f9b4ea5a7f104)) + +## [8.0.2](https://github.com/appium/WebDriverAgent/compare/v8.0.1...v8.0.2) (2024-03-26) + + +### Miscellaneous Chores + +* **deps:** bump appium-ios-simulator from 5.5.3 to 6.0.0 ([#874](https://github.com/appium/WebDriverAgent/issues/874)) ([72f2a97](https://github.com/appium/WebDriverAgent/commit/72f2a97ec31dbb3c66e5f459e0d7fd417c197d5d)) + ## [8.0.1](https://github.com/appium/WebDriverAgent/compare/v8.0.0...v8.0.1) (2024-03-26) diff --git a/Configurations/IOSSettings.xcconfig b/Configurations/IOSSettings.xcconfig index 70ae5ec6..3bde5a21 100644 --- a/Configurations/IOSSettings.xcconfig +++ b/Configurations/IOSSettings.xcconfig @@ -28,4 +28,4 @@ RUN_CLANG_STATIC_ANALYZER = YES GCC_PREPROCESSOR_DEFINITIONS = $(inherited) -WARNING_CFLAGS = $(inherited) -Weverything -Wno-objc-missing-property-synthesis -Wno-unused-macros -Wno-disabled-macro-expansion -Wno-gnu-statement-expression -Wno-language-extension-token -Wno-overriding-method-mismatch -Wno-missing-variable-declarations -Rno-module-build -Wno-auto-import -Wno-objc-interface-ivars -Wno-documentation-unknown-command -Wno-reserved-id-macro -Wno-unused-parameter -Wno-gnu-conditional-omitted-operand -Wno-explicit-ownership-type -Wno-date-time -Wno-cast-align -Wno-cstring-format-directive -Wno-double-promotion -Wno-partial-availability +WARNING_CFLAGS = $(inherited) -Weverything -Wno-objc-missing-property-synthesis -Wno-unused-macros -Wno-disabled-macro-expansion -Wno-gnu-statement-expression -Wno-language-extension-token -Wno-overriding-method-mismatch -Wno-missing-variable-declarations -Rno-module-build -Wno-auto-import -Wno-objc-interface-ivars -Wno-documentation-unknown-command -Wno-reserved-id-macro -Wno-unused-parameter -Wno-gnu-conditional-omitted-operand -Wno-explicit-ownership-type -Wno-date-time -Wno-cast-align -Wno-cstring-format-directive -Wno-double-promotion -Wno-partial-availability -Wno-declaration-after-statement -Wno-objc-messaging-id -Wno-direct-ivar-access -Wno-cast-qual -Wno-deprecated-declarations -Wno-reserved-identifier diff --git a/Configurations/TVOSSettings.xcconfig b/Configurations/TVOSSettings.xcconfig index 70ae5ec6..3bde5a21 100644 --- a/Configurations/TVOSSettings.xcconfig +++ b/Configurations/TVOSSettings.xcconfig @@ -28,4 +28,4 @@ RUN_CLANG_STATIC_ANALYZER = YES GCC_PREPROCESSOR_DEFINITIONS = $(inherited) -WARNING_CFLAGS = $(inherited) -Weverything -Wno-objc-missing-property-synthesis -Wno-unused-macros -Wno-disabled-macro-expansion -Wno-gnu-statement-expression -Wno-language-extension-token -Wno-overriding-method-mismatch -Wno-missing-variable-declarations -Rno-module-build -Wno-auto-import -Wno-objc-interface-ivars -Wno-documentation-unknown-command -Wno-reserved-id-macro -Wno-unused-parameter -Wno-gnu-conditional-omitted-operand -Wno-explicit-ownership-type -Wno-date-time -Wno-cast-align -Wno-cstring-format-directive -Wno-double-promotion -Wno-partial-availability +WARNING_CFLAGS = $(inherited) -Weverything -Wno-objc-missing-property-synthesis -Wno-unused-macros -Wno-disabled-macro-expansion -Wno-gnu-statement-expression -Wno-language-extension-token -Wno-overriding-method-mismatch -Wno-missing-variable-declarations -Rno-module-build -Wno-auto-import -Wno-objc-interface-ivars -Wno-documentation-unknown-command -Wno-reserved-id-macro -Wno-unused-parameter -Wno-gnu-conditional-omitted-operand -Wno-explicit-ownership-type -Wno-date-time -Wno-cast-align -Wno-cstring-format-directive -Wno-double-promotion -Wno-partial-availability -Wno-declaration-after-statement -Wno-objc-messaging-id -Wno-direct-ivar-access -Wno-cast-qual -Wno-deprecated-declarations -Wno-reserved-identifier diff --git a/Configurations/TVOSTestSettings.xcconfig b/Configurations/TVOSTestSettings.xcconfig index 08679e42..17824cc3 100644 --- a/Configurations/TVOSTestSettings.xcconfig +++ b/Configurations/TVOSTestSettings.xcconfig @@ -1,2 +1 @@ EXCLUDED_ARCHS = i386 - diff --git a/PATENTS b/PATENTS deleted file mode 100644 index f5c989c5..00000000 --- a/PATENTS +++ /dev/null @@ -1,33 +0,0 @@ -Additional Grant of Patent Rights Version 2 - -"Software" means the WebDriverAgent software distributed by Facebook, Inc. - -Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software -("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable -(subject to the termination provision below) license under any Necessary -Claims, to make, have made, use, sell, offer to sell, import, and otherwise -transfer the Software. For avoidance of doubt, no license is granted under -Facebook’s rights in any patent claims that are infringed by (i) modifications -to the Software made by you or any third party or (ii) the Software in -combination with any software or other technology. - -The license granted hereunder will terminate, automatically and without notice, -if you (or any of your subsidiaries, corporate affiliates or agents) initiate -directly or indirectly, or take a direct financial interest in, any Patent -Assertion: (i) against Facebook or any of its subsidiaries or corporate -affiliates, (ii) against any party if such Patent Assertion arises in whole or -in part from any software, technology, product or service of Facebook or any of -its subsidiaries or corporate affiliates, or (iii) against any party relating -to the Software. Notwithstanding the foregoing, if Facebook or any of its -subsidiaries or corporate affiliates files a lawsuit alleging patent -infringement against you in the first instance, and you respond by filing a -patent infringement counterclaim in that lawsuit against that party that is -unrelated to the Software, the license granted hereunder will not terminate -under section (i) of this paragraph due to such counterclaim. - -A "Necessary Claim" is a claim of a patent owned by Facebook that is -necessarily infringed by the Software standing alone. - -A "Patent Assertion" is any lawsuit or other action alleging direct, indirect, -or contributory infringement or inducement to infringe any patent, including a -cross-claim or counterclaim. diff --git a/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h b/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h index 8ed03ebf..d68f25c1 100644 --- a/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h +++ b/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h @@ -27,6 +27,7 @@ - (void)_XCT_requestElementAtPoint:(CGPoint)arg1 reply:(void (^)(id/*XCAccessibilityElement*/, NSError *))arg2; - (void)_XCT_fetchParameterizedAttributeForElement:(id/*XCAccessibilityElement*/)arg1 attributes:(NSNumber *)arg2 parameter:(id)arg3 reply:(void (^)(id, NSError *))arg4; - (void)_XCT_setAttribute:(NSNumber *)arg1 value:(id)arg2 element:(id/*XCAccessibilityElement*/)arg3 reply:(void (^)(BOOL, NSError *))arg4; +- (void)_XCT_fetchAttributes:(id)attributes forElement:(id)element reply:(void (^)(NSDictionary *, NSError *))reply; - (void)_XCT_fetchAttributesForElement:(id/*XCAccessibilityElement*/)arg1 attributes:(NSArray *)arg2 reply:(void (^)(NSDictionary *, NSError *))arg3; - (void)_XCT_terminateApplicationWithBundleID:(NSString *)arg1 completion:(void (^)(NSError *))arg2; - (void)_XCT_performAccessibilityAction:(int)arg1 onElement:(id/*XCAccessibilityElement*/)arg2 withValue:(id)arg3 reply:(void (^)(NSError *))arg4; diff --git a/PrivateHeaders/XCTest/XCUIApplicationProcess.h b/PrivateHeaders/XCTest/XCUIApplicationProcess.h index f0b4d358..64770393 100644 --- a/PrivateHeaders/XCTest/XCUIApplicationProcess.h +++ b/PrivateHeaders/XCTest/XCUIApplicationProcess.h @@ -65,7 +65,11 @@ - (void)terminate; - (void)waitForViewControllerViewDidDisappearWithTimeout:(double)arg1; - (void)waitForAutomationSession; +// Before Xcode16-beta5 - (void)waitForQuiescenceIncludingAnimationsIdle:(BOOL)arg1; +// Since Xcode16-beta5 +- (void)waitForQuiescenceIncludingAnimationsIdle:(BOOL)arg1 isPreEvent:(BOOL)arg2; + - (id)shortDescription; - (id)_queue_description; diff --git a/Scripts/build-webdriveragent.js b/Scripts/build-webdriveragent.js index 1958b876..b37bcbbc 100644 --- a/Scripts/build-webdriveragent.js +++ b/Scripts/build-webdriveragent.js @@ -34,7 +34,7 @@ async function buildWebDriverAgent (xcodeVersion) { await exec('xcodebuild', ['clean', '-derivedDataPath', DERIVED_DATA_PATH, '-scheme', 'WebDriverAgentRunner'], { cwd: ROOT_DIR }); - } catch (ign) {} + } catch {} // Get Xcode version xcodeVersion = xcodeVersion || await xcode.getVersion(); diff --git a/Scripts/build.sh b/Scripts/build.sh index 64195368..698d58b0 100755 --- a/Scripts/build.sh +++ b/Scripts/build.sh @@ -4,8 +4,7 @@ # All rights reserved. # # This source code is licensed under the BSD-style license found in the -# LICENSE file in the root directory of this source tree. An additional grant -# of patent rights can be found in the PATENTS file in the same directory. +# LICENSE file in the root directory of this source tree. # set -ex diff --git a/Scripts/ci/build-real.sh b/Scripts/ci/build-real.sh index 93eec114..bb41b0b6 100755 --- a/Scripts/ci/build-real.sh +++ b/Scripts/ci/build-real.sh @@ -1,7 +1,5 @@ #!/bin/bash -# To run build script for CI - xcodebuild clean build-for-testing \ -project WebDriverAgent.xcodeproj \ -derivedDataPath $DERIVED_DATA_PATH \ @@ -9,15 +7,18 @@ xcodebuild clean build-for-testing \ -destination "$DESTINATION" \ CODE_SIGNING_ALLOWED=NO ARCHS=arm64 -# Only .app is needed. - pushd $WD -# to remove test packages to refer to the device local instead of embedded ones -# XCTAutomationSupport.framework, XCTest.framewor, XCTestCore.framework, -# XCUIAutomation.framework, XCUnit.framework -rm -rf $SCHEME-Runner.app/Frameworks/XC*.framework - -zip -r $ZIP_PKG_NAME $SCHEME-Runner.app +# The reason why here excludes several frameworks are: +# - to remove test packages to refer to the device local instead of embedded ones +# XCTAutomationSupport.framework, XCTest.framewor, XCTestCore.framework, +# XCUIAutomation.framework, XCUnit.framework. +# This can be excluded only for real devices. +# - Xcode 16 started generating 5.9MB of 'Testing.framework', but it might not be necessary for WDA. +# - libXCTestSwiftSupport is used for Swift testing. WDA doesn't include Swift stuff, thus this is not needed. +zip -r $ZIP_PKG_NAME $SCHEME-Runner.app \ + -x "$SCHEME-Runner.app/Frameworks/XC*.framework*" \ + "$SCHEME-Runner.app/Frameworks/Testing.framework*" \ + "$SCHEME-Runner.app/Frameworks/libXCTestSwiftSupport.dylib" popd mv $WD/$ZIP_PKG_NAME ./ diff --git a/Scripts/ci/build-sim.sh b/Scripts/ci/build-sim.sh index de52abcc..b04cb48b 100755 --- a/Scripts/ci/build-sim.sh +++ b/Scripts/ci/build-sim.sh @@ -1,19 +1,15 @@ #!/bin/bash -# To run build script for CI - xcodebuild clean build-for-testing \ -project WebDriverAgent.xcodeproj \ - -derivedDataPath wda_build \ + -derivedDataPath $DERIVED_DATA_PATH \ -scheme $SCHEME \ -destination "$DESTINATION" \ CODE_SIGNING_ALLOWED=NO ARCHS=$ARCHS -# simulator needs to build entire build files +pushd $WD -pushd wda_build -# to remove unnecessary space consuming files -rm -rf Build/Intermediates.noindex -zip -r $ZIP_PKG_NAME Build +# Simulators might have an issue to lauch if we drop frameworks even we don't use them. +zip -r $ZIP_PKG_NAME $SCHEME-Runner.app popd -mv wda_build/$ZIP_PKG_NAME ./ +mv $WD/$ZIP_PKG_NAME ./ diff --git a/Scripts/fetch-prebuilt-wda.js b/Scripts/fetch-prebuilt-wda.js index 8bedd9a3..4bd6840f 100644 --- a/Scripts/fetch-prebuilt-wda.js +++ b/Scripts/fetch-prebuilt-wda.js @@ -47,7 +47,7 @@ async function fetchPrebuiltWebDriverAgentAssets () { try { const nameOfAgent = _.last(url.split('/')); agentsDownloading.push(downloadAgent(url, path.join(webdriveragentsDir, nameOfAgent))); - } catch (ign) { } + } catch { } } // Wait for them all to finish diff --git a/Scripts/update-wda-version.js b/Scripts/update-wda-version.js new file mode 100644 index 00000000..142efdce --- /dev/null +++ b/Scripts/update-wda-version.js @@ -0,0 +1,41 @@ +const {plist, logger} = require('@appium/support'); +const path = require('node:path'); +const semver = require('semver'); + +const log = logger.getLogger('Versioner'); + +/** + * @param {string} argName + * @returns {string|null} + */ +function parseArgValue (argName) { + const argNamePattern = new RegExp(`^--${argName}\\b`); + for (let i = 1; i < process.argv.length; ++i) { + const arg = process.argv[i]; + if (argNamePattern.test(arg)) { + return arg.includes('=') ? arg.split('=')[1] : process.argv[i + 1]; + } + } + return null; +} + +async function updateWdaVersion() { + const newVersion = parseArgValue('package-version'); + if (!newVersion) { + throw new Error('No package version argument (use `--package-version=xxx`)'); + } + if (!semver.valid(newVersion)) { + throw new Error( + `Invalid version specified '${newVersion}'. Version should be in the form '1.2.3'` + ); + } + + const libManifest = path.resolve('WebDriverAgentLib', 'Info.plist'); + log.info(`Updating the WebDriverAgent manifest at '${libManifest}' to version '${newVersion}'`); + await plist.updatePlistFile(libManifest, { + CFBundleShortVersionString: newVersion, + CFBundleVersion: newVersion, + }, false); +} + +(async () => await updateWdaVersion())(); diff --git a/WebDriverAgent.xcodeproj/project.pbxproj b/WebDriverAgent.xcodeproj/project.pbxproj index 2aef41e0..57624c4b 100644 --- a/WebDriverAgent.xcodeproj/project.pbxproj +++ b/WebDriverAgent.xcodeproj/project.pbxproj @@ -7,6 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 0E0413382DF1E15100AF007C /* XCUIElement+FBMinMax.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E0413372DF1E15100AF007C /* XCUIElement+FBMinMax.m */; }; + 0E0413392DF1E15100AF007C /* XCUIElement+FBMinMax.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E0413372DF1E15100AF007C /* XCUIElement+FBMinMax.m */; }; + 0E04133B2DF1E15900AF007C /* XCUIElement+FBMinMax.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E04133A2DF1E15900AF007C /* XCUIElement+FBMinMax.h */; }; + 0E04133C2DF1E15900AF007C /* XCUIElement+FBMinMax.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E04133A2DF1E15900AF007C /* XCUIElement+FBMinMax.h */; }; 1357E296233D05240054BDB8 /* XCUIHitPointResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1357E295233D05240054BDB8 /* XCUIHitPointResult.h */; }; 1357E297233D05240054BDB8 /* XCUIHitPointResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1357E295233D05240054BDB8 /* XCUIHitPointResult.h */; }; 13815F6F2328D20400CDAB61 /* FBActiveAppDetectionPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 13815F6D2328D20400CDAB61 /* FBActiveAppDetectionPoint.h */; }; @@ -21,12 +25,12 @@ 13DE7A4A287C4005003243C6 /* FBXCDeviceEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A47287C4005003243C6 /* FBXCDeviceEvent.h */; }; 13DE7A4B287C4005003243C6 /* FBXCDeviceEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A48287C4005003243C6 /* FBXCDeviceEvent.m */; }; 13DE7A4C287C4005003243C6 /* FBXCDeviceEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A48287C4005003243C6 /* FBXCDeviceEvent.m */; }; - 13DE7A4F287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A4D287C46BB003243C6 /* FBXCElementSnapshot.h */; }; - 13DE7A50287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A4D287C46BB003243C6 /* FBXCElementSnapshot.h */; }; + 13DE7A4F287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A4D287C46BB003243C6 /* FBXCElementSnapshot.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 13DE7A50287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A4D287C46BB003243C6 /* FBXCElementSnapshot.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13DE7A51287C46BB003243C6 /* FBXCElementSnapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A4E287C46BB003243C6 /* FBXCElementSnapshot.m */; }; 13DE7A52287C46BB003243C6 /* FBXCElementSnapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A4E287C46BB003243C6 /* FBXCElementSnapshot.m */; }; - 13DE7A55287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A53287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h */; }; - 13DE7A56287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A53287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h */; }; + 13DE7A55287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A53287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 13DE7A56287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A53287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13DE7A57287CA1EC003243C6 /* FBXCElementSnapshotWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A54287CA1EC003243C6 /* FBXCElementSnapshotWrapper.m */; }; 13DE7A58287CA1EC003243C6 /* FBXCElementSnapshotWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A54287CA1EC003243C6 /* FBXCElementSnapshotWrapper.m */; }; 13DE7A5B287CA444003243C6 /* FBXCElementSnapshotWrapper+Helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A59287CA444003243C6 /* FBXCElementSnapshotWrapper+Helpers.h */; }; @@ -374,6 +378,10 @@ 7155D704211DCEF400166C20 /* FBMjpegServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7155D702211DCEF400166C20 /* FBMjpegServer.m */; }; 7157B291221DADD2001C348C /* FBXCAXClientProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 7157B28F221DADD2001C348C /* FBXCAXClientProxy.h */; }; 7157B292221DADD2001C348C /* FBXCAXClientProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7157B290221DADD2001C348C /* FBXCAXClientProxy.m */; }; + 715A84CF2DD92AD3007134CC /* FBElementHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 715A84CE2DD92AD3007134CC /* FBElementHelpers.m */; }; + 715A84D02DD92AD3007134CC /* FBElementHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 715A84CD2DD92AD3007134CC /* FBElementHelpers.h */; }; + 715A84D12DD92AD3007134CC /* FBElementHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 715A84CE2DD92AD3007134CC /* FBElementHelpers.m */; }; + 715A84D22DD92AD3007134CC /* FBElementHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 715A84CD2DD92AD3007134CC /* FBElementHelpers.h */; }; 715AFAC11FFA29180053896D /* FBScreen.h in Headers */ = {isa = PBXBuildFile; fileRef = 715AFABF1FFA29180053896D /* FBScreen.h */; }; 715AFAC21FFA29180053896D /* FBScreen.m in Sources */ = {isa = PBXBuildFile; fileRef = 715AFAC01FFA29180053896D /* FBScreen.m */; }; 715AFAC41FFA2AAF0053896D /* FBScreenTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 715AFAC31FFA2AAF0053896D /* FBScreenTests.m */; }; @@ -451,6 +459,10 @@ 71A7EAFA1E224648001DA4F2 /* FBClassChainQueryParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 71A7EAF81E224648001DA4F2 /* FBClassChainQueryParser.m */; }; 71A7EAFC1E229302001DA4F2 /* FBClassChainTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71A7EAFB1E229302001DA4F2 /* FBClassChainTests.m */; }; 71ACF5B8242F2FDC00F0AAD4 /* FBSafariAlertTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71ACF5B7242F2FDC00F0AAD4 /* FBSafariAlertTests.m */; }; + 71AE3CF72D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 71AE3CF52D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h */; }; + 71AE3CF82D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 71AE3CF62D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m */; }; + 71AE3CF92D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 71AE3CF52D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h */; }; + 71AE3CFA2D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 71AE3CF62D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m */; }; 71B155DA23070ECF00646AFB /* FBHTTPStatusCodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B155D923070ECF00646AFB /* FBHTTPStatusCodes.h */; settings = {ATTRIBUTES = (Public, ); }; }; 71B155DC230711E900646AFB /* FBCommandStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B155DB230711E900646AFB /* FBCommandStatus.m */; }; 71B155DF23080CA600646AFB /* FBProtocolHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B155DD23080CA600646AFB /* FBProtocolHelpers.h */; }; @@ -531,6 +543,10 @@ ADBC39981D07842800327304 /* XCUIElementDouble.m in Sources */ = {isa = PBXBuildFile; fileRef = ADBC39971D07842800327304 /* XCUIElementDouble.m */; }; ADDA07241D6BB2BF001700AC /* FBScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ADDA07231D6BB2BF001700AC /* FBScrollViewController.m */; }; ADEF63AF1D09DEBE0070A7E3 /* FBRuntimeUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = ADEF63AE1D09DEBE0070A7E3 /* FBRuntimeUtilsTests.m */; }; + B316351C2DDF0CF5007D9317 /* FBAccessibilityTraits.m in Sources */ = {isa = PBXBuildFile; fileRef = B316351B2DDF0CF5007D9317 /* FBAccessibilityTraits.m */; }; + B316351D2DDF0CF5007D9317 /* FBAccessibilityTraits.m in Sources */ = {isa = PBXBuildFile; fileRef = B316351B2DDF0CF5007D9317 /* FBAccessibilityTraits.m */; }; + B316351F2DDF0D0B007D9317 /* FBAccessibilityTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = B316351E2DDF0D0B007D9317 /* FBAccessibilityTraits.h */; }; + B31635202DDF0D0B007D9317 /* FBAccessibilityTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = B316351E2DDF0D0B007D9317 /* FBAccessibilityTraits.h */; }; C845206222D5E79400EA68CB /* FBUnattachedAppLauncher.h in Headers */ = {isa = PBXBuildFile; fileRef = C8FB547722D4C1FC00B69954 /* FBUnattachedAppLauncher.h */; }; C845206322D5E79700EA68CB /* FBUnattachedAppLauncher.m in Sources */ = {isa = PBXBuildFile; fileRef = C8FB547822D4C1FC00B69954 /* FBUnattachedAppLauncher.m */; }; C8FB547422D3949C00B69954 /* LSApplicationWorkspace.h in Headers */ = {isa = PBXBuildFile; fileRef = C8FB547322D3949C00B69954 /* LSApplicationWorkspace.h */; }; @@ -906,6 +922,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0E0413372DF1E15100AF007C /* XCUIElement+FBMinMax.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBMinMax.m"; sourceTree = ""; }; + 0E04133A2DF1E15900AF007C /* XCUIElement+FBMinMax.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBMinMax.h"; sourceTree = ""; }; 1357E295233D05240054BDB8 /* XCUIHitPointResult.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCUIHitPointResult.h; sourceTree = ""; }; 13815F6D2328D20400CDAB61 /* FBActiveAppDetectionPoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBActiveAppDetectionPoint.h; sourceTree = ""; }; 13815F6E2328D20400CDAB61 /* FBActiveAppDetectionPoint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBActiveAppDetectionPoint.m; sourceTree = ""; }; @@ -1002,6 +1020,8 @@ 7155D702211DCEF400166C20 /* FBMjpegServer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBMjpegServer.m; sourceTree = ""; }; 7157B28F221DADD2001C348C /* FBXCAXClientProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBXCAXClientProxy.h; sourceTree = ""; }; 7157B290221DADD2001C348C /* FBXCAXClientProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXCAXClientProxy.m; sourceTree = ""; }; + 715A84CD2DD92AD3007134CC /* FBElementHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBElementHelpers.h; sourceTree = ""; }; + 715A84CE2DD92AD3007134CC /* FBElementHelpers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBElementHelpers.m; sourceTree = ""; }; 715AFABF1FFA29180053896D /* FBScreen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBScreen.h; sourceTree = ""; }; 715AFAC01FFA29180053896D /* FBScreen.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBScreen.m; sourceTree = ""; }; 715AFAC31FFA2AAF0053896D /* FBScreenTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBScreenTests.m; sourceTree = ""; }; @@ -1050,6 +1070,8 @@ 71A7EAF81E224648001DA4F2 /* FBClassChainQueryParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBClassChainQueryParser.m; sourceTree = ""; }; 71A7EAFB1E229302001DA4F2 /* FBClassChainTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBClassChainTests.m; sourceTree = ""; }; 71ACF5B7242F2FDC00F0AAD4 /* FBSafariAlertTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBSafariAlertTests.m; sourceTree = ""; }; + 71AE3CF52D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBVisibleFrame.h"; sourceTree = ""; }; + 71AE3CF62D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBVisibleFrame.m"; sourceTree = ""; }; 71B155D923070ECF00646AFB /* FBHTTPStatusCodes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBHTTPStatusCodes.h; sourceTree = ""; }; 71B155DB230711E900646AFB /* FBCommandStatus.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBCommandStatus.m; sourceTree = ""; }; 71B155DD23080CA600646AFB /* FBProtocolHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBProtocolHelpers.h; sourceTree = ""; }; @@ -1103,6 +1125,8 @@ ADDA07221D6BB2BF001700AC /* FBScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBScrollViewController.h; sourceTree = ""; }; ADDA07231D6BB2BF001700AC /* FBScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBScrollViewController.m; sourceTree = ""; }; ADEF63AE1D09DEBE0070A7E3 /* FBRuntimeUtilsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBRuntimeUtilsTests.m; sourceTree = ""; }; + B316351B2DDF0CF5007D9317 /* FBAccessibilityTraits.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBAccessibilityTraits.m; sourceTree = ""; }; + B316351E2DDF0D0B007D9317 /* FBAccessibilityTraits.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBAccessibilityTraits.h; sourceTree = ""; }; C8FB547322D3949C00B69954 /* LSApplicationWorkspace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LSApplicationWorkspace.h; sourceTree = ""; }; C8FB547722D4C1FC00B69954 /* FBUnattachedAppLauncher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBUnattachedAppLauncher.h; sourceTree = ""; }; C8FB547822D4C1FC00B69954 /* FBUnattachedAppLauncher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBUnattachedAppLauncher.m; sourceTree = ""; }; @@ -1767,6 +1791,8 @@ EE8DDD7C20C5733B004D4925 /* XCUIElement+FBForceTouch.m */, EE9AB7471CAEDF0C008C271F /* XCUIElement+FBIsVisible.h */, EE9AB7481CAEDF0C008C271F /* XCUIElement+FBIsVisible.m */, + 0E04133A2DF1E15900AF007C /* XCUIElement+FBMinMax.h */, + 0E0413372DF1E15100AF007C /* XCUIElement+FBMinMax.m */, 7136A4771E8918E60024FC3D /* XCUIElement+FBPickerWheel.h */, 7136A4781E8918E60024FC3D /* XCUIElement+FBPickerWheel.m */, 71D3B3D3267FC7260076473D /* XCUIElement+FBResolve.h */, @@ -1781,6 +1807,8 @@ 71B49EC61ED1A58100D51AD6 /* XCUIElement+FBUID.m */, EEE3763F1D59F81400ED88DD /* XCUIElement+FBUtilities.h */, EEE376401D59F81400ED88DD /* XCUIElement+FBUtilities.m */, + 71AE3CF52D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h */, + 71AE3CF62D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m */, EEE376471D59FAE900ED88DD /* XCUIElement+FBWebDriverAttributes.h */, EEE376481D59FAE900ED88DD /* XCUIElement+FBWebDriverAttributes.m */, 641EE7042240CDCF00173FCB /* XCUIElement+FBTVFocuse.h */, @@ -1904,6 +1932,8 @@ EE9B76A21CF7A43900275851 /* FBConfiguration.m */, EE7E27181D06C69F001BEC7B /* FBDebugLogDelegateDecorator.h */, EE7E27191D06C69F001BEC7B /* FBDebugLogDelegateDecorator.m */, + 715A84CD2DD92AD3007134CC /* FBElementHelpers.h */, + 715A84CE2DD92AD3007134CC /* FBElementHelpers.m */, EE9AB78F1CAEDF0C008C271F /* FBElementTypeTransformer.h */, EE9AB7901CAEDF0C008C271F /* FBElementTypeTransformer.m */, EE3A18601CDE618F00DE4205 /* FBErrorBuilder.h */, @@ -1963,6 +1993,8 @@ EE6B64FC1D0F86EF00E85F5D /* XCTestPrivateSymbols.m */, 633E904A220DEE7F007CADF9 /* XCUIApplicationProcessDelay.h */, 6385F4A5220A40760095BBDB /* XCUIApplicationProcessDelay.m */, + B316351B2DDF0CF5007D9317 /* FBAccessibilityTraits.m */, + B316351E2DDF0D0B007D9317 /* FBAccessibilityTraits.h */, ); name = Utilities; path = WebDriverAgentLib/Utilities; @@ -2276,6 +2308,8 @@ 641EE6392240C5CA00173FCB /* FBRouteRequest.h in Headers */, 648C10AC22AAAD9C00B81B9A /* UIKeyboardImpl.h in Headers */, 718226CD2587443700661B83 /* GCDAsyncSocket.h in Headers */, + 13DE7A50287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */, + 13DE7A56287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h in Headers */, 71F3E7D525417FF400E0C22B /* FBSettings.h in Headers */, 641EE63A2240C5CA00173FCB /* XCTest.h in Headers */, 641EE63B2240C5CA00173FCB /* FBAlertsMonitor.h in Headers */, @@ -2324,7 +2358,6 @@ 641EE6632240C5CA00173FCB /* FBUnknownCommands.h in Headers */, 641EE7062240CDCF00173FCB /* XCUIElement+FBTVFocuse.h in Headers */, 71822738258744B800661B83 /* HTTPConnection.h in Headers */, - 13DE7A56287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h in Headers */, 641EE6642240C5CA00173FCB /* NSPredicate+FBFormat.h in Headers */, 641EE6652240C5CA00173FCB /* UILongPressGestureRecognizer-RecordingAdditions.h in Headers */, 641EE6662240C5CA00173FCB /* XCTestCase.h in Headers */, @@ -2346,11 +2379,13 @@ 641EE6732240C5CA00173FCB /* FBDebugCommands.h in Headers */, 641EE6742240C5CA00173FCB /* XCTestSuite.h in Headers */, 641EE6752240C5CA00173FCB /* XCUICoordinate.h in Headers */, + 715A84D22DD92AD3007134CC /* FBElementHelpers.h in Headers */, 641EE6762240C5CA00173FCB /* XCTNSPredicateExpectation.h in Headers */, 641EE6772240C5CA00173FCB /* XCTestObservationCenter.h in Headers */, 641EE6782240C5CA00173FCB /* XCTNSNotificationExpectation.h in Headers */, 641EE6792240C5CA00173FCB /* XCUIRecorderNodeFinder.h in Headers */, 641EE67A2240C5CA00173FCB /* XCUIElement+FBAccessibility.h in Headers */, + 0E04133C2DF1E15900AF007C /* XCUIElement+FBMinMax.h in Headers */, 641EE67B2240C5CA00173FCB /* XCUIRecorderUtilities.h in Headers */, 6496A5DA230D6EB30087F8CB /* AXSettings.h in Headers */, 641EE67C2240C5CA00173FCB /* XCTestCaseRun.h in Headers */, @@ -2399,9 +2434,11 @@ 641EE6A42240C5CA00173FCB /* FBCommandHandler.h in Headers */, 641EE6A52240C5CA00173FCB /* FBSessionCommands.h in Headers */, 641EE70C2240CE2D00173FCB /* FBTVNavigationTracker.h in Headers */, + 71AE3CF72D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h in Headers */, 641EE6A62240C5CA00173FCB /* FBImageProcessor.h in Headers */, 641EE6A72240C5CA00173FCB /* FBSession-Private.h in Headers */, 641EE6A82240C5CA00173FCB /* NSString+FBXMLSafeString.h in Headers */, + B316351F2DDF0D0B007D9317 /* FBAccessibilityTraits.h in Headers */, 64E3502F2AC0B6FE005F3ACB /* NSDictionary+FBUtf8SafeDictionary.h in Headers */, 641EE6A92240C5CA00173FCB /* FBCommandStatus.h in Headers */, 71822702258744A400661B83 /* HTTPResponseProxy.h in Headers */, @@ -2483,7 +2520,6 @@ 641EE6E72240C5CA00173FCB /* XCUIElement+FBFind.h in Headers */, 641EE6E82240C5CA00173FCB /* XCTestManager_ManagerInterface-Protocol.h in Headers */, 641EE6E92240C5CA00173FCB /* FBFailureProofTestCase.h in Headers */, - 13DE7A50287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */, 641EE6EA2240C5CA00173FCB /* XCTTestRunSessionDelegate-Protocol.h in Headers */, 641EE6EB2240C5CA00173FCB /* XCTestCaseSuite.h in Headers */, 641EE6EC2240C5CA00173FCB /* _XCInternalTestRun.h in Headers */, @@ -2554,6 +2590,7 @@ EE35AD721E3B77D600A02D78 /* XCUIElementHitPointCoordinate.h in Headers */, EE35AD3F1E3B77D600A02D78 /* XCTDarwinNotificationExpectation.h in Headers */, EE35AD5F1E3B77D600A02D78 /* XCTRunnerAutomationSession.h in Headers */, + 13DE7A4F287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */, 71C9EAAC25E8415A00470CD8 /* FBScreenshot.h in Headers */, EE35AD371E3B77D600A02D78 /* XCSourceCodeTreeNodeEnumerator.h in Headers */, EE158AB01CBD456F00A3E3F0 /* XCUIElement+FBIsVisible.h in Headers */, @@ -2585,6 +2622,7 @@ 714EAA0D2673FDFE005C5B47 /* FBCapabilities.h in Headers */, EE35AD5C1E3B77D600A02D78 /* XCTNSPredicateExpectation.h in Headers */, EE35AD521E3B77D600A02D78 /* XCTestObservationCenter.h in Headers */, + 71AE3CF92D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h in Headers */, EE35AD5B1E3B77D600A02D78 /* XCTNSNotificationExpectation.h in Headers */, E444DC97249131D40060D7EB /* HTTPServer.h in Headers */, E444DCAE24913C220060D7EB /* HTTPResponseProxy.h in Headers */, @@ -2595,6 +2633,7 @@ EE35AD781E3B77D600A02D78 /* XCUIRecorderUtilities.h in Headers */, EE35AD421E3B77D600A02D78 /* XCTestCaseRun.h in Headers */, EE35AD441E3B77D600A02D78 /* XCTestConfiguration.h in Headers */, + 715A84D02DD92AD3007134CC /* FBElementHelpers.h in Headers */, EE35AD0B1E3B77D600A02D78 /* _XCTDarwinNotificationExpectationImplementation.h in Headers */, 718226CA2587443700661B83 /* GCDAsyncUdpSocket.h in Headers */, EE35AD491E3B77D600A02D78 /* XCTestExpectation.h in Headers */, @@ -2649,7 +2688,6 @@ EE158AB81CBD456F00A3E3F0 /* FBAlertViewCommands.h in Headers */, EE35AD651E3B77D600A02D78 /* XCTWaiter.h in Headers */, EE35AD681E3B77D600A02D78 /* XCTWaiterManagement-Protocol.h in Headers */, - 13DE7A4F287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */, EE35AD451E3B77D600A02D78 /* XCTestContext.h in Headers */, EE35AD661E3B77D600A02D78 /* XCTWaiterDelegate-Protocol.h in Headers */, EE35AD0E1E3B77D600A02D78 /* _XCTestExpectationImplementation.h in Headers */, @@ -2672,6 +2710,7 @@ EEE9B4721CD02B88009D2030 /* FBRunLoopSpinner.h in Headers */, EE3A18621CDE618F00DE4205 /* FBErrorBuilder.h in Headers */, EE35AD261E3B77D600A02D78 /* XCApplicationMonitor_iOS.h in Headers */, + 0E04133B2DF1E15900AF007C /* XCUIElement+FBMinMax.h in Headers */, EE3A18661CDE734B00DE4205 /* FBKeyboard.h in Headers */, AD6C269C1CF2494200F8B5FF /* XCUIApplication+FBHelpers.h in Headers */, 714D88CC2733FB970074A925 /* FBXMLGenerationOptions.h in Headers */, @@ -2692,6 +2731,7 @@ EE35AD571E3B77D600A02D78 /* XCTestSuiteRun.h in Headers */, EE35AD701E3B77D600A02D78 /* XCUIElementAsynchronousHandlerWrapper.h in Headers */, EE35AD4C1E3B77D600A02D78 /* XCTestLog.h in Headers */, + B31635202DDF0D0B007D9317 /* FBAccessibilityTraits.h in Headers */, 71BB58E82B96328700CB9BFE /* FBScreenRecordingRequest.h in Headers */, EE35AD231E3B77D600A02D78 /* UITapGestureRecognizer-RecordingAdditions.h in Headers */, EE35AD2A1E3B77D600A02D78 /* XCDebugLogDelegate-Protocol.h in Headers */, @@ -3153,6 +3193,7 @@ 641EE6082240C5CA00173FCB /* FBRuntimeUtils.m in Sources */, 641EE6092240C5CA00173FCB /* XCUIElement+FBUtilities.m in Sources */, 641EE60A2240C5CA00173FCB /* FBLogger.m in Sources */, + B316351D2DDF0CF5007D9317 /* FBAccessibilityTraits.m in Sources */, 641EE60B2240C5CA00173FCB /* FBCustomCommands.m in Sources */, 71BB58E42B9631F100CB9BFE /* FBScreenRecordingPromise.m in Sources */, 641EE60C2240C5CA00173FCB /* XCUIDevice+FBHelpers.m in Sources */, @@ -3160,6 +3201,8 @@ 641EE60E2240C5CA00173FCB /* XCUIElement+FBTyping.m in Sources */, 641EE60F2240C5CA00173FCB /* XCUIElement+FBAccessibility.m in Sources */, 641EE6102240C5CA00173FCB /* FBImageUtils.m in Sources */, + 71AE3CF82D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m in Sources */, + 715A84D12DD92AD3007134CC /* FBElementHelpers.m in Sources */, 641EE6112240C5CA00173FCB /* FBSession.m in Sources */, 641EE6122240C5CA00173FCB /* FBFindElementCommands.m in Sources */, 71A5C67629A4F39600421C37 /* XCTIssue+FBPatcher.m in Sources */, @@ -3169,6 +3212,7 @@ 71BB58F92B96531900CB9BFE /* FBScreenRecordingContainer.m in Sources */, 641EE6152240C5CA00173FCB /* XCUIElement+FBScrolling.m in Sources */, 641EE6162240C5CA00173FCB /* FBSessionCommands.m in Sources */, + 0E0413392DF1E15100AF007C /* XCUIElement+FBMinMax.m in Sources */, 641EE6192240C5CA00173FCB /* FBConfiguration.m in Sources */, 641EE61A2240C5CA00173FCB /* FBElementCache.m in Sources */, 71F5BE26252E576C00EE9EBA /* XCUIElement+FBSwiping.m in Sources */, @@ -3216,6 +3260,7 @@ 13DE7A45287C2A8D003243C6 /* FBXCAccessibilityElement.m in Sources */, 641EE70E2240CE4800173FCB /* FBTVNavigationTracker.m in Sources */, 71BD20741F86116100B36EC2 /* XCUIApplication+FBTouchAction.m in Sources */, + 0E0413382DF1E15100AF007C /* XCUIElement+FBMinMax.m in Sources */, EE158AE71CBD456F00A3E3F0 /* FBWebServer.m in Sources */, 715557D4211DBCE700613B26 /* FBTCPSocket.m in Sources */, EE3A18631CDE618F00DE4205 /* FBErrorBuilder.m in Sources */, @@ -3232,8 +3277,10 @@ 713AE576243A53BE0000D657 /* FBW3CActionsHelpers.m in Sources */, 71B155E123080CA600646AFB /* FBProtocolHelpers.m in Sources */, EE158AB11CBD456F00A3E3F0 /* XCUIElement+FBIsVisible.m in Sources */, + 71AE3CFA2D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m in Sources */, EEBBD48C1D47746D00656A81 /* XCUIElement+FBFind.m in Sources */, EE158ADD1CBD456F00A3E3F0 /* FBResponsePayload.m in Sources */, + B316351C2DDF0CF5007D9317 /* FBAccessibilityTraits.m in Sources */, E444DCB524913C220060D7EB /* RouteRequest.m in Sources */, C8FB547A22D4C1FC00B69954 /* FBUnattachedAppLauncher.m in Sources */, EE158ADF1CBD456F00A3E3F0 /* FBRoute.m in Sources */, @@ -3302,6 +3349,7 @@ EE158AB31CBD456F00A3E3F0 /* XCUIElement+FBScrolling.m in Sources */, 718226CE2587443700661B83 /* GCDAsyncSocket.m in Sources */, EE158AC91CBD456F00A3E3F0 /* FBSessionCommands.m in Sources */, + 715A84CF2DD92AD3007134CC /* FBElementHelpers.m in Sources */, EE9B76A71CF7A43900275851 /* FBConfiguration.m in Sources */, E444DC9C249131D40060D7EB /* HTTPServer.m in Sources */, 71414ED82670A1EE003A8C5D /* LRUCache.m in Sources */, diff --git a/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner.xcscheme b/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner.xcscheme index 8857b934..4c2919f7 100644 --- a/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner.xcscheme +++ b/WebDriverAgent.xcodeproj/xcshareddata/xcschemes/WebDriverAgentRunner.xcscheme @@ -66,6 +66,11 @@ value = "$(USE_PORT)" isEnabled = "YES"> + + + + snapshot, NSArray *types); @@ -65,10 +68,17 @@ - (NSString *)fb_description } - (id)fb_attributeValue:(NSString *)attribute + error:(NSError **)error { + NSDate *start = [NSDate date]; NSDictionary *result = [FBXCAXClientProxy.sharedClient attributesForElement:[self accessibilityElement] - attributes:@[attribute]]; - return result[attribute]; + attributes:@[attribute] + error:error]; + NSTimeInterval elapsed = ABS([start timeIntervalSinceNow]); + if (elapsed > ATTRIBUTE_FETCH_WARN_TIME_LIMIT) { + NSLog(@"! Fetching of %@ value for %@ took %@s", attribute, self.fb_description, @(elapsed)); + } + return [result objectForKey:attribute]; } inline static BOOL areValuesEqual(id value1, id value2); @@ -140,29 +150,6 @@ - (BOOL)fb_framelessFuzzyMatchesElement:(id)snapshot return targetCellSnapshot; } -- (CGRect)fb_visibleFrameWithFallback -{ - CGRect thisVisibleFrame = [self visibleFrame]; - if (!CGRectIsEmpty(thisVisibleFrame)) { - return thisVisibleFrame; - } - - NSDictionary *visibleFrameDict = (NSDictionary*)[self fb_attributeValue:@"XC_kAXXCAttributeVisibleFrame"]; - if (visibleFrameDict == nil) { - return thisVisibleFrame; - } - - id x = [visibleFrameDict objectForKey:@"X"]; - id y = [visibleFrameDict objectForKey:@"Y"]; - id height = [visibleFrameDict objectForKey:@"Height"]; - id width = [visibleFrameDict objectForKey:@"Width"]; - if (x != nil && y != nil && height != nil && width != nil) { - return CGRectMake([x doubleValue], [y doubleValue], [width doubleValue], [height doubleValue]); - } - - return thisVisibleFrame; -} - - (NSValue *)fb_hitPoint { NSError *error; diff --git a/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.h b/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.h index 0f657ab6..cb2b539a 100644 --- a/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.h +++ b/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.m b/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.m index 39976914..0a5905da 100644 --- a/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.m +++ b/WebDriverAgentLib/Categories/NSDictionary+FBUtf8SafeDictionary.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "NSDictionary+FBUtf8SafeDictionary.h" diff --git a/WebDriverAgentLib/Categories/NSExpression+FBFormat.h b/WebDriverAgentLib/Categories/NSExpression+FBFormat.h index feafbac4..274d4201 100644 --- a/WebDriverAgentLib/Categories/NSExpression+FBFormat.h +++ b/WebDriverAgentLib/Categories/NSExpression+FBFormat.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/NSExpression+FBFormat.m b/WebDriverAgentLib/Categories/NSExpression+FBFormat.m index 81858d65..d4c32aeb 100644 --- a/WebDriverAgentLib/Categories/NSExpression+FBFormat.m +++ b/WebDriverAgentLib/Categories/NSExpression+FBFormat.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "NSExpression+FBFormat.h" diff --git a/WebDriverAgentLib/Categories/NSString+FBVisualLength.h b/WebDriverAgentLib/Categories/NSString+FBVisualLength.h index a24eb690..ec065e28 100644 --- a/WebDriverAgentLib/Categories/NSString+FBVisualLength.h +++ b/WebDriverAgentLib/Categories/NSString+FBVisualLength.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/NSString+FBVisualLength.m b/WebDriverAgentLib/Categories/NSString+FBVisualLength.m index 9487bbeb..652f1a06 100644 --- a/WebDriverAgentLib/Categories/NSString+FBVisualLength.m +++ b/WebDriverAgentLib/Categories/NSString+FBVisualLength.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "NSString+FBVisualLength.h" diff --git a/WebDriverAgentLib/Categories/NSString+FBXMLSafeString.h b/WebDriverAgentLib/Categories/NSString+FBXMLSafeString.h index e51407b7..7cdceb79 100644 --- a/WebDriverAgentLib/Categories/NSString+FBXMLSafeString.h +++ b/WebDriverAgentLib/Categories/NSString+FBXMLSafeString.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/NSString+FBXMLSafeString.m b/WebDriverAgentLib/Categories/NSString+FBXMLSafeString.m index cdc7ab3b..dbb7573f 100644 --- a/WebDriverAgentLib/Categories/NSString+FBXMLSafeString.m +++ b/WebDriverAgentLib/Categories/NSString+FBXMLSafeString.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "NSString+FBXMLSafeString.h" diff --git a/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.h b/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.h index 8080f209..d984e0b9 100644 --- a/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.h +++ b/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.m b/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.m index 356a1ea0..0d39ba0b 100644 --- a/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.m +++ b/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCAXClient_iOS+FBSnapshotReqParams.h" @@ -65,6 +64,7 @@ @implementation XCAXClient_iOS (FBSnapshotReqParams) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-load-method" +#pragma clang diagnostic ignored "-Wcast-function-type-strict" + (void)load { diff --git a/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.h b/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.h index b4cdf1d4..fc81daa0 100644 --- a/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.h +++ b/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.m b/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.m index dc27e86a..70472e4a 100644 --- a/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.m +++ b/WebDriverAgentLib/Categories/XCTIssue+FBPatcher.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCTIssue+FBPatcher.h" @@ -20,6 +19,8 @@ @implementation XCTIssue (AMPatcher) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-load-method" +#pragma clang diagnostic ignored "-Wcast-function-type-strict" + + (void)load { SEL originalShouldInterruptTest = NSSelectorFromString(@"shouldInterruptTest"); @@ -28,6 +29,7 @@ + (void)load if (nil == originalShouldInterruptTestMethod) return; method_setImplementation(originalShouldInterruptTestMethod, (IMP)swizzledShouldInterruptTest); } + #pragma clang diagnostic pop @end diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.h b/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.h index 7c057699..01bea467 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.h +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m b/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m index 38b6586e..36628bc6 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBAlert.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIApplication+FBAlert.h" @@ -52,7 +51,7 @@ - (nullable XCUIElement *)fb_alertElementFromSafariWithScrollView:(XCUIElement * // and conatins at least one text view __block NSUInteger buttonsCount = 0; __block NSUInteger textViewsCount = 0; - id snapshot = candidate.fb_cachedSnapshot ?: candidate.fb_takeSnapshot; + id snapshot = candidate.fb_cachedSnapshot ?: [candidate fb_customSnapshot]; [snapshot enumerateDescendantsUsingBlock:^(id descendant) { XCUIElementType curType = descendant.elementType; if (curType == XCUIElementTypeButton) { @@ -73,7 +72,7 @@ - (XCUIElement *)fb_alertElement if (nil == alert) { return nil; } - id alertSnapshot = alert.fb_cachedSnapshot ?: alert.fb_takeSnapshot; + id alertSnapshot = alert.fb_cachedSnapshot ?: [alert fb_customSnapshot]; if (alertSnapshot.elementType == XCUIElementTypeAlert) { return alert; diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBFocused.h b/WebDriverAgentLib/Categories/XCUIApplication+FBFocused.h index 6951e760..4df5025c 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBFocused.h +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBFocused.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h index 3ef66423..f5d358ff 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -31,6 +30,12 @@ NS_ASSUME_NONNULL_BEGIN */ - (NSDictionary *)fb_tree; +/** + @param excludedAttributes Set of possible attributes to be excluded i.e frame, enabled, visible, accessible, focused. If set to nil or an empty array then no attributes will be excluded from the resulting JSON + @return application elements tree in form of nested dictionaries + */ +- (NSDictionary *)fb_tree:(nullable NSSet *) excludedAttributes; + /** Return application elements accessibility tree in form of nested dictionaries */ diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m index c3c99e6f..e5abde90 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIApplication+FBHelpers.h" @@ -37,9 +36,21 @@ #import "XCUIElement+FBUtilities.h" #import "XCUIElement+FBWebDriverAttributes.h" #import "XCUIElementQuery.h" +#import "FBElementHelpers.h" static NSString* const FBUnknownBundleId = @"unknown"; +static NSString* const FBExclusionAttributeFrame = @"frame"; +static NSString* const FBExclusionAttributeEnabled = @"enabled"; +static NSString* const FBExclusionAttributeVisible = @"visible"; +static NSString* const FBExclusionAttributeAccessible = @"accessible"; +static NSString* const FBExclusionAttributeFocused = @"focused"; +static NSString* const FBExclusionAttributePlaceholderValue = @"placeholderValue"; +static NSString* const FBExclusionAttributeNativeFrame = @"nativeFrame"; +static NSString* const FBExclusionAttributeTraits = @"traits"; +static NSString* const FBExclusionAttributeMinValue = @"minValue"; +static NSString* const FBExclusionAttributeMaxValue = @"maxValue"; + _Nullable id extractIssueProperty(id issue, NSString *propertyName) { SEL selector = NSSelectorFromString(propertyName); NSMethodSignature *methodSignature = [issue methodSignatureForSelector:selector]; @@ -88,6 +99,17 @@ _Nullable id extractIssueProperty(id issue, NSString *propertyName) { return result; } +NSDictionary *customExclusionAttributesMap(void) { + static dispatch_once_t onceToken; + static NSDictionary *result; + dispatch_once(&onceToken, ^{ + result = @{ + FBExclusionAttributeVisible: FB_XCAXAIsVisibleAttributeName, + FBExclusionAttributeAccessible: FB_XCAXAIsElementAttributeName, + }; + }); + return result; +} @implementation XCUIApplication (FBHelpers) @@ -153,21 +175,26 @@ - (BOOL)fb_deactivateWithDuration:(NSTimeInterval)duration error:(NSError **)err - (NSDictionary *)fb_tree { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : [self fb_snapshotWithAllAttributesAndMaxDepth:nil]; - return [self.class dictionaryForElement:snapshot recursive:YES]; + return [self fb_tree:nil]; +} + +- (NSDictionary *)fb_tree:(nullable NSSet *)excludedAttributes +{ + id snapshot = [self fb_standardSnapshot]; + return [self.class dictionaryForElement:snapshot + recursive:YES + excludedAttributes:excludedAttributes]; } - (NSDictionary *)fb_accessibilityTree { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : [self fb_snapshotWithAllAttributesAndMaxDepth:nil]; + id snapshot = [self fb_standardSnapshot]; return [self.class accessibilityInfoForElement:snapshot]; } -+ (NSDictionary *)dictionaryForElement:(id)snapshot recursive:(BOOL)recursive ++ (NSDictionary *)dictionaryForElement:(id)snapshot + recursive:(BOOL)recursive + excludedAttributes:(nullable NSSet *)excludedAttributes { NSMutableDictionary *info = [[NSMutableDictionary alloc] init]; info[@"type"] = [FBElementTypeTransformer shortStringWithElementType:snapshot.elementType]; @@ -177,11 +204,28 @@ + (NSDictionary *)dictionaryForElement:(id)snapshot recursi info[@"value"] = FBValueOrNull(wrappedSnapshot.wdValue); info[@"label"] = FBValueOrNull(wrappedSnapshot.wdLabel); info[@"rect"] = wrappedSnapshot.wdRect; - info[@"frame"] = NSStringFromCGRect(wrappedSnapshot.wdFrame); - info[@"isEnabled"] = [@([wrappedSnapshot isWDEnabled]) stringValue]; - info[@"isVisible"] = [@([wrappedSnapshot isWDVisible]) stringValue]; - info[@"isAccessible"] = [@([wrappedSnapshot isWDAccessible]) stringValue]; - info[@"isFocused"] = [@([wrappedSnapshot isWDFocused]) stringValue]; + + NSDictionary *attributeBlocks = [self fb_attributeBlockMapForWrappedSnapshot:wrappedSnapshot]; + + NSSet *nonPrefixedKeys = [NSSet setWithObjects: + FBExclusionAttributeFrame, + FBExclusionAttributePlaceholderValue, + FBExclusionAttributeNativeFrame, + FBExclusionAttributeTraits, + FBExclusionAttributeMinValue, + FBExclusionAttributeMaxValue, + nil]; + + for (NSString *key in attributeBlocks) { + if (excludedAttributes == nil || ![excludedAttributes containsObject:key]) { + NSString *value = ((NSString * (^)(void))attributeBlocks[key])(); + if ([nonPrefixedKeys containsObject:key]) { + info[key] = value; + } else { + info[[NSString stringWithFormat:@"is%@", [key capitalizedString]]] = value; + } + } + } if (!recursive) { return info.copy; @@ -191,12 +235,69 @@ + (NSDictionary *)dictionaryForElement:(id)snapshot recursi if ([childElements count]) { info[@"children"] = [[NSMutableArray alloc] init]; for (id childSnapshot in childElements) { - [info[@"children"] addObject:[self dictionaryForElement:childSnapshot recursive:YES]]; + @autoreleasepool { + [info[@"children"] addObject:[self dictionaryForElement:childSnapshot + recursive:YES + excludedAttributes:excludedAttributes]]; + } } } return info; } +// Helper used by `dictionaryForElement:` to assemble attribute value blocks, +// including both common attributes and conditionally included ones like placeholderValue. ++ (NSDictionary *)fb_attributeBlockMapForWrappedSnapshot:(FBXCElementSnapshotWrapper *)wrappedSnapshot + +{ + // Base attributes common to every element + NSMutableDictionary *blocks = + [@{ + FBExclusionAttributeFrame: ^{ + return NSStringFromCGRect(wrappedSnapshot.wdFrame); + }, + FBExclusionAttributeNativeFrame: ^{ + return NSStringFromCGRect(wrappedSnapshot.wdNativeFrame); + }, + FBExclusionAttributeEnabled: ^{ + return [@([wrappedSnapshot isWDEnabled]) stringValue]; + }, + FBExclusionAttributeVisible: ^{ + return [@([wrappedSnapshot isWDVisible]) stringValue]; + }, + FBExclusionAttributeAccessible: ^{ + return [@([wrappedSnapshot isWDAccessible]) stringValue]; + }, + FBExclusionAttributeFocused: ^{ + return [@([wrappedSnapshot isWDFocused]) stringValue]; + }, + FBExclusionAttributeTraits: ^{ + return wrappedSnapshot.wdTraits; + } + } mutableCopy]; + + XCUIElementType elementType = wrappedSnapshot.elementType; + + // Text-input placeholder (only for elements that support inner text) + if (FBDoesElementSupportInnerText(elementType)) { + blocks[FBExclusionAttributePlaceholderValue] = ^{ + return (NSString *)FBValueOrNull(wrappedSnapshot.wdPlaceholderValue); + }; + } + + // Only for elements that support min/max value + if (FBDoesElementSupportMinMaxValue(elementType)) { + blocks[FBExclusionAttributeMinValue] = ^{ + return wrappedSnapshot.wdMinValue; + }; + blocks[FBExclusionAttributeMaxValue] = ^{ + return wrappedSnapshot.wdMaxValue; + }; + } + + return [blocks copy]; +} + + (NSDictionary *)accessibilityInfoForElement:(id)snapshot { FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; @@ -213,9 +314,11 @@ + (NSDictionary *)accessibilityInfoForElement:(id)snapshot } else { NSMutableArray *children = [[NSMutableArray alloc] init]; for (id childSnapshot in snapshot.children) { - NSDictionary *childInfo = [self accessibilityInfoForElement:childSnapshot]; - if ([childInfo count]) { - [children addObject: childInfo]; + @autoreleasepool { + NSDictionary *childInfo = [self accessibilityInfoForElement:childSnapshot]; + if ([childInfo count]) { + [children addObject: childInfo]; + } } } if ([children count]) { @@ -363,33 +466,41 @@ - (BOOL)fb_dismissKeyboardWithKeyNames:(nullable NSArray *)keyNames return nil; } + // These custom attributes could take too long to fetch, thus excluded + NSSet *customAttributesToExclude = [NSSet setWithArray:[customExclusionAttributesMap() allKeys]]; NSMutableArray *resultArray = [NSMutableArray array]; NSMethodSignature *methodSignature = [self methodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; [invocation setSelector:selector]; [invocation setArgument:&auditTypes atIndex:2]; BOOL (^issueHandler)(id) = ^BOOL(id issue) { - NSString *auditType = @""; - NSDictionary *valuesToNamesMap = auditTypeValuesToNames(); - NSNumber *auditTypeValue = [issue valueForKey:@"auditType"]; - if (nil != auditTypeValue) { - auditType = valuesToNamesMap[auditTypeValue] ?: [auditTypeValue stringValue]; + @autoreleasepool { + NSString *auditType = @""; + NSDictionary *valuesToNamesMap = auditTypeValuesToNames(); + NSNumber *auditTypeValue = [issue valueForKey:@"auditType"]; + if (nil != auditTypeValue) { + auditType = valuesToNamesMap[auditTypeValue] ?: [auditTypeValue stringValue]; + } + + id extractedElement = extractIssueProperty(issue, @"element"); + + id elementSnapshot = [extractedElement fb_cachedSnapshot] ?: [extractedElement fb_standardSnapshot]; + NSDictionary *elementAttributes = elementSnapshot + ? [self.class dictionaryForElement:elementSnapshot + recursive:NO + excludedAttributes:customAttributesToExclude] + : @{}; + + [resultArray addObject:@{ + @"detailedDescription": extractIssueProperty(issue, @"detailedDescription") ?: @"", + @"compactDescription": extractIssueProperty(issue, @"compactDescription") ?: @"", + @"auditType": auditType, + @"element": [extractedElement description] ?: @"", + @"elementDescription": [extractedElement debugDescription] ?: @"", + @"elementAttributes": elementAttributes ?: @{}, + }]; + return YES; } - - id extractedElement = extractIssueProperty(issue, @"element"); - - id elementSnapshot = [extractedElement fb_takeSnapshot]; - NSDictionary *elementAttributes = elementSnapshot ? [self.class dictionaryForElement:elementSnapshot recursive:NO] : @{}; - - [resultArray addObject:@{ - @"detailedDescription": extractIssueProperty(issue, @"detailedDescription") ?: @"", - @"compactDescription": extractIssueProperty(issue, @"compactDescription") ?: @"", - @"auditType": auditType, - @"element": [extractedElement description] ?: @"", - @"elementDescription": [extractedElement debugDescription] ?: @"", - @"elementAttributes": elementAttributes ?: @{}, - }]; - return YES; }; [invocation setArgument:&issueHandler atIndex:3]; [invocation setArgument:&error atIndex:4]; @@ -509,23 +620,17 @@ + (BOOL)fb_switchToSystemApplicationWithError:(NSError **)error { XCUIApplication *systemApp = self.fb_systemApplication; @try { - if (!systemApp.running) { - [systemApp launch]; - } else { + if (systemApp.running) { [systemApp activate]; + } else { + [systemApp launch]; } } @catch (NSException *e) { return [[[FBErrorBuilder alloc] withDescription:nil == e ? @"Cannot open the home screen" : e.reason] buildError:error]; } - return [[[[FBRunLoopSpinner new] - timeout:5] - timeoutErrorMessage:@"Timeout waiting until the home screen is visible"] - spinUntilTrue:^BOOL{ - return [systemApp fb_isSameAppAs:self.fb_activeApplication]; - } - error:error]; + return YES; } - (BOOL)fb_isSameAppAs:(nullable XCUIApplication *)otherApp diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBQuiescence.h b/WebDriverAgentLib/Categories/XCUIApplication+FBQuiescence.h index ef036053..962a4814 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBQuiescence.h +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBQuiescence.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBQuiescence.m b/WebDriverAgentLib/Categories/XCUIApplication+FBQuiescence.m index 66f1f118..72febaa5 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBQuiescence.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBQuiescence.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIApplication+FBQuiescence.h" diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.h b/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.h index 6be298b4..79b220c5 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.h +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.m b/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.m index 622dac47..bbd1e574 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBTouchAction.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBUIInterruptions.h b/WebDriverAgentLib/Categories/XCUIApplication+FBUIInterruptions.h index 2078d8c2..e9527321 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBUIInterruptions.h +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBUIInterruptions.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIApplication+FBUIInterruptions.m b/WebDriverAgentLib/Categories/XCUIApplication+FBUIInterruptions.m index 5d48dffa..b662a1e5 100644 --- a/WebDriverAgentLib/Categories/XCUIApplication+FBUIInterruptions.m +++ b/WebDriverAgentLib/Categories/XCUIApplication+FBUIInterruptions.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIApplication+FBUIInterruptions.h" diff --git a/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.h b/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.h index 0c78f240..f911cbfd 100644 --- a/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.h +++ b/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -18,6 +17,11 @@ NS_ASSUME_NONNULL_BEGIN /*! Defines wtether the process should perform quiescence checks. YES by default */ @property (nonatomic) NSNumber* fb_shouldWaitForQuiescence; +/** + @param waitForAnimations Set it to YES if XCTest should also wait for application animations to complete + */ +- (void)fb_waitForQuiescenceIncludingAnimationsIdle:(bool)waitForAnimations; + @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m b/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m index cc60e429..1f6272db 100644 --- a/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m +++ b/WebDriverAgentLib/Categories/XCUIApplicationProcess+FBQuiescence.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIApplicationProcess+FBQuiescence.h" @@ -12,10 +11,12 @@ #import #import "FBConfiguration.h" +#import "FBExceptions.h" #import "FBLogger.h" #import "FBSettings.h" static void (*original_waitForQuiescenceIncludingAnimationsIdle)(id, SEL, BOOL); +static void (*original_waitForQuiescenceIncludingAnimationsIdlePreEvent)(id, SEL, BOOL, BOOL); static void swizzledWaitForQuiescenceIncludingAnimationsIdle(id self, SEL _cmd, BOOL includingAnimations) { @@ -38,17 +39,43 @@ static void swizzledWaitForQuiescenceIncludingAnimationsIdle(id self, SEL _cmd, } } +static void swizzledWaitForQuiescenceIncludingAnimationsIdlePreEvent(id self, SEL _cmd, BOOL includingAnimations, BOOL isPreEvent) +{ + NSString *bundleId = [self bundleID]; + if (![[self fb_shouldWaitForQuiescence] boolValue] || FBConfiguration.waitForIdleTimeout < DBL_EPSILON) { + [FBLogger logFmt:@"Quiescence checks are disabled for %@ application. Making it to believe it is idling", + bundleId]; + return; + } + + NSTimeInterval desiredTimeout = FBConfiguration.waitForIdleTimeout; + NSTimeInterval previousTimeout = _XCTApplicationStateTimeout(); + _XCTSetApplicationStateTimeout(desiredTimeout); + [FBLogger logFmt:@"Waiting up to %@s until %@ is in idle state (%@ animations)", + @(desiredTimeout), bundleId, includingAnimations ? @"including" : @"excluding"]; + @try { + original_waitForQuiescenceIncludingAnimationsIdlePreEvent(self, _cmd, includingAnimations, isPreEvent); + } @finally { + _XCTSetApplicationStateTimeout(previousTimeout); + } +} + @implementation XCUIApplicationProcess (FBQuiescence) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-load-method" +#pragma clang diagnostic ignored "-Wcast-function-type-strict" + (void)load { Method waitForQuiescenceIncludingAnimationsIdleMethod = class_getInstanceMethod(self.class, @selector(waitForQuiescenceIncludingAnimationsIdle:)); + Method waitForQuiescenceIncludingAnimationsIdlePreEventMethod = class_getInstanceMethod(self.class, @selector(waitForQuiescenceIncludingAnimationsIdle:isPreEvent:)); if (nil != waitForQuiescenceIncludingAnimationsIdleMethod) { IMP swizzledImp = (IMP)swizzledWaitForQuiescenceIncludingAnimationsIdle; original_waitForQuiescenceIncludingAnimationsIdle = (void (*)(id, SEL, BOOL)) method_setImplementation(waitForQuiescenceIncludingAnimationsIdleMethod, swizzledImp); + } else if (nil != waitForQuiescenceIncludingAnimationsIdlePreEventMethod) { + IMP swizzledImp = (IMP)swizzledWaitForQuiescenceIncludingAnimationsIdlePreEvent; + original_waitForQuiescenceIncludingAnimationsIdlePreEvent = (void (*)(id, SEL, BOOL, BOOL)) method_setImplementation(waitForQuiescenceIncludingAnimationsIdlePreEventMethod, swizzledImp); } else { [FBLogger log:@"Could not find method -[XCUIApplicationProcess waitForQuiescenceIncludingAnimationsIdle:]"]; } @@ -74,4 +101,18 @@ - (void)setFb_shouldWaitForQuiescence:(NSNumber *)value objc_setAssociatedObject(self, &XCUIAPPLICATIONPROCESS_SHOULD_WAIT_FOR_QUIESCENCE, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } +- (void)fb_waitForQuiescenceIncludingAnimationsIdle:(bool)waitForAnimations +{ + if ([self respondsToSelector:@selector(waitForQuiescenceIncludingAnimationsIdle:)]) { + [self waitForQuiescenceIncludingAnimationsIdle:waitForAnimations]; + } else if ([self respondsToSelector:@selector(waitForQuiescenceIncludingAnimationsIdle:isPreEvent:)]) { + [self waitForQuiescenceIncludingAnimationsIdle:waitForAnimations isPreEvent:NO]; + } else { + @throw [NSException exceptionWithName:FBIncompatibleWdaException + reason:@"The current WebDriverAgent build is not compatible to your device OS version" + userInfo:@{}]; + } +} + + @end diff --git a/WebDriverAgentLib/Categories/XCUIDevice+FBHealthCheck.h b/WebDriverAgentLib/Categories/XCUIDevice+FBHealthCheck.h index 65257ee1..1c1ab63c 100644 --- a/WebDriverAgentLib/Categories/XCUIDevice+FBHealthCheck.h +++ b/WebDriverAgentLib/Categories/XCUIDevice+FBHealthCheck.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIDevice+FBHealthCheck.m b/WebDriverAgentLib/Categories/XCUIDevice+FBHealthCheck.m index 315f0674..8f9de6ee 100644 --- a/WebDriverAgentLib/Categories/XCUIDevice+FBHealthCheck.m +++ b/WebDriverAgentLib/Categories/XCUIDevice+FBHealthCheck.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIDevice+FBHealthCheck.h" diff --git a/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.h b/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.h index 83bfbe4c..95fdbc21 100644 --- a/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.h +++ b/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m index 0079c116..b8dfcafa 100644 --- a/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIDevice+FBHelpers.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIDevice+FBHelpers.h" diff --git a/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.h b/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.h index 993c301c..b947fcdd 100644 --- a/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.h +++ b/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.m b/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.m index 68b9b20a..164b23e7 100644 --- a/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.m +++ b/WebDriverAgentLib/Categories/XCUIDevice+FBRotation.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIDevice+FBRotation.h" diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.h b/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.h index 2af37a8d..baa56565 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.h @@ -3,12 +3,11 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import -#import "FBXCElementSnapshotWrapper.h" +#import NS_ASSUME_NONNULL_BEGIN diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m b/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m index 327b2171..47d62e58 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBAccessibility.h" @@ -18,8 +17,7 @@ @implementation XCUIElement (FBAccessibility) - (BOOL)fb_isAccessibilityElement { - id snapshot = [self fb_snapshotWithAttributes:@[FB_XCAXAIsElementAttributeName] - maxDepth:@1]; + id snapshot = [self fb_standardSnapshot]; return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_isAccessibilityElement; } @@ -33,8 +31,20 @@ - (BOOL)fb_isAccessibilityElement if (nil != isAccessibilityElement) { return isAccessibilityElement.boolValue; } - - return [(NSNumber *)[self fb_attributeValue:FB_XCAXAIsElementAttributeName] boolValue]; + + NSError *error; + NSNumber *attributeValue = [self fb_attributeValue:FB_XCAXAIsElementAttributeName + error:&error]; + if (nil != attributeValue) { + NSMutableDictionary *updatedValue = [NSMutableDictionary dictionaryWithDictionary:self.additionalAttributes ?: @{}]; + [updatedValue setObject:attributeValue forKey:FB_XCAXAIsElementAttribute]; + self.snapshot.additionalAttributes = updatedValue.copy; + return [attributeValue boolValue]; + } + + NSLog(@"Cannot determine accessibility of '%@' natively: %@. Defaulting to: %@", + self.fb_description, error.description, @(NO)); + return NO; } @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBCaching.h b/WebDriverAgentLib/Categories/XCUIElement+FBCaching.h index 109a2637..119723aa 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBCaching.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBCaching.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -13,9 +12,6 @@ NS_ASSUME_NONNULL_BEGIN @interface XCUIElement (FBCaching) -/*! This property is set to YES if the given element has been resolved from the cache, so it is safe to use the `lastSnapshot` property */ -@property (nullable, nonatomic) NSNumber *fb_isResolvedFromCache; - @property (nonatomic, readonly) NSString *fb_cacheId; @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m b/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m index faa42ea8..c2e9f112 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBCaching.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBCaching.h" @@ -18,20 +17,6 @@ @implementation XCUIElement (FBCaching) -static char XCUIELEMENT_IS_RESOLVED_FROM_CACHE_KEY; - -@dynamic fb_isResolvedFromCache; - -- (void)setFb_isResolvedFromCache:(NSNumber *)isResolvedFromCache -{ - objc_setAssociatedObject(self, &XCUIELEMENT_IS_RESOLVED_FROM_CACHE_KEY, isResolvedFromCache, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -- (NSNumber *)fb_isResolvedFromCache -{ - return (NSNumber *)objc_getAssociatedObject(self, &XCUIELEMENT_IS_RESOLVED_FROM_CACHE_KEY); -} - static char XCUIELEMENT_CACHE_ID_KEY; @dynamic fb_cacheId; @@ -43,14 +28,7 @@ - (NSString *)fb_cacheId return (NSString *)result; } - NSString *uid; - if ([self isKindOfClass:XCUIApplication.class]) { - uid = self.fb_uid; - } else { - id snapshot = self.fb_cachedSnapshot ?: self.fb_takeSnapshot; - uid = [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]; - } - + NSString *uid = self.fb_uid; objc_setAssociatedObject(self, &XCUIELEMENT_CACHE_ID_KEY, uid, OBJC_ASSOCIATION_RETAIN_NONATOMIC); return uid; } diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.h b/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.h index 1cd1e8b9..0e56bfea 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -50,7 +49,8 @@ NS_ASSUME_NONNULL_BEGIN @return an array of descendants matching given class chain @throws FBUnknownAttributeException if any of predicates in the chain contains unknown attribute(s) */ -- (NSArray *)fb_descendantsMatchingClassChain:(NSString *)classChainQuery shouldReturnAfterFirstMatch:(BOOL)shouldReturnAfterFirstMatch; +- (NSArray *)fb_descendantsMatchingClassChain:(NSString *)classChainQuery + shouldReturnAfterFirstMatch:(BOOL)shouldReturnAfterFirstMatch; @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.m b/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.m index 9f70955b..88197ecc 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBClassChain.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBClassChain.h" diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBFind.h b/WebDriverAgentLib/Categories/XCUIElement+FBFind.h index 664d828b..8a91fcdb 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBFind.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBFind.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBFind.m b/WebDriverAgentLib/Categories/XCUIElement+FBFind.m index 4d46f4c8..ceab0adf 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBFind.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBFind.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ @@ -12,6 +11,7 @@ #import "FBMacros.h" #import "FBElementTypeTransformer.h" +#import "FBConfiguration.h" #import "NSPredicate+FBFormat.h" #import "FBXCElementSnapshotWrapper+Helpers.h" #import "FBXCodeCompatibility.h" @@ -109,9 +109,9 @@ @implementation XCUIElement (FBFind) id snapshot = matchingSnapshots.firstObject; matchingSnapshots = @[snapshot]; } - return [self fb_filterDescendantsWithSnapshots:matchingSnapshots - selfUID:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:self.lastSnapshot] - onlyChildren:NO]; + XCUIElement *scopeRoot = FBConfiguration.limitXpathContextScope ? self : self.application; + return [scopeRoot fb_filterDescendantsWithSnapshots:matchingSnapshots + onlyChildren:NO]; } @@ -122,7 +122,9 @@ @implementation XCUIElement (FBFind) { NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id snapshot, NSDictionary * _Nullable bindings) { - return [[FBXCElementSnapshotWrapper wdNameWithSnapshot:snapshot] isEqualToString:accessibilityId]; + @autoreleasepool { + return [[FBXCElementSnapshotWrapper wdNameWithSnapshot:snapshot] isEqualToString:accessibilityId]; + } }]; return [self fb_descendantsMatchingPredicate:predicate shouldReturnAfterFirstMatch:shouldReturnAfterFirstMatch]; diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.h b/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.h index 154cab24..8005b229 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.m b/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.m index 1c7a9ce0..bd5d0bdd 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBForceTouch.h" diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.h b/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.h index 2acc5651..fd17acca 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.h @@ -3,11 +3,10 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ -#import "FBXCElementSnapshotWrapper.h" +#import NS_ASSUME_NONNULL_BEGIN diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m b/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m index 87841fc3..75a228a3 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m @@ -3,218 +3,76 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBIsVisible.h" -#import "FBConfiguration.h" #import "FBElementUtils.h" -#import "FBMathUtils.h" -#import "FBActiveAppDetectionPoint.h" -#import "FBSession.h" -#import "FBXCAccessibilityElement.h" #import "FBXCodeCompatibility.h" #import "FBXCElementSnapshotWrapper+Helpers.h" #import "XCUIElement+FBUtilities.h" -#import "XCUIElement+FBUID.h" +#import "XCUIElement+FBVisibleFrame.h" #import "XCTestPrivateSymbols.h" -@implementation XCUIElement (FBIsVisible) - -- (BOOL)fb_isVisible +NSNumber* _Nullable fetchSnapshotVisibility(id snapshot) { - id snapshot = [self fb_snapshotWithAttributes:@[FB_XCAXAIsVisibleAttributeName] - maxDepth:@1]; - return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_isVisible; + return nil == snapshot.additionalAttributes ? nil : snapshot.additionalAttributes[FB_XCAXAIsVisibleAttribute]; } -@end - -@implementation FBXCElementSnapshotWrapper (FBIsVisible) - -+ (NSString *)fb_uniqIdWithSnapshot:(id)snapshot -{ - return [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot] ?: [NSString stringWithFormat:@"%p", (void *)snapshot]; -} +@implementation XCUIElement (FBIsVisible) -- (nullable NSNumber *)fb_cachedVisibilityValue +- (BOOL)fb_isVisible { - NSMutableDictionary *cache = FBSession.activeSession.elementsVisibilityCache; - if (nil == cache) { - return nil; + @autoreleasepool { + id snapshot = [self fb_standardSnapshot]; + return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_isVisible; } - - NSDictionary *result = cache[@(self.generation)]; - if (nil == result) { - // There is no need to keep the cached data for the previous generations - [cache removeAllObjects]; - cache[@(self.generation)] = [NSMutableDictionary dictionary]; - return nil; - } - return result[[self.class fb_uniqIdWithSnapshot:self.snapshot]]; } -- (BOOL)fb_cacheVisibilityWithValue:(BOOL)isVisible - forAncestors:(nullable NSArray> *)ancestors -{ - NSMutableDictionary *cache = FBSession.activeSession.elementsVisibilityCache; - if (nil == cache) { - return isVisible; - } - NSMutableDictionary *destination = cache[@(self.generation)]; - if (nil == destination) { - return isVisible; - } - - NSNumber *visibleObj = [NSNumber numberWithBool:isVisible]; - destination[[self.class fb_uniqIdWithSnapshot:self.snapshot]] = visibleObj; - if (isVisible && nil != ancestors) { - // if an element is visible then all its ancestors must be visible as well - for (id ancestor in ancestors) { - NSString *ancestorId = [self.class fb_uniqIdWithSnapshot:ancestor]; - if (nil == destination[ancestorId]) { - destination[ancestorId] = visibleObj; - } - } - } - return isVisible; -} +@end -- (CGRect)fb_frameInContainer:(id)container - hierarchyIntersection:(nullable NSValue *)intersectionRectange -{ - CGRect currentRectangle = nil == intersectionRectange ? self.frame : [intersectionRectange CGRectValue]; - id parent = self.parent; - CGRect parentFrame = parent.frame; - CGRect containerFrame = container.frame; - if (CGSizeEqualToSize(parentFrame.size, CGSizeZero) && - CGPointEqualToPoint(parentFrame.origin, CGPointZero)) { - // Special case (or XCTest bug). Shift the origin and return immediately after shift - id nextParent = parent.parent; - BOOL isGrandparent = YES; - while (nextParent && nextParent != container) { - CGRect nextParentFrame = nextParent.frame; - if (isGrandparent && - CGSizeEqualToSize(nextParentFrame.size, CGSizeZero) && - CGPointEqualToPoint(nextParentFrame.origin, CGPointZero)) { - // Double zero-size container inclusion means that element coordinates are absolute - return CGRectIntersection(currentRectangle, containerFrame); - } - isGrandparent = NO; - if (!CGPointEqualToPoint(nextParentFrame.origin, CGPointZero)) { - currentRectangle.origin.x += nextParentFrame.origin.x; - currentRectangle.origin.y += nextParentFrame.origin.y; - return CGRectIntersection(currentRectangle, containerFrame); - } - nextParent = nextParent.parent; - } - return CGRectIntersection(currentRectangle, containerFrame); - } - // Skip parent containers if they are outside of the viewport - CGRect intersectionWithParent = CGRectIntersectsRect(parentFrame, containerFrame) || parent.elementType != XCUIElementTypeOther - ? CGRectIntersection(currentRectangle, parentFrame) - : currentRectangle; - if (CGRectIsEmpty(intersectionWithParent) && - parent != container && - self.elementType == XCUIElementTypeOther) { - // Special case (or XCTest bug). Shift the origin - if (CGSizeEqualToSize(parentFrame.size, containerFrame.size) || - // The size might be inverted in landscape - CGSizeEqualToSize(parentFrame.size, CGSizeMake(containerFrame.size.height, containerFrame.size.width)) || - CGSizeEqualToSize(self.frame.size, CGSizeZero)) { - // Covers ActivityListView and RemoteBridgeView cases - currentRectangle.origin.x += parentFrame.origin.x; - currentRectangle.origin.y += parentFrame.origin.y; - return CGRectIntersection(currentRectangle, containerFrame); - } - } - if (CGRectIsEmpty(intersectionWithParent) || parent == container) { - return intersectionWithParent; - } - return [[FBXCElementSnapshotWrapper ensureWrapped:parent] fb_frameInContainer:container - hierarchyIntersection:[NSValue valueWithCGRect:intersectionWithParent]]; -} +@implementation FBXCElementSnapshotWrapper (FBIsVisible) -- (BOOL)fb_hasAnyVisibleLeafs +- (BOOL)fb_hasVisibleDescendants { - NSArray> *children = self.children; - if (0 == children.count) { - return self.fb_isVisible; - } - - for (id child in children) { - if ([FBXCElementSnapshotWrapper ensureWrapped:child].fb_hasAnyVisibleLeafs) { + for (id descendant in (self._allDescendants ?: @[])) { + if ([fetchSnapshotVisibility(descendant) boolValue]) { return YES; } } - return NO; } - (BOOL)fb_isVisible { - NSNumber *isVisible = self.additionalAttributes[FB_XCAXAIsVisibleAttribute]; - if (isVisible != nil) { + NSNumber *isVisible = fetchSnapshotVisibility(self); + if (nil != isVisible) { return isVisible.boolValue; } - - NSNumber *cachedValue = [self fb_cachedVisibilityValue]; - if (nil != cachedValue) { - return [cachedValue boolValue]; - } - CGRect selfFrame = self.frame; - if (CGRectIsEmpty(selfFrame)) { - return [self fb_cacheVisibilityWithValue:NO forAncestors:nil]; + // Fetching the attribute value is expensive. + // Shortcircuit here to save time and assume if any of descendants + // is already determined as visible then the container should be visible as well + if ([self fb_hasVisibleDescendants]) { + return YES; } - NSArray> *ancestors = self.fb_ancestors; - if ([FBConfiguration shouldUseTestManagerForVisibilityDetection]) { - BOOL visibleAttrValue = [(NSNumber *)[self fb_attributeValue:FB_XCAXAIsVisibleAttributeName] boolValue]; - return [self fb_cacheVisibilityWithValue:visibleAttrValue forAncestors:ancestors]; - } - - id parentWindow = ancestors.count > 1 ? [ancestors objectAtIndex:ancestors.count - 2] : nil; - CGRect visibleRect = selfFrame; - if (nil != parentWindow) { - visibleRect = [self fb_frameInContainer:parentWindow hierarchyIntersection:nil]; - } - if (CGRectIsEmpty(visibleRect)) { - return [self fb_cacheVisibilityWithValue:NO forAncestors:ancestors]; - } - CGPoint midPoint = CGPointMake(visibleRect.origin.x + visibleRect.size.width / 2, - visibleRect.origin.y + visibleRect.size.height / 2); - id hitElement = [FBActiveAppDetectionPoint axElementWithPoint:midPoint]; - if (nil != hitElement) { - if (FBIsAXElementEqualToOther(self.accessibilityElement, hitElement)) { - return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors]; - } - for (id ancestor in ancestors) { - if (FBIsAXElementEqualToOther(hitElement, ancestor.accessibilityElement)) { - return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors]; - } + NSError *error; + NSNumber *attributeValue = [self fb_attributeValue:FB_XCAXAIsVisibleAttributeName + error:&error]; + if (nil != attributeValue) { + NSMutableDictionary *updatedValue = [NSMutableDictionary dictionaryWithDictionary:self.additionalAttributes ?: @{}]; + [updatedValue setObject:attributeValue forKey:FB_XCAXAIsVisibleAttribute]; + self.snapshot.additionalAttributes = updatedValue.copy; + @autoreleasepool { + return [attributeValue boolValue]; } } - if (self.children.count > 0) { - if (nil != hitElement) { - for (id descendant in self._allDescendants) { - if (FBIsAXElementEqualToOther(hitElement, descendant.accessibilityElement)) { - return [self fb_cacheVisibilityWithValue:YES - forAncestors:[FBXCElementSnapshotWrapper ensureWrapped:descendant].fb_ancestors]; - } - } - } - if (self.fb_hasAnyVisibleLeafs) { - return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors]; - } - } else if (nil == hitElement) { - // Sometimes XCTest returns nil for leaf elements hit test even if such elements are hittable - // Assume such elements are visible if their rectInContainer is visible - return [self fb_cacheVisibilityWithValue:YES forAncestors:ancestors]; - } - return [self fb_cacheVisibilityWithValue:NO forAncestors:ancestors]; + + NSLog(@"Cannot determine visiblity of %@ natively: %@. Defaulting to: %@", + self.fb_description, error.description, @(NO)); + return NO; } @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBMinMax.h b/WebDriverAgentLib/Categories/XCUIElement+FBMinMax.h new file mode 100644 index 00000000..0873a65a --- /dev/null +++ b/WebDriverAgentLib/Categories/XCUIElement+FBMinMax.h @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface XCUIElement (FBMinMax) + +/*! Minimum value (minValue) – may be nil if the element does not have this attribute */ +@property (nonatomic, readonly, nullable) NSNumber *fb_minValue; + +/*! Maximum value (maxValue) - may be nil if the element does not have this attribute */ +@property (nonatomic, readonly, nullable) NSNumber *fb_maxValue; + +@end + +@interface FBXCElementSnapshotWrapper (FBMinMax) + +/*! Minimum value (minValue) – may be nil if the element does not have this attribute */ +@property (nonatomic, readonly, nullable) NSNumber *fb_minValue; + +/*! Maximum value (maxValue) - may be nil if the element does not have this attribute */ +@property (nonatomic, readonly, nullable) NSNumber *fb_maxValue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBMinMax.m b/WebDriverAgentLib/Categories/XCUIElement+FBMinMax.m new file mode 100644 index 00000000..87514906 --- /dev/null +++ b/WebDriverAgentLib/Categories/XCUIElement+FBMinMax.m @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FBLogger.h" +#import "XCUIElement+FBMinMax.h" +#import "FBXCElementSnapshotWrapper+Helpers.h" +#import "XCUIElement+FBUtilities.h" +#import "XCTestPrivateSymbols.h" + +@interface FBXCElementSnapshotWrapper (FBMinMaxInternal) + +- (NSNumber *)fb_numericAttribute:(NSString *)attributeName symbol:(NSNumber *)symbol; + +@end + +@implementation XCUIElement (FBMinMax) + +- (NSNumber *)fb_minValue +{ + @autoreleasepool { + id snapshot = [self fb_standardSnapshot]; + return [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_minValue]; + } +} + +- (NSNumber *)fb_maxValue +{ + @autoreleasepool { + id snapshot = [self fb_standardSnapshot]; + return [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_maxValue]; + } +} + +@end + +@implementation FBXCElementSnapshotWrapper (FBMinMax) + +- (NSNumber *)fb_minValue +{ + return [self fb_numericAttribute:FB_XCAXACustomMinValueAttributeName + symbol:FB_XCAXACustomMinValueAttribute]; +} + +- (NSNumber *)fb_maxValue +{ + return [self fb_numericAttribute:FB_XCAXACustomMaxValueAttributeName + symbol:FB_XCAXACustomMaxValueAttribute]; +} + +- (NSNumber *)fb_numericAttribute:(NSString *)attributeName symbol:(NSNumber *)symbol +{ + NSNumber *cached = (self.snapshot.additionalAttributes ?: @{})[symbol]; + if (cached) { + return cached; + } + + NSError *error = nil; + NSNumber *raw = [self fb_attributeValue:attributeName error:&error]; + if (nil != raw) { + NSMutableDictionary *updated = [NSMutableDictionary dictionaryWithDictionary:self.additionalAttributes ?: @{}]; + updated[symbol] = raw; + self.snapshot.additionalAttributes = updated.copy; + return raw; + } + + [FBLogger logFmt:@"[FBMinMax] Cannot determine %@ for %@: %@", attributeName, self.fb_description, error.localizedDescription]; + return nil; +} + +@end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.h b/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.h index a63cf934..72762a3c 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m b/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m index 71ebaf65..55189213 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBPickerWheel.h" @@ -12,6 +11,7 @@ #import "FBRunLoopSpinner.h" #import "FBXCElementSnapshot.h" #import "FBXCodeCompatibility.h" +#import "XCUIElement+FBUID.h" #import "XCUICoordinate.h" #import "XCUIElement+FBCaching.h" #import "XCUIElement+FBResolve.h" @@ -23,9 +23,7 @@ @implementation XCUIElement (FBPickerWheel) - (BOOL)fb_scrollWithOffset:(CGFloat)relativeHeightOffset error:(NSError **)error { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_standardSnapshot]; NSString *previousValue = snapshot.value; XCUICoordinate *startCoord = [self coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)]; XCUICoordinate *endCoord = [startCoord coordinateWithOffset:CGVectorMake(0.0, relativeHeightOffset * snapshot.frame.size.height)]; @@ -35,7 +33,7 @@ - (BOOL)fb_scrollWithOffset:(CGFloat)relativeHeightOffset error:(NSError **)erro // Fetching stable instance of an element allows it to be bounded to the // unique element identifier (UID), so it could be found next time even if its // id is different from the initial one. See https://github.com/appium/appium/issues/17569 - XCUIElement *stableInstance = self.fb_stableInstance; + XCUIElement *stableInstance = [self fb_stableInstanceWithUid:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]]; [endCoord tap]; return [[[[FBRunLoopSpinner new] timeout:VALUE_CHANGE_TIMEOUT] diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h b/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h index 80b218b0..09b174f2 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBResolve.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -27,10 +26,11 @@ NS_ASSUME_NONNULL_BEGIN Although, if the cached element instance is the one returned by this API call then the same element is going to be matched and no staleness exception will be thrown. + @param uid Element UUID @return Either the same element instance if `fb_isResolvedNatively` was set to NO (usually the cache for elements matched by xpath locators) or the stable instance of the self element based on the query by element's UUID. */ -- (XCUIElement *)fb_stableInstance; +- (XCUIElement *)fb_stableInstanceWithUid:(NSString *__nullable)uid; @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m b/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m index f52c72bf..f288114d 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBResolve.h" @@ -32,23 +31,21 @@ - (NSNumber *)fb_isResolvedNatively return nil == result ? @YES : result; } -- (XCUIElement *)fb_stableInstance +- (XCUIElement *)fb_stableInstanceWithUid:(NSString *)uid { - if (![self.fb_isResolvedNatively boolValue]) { + if (nil == uid || ![self.fb_isResolvedNatively boolValue] || [self isKindOfClass:XCUIApplication.class]) { return self; } - - XCUIElementQuery *query = [self isKindOfClass:XCUIApplication.class] - ? self.application.fb_query - : [self.application.fb_query descendantsMatchingType:XCUIElementTypeAny]; - NSString *uid = nil == self.fb_cachedSnapshot - ? self.fb_uid - : [FBXCElementSnapshotWrapper wdUIDWithSnapshot:(id)self.fb_cachedSnapshot]; - if (nil == uid) { - return self; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K = %@", FBStringify(FBXCElementSnapshotWrapper, fb_uid), uid]; + @autoreleasepool { + XCUIElementQuery *query = [self.application.fb_query descendantsMatchingType:XCUIElementTypeAny]; + XCUIElement *result = [query matchingPredicate:predicate].allElementsBoundByIndex.firstObject; + if (nil != result) { + result.fb_isResolvedNatively = @NO; + return result; + } } - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K = %@",FBStringify(FBXCElementSnapshotWrapper, fb_uid), uid]; - return [query matchingPredicate:predicate].allElementsBoundByIndex.firstObject ?: self; + return self; } @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.h b/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.h index 680fddbf..416544e3 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m b/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m index 52be1a55..6b63d0a9 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBScrolling.h" @@ -20,9 +19,11 @@ #import "XCUIApplication.h" #import "XCUICoordinate.h" #import "XCUIElement+FBIsVisible.h" +#import "XCUIElement+FBVisibleFrame.h" #import "XCUIElement.h" #import "XCUIElement+FBUtilities.h" #import "XCUIElement+FBWebDriverAttributes.h" +#import "XCTestPrivateSymbols.h" const CGFloat FBFuzzyPointThreshold = 20.f; //Smallest determined value that is not interpreted as touch const CGFloat FBScrollToVisibleNormalizedDistance = .5f; @@ -47,45 +48,35 @@ @implementation XCUIElement (FBScrolling) - (BOOL)fb_nativeScrollToVisibleWithError:(NSError **)error { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_customSnapshot]; return nil != [self _hitPointByAttemptingToScrollToVisibleSnapshot:snapshot error:error]; } - (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_customSnapshot]; [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollUpByNormalizedDistance:distance inApplication:self.application]; } - (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_customSnapshot]; [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollDownByNormalizedDistance:distance inApplication:self.application]; } - (void)fb_scrollLeftByNormalizedDistance:(CGFloat)distance { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_customSnapshot]; [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollLeftByNormalizedDistance:distance inApplication:self.application]; } - (void)fb_scrollRightByNormalizedDistance:(CGFloat)distance { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_customSnapshot]; [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_scrollRightByNormalizedDistance:distance inApplication:self.application]; } @@ -95,7 +86,8 @@ - (BOOL)fb_scrollToVisibleWithError:(NSError **)error return [self fb_scrollToVisibleWithNormalizedScrollDistance:FBScrollToVisibleNormalizedDistance error:error]; } -- (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScrollDistance error:(NSError **)error +- (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScrollDistance + error:(NSError **)error { return [self fb_scrollToVisibleWithNormalizedScrollDistance:normalizedScrollDistance scrollDirection:FBXCUIElementScrollDirectionUnknown @@ -106,7 +98,8 @@ - (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScroll scrollDirection:(FBXCUIElementScrollDirection)scrollDirection error:(NSError **)error { - FBXCElementSnapshotWrapper *prescrollSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot]]; + FBXCElementSnapshotWrapper *prescrollSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_customSnapshot]]; + if (prescrollSnapshot.isWDVisible) { return YES; } @@ -138,12 +131,12 @@ - (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScroll FBXCElementSnapshotWrapper *wrappedCellSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:cellSnapshot]; if (wrappedCellSnapshot.wdVisible) { [visibleCellSnapshots addObject:cellSnapshot]; + if (visibleCellSnapshots.count > 1) { + return YES; + } } } - if (visibleCellSnapshots.count > 1) { - return YES; - } return NO; }]; @@ -184,23 +177,25 @@ - (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScroll FBXCElementSnapshotWrapper *scrollViewWrapped = [FBXCElementSnapshotWrapper ensureWrapped:scrollView]; // Scrolling till cell is visible and get current value of frames while (![self fb_isEquivalentElementSnapshotVisible:prescrollSnapshot] && scrollCount < maxScrollCount) { - if (targetCellIndex < visibleCellIndex) { - scrollDirection == FBXCUIElementScrollDirectionVertical ? - [scrollViewWrapped fb_scrollUpByNormalizedDistance:normalizedScrollDistance - inApplication:self.application] : - [scrollViewWrapped fb_scrollLeftByNormalizedDistance:normalizedScrollDistance - inApplication:self.application]; - } - else { - scrollDirection == FBXCUIElementScrollDirectionVertical ? - [scrollViewWrapped fb_scrollDownByNormalizedDistance:normalizedScrollDistance + @autoreleasepool { + if (targetCellIndex < visibleCellIndex) { + scrollDirection == FBXCUIElementScrollDirectionVertical ? + [scrollViewWrapped fb_scrollUpByNormalizedDistance:normalizedScrollDistance inApplication:self.application] : - [scrollViewWrapped fb_scrollRightByNormalizedDistance:normalizedScrollDistance - inApplication:self.application]; + [scrollViewWrapped fb_scrollLeftByNormalizedDistance:normalizedScrollDistance + inApplication:self.application]; + } + else { + scrollDirection == FBXCUIElementScrollDirectionVertical ? + [scrollViewWrapped fb_scrollDownByNormalizedDistance:normalizedScrollDistance + inApplication:self.application] : + [scrollViewWrapped fb_scrollRightByNormalizedDistance:normalizedScrollDistance + inApplication:self.application]; + } + scrollCount++; + // Wait for scroll animation + [self fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; } - scrollCount++; - // Wait for scroll animation - [self fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; } if (scrollCount >= maxScrollCount) { @@ -213,9 +208,9 @@ - (BOOL)fb_scrollToVisibleWithNormalizedScrollDistance:(CGFloat)normalizedScroll // Cell is now visible, but it might be only partialy visible, scrolling till whole frame is visible. // Sometimes, attempting to grab the parent snapshot of the target cell after scrolling is complete causes a stale element reference exception. // Trying fb_cachedSnapshot first - FBXCElementSnapshotWrapper *targetCellSnapshotWrapped = [FBXCElementSnapshotWrapper ensureWrapped:([self fb_cachedSnapshot] ?: [self fb_takeSnapshot])]; + FBXCElementSnapshotWrapper *targetCellSnapshotWrapped = [FBXCElementSnapshotWrapper ensureWrapped:[self fb_customSnapshot]]; targetCellSnapshot = [targetCellSnapshotWrapped fb_parentCellSnapshot]; - CGRect visibleFrame = [FBXCElementSnapshotWrapper ensureWrapped:targetCellSnapshot].fb_visibleFrameWithFallback; + CGRect visibleFrame = [FBXCElementSnapshotWrapper ensureWrapped:targetCellSnapshot].fb_visibleFrame; CGVector scrollVector = CGVectorMake(visibleFrame.size.width - targetCellSnapshot.frame.size.width, visibleFrame.size.height - targetCellSnapshot.frame.size.height @@ -233,7 +228,7 @@ - (BOOL)fb_isEquivalentElementSnapshotVisible:(id)snapshot return YES; } - id appSnapshot = [self.application fb_takeSnapshot]; + id appSnapshot = [self.application fb_standardSnapshot]; for (id elementSnapshot in appSnapshot._allDescendants.copy) { FBXCElementSnapshotWrapper *wrappedElementSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:elementSnapshot]; // We are comparing pre-scroll snapshot so frames are irrelevant. @@ -255,27 +250,32 @@ - (CGRect)scrollingFrame return self.visibleFrame; } -- (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance inApplication:(XCUIApplication *)application +- (void)fb_scrollUpByNormalizedDistance:(CGFloat)distance + inApplication:(XCUIApplication *)application { [self fb_scrollByNormalizedVector:CGVectorMake(0.0, distance) inApplication:application]; } -- (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance inApplication:(XCUIApplication *)application +- (void)fb_scrollDownByNormalizedDistance:(CGFloat)distance + inApplication:(XCUIApplication *)application { [self fb_scrollByNormalizedVector:CGVectorMake(0.0, -distance) inApplication:application]; } -- (void)fb_scrollLeftByNormalizedDistance:(CGFloat)distance inApplication:(XCUIApplication *)application +- (void)fb_scrollLeftByNormalizedDistance:(CGFloat)distance + inApplication:(XCUIApplication *)application { [self fb_scrollByNormalizedVector:CGVectorMake(distance, 0.0) inApplication:application]; } -- (void)fb_scrollRightByNormalizedDistance:(CGFloat)distance inApplication:(XCUIApplication *)application +- (void)fb_scrollRightByNormalizedDistance:(CGFloat)distance + inApplication:(XCUIApplication *)application { [self fb_scrollByNormalizedVector:CGVectorMake(-distance, 0.0) inApplication:application]; } -- (BOOL)fb_scrollByNormalizedVector:(CGVector)normalizedScrollVector inApplication:(XCUIApplication *)application +- (BOOL)fb_scrollByNormalizedVector:(CGVector)normalizedScrollVector + inApplication:(XCUIApplication *)application { CGVector scrollVector = CGVectorMake(CGRectGetWidth(self.scrollingFrame) * normalizedScrollVector.dx, CGRectGetHeight(self.scrollingFrame) * normalizedScrollVector.dy @@ -283,7 +283,9 @@ - (BOOL)fb_scrollByNormalizedVector:(CGVector)normalizedScrollVector inApplicati return [self fb_scrollByVector:scrollVector inApplication:application error:nil]; } -- (BOOL)fb_scrollByVector:(CGVector)vector inApplication:(XCUIApplication *)application error:(NSError **)error +- (BOOL)fb_scrollByVector:(CGVector)vector + inApplication:(XCUIApplication *)application + error:(NSError **)error { CGVector scrollBoundingVector = CGVectorMake( CGRectGetWidth(self.scrollingFrame) * FBScrollTouchProportion, @@ -314,7 +316,9 @@ - (CGVector)fb_hitPointOffsetForScrollingVector:(CGVector)scrollingVector return CGVectorMake((CGFloat)floor(x), (CGFloat)floor(y)); } -- (BOOL)fb_scrollAncestorScrollViewByVectorWithinScrollViewFrame:(CGVector)vector inApplication:(XCUIApplication *)application error:(NSError **)error +- (BOOL)fb_scrollAncestorScrollViewByVectorWithinScrollViewFrame:(CGVector)vector + inApplication:(XCUIApplication *)application + error:(NSError **)error { CGVector hitpointOffset = [self fb_hitPointOffsetForScrollingVector:vector]; diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.h b/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.h index c30707df..4a2b5c1a 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.m b/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.m index 4be4d34d..8f64b483 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBSwiping.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBSwiping.h" diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.h b/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.h index 6b25f9ab..0a3bc079 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.m b/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.m index 30037646..5aa85084 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTVFocuse.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBTVFocuse.h" diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.h b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.h index c44aa7c5..0b775589 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m index db516a22..1d76f6ca 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBTyping.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBTyping.h" @@ -91,7 +90,7 @@ - (void)fb_prepareForTextInputWithSnapshot:(FBXCElementSnapshotWrapper *)snapsho [FBLogger logFmt:@"Trying to tap the \"%@\" element to have it focused", snapshot.fb_description]; [self tap]; // It might take some time to update the UI - [self fb_takeSnapshot]; + [self fb_standardSnapshot]; #endif } @@ -110,9 +109,7 @@ - (BOOL)fb_typeText:(NSString *)text frequency:(NSUInteger)frequency error:(NSError **)error { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_standardSnapshot]; FBXCElementSnapshotWrapper *wrapped = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; [self fb_prepareForTextInputWithSnapshot:wrapped]; if (shouldClear && ![self fb_clearTextWithSnapshot:wrapped shouldPrepareForInput:NO error:error]) { @@ -123,9 +120,7 @@ - (BOOL)fb_typeText:(NSString *)text - (BOOL)fb_clearTextWithError:(NSError **)error { - id snapshot = self.fb_isResolvedFromCache.boolValue - ? self.lastSnapshot - : self.fb_takeSnapshot; + id snapshot = [self fb_standardSnapshot]; return [self fb_clearTextWithSnapshot:[FBXCElementSnapshotWrapper ensureWrapped:snapshot] shouldPrepareForInput:YES error:error]; @@ -166,7 +161,7 @@ - (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot [self fb_prepareForTextInputWithSnapshot:snapshot]; } - if (retry == 0) { + if (retry == 0 && FBConfiguration.useClearTextShortcut) { // 1st attempt is via the IOHIDEvent as the fastest operation // https://github.com/appium/appium/issues/19389 [[XCUIDevice sharedDevice] fb_performIOHIDEventWithPage:0x07 // kHIDPage_KeyboardOrKeypad @@ -182,7 +177,7 @@ - (BOOL)fb_clearTextWithSnapshot:(FBXCElementSnapshotWrapper *)snapshot return NO; } - currentValue = self.fb_takeSnapshot.value; + currentValue = [self fb_standardSnapshot].value; if (nil != placeholderValue && [currentValue isEqualToString:placeholderValue]) { // Short circuit if only the placeholder value left return YES; diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUID.h b/WebDriverAgentLib/Categories/XCUIElement+FBUID.h index 8b1a2da6..5a406ade 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUID.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUID.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBXCElementSnapshotWrapper.h" diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUID.m b/WebDriverAgentLib/Categories/XCUIElement+FBUID.m index 765b410c..ebbb0665 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUID.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUID.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -22,14 +21,14 @@ - (unsigned long long)fb_accessibiltyId { return [FBElementUtils idWithAccessibilityElement:([self isKindOfClass:XCUIApplication.class] ? [(XCUIApplication *)self accessibilityElement] - : [self fb_takeSnapshot].accessibilityElement)]; + : [self fb_standardSnapshot].accessibilityElement)]; } - (NSString *)fb_uid { return [self isKindOfClass:XCUIApplication.class] ? [FBElementUtils uidWithAccessibilityElement:[(XCUIApplication *)self accessibilityElement]] - : [FBXCElementSnapshotWrapper ensureWrapped:[self fb_takeSnapshot]].fb_uid; + : [FBXCElementSnapshotWrapper ensureWrapped:[self fb_standardSnapshot]].fb_uid; } @end @@ -42,6 +41,7 @@ static void swizzled_validatePredicateWithExpressionsAllowed(id self, SEL _cmd, #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-load-method" +#pragma clang diagnostic ignored "-Wcast-function-type-strict" + (void)load { Class XCElementSnapshotCls = objc_lookUpClass("XCElementSnapshot"); diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h index 66b9ee2c..6f466668 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h @@ -3,13 +3,12 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import #import -#import "FBXCElementSnapshot.h" +#import NS_ASSUME_NONNULL_BEGIN @@ -18,70 +17,71 @@ NS_ASSUME_NONNULL_BEGIN /** Gets the most recent snapshot of the current element. The element will be automatically resolved if the snapshot is not available yet. - Calls to this method mutate the `lastSnapshot` instance property.. - Calls to this method reset the `fb_isResolvedFromCache` property value to `NO`. + Calls to this method mutate the `lastSnapshot` instance property. + The snapshot is taken by the native API provided by XCTest. + The maximum snapshot tree depth is set by `FBConfiguration.snapshotMaxDepth` + + Snapshot specifics: + - Most performant + - Memory-friedly + - `children` property is set to `nil` if not taken from XCUIApplication + - `value` property is cut off to max 512 bytes @return The recent snapshot of the element @throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made */ -- (id)fb_takeSnapshot; +- (id)fb_standardSnapshot; /** - Extracts the cached element snapshot from its query. - No requests to the accessiblity framework is made. - It is only safe to use this call right after element lookup query - has been executed. + Gets the most recent snapshot of the current element. The element will be + automatically resolved if the snapshot is not available yet. + Calls to this method mutate the `lastSnapshot` instance property. + The maximum snapshot tree depth is set by `FBConfiguration.snapshotMaxDepth` - @return Either the cached snapshot or nil + Snapshot specifics: + - Less performant in comparison to the standard one + - `children` property is always defined + - `value` property is not cut off + + @return The recent snapshot of the element + @throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made */ -- (nullable id)fb_cachedSnapshot; +- (id)fb_customSnapshot; /** - Gets the most recent snapshot of the current element and already resolves the accessibility attributes - needed for creating the page source of this element. No additional calls to the accessibility layer - are required. + Gets the most recent snapshot of the current element. The element will be + automatically resolved if the snapshot is not available yet. Calls to this method mutate the `lastSnapshot` instance property. - Calls to this method reset the `fb_isResolvedFromCache` property value to `NO`. + The maximum snapshot tree depth is set by `FBConfiguration.snapshotMaxDepth` + + Snapshot specifics: + - Less performant in comparison to the standard one + - The `hittable` property calculation is aligned with the native calculation logic - @param maxDepth The maximum depth of the snapshot. nil value means to use the default depth. - with custom attributes cannot be resolved - - @return The recent snapshot of the element with all attributes resolved or a snapshot with default - attributes resolved if there was a failure while resolving additional attributes + @return The recent snapshot of the element @throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made */ -- (nullable id)fb_snapshotWithAllAttributesAndMaxDepth:(nullable NSNumber *)maxDepth; +- (id)fb_nativeSnapshot; /** - Gets the most recent snapshot of the current element with given attributes resolved. - No additional calls to the accessibility layer are required. - Calls to this method mutate the `lastSnapshot` instance property. - Calls to this method reset the `fb_isResolvedFromCache` property value to `NO`. - - @param attributeNames The list of attribute names to resolve. Must be one of - FB_...Name values exported by XCTestPrivateSymbols.h module. - `nil` value means that only the default attributes must be extracted - @param maxDepth The maximum depth of the snapshot. nil value means to use the default depth. + Extracts the cached element snapshot from its query. + No requests to the accessiblity framework is made. + It is only safe to use this call right after element lookup query + has been executed. - @return The recent snapshot of the element with the given attributes resolved or a snapshot with default - attributes resolved if there was a failure while resolving additional attributes - @throws FBStaleElementException if the element is not present in DOM and thus no snapshot could be made -*/ -- (nullable id)fb_snapshotWithAttributes:(nullable NSArray *)attributeNames - maxDepth:(nullable NSNumber *)maxDepth; + @return Either the cached snapshot or nil + */ +- (nullable id)fb_cachedSnapshot; /** Filters elements by matching them to snapshots from the corresponding array @param snapshots Array of snapshots to be matched with - @param selfUID Optionally the unique identifier of the current element. - Providing it as an argument improves the performance of the method. @param onlyChildren Whether to only look for direct element children @return Array of filtered elements, which have matches in snapshots array */ - (NSArray *)fb_filterDescendantsWithSnapshots:(NSArray> *)snapshots - selfUID:(nullable NSString *)selfUID onlyChildren:(BOOL)onlyChildren; /** diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m index b5a072c0..b627fc86 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBUtilities.h" @@ -14,6 +13,7 @@ #import "FBConfiguration.h" #import "FBExceptions.h" #import "FBImageUtils.h" +#import "FBElementUtils.h" #import "FBLogger.h" #import "FBMacros.h" #import "FBMathUtils.h" @@ -31,6 +31,8 @@ #import "XCTElementSetTransformer-Protocol.h" #import "XCTestPrivateSymbols.h" #import "XCTRunnerDaemonSession.h" +#import "XCUIApplicationProcess+FBQuiescence.h" +#import "XCUIApplication.h" #import "XCUIElement+FBCaching.h" #import "XCUIElement+FBWebDriverAttributes.h" #import "XCUIElementQuery.h" @@ -39,94 +41,50 @@ #import "XCUIScreen.h" #import "XCUIElement+FBResolve.h" -#define DEFAULT_AX_TIMEOUT 60. - @implementation XCUIElement (FBUtilities) -- (id)fb_takeSnapshot +- (id)fb_takeSnapshot:(BOOL)isCustom { - NSError *error = nil; - self.fb_isResolvedFromCache = @(NO); - self.lastSnapshot = [self.fb_query fb_uniqueSnapshotWithError:&error]; - if (nil == self.lastSnapshot) { - NSString *hintText = @"Make sure the application UI has the expected state"; - if (nil != error - && [error.localizedDescription containsString:@"Identity Binding"]) { - hintText = [NSString stringWithFormat:@"%@. You could also try to switch the binding strategy using the 'boundElementsByIndex' setting for the element lookup", hintText]; - } - NSString *reason = [NSString stringWithFormat:@"The previously found element \"%@\" is not present in the current view anymore. %@", self.description, hintText]; - if (nil != error) { - reason = [NSString stringWithFormat:@"%@. Original error: %@", reason, error.localizedDescription]; + __block id snapshot = nil; + @autoreleasepool { + NSError *error = nil; + snapshot = isCustom + ? [self.fb_query fb_uniqueSnapshotWithError:&error] + : (id)[self snapshotWithError:&error]; + if (nil == snapshot) { + [self fb_raiseStaleElementExceptionWithError:error]; } - @throw [NSException exceptionWithName:FBStaleElementException reason:reason userInfo:@{}]; } + self.lastSnapshot = snapshot; return self.lastSnapshot; } -- (id)fb_cachedSnapshot +- (id)fb_standardSnapshot { - return [self.query fb_cachedSnapshot]; + return [self fb_takeSnapshot:NO]; } -- (nullable id)fb_snapshotWithAllAttributesAndMaxDepth:(NSNumber *)maxDepth +- (id)fb_customSnapshot { - NSMutableArray *allNames = [NSMutableArray arrayWithArray:FBStandardAttributeNames()]; - [allNames addObjectsFromArray:FBCustomAttributeNames()]; - return [self fb_snapshotWithAttributes:allNames.copy - maxDepth:maxDepth]; + return [self fb_takeSnapshot:YES]; } -- (nullable id)fb_snapshotWithAttributes:(NSArray *)attributeNames - maxDepth:(NSNumber *)maxDepth +- (id)fb_nativeSnapshot { - NSSet *standardAttributes = [NSSet setWithArray:FBStandardAttributeNames()]; - id snapshot = self.fb_takeSnapshot; - NSTimeInterval axTimeout = FBConfiguration.customSnapshotTimeout; - if (nil == attributeNames - || [[NSSet setWithArray:attributeNames] isSubsetOfSet:standardAttributes] - || axTimeout < DBL_EPSILON) { - // return the "normal" element snapshot if no custom attributes are requested - return snapshot; - } - - id axElement = snapshot.accessibilityElement; - if (nil == axElement) { - return nil; - } - - NSError *setTimeoutError; - BOOL isTimeoutSet = [FBXCAXClientProxy.sharedClient setAXTimeout:axTimeout - error:&setTimeoutError]; - if (!isTimeoutSet) { - [FBLogger logFmt:@"Cannot set snapshoting timeout to %.1fs. Original error: %@", - axTimeout, setTimeoutError.localizedDescription]; - } - - NSError *error; - id snapshotWithAttributes = [FBXCAXClientProxy.sharedClient snapshotForElement:axElement - attributes:attributeNames - maxDepth:maxDepth - error:&error]; - if (nil == snapshotWithAttributes) { - NSString *description = [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_description; - [FBLogger logFmt:@"Cannot take a snapshot with attribute(s) %@ of '%@' after %.2f seconds", - attributeNames, description, axTimeout]; - [FBLogger logFmt:@"This timeout could be customized via '%@' setting", FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT]; - [FBLogger logFmt:@"Internal error: %@", error.localizedDescription]; - [FBLogger logFmt:@"Falling back to the default snapshotting mechanism for the element '%@' (some attribute values, like visibility or accessibility might not be precise though)", description]; - snapshotWithAttributes = self.lastSnapshot; - } else { - self.lastSnapshot = snapshotWithAttributes; + NSError *error = nil; + BOOL isSuccessful = [self resolveOrRaiseTestFailure:NO error:&error]; + if (nil == self.lastSnapshot || !isSuccessful) { + [self fb_raiseStaleElementExceptionWithError:error]; } + return self.lastSnapshot; +} - if (isTimeoutSet) { - [FBXCAXClientProxy.sharedClient setAXTimeout:DEFAULT_AX_TIMEOUT error:nil]; - } - return snapshotWithAttributes; +- (id)fb_cachedSnapshot +{ + return [self.query fb_cachedSnapshot]; } - (NSArray *)fb_filterDescendantsWithSnapshots:(NSArray> *)snapshots - selfUID:(NSString *)selfUID onlyChildren:(BOOL)onlyChildren { if (0 == snapshots.count) { @@ -134,21 +92,19 @@ @implementation XCUIElement (FBUtilities) } NSMutableArray *matchedIds = [NSMutableArray new]; for (id snapshot in snapshots) { - NSString *uid = [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]; - if (nil != uid) { - [matchedIds addObject:uid]; + @autoreleasepool { + NSString *uid = [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]; + if (nil != uid) { + [matchedIds addObject:uid]; + } } } NSMutableArray *matchedElements = [NSMutableArray array]; - NSString *uid = selfUID; - if (nil == uid) { - uid = self.fb_isResolvedFromCache.boolValue - ? [FBXCElementSnapshotWrapper wdUIDWithSnapshot:self.lastSnapshot] - : self.fb_uid; - } + NSString *uid = nil == self.lastSnapshot + ? self.fb_uid + : [FBXCElementSnapshotWrapper wdUIDWithSnapshot:self.lastSnapshot]; if (nil != uid && [matchedIds containsObject:uid]) { - XCUIElement *stableSelf = self.fb_stableInstance; - stableSelf.fb_isResolvedNatively = @NO; + XCUIElement *stableSelf = [self fb_stableInstanceWithUid:uid]; if (1 == snapshots.count) { return @[stableSelf]; } @@ -190,11 +146,25 @@ - (void)fb_waitUntilStableWithTimeout:(NSTimeInterval)timeout self.application.fb_shouldWaitForQuiescence = YES; } [[[self.application applicationImpl] currentProcess] - waitForQuiescenceIncludingAnimationsIdle:YES]; + fb_waitForQuiescenceIncludingAnimationsIdle:YES]; if (previousQuiescence != self.application.fb_shouldWaitForQuiescence) { self.application.fb_shouldWaitForQuiescence = previousQuiescence; } FBConfiguration.waitForIdleTimeout = previousTimeout; } +- (void)fb_raiseStaleElementExceptionWithError:(NSError *)error __attribute__((noreturn)) +{ + NSString *hintText = @"Make sure the application UI has the expected state"; + if (nil != error && [error.localizedDescription containsString:@"Identity Binding"]) { + hintText = [NSString stringWithFormat:@"%@. You could also try to switch the binding strategy using the 'boundElementsByIndex' setting for the element lookup", hintText]; + } + NSString *reason = [NSString stringWithFormat:@"The previously found element \"%@\" is not present in the current view anymore. %@", + self.description, hintText]; + if (nil != error) { + reason = [NSString stringWithFormat:@"%@. Original error: %@", reason, error.localizedDescription]; + } + @throw [NSException exceptionWithName:FBStaleElementException reason:reason userInfo:@{}]; +} + @end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.h b/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.h new file mode 100644 index 00000000..e2355c99 --- /dev/null +++ b/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.h @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FBXCElementSnapshotWrapper.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface XCUIElement (FBVisibleFrame) + +/** + Returns the snapshot visibleFrame with a fallback to direct attribute retrieval from FBXCAXClient in case of a snapshot fault (nil visibleFrame) + + @return the snapshot visibleFrame + */ +- (CGRect)fb_visibleFrame; + +@end + +@interface FBXCElementSnapshotWrapper (FBVisibleFrame) + +/** + Returns the snapshot visibleFrame with a fallback to direct attribute retrieval from FBXCAXClient in case of a snapshot fault (nil visibleFrame) + + @return the snapshot visibleFrame + */ +- (CGRect)fb_visibleFrame; + +@end + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.m b/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.m new file mode 100644 index 00000000..8ba5b0ea --- /dev/null +++ b/WebDriverAgentLib/Categories/XCUIElement+FBVisibleFrame.m @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "XCUIElement+FBVisibleFrame.h" +#import "FBElementUtils.h" +#import "FBXCodeCompatibility.h" +#import "FBXCElementSnapshotWrapper+Helpers.h" +#import "XCUIElement+FBUtilities.h" +#import "XCTestPrivateSymbols.h" + +@implementation XCUIElement (FBVisibleFrame) + +- (CGRect)fb_visibleFrame +{ + id snapshot = [self fb_standardSnapshot]; + return [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_visibleFrame; +} + +@end + +@implementation FBXCElementSnapshotWrapper (FBVisibleFrame) + +- (CGRect)fb_visibleFrame +{ + CGRect thisVisibleFrame = [self visibleFrame]; + if (!CGRectIsEmpty(thisVisibleFrame)) { + return thisVisibleFrame; + } + + NSDictionary *visibleFrameDict = [self fb_attributeValue:FB_XCAXAVisibleFrameAttributeName + error:nil]; + if (nil == visibleFrameDict) { + return thisVisibleFrame; + } + + id x = [visibleFrameDict objectForKey:@"X"]; + id y = [visibleFrameDict objectForKey:@"Y"]; + id height = [visibleFrameDict objectForKey:@"Height"]; + id width = [visibleFrameDict objectForKey:@"Width"]; + if (x != nil && y != nil && height != nil && width != nil) { + return CGRectMake([x doubleValue], [y doubleValue], [width doubleValue], [height doubleValue]); + } + + return thisVisibleFrame; +} + +@end diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.h b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.h index fdeedaf9..8e598d7a 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.h +++ b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.h @@ -3,13 +3,12 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import #import -#import "FBXCElementSnapshotWrapper.h" +#import NS_ASSUME_NONNULL_BEGIN diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m index b29c5a8b..ca3023bf 100644 --- a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +++ b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m @@ -3,13 +3,13 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElement+FBWebDriverAttributes.h" #import "FBElementTypeTransformer.h" +#import "FBElementHelpers.h" #import "FBLogger.h" #import "FBMacros.h" #import "FBXCElementSnapshotWrapper.h" @@ -21,6 +21,8 @@ #import "FBElementUtils.h" #import "XCTestPrivateSymbols.h" #import "XCUIHitPointResult.h" +#import "FBAccessibilityTraits.h" +#import "XCUIElement+FBMinMax.h" #define BROKEN_RECT CGRectMake(-1, -1, 0, 0) @@ -28,24 +30,20 @@ @implementation XCUIElement (WebDriverAttributesForwarding) - (id)fb_snapshotForAttributeName:(NSString *)name { - // These attributes are special, because we can only retrieve them from - // the snapshot if we explicitly ask XCTest to include them into the query while taking it. - // That is why fb_snapshotWithAllAttributes method must be used instead of the default snapshot - // call - if ([name isEqualToString:FBStringify(XCUIElement, isWDVisible)]) { - return [self fb_snapshotWithAttributes:@[FB_XCAXAIsVisibleAttributeName] - maxDepth:@1]; + // https://github.com/appium/appium-xcuitest-driver/pull/2565 + if ([name isEqualToString:FBStringify(XCUIElement, isWDHittable)]) { + return [self fb_nativeSnapshot]; } - if ([name isEqualToString:FBStringify(XCUIElement, isWDAccessible)]) { - return [self fb_snapshotWithAttributes:@[FB_XCAXAIsElementAttributeName] - maxDepth:@1]; + // https://github.com/appium/appium-xcuitest-driver/issues/2552 + BOOL isValueRequest = [name isEqualToString:FBStringify(XCUIElement, wdValue)]; + if ([self isKindOfClass:XCUIApplication.class] && !isValueRequest) { + return [self fb_standardSnapshot]; } - if ([name isEqualToString:FBStringify(XCUIElement, isWDAccessibilityContainer)]) { - return [self fb_snapshotWithAttributes:@[FB_XCAXAIsElementAttributeName] - maxDepth:nil]; - } - - return self.fb_takeSnapshot; + BOOL isCustomSnapshot = [name isEqualToString:FBStringify(XCUIElement, isWDAccessible)] + || [name isEqualToString:FBStringify(XCUIElement, isWDAccessibilityContainer)] + || [name isEqualToString:FBStringify(XCUIElement, wdIndex)] + || isValueRequest; + return isCustomSnapshot ? [self fb_customSnapshot] : [self fb_standardSnapshot]; } - (id)fb_valueForWDAttributeName:(NSString *)name @@ -78,6 +76,16 @@ - (id)fb_valueForWDAttributeName:(NSString *)name return [self valueForKey:[FBElementUtils wdAttributeNameForAttributeName:name]]; } +- (NSNumber *)wdMinValue +{ + return self.fb_minValue; +} + +- (NSNumber *)wdMaxValue +{ + return self.fb_maxValue; +} + - (NSString *)wdValue { id value = self.value; @@ -90,9 +98,7 @@ - (NSString *)wdValue value = FBFirstNonEmptyValue(value, isSelected); } else if (elementType == XCUIElementTypeSwitch) { value = @([value boolValue]); - } else if (elementType == XCUIElementTypeTextView || - elementType == XCUIElementTypeTextField || - elementType == XCUIElementTypeSecureTextField) { + } else if (FBDoesElementSupportInnerText(elementType)) { NSString *placeholderValue = self.placeholderValue; value = FBFirstNonEmptyValue(value, placeholderValue); } @@ -120,12 +126,18 @@ - (NSString *)wdName - (NSString *)wdLabel { - NSString *label = self.label; XCUIElementType elementType = self.elementType; - if (elementType == XCUIElementTypeTextField || elementType == XCUIElementTypeSecureTextField ) { - return label; - } - return FBTransferEmptyStringToNil(label); + return (elementType == XCUIElementTypeTextField + || elementType == XCUIElementTypeSecureTextField) + ? self.label + : FBTransferEmptyStringToNil(self.label); +} + +- (NSString *)wdPlaceholderValue +{ + return FBDoesElementSupportInnerText(self.elementType) + ? self.placeholderValue + : FBTransferEmptyStringToNil(self.placeholderValue); } - (NSString *)wdType @@ -150,6 +162,30 @@ - (CGRect)wdFrame : CGRectIntegral(frame); } +- (CGRect)wdNativeFrame +{ + // To avoid confusion regarding the frame returned by `wdFrame`, + // the current property is provided to represent the element's + // actual rendered frame. + return self.frame; +} + +/** + Returns a comma-separated string of accessibility traits for the element. + This method converts the element's accessibility traits bitmask into human-readable strings + using FBAccessibilityTraitsToStringsArray. The traits represent various accessibility + characteristics of the element such as Button, Link, Image, etc. + You can find the list of possible traits in the Apple documentation: + https://developer.apple.com/documentation/uikit/uiaccessibilitytraits?language=objc + + @return A comma-separated string of accessibility traits, or an empty string if no traits are set + */ +- (NSString *)wdTraits +{ + NSArray *traits = FBAccessibilityTraitsToStringsArray(self.snapshot.traits); + return [traits componentsJoinedByString:@", "]; +} + - (BOOL)isWDVisible { return self.fb_isVisible; @@ -183,8 +219,8 @@ - (BOOL)isWDAccessible // In the scenario when table provides Search results controller, table could be marked as accessible element, even though it isn't // As it is highly unlikely that table view should ever be an accessibility element itself, // for now we work around that by skipping Table View in container checks - if ([FBXCElementSnapshotWrapper ensureWrapped:parentSnapshot].fb_isAccessibilityElement - && parentSnapshot.elementType != XCUIElementTypeTable) { + if (parentSnapshot.elementType != XCUIElementTypeTable + && [FBXCElementSnapshotWrapper ensureWrapped:parentSnapshot].fb_isAccessibilityElement) { return NO; } parentSnapshot = parentSnapshot.parent; diff --git a/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.h b/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.h index 04ff8bfa..8c828907 100644 --- a/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.h +++ b/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.m b/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.m index 81e2a522..d2438a0c 100644 --- a/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.m +++ b/WebDriverAgentLib/Categories/XCUIElementQuery+FBHelpers.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIElementQuery+FBHelpers.h" diff --git a/WebDriverAgentLib/Commands/FBAlertViewCommands.h b/WebDriverAgentLib/Commands/FBAlertViewCommands.h index 3d4c2638..687c39ce 100644 --- a/WebDriverAgentLib/Commands/FBAlertViewCommands.h +++ b/WebDriverAgentLib/Commands/FBAlertViewCommands.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Commands/FBAlertViewCommands.m b/WebDriverAgentLib/Commands/FBAlertViewCommands.m index 76024462..50479936 100644 --- a/WebDriverAgentLib/Commands/FBAlertViewCommands.m +++ b/WebDriverAgentLib/Commands/FBAlertViewCommands.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBAlertViewCommands.h" diff --git a/WebDriverAgentLib/Commands/FBCustomCommands.h b/WebDriverAgentLib/Commands/FBCustomCommands.h index 869d14fd..dca15422 100644 --- a/WebDriverAgentLib/Commands/FBCustomCommands.h +++ b/WebDriverAgentLib/Commands/FBCustomCommands.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Commands/FBCustomCommands.m b/WebDriverAgentLib/Commands/FBCustomCommands.m index 88008655..47aa4ae0 100644 --- a/WebDriverAgentLib/Commands/FBCustomCommands.m +++ b/WebDriverAgentLib/Commands/FBCustomCommands.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBCustomCommands.h" @@ -15,6 +14,7 @@ #import "FBConfiguration.h" #import "FBKeyboard.h" #import "FBNotificationsHelper.h" +#import "FBMathUtils.h" #import "FBPasteboard.h" #import "FBResponsePayload.h" #import "FBRoute.h" @@ -49,6 +49,7 @@ + (NSArray *)routes [[FBRoute GET:@"/wda/locked"].withoutSession respondWithTarget:self action:@selector(handleIsLocked:)], [[FBRoute GET:@"/wda/locked"] respondWithTarget:self action:@selector(handleIsLocked:)], [[FBRoute GET:@"/wda/screen"] respondWithTarget:self action:@selector(handleGetScreen:)], + [[FBRoute GET:@"/wda/screen"].withoutSession respondWithTarget:self action:@selector(handleGetScreen:)], [[FBRoute GET:@"/wda/activeAppInfo"] respondWithTarget:self action:@selector(handleActiveAppInfo:)], [[FBRoute GET:@"/wda/activeAppInfo"].withoutSession respondWithTarget:self action:@selector(handleActiveAppInfo:)], #if !TARGET_OS_TV // tvOS does not provide relevant APIs @@ -148,10 +149,22 @@ + (NSArray *)routes + (id)handleGetScreen:(FBRouteRequest *)request { - FBSession *session = request.session; - CGSize statusBarSize = [FBScreen statusBarSizeForApplication:session.activeApplication]; + XCUIApplication *app = XCUIApplication.fb_systemApplication; + + XCUIElement *mainStatusBar = app.statusBars.allElementsBoundByIndex.firstObject; + CGSize statusBarSize = (nil == mainStatusBar) ? CGSizeZero : mainStatusBar.frame.size; + +#if TARGET_OS_TV + CGSize screenSize = app.frame.size; +#else + CGSize screenSize = FBAdjustDimensionsForApplication(app.wdFrame.size, app.interfaceOrientation); +#endif + return FBResponseWithObject( @{ + @"screenSize":@{@"width": @(screenSize.width), + @"height": @(screenSize.height) + }, @"statusBarSize": @{@"width": @(statusBarSize.width), @"height": @(statusBarSize.height), }, @@ -595,7 +608,8 @@ + (NSString *)timeZone FBElementCache *elementCache = request.session.elementCache; BOOL hasElement = ![request.parameters[@"uuid"] isEqual:@"0"]; XCUIElement *destination = hasElement - ? [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]] + ? [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] + checkStaleness:YES] : request.session.activeApplication; id keys = request.arguments[@"keys"]; diff --git a/WebDriverAgentLib/Commands/FBDebugCommands.h b/WebDriverAgentLib/Commands/FBDebugCommands.h index 32f28b1b..99728e03 100644 --- a/WebDriverAgentLib/Commands/FBDebugCommands.h +++ b/WebDriverAgentLib/Commands/FBDebugCommands.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Commands/FBDebugCommands.m b/WebDriverAgentLib/Commands/FBDebugCommands.m index dc96958d..42ea74b3 100644 --- a/WebDriverAgentLib/Commands/FBDebugCommands.m +++ b/WebDriverAgentLib/Commands/FBDebugCommands.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBDebugCommands.h" @@ -54,7 +53,12 @@ + (NSArray *)routes withExcludedAttributes:excludedAttributes] withScope:sourceScope]]; } else if ([sourceType caseInsensitiveCompare:SOURCE_FORMAT_JSON] == NSOrderedSame) { - result = application.fb_tree; + NSString *excludedAttributesString = request.parameters[@"excluded_attributes"]; + NSSet *excludedAttributes = (excludedAttributesString == nil) + ? nil + : [NSSet setWithArray:[excludedAttributesString componentsSeparatedByString:@","]]; + + result = [application fb_tree:excludedAttributes]; } else if ([sourceType caseInsensitiveCompare:SOURCE_FORMAT_DESCRIPTION] == NSOrderedSame) { result = application.fb_descriptionRepresentation; } else { diff --git a/WebDriverAgentLib/Commands/FBElementCommands.h b/WebDriverAgentLib/Commands/FBElementCommands.h index fcd1c86e..3c07ee6d 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.h +++ b/WebDriverAgentLib/Commands/FBElementCommands.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Commands/FBElementCommands.m b/WebDriverAgentLib/Commands/FBElementCommands.m index 0313302f..9c2ea009 100644 --- a/WebDriverAgentLib/Commands/FBElementCommands.m +++ b/WebDriverAgentLib/Commands/FBElementCommands.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBElementCommands.h" @@ -35,6 +34,7 @@ #import "XCUIElement+FBWebDriverAttributes.h" #import "XCUIElement+FBTVFocuse.h" #import "XCUIElement+FBResolve.h" +#import "XCUIElement+FBUID.h" #import "FBElementTypeTransformer.h" #import "XCUIElement.h" #import "XCUIElementQuery.h" @@ -52,6 +52,7 @@ + (NSArray *)routes return @[ [[FBRoute GET:@"/window/size"] respondWithTarget:self action:@selector(handleGetWindowSize:)], + [[FBRoute GET:@"/window/rect"] respondWithTarget:self action:@selector(handleGetWindowRect:)], [[FBRoute GET:@"/window/size"].withoutSession respondWithTarget:self action:@selector(handleGetWindowSize:)], [[FBRoute GET:@"/element/:uuid/enabled"] respondWithTarget:self action:@selector(handleGetEnabled:)], [[FBRoute GET:@"/element/:uuid/rect"] respondWithTarget:self action:@selector(handleGetRect:)], @@ -126,38 +127,22 @@ + (NSArray *)routes { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - BOOL isEnabled = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDEnabled; - return FBResponseWithObject(isEnabled ? @YES : @NO); + return FBResponseWithObject(@(element.isWDEnabled)); } + (id)handleGetRect:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - return FBResponseWithObject([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdRect); + return FBResponseWithObject(element.wdRect); } + (id)handleGetAttribute:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; NSString *attributeName = request.parameters[@"name"]; - NSString *wdAttributeName = [FBElementUtils wdAttributeNameForAttributeName:attributeName]; - NSArray *additionalAttributes = nil; - NSNumber *maxDepth = nil; - if ([wdAttributeName isEqualToString:FBStringify(XCUIElement, isWDVisible)]) { - additionalAttributes = @[FB_XCAXAIsVisibleAttributeName]; - maxDepth = @1; - } else if ([wdAttributeName isEqualToString:FBStringify(XCUIElement, isWDEnabled)]) { - additionalAttributes = @[FB_XCAXAIsElementAttributeName]; - maxDepth = @1; - } else if ([wdAttributeName isEqualToString:FBStringify(XCUIElement, isWDAccessibilityContainer)]) { - additionalAttributes = @[FB_XCAXAIsElementAttributeName]; - } - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] - resolveForAdditionalAttributes:additionalAttributes - andMaxDepth:maxDepth]; - FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot]; - id attributeValue = [wrappedSnapshot fb_valueForWDAttributeName:attributeName]; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + id attributeValue = [element fb_valueForWDAttributeName:attributeName]; return FBResponseWithObject(attributeValue ?: [NSNull null]); } @@ -165,7 +150,9 @@ + (NSArray *)routes { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot]; + // https://github.com/appium/appium-xcuitest-driver/issues/2552 + id snapshot = [element fb_customSnapshot]; + FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; id text = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel); return FBResponseWithObject(text ?: @""); } @@ -173,48 +160,43 @@ + (NSArray *)routes + (id)handleGetDisplayed:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] - resolveForAdditionalAttributes:@[FB_XCAXAIsVisibleAttributeName] - andMaxDepth:@1]; - return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDVisible)); + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + return FBResponseWithObject(@(element.isWDVisible)); } + (id)handleGetAccessible:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] - resolveForAdditionalAttributes:@[FB_XCAXAIsElementAttributeName] - andMaxDepth:@1]; - return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDAccessible)); + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + return FBResponseWithObject(@(element.isWDAccessible)); } + (id)handleGetIsAccessibilityContainer:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] - resolveForAdditionalAttributes:@[FB_XCAXAIsElementAttributeName] - andMaxDepth:nil]; - return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].isWDAccessibilityContainer)); + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + return FBResponseWithObject(@(element.isWDAccessibilityContainer)); } + (id)handleGetName:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - return FBResponseWithObject([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdType); + return FBResponseWithObject(element.wdType); } + (id)handleGetSelected:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - return FBResponseWithObject(@([FBXCElementSnapshotWrapper ensureWrapped:element.lastSnapshot].wdSelected)); + return FBResponseWithObject(@(element.wdSelected)); } + (id)handleSetValue:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] + checkStaleness:YES]; id value = request.arguments[@"value"] ?: request.arguments[@"text"]; if (!value) { return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:@"Neither 'value' nor 'text' parameter is provided" traceback:nil]); @@ -222,7 +204,7 @@ + (NSArray *)routes NSString *textToType = [value isKindOfClass:NSArray.class] ? [value componentsJoinedByString:@""] : value; - XCUIElementType elementType = [(id)element.lastSnapshot elementType]; + XCUIElementType elementType = [element elementType]; #if !TARGET_OS_TV if (elementType == XCUIElementTypePickerWheel) { [element adjustToPickerWheelValue:textToType]; @@ -251,7 +233,7 @@ + (NSArray *)routes + (id)handleClick:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] checkStaleness:YES]; #if TARGET_OS_IOS [element tap]; #elif TARGET_OS_TV @@ -285,7 +267,10 @@ + (NSArray *)routes if (focusedElement != nil) { FBElementCache *elementCache = request.session.elementCache; BOOL useNativeCachingStrategy = request.session.useNativeCachingStrategy; - NSString *focusedUUID = [elementCache storeElement:(useNativeCachingStrategy ? focusedElement : focusedElement.fb_stableInstance)]; + NSString *focusedUUID = [elementCache storeElement:(useNativeCachingStrategy + ? focusedElement + : [focusedElement fb_stableInstanceWithUid:focusedElement.fb_uid])]; + focusedElement.lastSnapshot = nil; if (focusedUUID && [focusedUUID isEqualToString:(id)request.parameters[@"uuid"]]) { isFocused = YES; } @@ -352,12 +337,8 @@ + (NSArray *)routes { FBElementCache *elementCache = request.session.elementCache; XCUIElement *element = [self targetFromRequest:request]; - if (![element respondsToSelector:@selector(pressForDuration:thenDragToElement:withVelocity:thenHoldForDuration:)]) { - return FBResponseWithStatus([FBCommandStatus unsupportedOperationErrorWithMessage:@"This method is only supported in Xcode 12 and above" - traceback:nil]); - } [element pressForDuration:[request.arguments[@"pressDuration"] doubleValue] - thenDragToElement:[elementCache elementForUUID:(NSString *)request.arguments[@"toElement"]] + thenDragToElement:[elementCache elementForUUID:(NSString *)request.arguments[@"toElement"] checkStaleness:YES] withVelocity:[request.arguments[@"velocity"] doubleValue] thenHoldForDuration:[request.arguments[@"holdDuration"] doubleValue]]; return FBResponseWithOK(); @@ -370,10 +351,6 @@ + (NSArray *)routes (CGFloat)[request.arguments[@"fromY"] doubleValue]); XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithOffset:startOffset element:session.activeApplication]; - if (![startCoordinate respondsToSelector:@selector(pressForDuration:thenDragToCoordinate:withVelocity:thenHoldForDuration:)]) { - return FBResponseWithStatus([FBCommandStatus unsupportedOperationErrorWithMessage:@"This method is only supported in Xcode 12 and above" - traceback:nil]); - } CGVector endOffset = CGVectorMake((CGFloat)[request.arguments[@"toX"] doubleValue], (CGFloat)[request.arguments[@"toY"] doubleValue]); XCUICoordinate *endCoordinate = [self.class gestureCoordinateWithOffset:endOffset @@ -449,10 +426,7 @@ + (NSArray *)routes + (id)handleDrag:(FBRouteRequest *)request { - NSString *elementUdid = (NSString *)request.parameters[@"uuid"]; - XCUIElement *target = nil == elementUdid - ? request.session.activeApplication - : [request.session.elementCache elementForUUID:elementUdid]; + XCUIElement *target = [self targetFromRequest:request]; CGVector startOffset = CGVectorMake([request.arguments[@"fromX"] doubleValue], [request.arguments[@"fromY"] doubleValue]); XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithOffset:startOffset element:target]; @@ -554,13 +528,32 @@ + (NSArray *)routes { XCUIApplication *app = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; + CGRect frame = app.wdFrame; #if TARGET_OS_TV - CGSize screenSize = app.frame.size; + CGSize screenSize = frame.size; #else + CGSize screenSize = FBAdjustDimensionsForApplication(frame.size, app.interfaceOrientation); +#endif + return FBResponseWithObject(@{ + @"width": @(screenSize.width), + @"height": @(screenSize.height), + }); +} + + ++ (id)handleGetWindowRect:(FBRouteRequest *)request +{ + XCUIApplication *app = request.session.activeApplication ?: XCUIApplication.fb_activeApplication; + CGRect frame = app.wdFrame; +#if TARGET_OS_TV + CGSize screenSize = frame.size; +#else CGSize screenSize = FBAdjustDimensionsForApplication(frame.size, app.interfaceOrientation); #endif return FBResponseWithObject(@{ + @"x": @(frame.origin.x), + @"y": @(frame.origin.y), @"width": @(screenSize.width), @"height": @(screenSize.height), }); @@ -568,16 +561,23 @@ + (NSArray *)routes + (id)handleElementScreenshot:(FBRouteRequest *)request { - FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - NSData *screenshotData = [element.screenshot PNGRepresentation]; - if (nil == screenshotData) { - NSString *errMsg = [NSString stringWithFormat:@"Cannot take a screenshot of %@", element.description]; - return FBResponseWithStatus([FBCommandStatus unableToCaptureScreenErrorWithMessage:errMsg - traceback:nil]); + @autoreleasepool { + FBElementCache *elementCache = request.session.elementCache; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] + checkStaleness:YES]; + NSData *screenshotData = nil; + @autoreleasepool { + screenshotData = [element.screenshot PNGRepresentation]; + if (nil == screenshotData) { + NSString *errMsg = [NSString stringWithFormat:@"Cannot take a screenshot of %@", element.description]; + return FBResponseWithStatus([FBCommandStatus unableToCaptureScreenErrorWithMessage:errMsg + traceback:nil]); + } + } + NSString *screenshot = [screenshotData base64EncodedStringWithOptions:0]; + screenshotData = nil; + return FBResponseWithObject(screenshot); } - NSString *screenshot = [screenshotData base64EncodedStringWithOptions:0]; - return FBResponseWithObject(screenshot); } @@ -589,8 +589,9 @@ + (NSArray *)routes + (id)handleWheelSelect:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; - if ([element.lastSnapshot elementType] != XCUIElementTypePickerWheel) { + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] + checkStaleness:YES]; + if ([element elementType] != XCUIElementTypePickerWheel) { NSString *errMsg = [NSString stringWithFormat:@"The element is expected to be a valid Picker Wheel control. '%@' was given instead", element.wdType]; return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:errMsg traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]); @@ -696,7 +697,7 @@ + (XCUIElement *)targetFromRequest:(FBRouteRequest *)request NSString *elementUuid = (NSString *)request.parameters[@"uuid"]; return nil == elementUuid ? request.session.activeApplication - : [elementCache elementForUUID:elementUuid]; + : [elementCache elementForUUID:elementUuid checkStaleness:YES]; } #endif diff --git a/WebDriverAgentLib/Commands/FBFindElementCommands.h b/WebDriverAgentLib/Commands/FBFindElementCommands.h index 9c20b0d4..7349e10c 100644 --- a/WebDriverAgentLib/Commands/FBFindElementCommands.h +++ b/WebDriverAgentLib/Commands/FBFindElementCommands.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Commands/FBFindElementCommands.m b/WebDriverAgentLib/Commands/FBFindElementCommands.m index ba30a717..c370f11c 100644 --- a/WebDriverAgentLib/Commands/FBFindElementCommands.m +++ b/WebDriverAgentLib/Commands/FBFindElementCommands.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBFindElementCommands.h" @@ -80,15 +79,13 @@ + (NSArray *)routes + (id)handleFindVisibleCells:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] - resolveForAdditionalAttributes:@[FB_XCAXAIsVisibleAttributeName] - andMaxDepth:nil]; - NSArray> *visibleCellSnapshots = [element.lastSnapshot descendantsByFilteringWithBlock:^BOOL(id snapshot) { - return snapshot.elementType == XCUIElementTypeCell - && [FBXCElementSnapshotWrapper ensureWrapped:snapshot].wdVisible; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + id snapshot = [element fb_customSnapshot]; + NSArray> *visibleCellSnapshots = [snapshot descendantsByFilteringWithBlock:^BOOL(id shot) { + return shot.elementType == XCUIElementTypeCell + && [FBXCElementSnapshotWrapper ensureWrapped:shot].wdVisible; }]; NSArray *cells = [element fb_filterDescendantsWithSnapshots:visibleCellSnapshots - selfUID:[FBXCElementSnapshotWrapper wdUIDWithSnapshot:element.lastSnapshot] onlyChildren:NO]; return FBResponseWithCachedElements(cells, request.session.elementCache, FBConfiguration.shouldUseCompactResponses); } @@ -96,7 +93,8 @@ + (NSArray *)routes + (id)handleFindSubElement:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] + checkStaleness:NO]; XCUIElement *foundElement = [self.class elementUsing:request.arguments[@"using"] withValue:request.arguments[@"value"] under:element]; @@ -109,7 +107,8 @@ + (NSArray *)routes + (id)handleFindSubElements:(FBRouteRequest *)request { FBElementCache *elementCache = request.session.elementCache; - XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]]; + XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"] + checkStaleness:NO]; NSArray *foundElements = [self.class elementsUsing:request.arguments[@"using"] withValue:request.arguments[@"value"] under:element diff --git a/WebDriverAgentLib/Commands/FBOrientationCommands.h b/WebDriverAgentLib/Commands/FBOrientationCommands.h index 50bd5b6b..1aaaacd6 100644 --- a/WebDriverAgentLib/Commands/FBOrientationCommands.h +++ b/WebDriverAgentLib/Commands/FBOrientationCommands.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Commands/FBOrientationCommands.m b/WebDriverAgentLib/Commands/FBOrientationCommands.m index aa4de26f..8e0bea43 100644 --- a/WebDriverAgentLib/Commands/FBOrientationCommands.m +++ b/WebDriverAgentLib/Commands/FBOrientationCommands.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBOrientationCommands.h" diff --git a/WebDriverAgentLib/Commands/FBScreenshotCommands.h b/WebDriverAgentLib/Commands/FBScreenshotCommands.h index ecb4a5eb..3f4fa4a2 100644 --- a/WebDriverAgentLib/Commands/FBScreenshotCommands.h +++ b/WebDriverAgentLib/Commands/FBScreenshotCommands.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Commands/FBScreenshotCommands.m b/WebDriverAgentLib/Commands/FBScreenshotCommands.m index 0b6e4242..71d6ba59 100644 --- a/WebDriverAgentLib/Commands/FBScreenshotCommands.m +++ b/WebDriverAgentLib/Commands/FBScreenshotCommands.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBScreenshotCommands.h" diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.h b/WebDriverAgentLib/Commands/FBSessionCommands.h index 3f925aca..95f3f258 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.h +++ b/WebDriverAgentLib/Commands/FBSessionCommands.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Commands/FBSessionCommands.m b/WebDriverAgentLib/Commands/FBSessionCommands.m index b7fcca71..65cc7619 100644 --- a/WebDriverAgentLib/Commands/FBSessionCommands.m +++ b/WebDriverAgentLib/Commands/FBSessionCommands.m @@ -3,13 +3,13 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBSessionCommands.h" #import "FBCapabilities.h" +#import "FBClassChainQueryParser.h" #import "FBConfiguration.h" #import "FBExceptions.h" #import "FBLogger.h" @@ -66,6 +66,7 @@ + (NSArray *)routes return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:@"URL is required" traceback:nil]); } NSString* bundleId = request.arguments[@"bundleId"]; + NSNumber* idleTimeoutMs = request.arguments[@"idleTimeoutMs"]; NSError *error; if (nil == bundleId) { if (![XCUIDevice.sharedDevice fb_openUrl:urlString error:&error]) { @@ -75,6 +76,10 @@ + (NSArray *)routes if (![XCUIDevice.sharedDevice fb_openUrl:urlString withApplication:bundleId error:&error]) { return FBResponseWithUnknownError(error); } + if (idleTimeoutMs.doubleValue > 0) { + XCUIApplication *app = [[XCUIApplication alloc] initWithBundleIdentifier:bundleId]; + [app fb_waitUntilStableWithTimeout:FBMillisToSeconds(idleTimeoutMs.doubleValue)]; + } } return FBResponseWithOK(); } @@ -156,19 +161,25 @@ + (NSArray *)routes if (app.running) { [app terminate]; } - NSError *openError; - if (![XCUIDevice.sharedDevice fb_openUrl:initialUrl - withApplication:bundleID - error:&openError]) { - NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ with the %@ application. Original error: %@", - initialUrl, bundleID, openError.localizedDescription]; - return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); + id errorResponse = [self openDeepLink:initialUrl + withApplication:bundleID + timeout:capabilities[FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC]]; + if (nil != errorResponse) { + return errorResponse; } } else { + NSTimeInterval defaultTimeout = _XCTApplicationStateTimeout(); + if (nil != capabilities[FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC]) { + _XCTSetApplicationStateTimeout([capabilities[FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC] doubleValue]); + } @try { [app launch]; } @catch (NSException *e) { return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:e.reason traceback:nil]); + } @finally { + if (nil != capabilities[FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC]) { + _XCTSetApplicationStateTimeout(defaultTimeout); + } } } if (!app.running) { @@ -178,13 +189,11 @@ + (NSArray *)routes } } else if (appState == XCUIApplicationStateRunningBackground && !forceAppLaunch) { if (nil != initialUrl) { - NSError *openError; - if (![XCUIDevice.sharedDevice fb_openUrl:initialUrl - withApplication:bundleID - error:&openError]) { - NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ with the %@ application. Original error: %@", - initialUrl, bundleID, openError.localizedDescription]; - return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); + id errorResponse = [self openDeepLink:initialUrl + withApplication:bundleID + timeout:nil]; + if (nil != errorResponse) { + return errorResponse; } } else { [app activate]; @@ -193,11 +202,11 @@ + (NSArray *)routes } if (nil != initialUrl && nil == bundleID) { - NSError *openError; - if (![XCUIDevice.sharedDevice fb_openUrl:initialUrl error:&openError]) { - NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@. Original error: %@", - initialUrl, openError.localizedDescription]; - return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); + id errorResponse = [self openDeepLink:initialUrl + withApplication:nil + timeout:capabilities[FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC]]; + if (nil != errorResponse) { + return errorResponse; } } @@ -275,6 +284,11 @@ + (NSArray *)routes if (nil != upgradeTimestamp && upgradeTimestamp.length > 0) { [buildInfo setObject:upgradeTimestamp forKey:@"upgradedAt"]; } + NSDictionary *infoDict = [[NSBundle bundleForClass:self.class] infoDictionary]; + NSString *version = [infoDict objectForKey:@"CFBundleShortVersionString"]; + if (nil != version) { + [buildInfo setObject:version forKey:@"version"]; + } return FBResponseWithObject( @{ @@ -324,7 +338,6 @@ + (NSArray *)routes FB_SETTING_SCREENSHOT_QUALITY: @([FBConfiguration screenshotQuality]), FB_SETTING_KEYBOARD_AUTOCORRECTION: @([FBConfiguration keyboardAutocorrection]), FB_SETTING_KEYBOARD_PREDICTION: @([FBConfiguration keyboardPrediction]), - FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT: @([FBConfiguration customSnapshotTimeout]), FB_SETTING_SNAPSHOT_MAX_DEPTH: @([FBConfiguration snapshotMaxDepth]), FB_SETTING_USE_FIRST_MATCH: @([FBConfiguration useFirstMatch]), FB_SETTING_WAIT_FOR_IDLE_TIMEOUT: @([FBConfiguration waitForIdleTimeout]), @@ -336,7 +349,15 @@ + (NSArray *)routes FB_SETTING_INCLUDE_NON_MODAL_ELEMENTS: @([FBConfiguration includeNonModalElements]), FB_SETTING_ACCEPT_ALERT_BUTTON_SELECTOR: FBConfiguration.acceptAlertButtonSelector, FB_SETTING_DISMISS_ALERT_BUTTON_SELECTOR: FBConfiguration.dismissAlertButtonSelector, + FB_SETTING_AUTO_CLICK_ALERT_SELECTOR: FBConfiguration.autoClickAlertSelector, FB_SETTING_DEFAULT_ALERT_ACTION: request.session.defaultAlertAction ?: @"", + FB_SETTING_MAX_TYPING_FREQUENCY: @([FBConfiguration maxTypingFrequency]), + FB_SETTING_RESPECT_SYSTEM_ALERTS: @([FBConfiguration shouldRespectSystemAlerts]), + FB_SETTING_USE_CLEAR_TEXT_SHORTCUT: @([FBConfiguration useClearTextShortcut]), + FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE: @([FBConfiguration includeHittableInPageSource]), + FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE: @([FBConfiguration includeNativeFrameInPageSource]), + FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE: @([FBConfiguration includeMinMaxValueInPageSource]), + FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE: @([FBConfiguration limitXpathContextScope]), #if !TARGET_OS_TV FB_SETTING_SCREENSHOT_ORIENTATION: [FBConfiguration humanReadableScreenshotOrientation], #endif @@ -366,7 +387,7 @@ + (NSArray *)routes [FBConfiguration setScreenshotQuality:[[settings objectForKey:FB_SETTING_SCREENSHOT_QUALITY] unsignedIntegerValue]]; } if (nil != [settings objectForKey:FB_SETTING_MJPEG_SCALING_FACTOR]) { - [FBConfiguration setMjpegScalingFactor:[[settings objectForKey:FB_SETTING_MJPEG_SCALING_FACTOR] unsignedIntegerValue]]; + [FBConfiguration setMjpegScalingFactor:[[settings objectForKey:FB_SETTING_MJPEG_SCALING_FACTOR] floatValue]]; } if (nil != [settings objectForKey:FB_SETTING_MJPEG_FIX_ORIENTATION]) { [FBConfiguration setMjpegShouldFixOrientation:[[settings objectForKey:FB_SETTING_MJPEG_FIX_ORIENTATION] boolValue]]; @@ -377,12 +398,8 @@ + (NSArray *)routes if (nil != [settings objectForKey:FB_SETTING_KEYBOARD_PREDICTION]) { [FBConfiguration setKeyboardPrediction:[[settings objectForKey:FB_SETTING_KEYBOARD_PREDICTION] boolValue]]; } - // SNAPSHOT_TIMEOUT setting is deprecated. Please use CUSTOM_SNAPSHOT_TIMEOUT instead - if (nil != [settings objectForKey:FB_SETTING_SNAPSHOT_TIMEOUT]) { - [FBConfiguration setCustomSnapshotTimeout:[[settings objectForKey:FB_SETTING_SNAPSHOT_TIMEOUT] doubleValue]]; - } - if (nil != [settings objectForKey:FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT]) { - [FBConfiguration setCustomSnapshotTimeout:[[settings objectForKey:FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT] doubleValue]]; + if (nil != [settings objectForKey:FB_SETTING_RESPECT_SYSTEM_ALERTS]) { + [FBConfiguration setShouldRespectSystemAlerts:[[settings objectForKey:FB_SETTING_RESPECT_SYSTEM_ALERTS] boolValue]]; } if (nil != [settings objectForKey:FB_SETTING_SNAPSHOT_MAX_DEPTH]) { [FBConfiguration setSnapshotMaxDepth:[[settings objectForKey:FB_SETTING_SNAPSHOT_MAX_DEPTH] intValue]]; @@ -420,6 +437,13 @@ + (NSArray *)routes if (nil != [settings objectForKey:FB_SETTING_DISMISS_ALERT_BUTTON_SELECTOR]) { [FBConfiguration setDismissAlertButtonSelector:(NSString *)[settings objectForKey:FB_SETTING_DISMISS_ALERT_BUTTON_SELECTOR]]; } + if (nil != [settings objectForKey:FB_SETTING_AUTO_CLICK_ALERT_SELECTOR]) { + FBCommandStatus *status = [self.class configureAutoClickAlertWithSelector:settings[FB_SETTING_AUTO_CLICK_ALERT_SELECTOR] + forSession:request.session]; + if (status.hasError) { + return FBResponseWithStatus(status); + } + } if (nil != [settings objectForKey:FB_SETTING_WAIT_FOR_IDLE_TIMEOUT]) { [FBConfiguration setWaitForIdleTimeout:[[settings objectForKey:FB_SETTING_WAIT_FOR_IDLE_TIMEOUT] doubleValue]]; } @@ -429,6 +453,24 @@ + (NSArray *)routes if ([[settings objectForKey:FB_SETTING_DEFAULT_ALERT_ACTION] isKindOfClass:NSString.class]) { request.session.defaultAlertAction = [settings[FB_SETTING_DEFAULT_ALERT_ACTION] lowercaseString]; } + if (nil != [settings objectForKey:FB_SETTING_MAX_TYPING_FREQUENCY]) { + [FBConfiguration setMaxTypingFrequency:[[settings objectForKey:FB_SETTING_MAX_TYPING_FREQUENCY] unsignedIntegerValue]]; + } + if (nil != [settings objectForKey:FB_SETTING_USE_CLEAR_TEXT_SHORTCUT]) { + [FBConfiguration setUseClearTextShortcut:[[settings objectForKey:FB_SETTING_USE_CLEAR_TEXT_SHORTCUT] boolValue]]; + } + if (nil != [settings objectForKey:FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE]) { + [FBConfiguration setIncludeHittableInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE] boolValue]]; + } + if (nil != [settings objectForKey:FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE]) { + [FBConfiguration setIncludeNativeFrameInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE] boolValue]]; + } + if (nil != [settings objectForKey:FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE]) { + [FBConfiguration setIncludeMinMaxValueInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE] boolValue]]; + } + if (nil != [settings objectForKey:FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE]) { + [FBConfiguration setLimitXpathContextScope:[[settings objectForKey:FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE] boolValue]]; + } #if !TARGET_OS_TV if (nil != [settings objectForKey:FB_SETTING_SCREENSHOT_ORIENTATION]) { @@ -447,6 +489,26 @@ + (NSArray *)routes #pragma mark - Helpers ++ (FBCommandStatus *)configureAutoClickAlertWithSelector:(NSString *)selector + forSession:(FBSession *)session +{ + if (0 == [selector length]) { + [FBConfiguration setAutoClickAlertSelector:selector]; + [session disableAlertsMonitor]; + return [FBCommandStatus ok]; + } + + NSError *error; + FBClassChain *parsedChain = [FBClassChainQueryParser parseQuery:selector error:&error]; + if (nil == parsedChain) { + return [FBCommandStatus invalidSelectorErrorWithMessage:error.localizedDescription + traceback:nil]; + } + [FBConfiguration setAutoClickAlertSelector:selector]; + [session enableAlertsMonitor]; + return [FBCommandStatus ok]; +} + + (NSString *)buildTimestamp { return [NSString stringWithFormat:@"%@ %@", @@ -494,4 +556,33 @@ + (NSDictionary *)currentCapabilities }; } ++(nullable id)openDeepLink:(NSString *)initialUrl + withApplication:(nullable NSString *)bundleID + timeout:(nullable NSNumber *)timeout +{ + NSError *openError; + NSTimeInterval defaultTimeout = _XCTApplicationStateTimeout(); + if (nil != timeout) { + _XCTSetApplicationStateTimeout([timeout doubleValue]); + } + @try { + BOOL result = nil == bundleID + ? [XCUIDevice.sharedDevice fb_openUrl:initialUrl + error:&openError] + : [XCUIDevice.sharedDevice fb_openUrl:initialUrl + withApplication:(id)bundleID + error:&openError]; + if (result) { + return nil; + } + NSString *errorMsg = [NSString stringWithFormat:@"Cannot open the URL %@ with the %@ application. Original error: %@", + initialUrl, bundleID ?: @"default", openError.localizedDescription]; + return FBResponseWithStatus([FBCommandStatus sessionNotCreatedError:errorMsg traceback:nil]); + } @finally { + if (nil != timeout) { + _XCTSetApplicationStateTimeout(defaultTimeout); + } + } +} + @end diff --git a/WebDriverAgentLib/Commands/FBTouchActionCommands.h b/WebDriverAgentLib/Commands/FBTouchActionCommands.h index b3a8e3f2..d9b84fc7 100644 --- a/WebDriverAgentLib/Commands/FBTouchActionCommands.h +++ b/WebDriverAgentLib/Commands/FBTouchActionCommands.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Commands/FBTouchActionCommands.m b/WebDriverAgentLib/Commands/FBTouchActionCommands.m index c14edcb6..7788175e 100644 --- a/WebDriverAgentLib/Commands/FBTouchActionCommands.m +++ b/WebDriverAgentLib/Commands/FBTouchActionCommands.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBTouchActionCommands.h" diff --git a/WebDriverAgentLib/Commands/FBTouchIDCommands.h b/WebDriverAgentLib/Commands/FBTouchIDCommands.h index 6240a5f0..ffcf2e81 100644 --- a/WebDriverAgentLib/Commands/FBTouchIDCommands.h +++ b/WebDriverAgentLib/Commands/FBTouchIDCommands.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Commands/FBTouchIDCommands.m b/WebDriverAgentLib/Commands/FBTouchIDCommands.m index f965c1f0..9594dd6f 100644 --- a/WebDriverAgentLib/Commands/FBTouchIDCommands.m +++ b/WebDriverAgentLib/Commands/FBTouchIDCommands.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBTouchIDCommands.h" diff --git a/WebDriverAgentLib/Commands/FBUnknownCommands.h b/WebDriverAgentLib/Commands/FBUnknownCommands.h index 54262caf..3e37d789 100644 --- a/WebDriverAgentLib/Commands/FBUnknownCommands.h +++ b/WebDriverAgentLib/Commands/FBUnknownCommands.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Commands/FBUnknownCommands.m b/WebDriverAgentLib/Commands/FBUnknownCommands.m index ca27e9a7..7fc35b96 100644 --- a/WebDriverAgentLib/Commands/FBUnknownCommands.m +++ b/WebDriverAgentLib/Commands/FBUnknownCommands.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBUnknownCommands.h" diff --git a/WebDriverAgentLib/Commands/FBVideoCommands.h b/WebDriverAgentLib/Commands/FBVideoCommands.h index b2e3eb79..a3e7a0a6 100644 --- a/WebDriverAgentLib/Commands/FBVideoCommands.h +++ b/WebDriverAgentLib/Commands/FBVideoCommands.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Commands/FBVideoCommands.m b/WebDriverAgentLib/Commands/FBVideoCommands.m index 8366c3a7..a5c36a56 100644 --- a/WebDriverAgentLib/Commands/FBVideoCommands.m +++ b/WebDriverAgentLib/Commands/FBVideoCommands.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBVideoCommands.h" diff --git a/WebDriverAgentLib/FBAlert.h b/WebDriverAgentLib/FBAlert.h index 22f28a71..8e9ec8cd 100644 --- a/WebDriverAgentLib/FBAlert.h +++ b/WebDriverAgentLib/FBAlert.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/FBAlert.m b/WebDriverAgentLib/FBAlert.m index b06e2678..2e2de763 100644 --- a/WebDriverAgentLib/FBAlert.m +++ b/WebDriverAgentLib/FBAlert.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBAlert.h" @@ -50,7 +49,7 @@ - (BOOL)isPresent if (nil == self.alertElement) { return NO; } - [self.alertElement fb_takeSnapshot]; + [self.alertElement fb_customSnapshot]; return YES; } @catch (NSException *) { return NO; @@ -82,7 +81,7 @@ - (NSString *)text } NSMutableArray *resultText = [NSMutableArray array]; - id snapshot = self.alertElement.lastSnapshot; + id snapshot = self.alertElement.lastSnapshot ?: [self.alertElement fb_customSnapshot]; BOOL isSafariAlert = [self.class isSafariWebAlertWithSnapshot:snapshot]; [snapshot enumerateDescendantsUsingBlock:^(id descendant) { XCUIElementType elementType = descendant.elementType; @@ -145,7 +144,8 @@ - (NSArray *)buttonLabels } NSMutableArray *labels = [NSMutableArray array]; - [self.alertElement.lastSnapshot enumerateDescendantsUsingBlock:^(id descendant) { + id alertSnapshot = self.alertElement.lastSnapshot ?: [self.alertElement fb_customSnapshot]; + [alertSnapshot enumerateDescendantsUsingBlock:^(id descendant) { if (descendant.elementType != XCUIElementTypeButton) { return; } @@ -163,7 +163,7 @@ - (BOOL)acceptWithError:(NSError **)error return [self notPresentWithError:error]; } - id alertSnapshot = self.alertElement.lastSnapshot; + id alertSnapshot = self.alertElement.lastSnapshot ?: [self.alertElement fb_customSnapshot]; XCUIElement *acceptButton = nil; if (FBConfiguration.acceptAlertButtonSelector.length) { NSString *errorReason = nil; @@ -204,7 +204,7 @@ - (BOOL)dismissWithError:(NSError **)error return [self notPresentWithError:error]; } - id alertSnapshot = self.alertElement.lastSnapshot; + id alertSnapshot = self.alertElement.lastSnapshot ?: [self.alertElement fb_customSnapshot]; XCUIElement *dismissButton = nil; if (FBConfiguration.dismissAlertButtonSelector.length) { NSString *errorReason = nil; diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist index 1b89f4fc..d27f61f6 100644 --- a/WebDriverAgentLib/Info.plist +++ b/WebDriverAgentLib/Info.plist @@ -1,26 +1,26 @@ - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - com.facebook.wda.lib - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSPrincipalClass - - - + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 10.2.2 + CFBundleSignature + ???? + CFBundleVersion + 10.2.2 + NSPrincipalClass + + + \ No newline at end of file diff --git a/WebDriverAgentLib/Routing/FBCommandHandler.h b/WebDriverAgentLib/Routing/FBCommandHandler.h index bde028d6..c4ac83b7 100644 --- a/WebDriverAgentLib/Routing/FBCommandHandler.h +++ b/WebDriverAgentLib/Routing/FBCommandHandler.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBCommandStatus.h b/WebDriverAgentLib/Routing/FBCommandStatus.h index 82bee1f6..0929ff10 100644 --- a/WebDriverAgentLib/Routing/FBCommandStatus.h +++ b/WebDriverAgentLib/Routing/FBCommandStatus.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -19,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, nullable, readonly) NSString* message; @property (nonatomic, nullable, readonly) NSString* traceback; @property (nonatomic, readonly) HTTPStatusCode statusCode; - +@property (nonatomic, readonly) BOOL hasError; + (instancetype)ok; diff --git a/WebDriverAgentLib/Routing/FBCommandStatus.m b/WebDriverAgentLib/Routing/FBCommandStatus.m index 453fb619..fb5d2439 100644 --- a/WebDriverAgentLib/Routing/FBCommandStatus.m +++ b/WebDriverAgentLib/Routing/FBCommandStatus.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBCommandStatus.h" @@ -109,6 +108,11 @@ - (instancetype)initWithError:(NSString *)error return self; } +- (BOOL)hasError +{ + return self.statusCode != kHTTPStatusCodeOK; +} + + (instancetype)ok { return [[FBCommandStatus alloc] initWithValue:nil]; diff --git a/WebDriverAgentLib/Routing/FBElement.h b/WebDriverAgentLib/Routing/FBElement.h index 7cc8f269..b4e6a752 100644 --- a/WebDriverAgentLib/Routing/FBElement.h +++ b/WebDriverAgentLib/Routing/FBElement.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -20,6 +19,9 @@ NS_ASSUME_NONNULL_BEGIN /*! Element's frame in normalized (rounded dimensions without Infinity values) CGRect format */ @property (nonatomic, readonly, assign) CGRect wdFrame; +/*! Represents the element's frame as a CGRect, preserving the actual values. */ +@property (nonatomic, readonly, assign) CGRect wdNativeFrame; + /*! Element's wsFrame in NSDictionary format */ @property (nonatomic, readonly, copy) NSDictionary *wdRect; @@ -35,6 +37,9 @@ NS_ASSUME_NONNULL_BEGIN /*! Element's type */ @property (nonatomic, readonly, copy) NSString *wdType; +/*! Element's accessibility traits as a comma-separated string */ +@property (nonatomic, readonly, copy) NSString *wdTraits; + /*! Element's value */ @property (nonatomic, readonly, strong, nullable) NSString *wdValue; @@ -62,6 +67,15 @@ NS_ASSUME_NONNULL_BEGIN /*! Element's index relatively to its parent. Starts from zero */ @property (nonatomic, readonly) NSUInteger wdIndex; +/*! Element's placeholder value */ +@property (nonatomic, readonly, copy, nullable) NSString *wdPlaceholderValue; + +/*! Element's minimum value */ +@property (nonatomic, readonly, strong, nullable) NSNumber *wdMinValue; + +/*! Element's maximum value */ +@property (nonatomic, readonly, strong, nullable) NSNumber *wdMaxValue; + /** Returns value of given property specified in WebDriver Spec Check the FBElement protocol to get list of supported attributes. diff --git a/WebDriverAgentLib/Routing/FBElementCache.h b/WebDriverAgentLib/Routing/FBElementCache.h index 13100eeb..1c7eb476 100644 --- a/WebDriverAgentLib/Routing/FBElementCache.h +++ b/WebDriverAgentLib/Routing/FBElementCache.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -35,26 +34,20 @@ extern const int ELEMENT_CACHE_SIZE; @param uuid uuid of element to fetch @return element - @throws FBStaleElementException if the found element is not present in DOM anymore @throws FBInvalidArgumentException if uuid is nil */ - (XCUIElement *)elementForUUID:(NSString *)uuid; /** - Returns cached element + Returns cached element resolved with default snapshot attributes @param uuid uuid of element to fetch - @param additionalAttributes Add additonal attribute names if the snapshot should contain - them in `addtionalAttributes` section. nil value resolves the snapshot with standard attributes. - @param maxDepth The maximum depth of the snapshot. Only works if additional attributes are provided. - `nil` value means to use the default maximum depth value. + @param checkStaleness Whether to throw FBStaleElementException if the found element is not present in DOM anymore @return element - @throws FBStaleElementException if the found element is not present in DOM anymore + @throws FBStaleElementException if `checkStaleness` is enabled @throws FBInvalidArgumentException if uuid is nil */ -- (XCUIElement *)elementForUUID:(NSString *)uuid - resolveForAdditionalAttributes:(nullable NSArray *)additionalAttributes - andMaxDepth:(nullable NSNumber *)maxDepth; +- (XCUIElement *)elementForUUID:(NSString *)uuid checkStaleness:(BOOL)checkStaleness; /** Checks element existence in the cache diff --git a/WebDriverAgentLib/Routing/FBElementCache.m b/WebDriverAgentLib/Routing/FBElementCache.m index 1f069bec..75662424 100644 --- a/WebDriverAgentLib/Routing/FBElementCache.m +++ b/WebDriverAgentLib/Routing/FBElementCache.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBElementCache.h" @@ -26,7 +25,6 @@ @interface FBElementCache () @property (nonatomic, strong) LRUCache *elementCache; -@property (nonatomic) BOOL elementsNeedReset; @end @implementation FBElementCache @@ -38,7 +36,6 @@ - (instancetype)init return nil; } _elementCache = [[LRUCache alloc] initWithCapacity:ELEMENT_CACHE_SIZE]; - _elementsNeedReset = NO; return self; } @@ -50,19 +47,16 @@ - (NSString *)storeElement:(XCUIElement *)element } @synchronized (self.elementCache) { [self.elementCache setObject:element forKey:uuid]; - self.elementsNeedReset = YES; } return uuid; } - (XCUIElement *)elementForUUID:(NSString *)uuid { - return [self elementForUUID:uuid resolveForAdditionalAttributes:nil andMaxDepth:nil]; + return [self elementForUUID:uuid checkStaleness:NO]; } -- (XCUIElement *)elementForUUID:(NSString *)uuid - resolveForAdditionalAttributes:(NSArray *)additionalAttributes - andMaxDepth:(NSNumber *)maxDepth +- (XCUIElement *)elementForUUID:(NSString *)uuid checkStaleness:(BOOL)checkStaleness { if (!uuid) { NSString *reason = [NSString stringWithFormat:@"Cannot extract cached element for UUID: %@", uuid]; @@ -71,23 +65,25 @@ - (XCUIElement *)elementForUUID:(NSString *)uuid XCUIElement *element; @synchronized (self.elementCache) { - [self resetElements]; element = [self.elementCache objectForKey:uuid]; } if (nil == element) { NSString *reason = [NSString stringWithFormat:@"The element identified by \"%@\" is either not present or it has expired from the internal cache. Try to find it again", uuid]; @throw [NSException exceptionWithName:FBStaleElementException reason:reason userInfo:@{}]; } - // This will throw FBStaleElementException exception if the element is stale - // or resolve the element and set lastSnapshot property - if (nil == additionalAttributes) { - [element fb_takeSnapshot]; - } else { - NSMutableArray *attributes = [NSMutableArray arrayWithArray:FBStandardAttributeNames()]; - [attributes addObjectsFromArray:additionalAttributes]; - [element fb_snapshotWithAttributes:attributes.copy maxDepth:maxDepth]; + if (checkStaleness) { + @try { + [element fb_standardSnapshot]; + } @catch (NSException *exception) { + // if the snapshot method threw FBStaleElementException (implying the element is stale) we need to explicitly remove it from the cache, PR: https://github.com/appium/WebDriverAgent/pull/985 + if ([exception.name isEqualToString:FBStaleElementException]) { + @synchronized (self.elementCache) { + [self.elementCache removeObjectForKey:uuid]; + } + } + @throw exception; + } } - element.fb_isResolvedFromCache = @(YES); return element; } @@ -101,20 +97,4 @@ - (BOOL)hasElementWithUUID:(NSString *)uuid } } -- (void)resetElements -{ - if (!self.elementsNeedReset) { - return; - } - - for (XCUIElement *element in self.elementCache.allObjects) { - element.lastSnapshot = nil; - if (nil != element.query) { - element.query.rootElementSnapshot = nil; - } - element.fb_isResolvedFromCache = @(NO); - } - self.elementsNeedReset = NO; -} - @end diff --git a/WebDriverAgentLib/Routing/FBElementUtils.h b/WebDriverAgentLib/Routing/FBElementUtils.h index a0b6da83..0c4de4b7 100644 --- a/WebDriverAgentLib/Routing/FBElementUtils.h +++ b/WebDriverAgentLib/Routing/FBElementUtils.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBElementUtils.m b/WebDriverAgentLib/Routing/FBElementUtils.m index 8aec9d8a..cc89d2fc 100644 --- a/WebDriverAgentLib/Routing/FBElementUtils.m +++ b/WebDriverAgentLib/Routing/FBElementUtils.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBExceptionHandler.h b/WebDriverAgentLib/Routing/FBExceptionHandler.h index 693e5c40..cc1dc0f2 100644 --- a/WebDriverAgentLib/Routing/FBExceptionHandler.h +++ b/WebDriverAgentLib/Routing/FBExceptionHandler.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBExceptionHandler.m b/WebDriverAgentLib/Routing/FBExceptionHandler.m index 811a0efb..b5e1ec06 100644 --- a/WebDriverAgentLib/Routing/FBExceptionHandler.m +++ b/WebDriverAgentLib/Routing/FBExceptionHandler.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBExceptionHandler.h" diff --git a/WebDriverAgentLib/Routing/FBExceptions.h b/WebDriverAgentLib/Routing/FBExceptions.h index a7263bae..b802da67 100644 --- a/WebDriverAgentLib/Routing/FBExceptions.h +++ b/WebDriverAgentLib/Routing/FBExceptions.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -55,4 +54,7 @@ extern NSString *const FBApplicationCrashedException; /*! Exception used to notify about the application is not installed */ extern NSString *const FBApplicationMissingException; +/*! Exception used to notify about WDA incompatibility with the current platform version */ +extern NSString *const FBIncompatibleWdaException; + NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Routing/FBExceptions.m b/WebDriverAgentLib/Routing/FBExceptions.m index 9e1f2141..feb8a4d5 100644 --- a/WebDriverAgentLib/Routing/FBExceptions.m +++ b/WebDriverAgentLib/Routing/FBExceptions.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBExceptions.h" @@ -22,3 +21,4 @@ NSString *const FBClassChainQueryParseException = @"FBClassChainQueryParseException"; NSString *const FBApplicationCrashedException = @"FBApplicationCrashedException"; NSString *const FBApplicationMissingException = @"FBApplicationMissingException"; +NSString *const FBIncompatibleWdaException = @"FBIncompatibleWdaException"; diff --git a/WebDriverAgentLib/Routing/FBResponseJSONPayload.h b/WebDriverAgentLib/Routing/FBResponseJSONPayload.h index 14f6c1c8..8c863e99 100644 --- a/WebDriverAgentLib/Routing/FBResponseJSONPayload.h +++ b/WebDriverAgentLib/Routing/FBResponseJSONPayload.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBResponseJSONPayload.m b/WebDriverAgentLib/Routing/FBResponseJSONPayload.m index 4ad1c37a..8782b8e9 100644 --- a/WebDriverAgentLib/Routing/FBResponseJSONPayload.m +++ b/WebDriverAgentLib/Routing/FBResponseJSONPayload.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBResponseJSONPayload.h" diff --git a/WebDriverAgentLib/Routing/FBResponsePayload.h b/WebDriverAgentLib/Routing/FBResponsePayload.h index 9ff7a930..b29b8f98 100644 --- a/WebDriverAgentLib/Routing/FBResponsePayload.h +++ b/WebDriverAgentLib/Routing/FBResponsePayload.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBResponsePayload.m b/WebDriverAgentLib/Routing/FBResponsePayload.m index 08fcd63f..809cd41e 100644 --- a/WebDriverAgentLib/Routing/FBResponsePayload.m +++ b/WebDriverAgentLib/Routing/FBResponsePayload.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBResponsePayload.h" @@ -34,24 +33,41 @@ return FBResponseWithStatus([FBCommandStatus okWithValue:object]); } -id FBResponseWithCachedElement(XCUIElement *element, FBElementCache *elementCache, BOOL compact) +XCUIElement *maybeStable(XCUIElement *element) { BOOL useNativeCachingStrategy = nil == FBSession.activeSession ? YES : FBSession.activeSession.useNativeCachingStrategy; - [elementCache storeElement:(useNativeCachingStrategy ? element : element.fb_stableInstance)]; - return FBResponseWithStatus([FBCommandStatus okWithValue:FBDictionaryResponseWithElement(element, compact)]); + if (useNativeCachingStrategy) { + return element; + } + + XCUIElement *result = element; + id snapshot = element.lastSnapshot + ?: element.fb_cachedSnapshot + ?: [element fb_standardSnapshot]; + NSString *uid = [FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]; + if (nil != uid) { + result = [element fb_stableInstanceWithUid:uid]; + } + return result; +} + +id FBResponseWithCachedElement(XCUIElement *element, FBElementCache *elementCache, BOOL compact) +{ + [elementCache storeElement:maybeStable(element)]; + NSDictionary *response = FBDictionaryResponseWithElement(element, compact); + element.lastSnapshot = nil; + return FBResponseWithStatus([FBCommandStatus okWithValue:response]); } id FBResponseWithCachedElements(NSArray *elements, FBElementCache *elementCache, BOOL compact) { NSMutableArray *elementsResponse = [NSMutableArray array]; - BOOL useNativeCachingStrategy = nil == FBSession.activeSession - ? YES - : FBSession.activeSession.useNativeCachingStrategy; for (XCUIElement *element in elements) { - [elementCache storeElement:(useNativeCachingStrategy ? element : element.fb_stableInstance)]; + [elementCache storeElement:maybeStable(element)]; [elementsResponse addObject:FBDictionaryResponseWithElement(element, compact)]; + element.lastSnapshot = nil; } return FBResponseWithStatus([FBCommandStatus okWithValue:elementsResponse]); } @@ -91,41 +107,42 @@ inline NSDictionary *FBDictionaryResponseWithElement(XCUIElement *element, BOOL compact) { - id snapshot = nil; - if (nil != element.query.rootElementSnapshot) { - snapshot = element.fb_cachedSnapshot; - } - if (nil == snapshot) { - snapshot = element.lastSnapshot ?: element.fb_takeSnapshot; - } - NSDictionary *compactResult = FBToElementDict((NSString *)[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]); - if (compact) { - return compactResult; - } + __block NSDictionary *elementResponse = nil; + @autoreleasepool { + id snapshot = element.lastSnapshot + ?: element.fb_cachedSnapshot + ?: [element fb_customSnapshot]; + NSDictionary *compactResult = FBToElementDict((NSString *)[FBXCElementSnapshotWrapper wdUIDWithSnapshot:snapshot]); + if (compact) { + elementResponse = compactResult; + return elementResponse; + } - NSMutableDictionary *result = compactResult.mutableCopy; - FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; - NSArray *fields = [FBConfiguration.elementResponseAttributes componentsSeparatedByString:@","]; - for (NSString *field in fields) { - // 'name' here is the w3c-approved identifier for what we mean by 'type' - if ([field isEqualToString:@"name"] || [field isEqualToString:@"type"]) { - result[field] = wrappedSnapshot.wdType; - } else if ([field isEqualToString:@"text"]) { - result[field] = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel) ?: [NSNull null]; - } else if ([field isEqualToString:@"rect"]) { - result[field] = wrappedSnapshot.wdRect; - } else if ([field isEqualToString:@"enabled"]) { - result[field] = @(wrappedSnapshot.wdEnabled); - } else if ([field isEqualToString:@"displayed"]) { - result[field] = @(wrappedSnapshot.wdVisible); - } else if ([field isEqualToString:@"selected"]) { - result[field] = @(wrappedSnapshot.wdSelected); - } else if ([field isEqualToString:@"label"]) { - result[field] = wrappedSnapshot.wdLabel ?: [NSNull null]; - } else if ([field hasPrefix:arbitraryAttrPrefix]) { - NSString *attributeName = [field substringFromIndex:[arbitraryAttrPrefix length]]; - result[field] = [wrappedSnapshot fb_valueForWDAttributeName:attributeName] ?: [NSNull null]; + NSMutableDictionary *result = compactResult.mutableCopy; + FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:snapshot]; + NSArray *fields = [FBConfiguration.elementResponseAttributes componentsSeparatedByString:@","]; + for (NSString *field in fields) { + // 'name' here is the w3c-approved identifier for what we mean by 'type' + if ([field isEqualToString:@"name"] || [field isEqualToString:@"type"]) { + result[field] = wrappedSnapshot.wdType; + } else if ([field isEqualToString:@"text"]) { + result[field] = FBFirstNonEmptyValue(wrappedSnapshot.wdValue, wrappedSnapshot.wdLabel) ?: [NSNull null]; + } else if ([field isEqualToString:@"rect"]) { + result[field] = wrappedSnapshot.wdRect; + } else if ([field isEqualToString:@"enabled"]) { + result[field] = @(wrappedSnapshot.wdEnabled); + } else if ([field isEqualToString:@"displayed"]) { + result[field] = @(wrappedSnapshot.wdVisible); + } else if ([field isEqualToString:@"selected"]) { + result[field] = @(wrappedSnapshot.wdSelected); + } else if ([field isEqualToString:@"label"]) { + result[field] = wrappedSnapshot.wdLabel ?: [NSNull null]; + } else if ([field hasPrefix:arbitraryAttrPrefix]) { + NSString *attributeName = [field substringFromIndex:[arbitraryAttrPrefix length]]; + result[field] = [wrappedSnapshot fb_valueForWDAttributeName:attributeName] ?: [NSNull null]; + } } + elementResponse = result.copy; } - return result.copy; + return elementResponse; } diff --git a/WebDriverAgentLib/Routing/FBRoute.h b/WebDriverAgentLib/Routing/FBRoute.h index 2d313868..fce8dd8a 100644 --- a/WebDriverAgentLib/Routing/FBRoute.h +++ b/WebDriverAgentLib/Routing/FBRoute.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBRoute.m b/WebDriverAgentLib/Routing/FBRoute.m index 745ddaf3..fbe69b8c 100644 --- a/WebDriverAgentLib/Routing/FBRoute.m +++ b/WebDriverAgentLib/Routing/FBRoute.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBRoute.h" @@ -39,7 +38,10 @@ @implementation FBRoute_TargetAction - (void)mountRequest:(FBRouteRequest *)request intoResponse:(RouteResponse *)response { [self decorateRequest:request]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-function-type-strict" id (*requestMsgSend)(id, SEL, FBRouteRequest *) = ((id(*)(id, SEL, FBRouteRequest *))objc_msgSend); +#pragma clang diagnostic pop id payload = requestMsgSend(self.target, self.action, request); [payload dispatchWithResponse:response]; } diff --git a/WebDriverAgentLib/Routing/FBRouteRequest-Private.h b/WebDriverAgentLib/Routing/FBRouteRequest-Private.h index d5bd31f1..7144bd80 100644 --- a/WebDriverAgentLib/Routing/FBRouteRequest-Private.h +++ b/WebDriverAgentLib/Routing/FBRouteRequest-Private.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBRouteRequest.h b/WebDriverAgentLib/Routing/FBRouteRequest.h index 7647cd82..c7938d5d 100644 --- a/WebDriverAgentLib/Routing/FBRouteRequest.h +++ b/WebDriverAgentLib/Routing/FBRouteRequest.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBRouteRequest.m b/WebDriverAgentLib/Routing/FBRouteRequest.m index e7d2743f..b8656d28 100644 --- a/WebDriverAgentLib/Routing/FBRouteRequest.m +++ b/WebDriverAgentLib/Routing/FBRouteRequest.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBRouteRequest-Private.h" diff --git a/WebDriverAgentLib/Routing/FBScreenRecordingContainer.h b/WebDriverAgentLib/Routing/FBScreenRecordingContainer.h index 48e5c748..ce655dd7 100644 --- a/WebDriverAgentLib/Routing/FBScreenRecordingContainer.h +++ b/WebDriverAgentLib/Routing/FBScreenRecordingContainer.h @@ -4,8 +4,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBScreenRecordingContainer.m b/WebDriverAgentLib/Routing/FBScreenRecordingContainer.m index b0a744dc..608d7bfd 100644 --- a/WebDriverAgentLib/Routing/FBScreenRecordingContainer.m +++ b/WebDriverAgentLib/Routing/FBScreenRecordingContainer.m @@ -4,8 +4,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBScreenRecordingContainer.h" diff --git a/WebDriverAgentLib/Routing/FBScreenRecordingPromise.h b/WebDriverAgentLib/Routing/FBScreenRecordingPromise.h index a8691876..6b3fcb3c 100644 --- a/WebDriverAgentLib/Routing/FBScreenRecordingPromise.h +++ b/WebDriverAgentLib/Routing/FBScreenRecordingPromise.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBScreenRecordingPromise.m b/WebDriverAgentLib/Routing/FBScreenRecordingPromise.m index 9de9dbaf..e1193a13 100644 --- a/WebDriverAgentLib/Routing/FBScreenRecordingPromise.m +++ b/WebDriverAgentLib/Routing/FBScreenRecordingPromise.m @@ -4,8 +4,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBScreenRecordingPromise.h" diff --git a/WebDriverAgentLib/Routing/FBScreenRecordingRequest.h b/WebDriverAgentLib/Routing/FBScreenRecordingRequest.h index 5e24e558..f0a61ef2 100644 --- a/WebDriverAgentLib/Routing/FBScreenRecordingRequest.h +++ b/WebDriverAgentLib/Routing/FBScreenRecordingRequest.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBScreenRecordingRequest.m b/WebDriverAgentLib/Routing/FBScreenRecordingRequest.m index 5249b76b..32c5b057 100644 --- a/WebDriverAgentLib/Routing/FBScreenRecordingRequest.m +++ b/WebDriverAgentLib/Routing/FBScreenRecordingRequest.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBScreenRecordingRequest.h" diff --git a/WebDriverAgentLib/Routing/FBSession-Private.h b/WebDriverAgentLib/Routing/FBSession-Private.h index 45d5a8c3..792fcd73 100644 --- a/WebDriverAgentLib/Routing/FBSession-Private.h +++ b/WebDriverAgentLib/Routing/FBSession-Private.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBSession.h b/WebDriverAgentLib/Routing/FBSession.h index 9b73d4d1..61b1f874 100644 --- a/WebDriverAgentLib/Routing/FBSession.h +++ b/WebDriverAgentLib/Routing/FBSession.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -14,6 +13,9 @@ NS_ASSUME_NONNULL_BEGIN +/** Bundle identifier of Mobile Safari browser */ +extern NSString* const FB_SAFARI_BUNDLE_ID; + /** Class that represents testing session */ @@ -118,6 +120,22 @@ NS_ASSUME_NONNULL_BEGIN */ - (NSUInteger)applicationStateWithBundleId:(NSString *)bundleIdentifier; +/** + Allows to enable automated session alerts monitoring. + Repeated calls are ignored if alerts monitoring has been already enabled. + + @returns YES if the actual alerts monitoring state has been changed + */ +- (BOOL)enableAlertsMonitor; + +/** + Allows to disable automated alerts monitoring + Repeated calls are ignored if alerts monitoring has been already disabled. + + @returns YES if the actual alerts monitoring state has been changed + */ +- (BOOL)disableAlertsMonitor; + @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Routing/FBSession.m b/WebDriverAgentLib/Routing/FBSession.m index 82134e0c..b8de5edf 100644 --- a/WebDriverAgentLib/Routing/FBSession.m +++ b/WebDriverAgentLib/Routing/FBSession.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBSession.h" @@ -25,6 +24,7 @@ #import "FBXCTestDaemonsProxy.h" #import "XCUIApplication+FBQuiescence.h" #import "XCUIElement.h" +#import "XCUIElement+FBClassChain.h" /*! The intial value for the default application property. @@ -33,6 +33,8 @@ */ NSString *const FBDefaultApplicationAuto = @"auto"; +NSString *const FB_SAFARI_BUNDLE_ID = @"com.apple.mobilesafari"; + @interface FBSession () @property (nullable, nonatomic) XCUIApplication *testedApplication; @property (nonatomic) BOOL isTestedApplicationExpectedToRun; @@ -51,6 +53,22 @@ @implementation FBSession (FBAlertsMonitorDelegate) - (void)didDetectAlert:(FBAlert *)alert { + NSString *autoClickAlertSelector = FBConfiguration.autoClickAlertSelector; + if ([autoClickAlertSelector length] > 0) { + @try { + NSArray *matches = [alert.alertElement fb_descendantsMatchingClassChain:autoClickAlertSelector + shouldReturnAfterFirstMatch:YES]; + if (matches.count > 0) { + [[matches objectAtIndex:0] tap]; + } + } @catch (NSException *e) { + [FBLogger logFmt:@"Could not click at the alert element '%@'. Original error: %@", + autoClickAlertSelector, e.description]; + } + // This setting has priority over other settings if enabled + return; + } + if (nil == self.defaultAlertAction || 0 == self.defaultAlertAction.length) { return; } @@ -123,23 +141,41 @@ + (instancetype)initWithApplication:(nullable XCUIApplication *)application defaultAlertAction:(NSString *)defaultAlertAction { FBSession *session = [self.class initWithApplication:application]; - session.alertsMonitor = [[FBAlertsMonitor alloc] init]; - session.alertsMonitor.delegate = (id)session; session.defaultAlertAction = [defaultAlertAction lowercaseString]; - [session.alertsMonitor enable]; + [session enableAlertsMonitor]; return session; } +- (BOOL)enableAlertsMonitor +{ + if (nil != self.alertsMonitor) { + return NO; + } + + self.alertsMonitor = [[FBAlertsMonitor alloc] init]; + self.alertsMonitor.delegate = (id)self; + [self.alertsMonitor enable]; + return YES; +} + +- (BOOL)disableAlertsMonitor +{ + if (nil == self.alertsMonitor) { + return NO; + } + + [self.alertsMonitor disable]; + self.alertsMonitor = nil; + return YES; +} + - (void)kill { if (nil == _activeSession) { return; } - if (nil != self.alertsMonitor) { - [self.alertsMonitor disable]; - self.alertsMonitor = nil; - } + [self disableAlertsMonitor]; FBScreenRecordingPromise *activeScreenRecording = FBScreenRecordingContainer.sharedInstance.screenRecordingPromise; if (nil != activeScreenRecording) { @@ -176,6 +212,18 @@ - (XCUIApplication *)activeApplication if (nil != self.testedApplication) { XCUIApplicationState testedAppState = self.testedApplication.state; if (testedAppState >= XCUIApplicationStateRunningForeground) { + NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"%K == %@ OR %K IN {%@, %@}", + @"elementType", @(XCUIElementTypeAlert), + // To look for `SBTransientOverlayWindow` elements. See https://github.com/appium/WebDriverAgent/pull/946 + @"identifier", @"SBTransientOverlayWindow", + // To look for 'criticalAlertSetting' elements https://developer.apple.com/documentation/usernotifications/unnotificationsettings/criticalalertsetting + // See https://github.com/appium/appium/issues/20835 + @"NotificationShortLookView"]; + if ([FBConfiguration shouldRespectSystemAlerts] + && [[XCUIApplication.fb_systemApplication descendantsMatchingType:XCUIElementTypeAny] + matchingPredicate:searchPredicate].count > 0) { + return XCUIApplication.fb_systemApplication; + } return (XCUIApplication *)self.testedApplication; } if (self.isTestedApplicationExpectedToRun && testedAppState <= XCUIApplicationStateNotRunning) { diff --git a/WebDriverAgentLib/Routing/FBTCPSocket.h b/WebDriverAgentLib/Routing/FBTCPSocket.h index 895ae75f..31adc7e2 100644 --- a/WebDriverAgentLib/Routing/FBTCPSocket.h +++ b/WebDriverAgentLib/Routing/FBTCPSocket.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "GCDAsyncSocket.h" diff --git a/WebDriverAgentLib/Routing/FBTCPSocket.m b/WebDriverAgentLib/Routing/FBTCPSocket.m index 527acdf4..fabd2207 100644 --- a/WebDriverAgentLib/Routing/FBTCPSocket.m +++ b/WebDriverAgentLib/Routing/FBTCPSocket.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBTCPSocket.h" diff --git a/WebDriverAgentLib/Routing/FBWebServer.h b/WebDriverAgentLib/Routing/FBWebServer.h index a857a10c..34bca651 100644 --- a/WebDriverAgentLib/Routing/FBWebServer.h +++ b/WebDriverAgentLib/Routing/FBWebServer.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBWebServer.m b/WebDriverAgentLib/Routing/FBWebServer.m index 7e991e0e..0b82eaff 100644 --- a/WebDriverAgentLib/Routing/FBWebServer.m +++ b/WebDriverAgentLib/Routing/FBWebServer.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBWebServer.h" @@ -93,6 +92,12 @@ - (void)startHTTPServer [self registerServerKeyRouteHandlers]; NSRange serverPortRange = FBConfiguration.bindingPortRange; + NSString *bindingIP = FBConfiguration.bindingIPAddress; + if (bindingIP != nil) { + [self.server setInterface:bindingIP]; + [FBLogger logFmt:@"Using custom binding IP address: %@", bindingIP]; + } + NSError *error; BOOL serverStarted = NO; @@ -112,7 +117,9 @@ - (void)startHTTPServer [FBLogger logFmt:@"Last attempt to start web server failed with error %@", [error description]]; abort(); } - [FBLogger logFmt:@"%@http://%@:%d%@", FBServerURLBeginMarker, [XCUIDevice sharedDevice].fb_wifiIPAddress ?: @"localhost", [self.server port], FBServerURLEndMarker]; + + NSString *serverHost = bindingIP ?: ([XCUIDevice sharedDevice].fb_wifiIPAddress ?: @"127.0.0.1"); + [FBLogger logFmt:@"%@http://%@:%d%@", FBServerURLBeginMarker, serverHost, [self.server port], FBServerURLEndMarker]; } - (void)initScreenshotsBroadcaster @@ -142,7 +149,7 @@ - (void)readMjpegSettingsFromEnv NSDictionary *env = NSProcessInfo.processInfo.environment; NSString *scalingFactor = [env objectForKey:@"MJPEG_SCALING_FACTOR"]; if (scalingFactor != nil && [scalingFactor length] > 0) { - [FBConfiguration setMjpegScalingFactor:[scalingFactor integerValue]]; + [FBConfiguration setMjpegScalingFactor:[scalingFactor floatValue]]; } NSString *screenshotQuality = [env objectForKey:@"MJPEG_SERVER_SCREENSHOT_QUALITY"]; if (screenshotQuality != nil && [screenshotQuality length] > 0) { @@ -217,7 +224,7 @@ - (void)handleException:(NSException *)exception forResponse:(RouteResponse *)re - (void)registerServerKeyRouteHandlers { [self.server get:@"/health" withBlock:^(RouteRequest *request, RouteResponse *response) { - [response respondWithString:@"I-AM-ALIVE"]; + [response respondWithString:@"Health Check

I-AM-ALIVE

"]; }]; NSString *calibrationPage = @"" diff --git a/WebDriverAgentLib/Routing/FBXCAccessibilityElement.h b/WebDriverAgentLib/Routing/FBXCAccessibilityElement.h index 701edcd8..dd35a378 100644 --- a/WebDriverAgentLib/Routing/FBXCAccessibilityElement.h +++ b/WebDriverAgentLib/Routing/FBXCAccessibilityElement.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBXCAccessibilityElement.m b/WebDriverAgentLib/Routing/FBXCAccessibilityElement.m index 4535be67..39f22913 100644 --- a/WebDriverAgentLib/Routing/FBXCAccessibilityElement.m +++ b/WebDriverAgentLib/Routing/FBXCAccessibilityElement.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBXCAccessibilityElement.h" diff --git a/WebDriverAgentLib/Routing/FBXCDeviceEvent.h b/WebDriverAgentLib/Routing/FBXCDeviceEvent.h index b27b667e..64139f9f 100644 --- a/WebDriverAgentLib/Routing/FBXCDeviceEvent.h +++ b/WebDriverAgentLib/Routing/FBXCDeviceEvent.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBXCDeviceEvent.m b/WebDriverAgentLib/Routing/FBXCDeviceEvent.m index 8f2c9609..6a673e15 100644 --- a/WebDriverAgentLib/Routing/FBXCDeviceEvent.m +++ b/WebDriverAgentLib/Routing/FBXCDeviceEvent.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBXCDeviceEvent.h" diff --git a/WebDriverAgentLib/Routing/FBXCElementSnapshot.h b/WebDriverAgentLib/Routing/FBXCElementSnapshot.h index a3076ec2..500d9a84 100644 --- a/WebDriverAgentLib/Routing/FBXCElementSnapshot.h +++ b/WebDriverAgentLib/Routing/FBXCElementSnapshot.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Routing/FBXCElementSnapshot.m b/WebDriverAgentLib/Routing/FBXCElementSnapshot.m index 11d10689..5fe60204 100644 --- a/WebDriverAgentLib/Routing/FBXCElementSnapshot.m +++ b/WebDriverAgentLib/Routing/FBXCElementSnapshot.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBXCElementSnapshot.h" diff --git a/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.h b/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.h index e9b76314..2309d6b5 100644 --- a/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.h +++ b/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBXCElementSnapshot.h" diff --git a/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.m b/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.m index 1beb87bb..4b3e0e7f 100644 --- a/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.m +++ b/WebDriverAgentLib/Routing/FBXCElementSnapshotWrapper.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBXCElementSnapshotWrapper.h" diff --git a/WebDriverAgentLib/Utilities/FBAccessibilityTraits.h b/WebDriverAgentLib/Utilities/FBAccessibilityTraits.h new file mode 100644 index 00000000..b5ffa599 --- /dev/null +++ b/WebDriverAgentLib/Utilities/FBAccessibilityTraits.h @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + Converts accessibility traits bitmask to an array of string representations + @param traits The accessibility traits bitmask + @return Array of strings representing the accessibility traits + */ +NSArray *FBAccessibilityTraitsToStringsArray(unsigned long long traits); + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBAccessibilityTraits.m b/WebDriverAgentLib/Utilities/FBAccessibilityTraits.m new file mode 100644 index 00000000..74ce9ec7 --- /dev/null +++ b/WebDriverAgentLib/Utilities/FBAccessibilityTraits.m @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FBAccessibilityTraits.h" + +NSArray *FBAccessibilityTraitsToStringsArray(unsigned long long traits) { + NSMutableArray *traitStringsArray; + NSNumber *key; + + static NSDictionary *traitsMapping; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + NSMutableDictionary *mapping = [@{ + @(UIAccessibilityTraitNone): @"None", + @(UIAccessibilityTraitButton): @"Button", + @(UIAccessibilityTraitLink): @"Link", + @(UIAccessibilityTraitHeader): @"Header", + @(UIAccessibilityTraitSearchField): @"SearchField", + @(UIAccessibilityTraitImage): @"Image", + @(UIAccessibilityTraitSelected): @"Selected", + @(UIAccessibilityTraitPlaysSound): @"PlaysSound", + @(UIAccessibilityTraitKeyboardKey): @"KeyboardKey", + @(UIAccessibilityTraitStaticText): @"StaticText", + @(UIAccessibilityTraitSummaryElement): @"SummaryElement", + @(UIAccessibilityTraitNotEnabled): @"NotEnabled", + @(UIAccessibilityTraitUpdatesFrequently): @"UpdatesFrequently", + @(UIAccessibilityTraitStartsMediaSession): @"StartsMediaSession", + @(UIAccessibilityTraitAdjustable): @"Adjustable", + @(UIAccessibilityTraitAllowsDirectInteraction): @"AllowsDirectInteraction", + @(UIAccessibilityTraitCausesPageTurn): @"CausesPageTurn", + @(UIAccessibilityTraitTabBar): @"TabBar" + } mutableCopy]; + + #if __clang_major__ >= 16 + // Add iOS 17.0 specific traits if available + if (@available(iOS 17.0, *)) { + [mapping addEntriesFromDictionary:@{ + @(UIAccessibilityTraitToggleButton): @"ToggleButton", + @(UIAccessibilityTraitSupportsZoom): @"SupportsZoom" + }]; + } + #endif + + traitsMapping = [mapping copy]; + }); + + traitStringsArray = [NSMutableArray array]; + for (key in traitsMapping) { + if (traits & [key unsignedLongLongValue] && nil != traitsMapping[key]) { + [traitStringsArray addObject:(id)traitsMapping[key]]; + } + } + + return [traitStringsArray copy]; +} diff --git a/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.h b/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.h index 6bc4887e..a65bd388 100644 --- a/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.h +++ b/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.m b/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.m index db571b58..2f05ab87 100644 --- a/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.m +++ b/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the -* LICENSE file in the root directory of this source tree. An additional grant -* of patent rights can be found in the PATENTS file in the same directory. +* LICENSE file in the root directory of this source tree. */ #import "FBActiveAppDetectionPoint.h" diff --git a/WebDriverAgentLib/Utilities/FBAlertsMonitor.h b/WebDriverAgentLib/Utilities/FBAlertsMonitor.h index 79bb6a3f..069a7347 100644 --- a/WebDriverAgentLib/Utilities/FBAlertsMonitor.h +++ b/WebDriverAgentLib/Utilities/FBAlertsMonitor.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBAlertsMonitor.m b/WebDriverAgentLib/Utilities/FBAlertsMonitor.m index 1a1b6f34..3dd22119 100644 --- a/WebDriverAgentLib/Utilities/FBAlertsMonitor.m +++ b/WebDriverAgentLib/Utilities/FBAlertsMonitor.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBAlertsMonitor.h" diff --git a/WebDriverAgentLib/Utilities/FBBaseActionsParser.m b/WebDriverAgentLib/Utilities/FBBaseActionsParser.m deleted file mode 100644 index 872dc268..00000000 --- a/WebDriverAgentLib/Utilities/FBBaseActionsParser.m +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "FBBaseActionsSynthesizer.h" - -#import "FBErrorBuilder.h" - -@implementation FBBaseActionsSynthesizer - -- (instancetype)initWithActions:(NSArray *)actions forApplication:(XCUIApplication *)application -{ - self = [super init]; - if (self) { - _actions = actions; - _application = application; - } - return self; -} - -- (nullable XCSynthesizedEventRecord *)synthesizeWithError:(NSError **)error -{ - @throw [[FBErrorBuilder.builder withDescription:@"Override this method in subclasses"] build]; - return nil; -} - -@end diff --git a/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h b/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h index 5f779194..7dc7c424 100644 --- a/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h +++ b/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBElementCache.h" diff --git a/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m b/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m index 6d4c046a..57f9d2d8 100644 --- a/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m +++ b/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBBaseActionsSynthesizer.h" diff --git a/WebDriverAgentLib/Utilities/FBCapabilities.h b/WebDriverAgentLib/Utilities/FBCapabilities.h index 1045a985..d1339c7a 100644 --- a/WebDriverAgentLib/Utilities/FBCapabilities.h +++ b/WebDriverAgentLib/Utilities/FBCapabilities.h @@ -3,15 +3,14 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import /** Whether to use alternative elements visivility detection method */ extern NSString* const FB_CAP_USE_TEST_MANAGER_FOR_VISIBLITY_DETECTION; -/** Set the maximum amount of charatcers that could be typed within a minute (60 by default) */ +/** Set the maximum amount of characters that could be typed within a minute (60 by default) */ extern NSString* const FB_CAP_MAX_TYPING_FREQUENCY; /** this setting was needed for some legacy stuff */ extern NSString* const FB_CAP_USE_SINGLETON_TEST_MANAGER; @@ -42,3 +41,5 @@ extern NSString* const FB_CAP_ENVIRNOMENT; extern NSString* const FB_CAP_USE_NATIVE_CACHING_STRATEGY; /** Whether to enforce software keyboard presence on simulator */ extern NSString* const FB_CAP_FORCE_SIMULATOR_SOFTWARE_KEYBOARD_PRESENCE; +/** Sets the application state change timeout for the initial app startup */ +extern NSString* const FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC; diff --git a/WebDriverAgentLib/Utilities/FBCapabilities.m b/WebDriverAgentLib/Utilities/FBCapabilities.m index 1798c219..351f23e6 100644 --- a/WebDriverAgentLib/Utilities/FBCapabilities.m +++ b/WebDriverAgentLib/Utilities/FBCapabilities.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBCapabilities.h" @@ -23,3 +22,4 @@ NSString* const FB_CAP_ENVIRNOMENT = @"environment"; NSString* const FB_CAP_USE_NATIVE_CACHING_STRATEGY = @"useNativeCachingStrategy"; NSString* const FB_CAP_FORCE_SIMULATOR_SOFTWARE_KEYBOARD_PRESENCE = @"forceSimulatorSoftwareKeyboardPresence"; +NSString* const FB_CAP_APP_LAUNCH_STATE_TIMEOUT_SEC = @"appLaunchStateTimeoutSec"; diff --git a/WebDriverAgentLib/Utilities/FBClassChainQueryParser.h b/WebDriverAgentLib/Utilities/FBClassChainQueryParser.h index 08081064..c2ca9c52 100644 --- a/WebDriverAgentLib/Utilities/FBClassChainQueryParser.h +++ b/WebDriverAgentLib/Utilities/FBClassChainQueryParser.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBClassChainQueryParser.m b/WebDriverAgentLib/Utilities/FBClassChainQueryParser.m index f04240d0..933d0ad8 100644 --- a/WebDriverAgentLib/Utilities/FBClassChainQueryParser.m +++ b/WebDriverAgentLib/Utilities/FBClassChainQueryParser.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBClassChainQueryParser.h" diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.h b/WebDriverAgentLib/Utilities/FBConfiguration.h index c07c31a1..e6a7d455 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.h +++ b/WebDriverAgentLib/Utilities/FBConfiguration.h @@ -3,16 +3,11 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import -#import "AXSettings.h" -#import "UIKeyboardImpl.h" -#import "TIPreferencesController.h" - NS_ASSUME_NONNULL_BEGIN extern NSString *const FBSnapshotMaxDepthKey; @@ -66,6 +61,10 @@ extern NSString *const FBSnapshotMaxDepthKey; + (void)setShouldUseSingletonTestManager:(BOOL)value; + (BOOL)shouldUseSingletonTestManager; +/* Enforces WDA to verify the presense of system alerts while checking for an active app */ ++ (void)setShouldRespectSystemAlerts:(BOOL)value; ++ (BOOL)shouldRespectSystemAlerts; + /** * Extract switch value from arguments * @@ -103,6 +102,14 @@ extern NSString *const FBSnapshotMaxDepthKey; + (NSUInteger)mjpegServerFramerate; + (void)setMjpegServerFramerate:(NSUInteger)framerate; +/** + Whether to limit the XPath scope to descendant items only while performing a lookup + in an element context. Enabled by default. Being disabled, allows to use XPath locators + like ".." in order to match parent items of the current context root. + */ ++ (BOOL)limitXpathContextScope; ++ (void)setLimitXpathContextScope:(BOOL)enabled; + /** The quality of display screenshots. The higher quality you set is the bigger screenshot size is. The highest quality value is 0 (lossless PNG) or 3 (lossless HEIC). The lowest quality is 2 (highly compressed JPEG). @@ -117,6 +124,12 @@ extern NSString *const FBSnapshotMaxDepthKey; */ + (NSRange)bindingPortRange; +/** + The IP address that the HTTP Server should bind to on launch. + Returns nil if not specified, which causes the server to listen on all interfaces. + */ ++ (NSString * _Nullable)bindingIPAddress; + /** The port number where the background screenshots broadcaster is supposed to run */ @@ -128,8 +141,8 @@ extern NSString *const FBSnapshotMaxDepthKey; ! Setting this to a value less than 100, especially together with orientation fixing enabled ! may lead to WDA process termination because of an excessive CPU usage. */ -+ (NSUInteger)mjpegScalingFactor; -+ (void)setMjpegScalingFactor:(NSUInteger)scalingFactor; ++ (CGFloat)mjpegScalingFactor; ++ (void)setMjpegScalingFactor:(CGFloat)scalingFactor; /** YES if verbose logging is enabled. NO otherwise. @@ -177,14 +190,6 @@ typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) { + (void)setKeyboardPrediction:(BOOL)isEnabled; + (FBConfigurationKeyboardPreference)keyboardPrediction; -/** - * The maximum time to wait until accessibility snapshot is taken - * - * @param timeout The number of float seconds to wait (15 seconds by default) - */ -+ (void)setCustomSnapshotTimeout:(NSTimeInterval)timeout; -+ (NSTimeInterval)customSnapshotTimeout; - /** Sets maximum depth for traversing elements tree from parents to children while requesting XCElementSnapshot. Used to set maxDepth value in a dictionary provided by XCAXClient_iOS's method defaultParams. @@ -283,6 +288,21 @@ typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) { + (void)setDismissAlertButtonSelector:(NSString *)classChainSelector; + (NSString *)dismissAlertButtonSelector; +/** + Sets class chain selector to apply for an automated alert click + */ ++ (void)setAutoClickAlertSelector:(NSString *)classChainSelector; ++ (NSString *)autoClickAlertSelector; + +/** + * Whether to use HIDEvent for text clear. + * By default this is enabled and HIDEvent is used for text clear. + * + * @param enabled Either YES or NO + */ ++ (void)setUseClearTextShortcut:(BOOL)enabled; ++ (BOOL)useClearTextShortcut; + #if !TARGET_OS_TV /** Set the screenshot orientation for iOS @@ -317,6 +337,45 @@ typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) { */ + (void)resetSessionSettings; +/** + * Whether to calculate `hittable` attribute using native APIs + * instead of legacy heuristics. + * This flag improves accuracy, but may affect performance. + * Disabled by default. + * + * @param enabled Either YES or NO + */ ++ (void)setIncludeHittableInPageSource:(BOOL)enabled; ++ (BOOL)includeHittableInPageSource; + +/** + * Whether to include `nativeFrame` attribute in the XML page source. + * + * When enabled, the XML representation will contain the precise rendered + * frame of the UI element. + * + * This value is more accurate than the legacy `wdFrame`, which applies rounding + * and may introduce inconsistencies in size and position calculations. + * + * The value is disabled by default to avoid potential performance overhead. + * + * @param enabled Either YES or NO + */ ++ (void)setIncludeNativeFrameInPageSource:(BOOL)enabled; ++ (BOOL)includeNativeFrameInPageSource; + +/** + * Whether to include `minValue`/`maxValue` attributes in the page source. + * These attributes are retrieved from native element snapshots and represent + * value boundaries for elements like sliders or progress indicators. + * This may affect performance if used on many elements. + * Disabled by default. + * + * @param enabled Either YES or NO + */ ++ (void)setIncludeMinMaxValueInPageSource:(BOOL)enabled; ++ (BOOL)includeMinMaxValueInPageSource; + @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBConfiguration.m b/WebDriverAgentLib/Utilities/FBConfiguration.m index 3bb740a0..61f9adec 100644 --- a/WebDriverAgentLib/Utilities/FBConfiguration.m +++ b/WebDriverAgentLib/Utilities/FBConfiguration.m @@ -3,12 +3,15 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBConfiguration.h" +#import "AXSettings.h" +#import "UIKeyboardImpl.h" +#import "TIPreferencesController.h" + #include #import @@ -31,8 +34,9 @@ static BOOL FBShouldUseTestManagerForVisibilityDetection = NO; static BOOL FBShouldUseSingletonTestManager = YES; +static BOOL FBShouldRespectSystemAlerts = NO; -static NSUInteger FBMjpegScalingFactor = 100; +static CGFloat FBMjpegScalingFactor = 100.0; static BOOL FBMjpegShouldFixOrientation = NO; static NSUInteger FBMjpegServerScreenshotQuality = 25; static NSUInteger FBMjpegServerFramerate = 10; @@ -41,19 +45,24 @@ static BOOL FBShouldTerminateApp; static NSNumber* FBMaxTypingFrequency; static NSUInteger FBScreenshotQuality; -static NSTimeInterval FBCustomSnapshotTimeout; static BOOL FBShouldUseFirstMatch; static BOOL FBShouldBoundElementsByIndex; static BOOL FBIncludeNonModalElements; static NSString *FBAcceptAlertButtonSelector; static NSString *FBDismissAlertButtonSelector; +static NSString *FBAutoClickAlertSelector; static NSTimeInterval FBWaitForIdleTimeout; static NSTimeInterval FBAnimationCoolOffTimeout; static BOOL FBShouldUseCompactResponses; static NSString *FBElementResponseAttributes; +static BOOL FBUseClearTextShortcut; +static BOOL FBLimitXpathContextScope = YES; #if !TARGET_OS_TV static UIInterfaceOrientation FBScreenshotOrientation; #endif +static BOOL FBShouldIncludeHittableInPageSource = NO; +static BOOL FBShouldIncludeNativeFrameInPageSource = NO; +static BOOL FBShouldIncludeMinMaxValueInPageSource = NO; @implementation FBConfiguration @@ -128,6 +137,17 @@ + (NSRange)bindingPortRange return NSMakeRange(DefaultStartingPort, DefaultPortRange); } ++ (NSString *)bindingIPAddress +{ + // Existence of USE_IP in the environment allows specifying which interface to bind to + if (NSProcessInfo.processInfo.environment[@"USE_IP"] && + [NSProcessInfo.processInfo.environment[@"USE_IP"] length] > 0) { + return NSProcessInfo.processInfo.environment[@"USE_IP"]; + } + + return nil; +} + + (NSInteger)mjpegServerPort { if (self.mjpegServerPortFromArguments != NSNotFound) { @@ -142,12 +162,12 @@ + (NSInteger)mjpegServerPort return DefaultMjpegServerPort; } -+ (NSUInteger)mjpegScalingFactor ++ (CGFloat)mjpegScalingFactor { return FBMjpegScalingFactor; } -+ (void)setMjpegScalingFactor:(NSUInteger)scalingFactor { ++ (void)setMjpegScalingFactor:(CGFloat)scalingFactor { FBMjpegScalingFactor = scalingFactor; } @@ -353,24 +373,24 @@ + (void)setKeyboardPrediction:(BOOL)isEnabled [self configureKeyboardsPreference:isEnabled forPreferenceKey:FBKeyboardPredictionKey]; } -+ (void)setCustomSnapshotTimeout:(NSTimeInterval)timeout ++ (void)setSnapshotMaxDepth:(int)maxDepth { - FBCustomSnapshotTimeout = timeout; + FBSetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey, @(maxDepth)); } -+ (NSTimeInterval)customSnapshotTimeout ++ (int)snapshotMaxDepth { - return FBCustomSnapshotTimeout; + return [FBGetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey) intValue]; } -+ (void)setSnapshotMaxDepth:(int)maxDepth ++ (void)setShouldRespectSystemAlerts:(BOOL)value { - FBSetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey, @(maxDepth)); + FBShouldRespectSystemAlerts = value; } -+ (int)snapshotMaxDepth ++ (BOOL)shouldRespectSystemAlerts { - return [FBGetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey) intValue]; + return FBShouldRespectSystemAlerts; } + (void)setUseFirstMatch:(BOOL)enabled @@ -423,6 +443,36 @@ + (NSString *)dismissAlertButtonSelector return FBDismissAlertButtonSelector; } ++ (void)setAutoClickAlertSelector:(NSString *)classChainSelector +{ + FBAutoClickAlertSelector = classChainSelector; +} + ++ (NSString *)autoClickAlertSelector +{ + return FBAutoClickAlertSelector; +} + ++ (void)setUseClearTextShortcut:(BOOL)enabled +{ + FBUseClearTextShortcut = enabled; +} + ++ (BOOL)useClearTextShortcut +{ + return FBUseClearTextShortcut; +} + ++ (BOOL)limitXpathContextScope +{ + return FBLimitXpathContextScope; +} + ++ (void)setLimitXpathContextScope:(BOOL)enabled +{ + FBLimitXpathContextScope = enabled; +} + #if !TARGET_OS_TV + (BOOL)setScreenshotOrientation:(NSString *)orientation error:(NSError **)error { @@ -476,7 +526,6 @@ + (void)resetSessionSettings FBElementResponseAttributes = @"type,label"; FBMaxTypingFrequency = @([self defaultTypingFrequency]); FBScreenshotQuality = 3; - FBCustomSnapshotTimeout = 15.; FBShouldUseFirstMatch = NO; FBShouldBoundElementsByIndex = NO; // This is diabled by default because enabling it prevents the accessbility snapshot to be taken @@ -484,10 +533,13 @@ + (void)resetSessionSettings FBIncludeNonModalElements = NO; FBAcceptAlertButtonSelector = @""; FBDismissAlertButtonSelector = @""; + FBAutoClickAlertSelector = @""; FBWaitForIdleTimeout = 10.; FBAnimationCoolOffTimeout = 2.; // 50 should be enough for the majority of the cases. The performance is acceptable for values up to 100. FBSetCustomParameterForElementSnapshot(FBSnapshotMaxDepthKey, @50); + FBUseClearTextShortcut = YES; + FBLimitXpathContextScope = YES; #if !TARGET_OS_TV FBScreenshotOrientation = UIInterfaceOrientationUnknown; #endif @@ -603,4 +655,34 @@ + (BOOL)reduceMotionEnabled return NO; } ++ (void)setIncludeHittableInPageSource:(BOOL)enabled +{ + FBShouldIncludeHittableInPageSource = enabled; +} + ++ (BOOL)includeHittableInPageSource +{ + return FBShouldIncludeHittableInPageSource; +} + ++ (void)setIncludeNativeFrameInPageSource:(BOOL)enabled +{ + FBShouldIncludeNativeFrameInPageSource = enabled; +} + ++ (BOOL)includeNativeFrameInPageSource +{ + return FBShouldIncludeNativeFrameInPageSource; +} + ++ (void)setIncludeMinMaxValueInPageSource:(BOOL)enabled +{ + FBShouldIncludeMinMaxValueInPageSource = enabled; +} + ++ (BOOL)includeMinMaxValueInPageSource +{ + return FBShouldIncludeMinMaxValueInPageSource; +} + @end diff --git a/WebDriverAgentLib/Utilities/FBDebugLogDelegateDecorator.h b/WebDriverAgentLib/Utilities/FBDebugLogDelegateDecorator.h index edc1c0fc..02ebf89d 100644 --- a/WebDriverAgentLib/Utilities/FBDebugLogDelegateDecorator.h +++ b/WebDriverAgentLib/Utilities/FBDebugLogDelegateDecorator.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBDebugLogDelegateDecorator.m b/WebDriverAgentLib/Utilities/FBDebugLogDelegateDecorator.m index 2846a181..b4c2c539 100644 --- a/WebDriverAgentLib/Utilities/FBDebugLogDelegateDecorator.m +++ b/WebDriverAgentLib/Utilities/FBDebugLogDelegateDecorator.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBDebugLogDelegateDecorator.h" diff --git a/WebDriverAgentLib/Utilities/FBElementHelpers.h b/WebDriverAgentLib/Utilities/FBElementHelpers.h new file mode 100644 index 00000000..d0cf1b3d --- /dev/null +++ b/WebDriverAgentLib/Utilities/FBElementHelpers.h @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + Checks if the element is a text field + + @param elementType XCTest element type + @return YES if the element is a text field + */ +BOOL FBDoesElementSupportInnerText(XCUIElementType elementType); + +/** + Checks if the element supports min/max value attributes + + @param elementType XCTest element type + @return YES if the element type supports min/max value attributes + */ +BOOL FBDoesElementSupportMinMaxValue(XCUIElementType elementType); + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBElementHelpers.m b/WebDriverAgentLib/Utilities/FBElementHelpers.m new file mode 100644 index 00000000..6b9d340f --- /dev/null +++ b/WebDriverAgentLib/Utilities/FBElementHelpers.m @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FBElementHelpers.h" + +BOOL FBDoesElementSupportInnerText(XCUIElementType elementType) { + return elementType == XCUIElementTypeTextView + || elementType == XCUIElementTypeTextField + || elementType == XCUIElementTypeSearchField + || elementType == XCUIElementTypeSecureTextField; +} + +BOOL FBDoesElementSupportMinMaxValue(XCUIElementType elementType) { + return elementType == XCUIElementTypeSlider + || elementType == XCUIElementTypeStepper; +} diff --git a/WebDriverAgentLib/Utilities/FBElementTypeTransformer.h b/WebDriverAgentLib/Utilities/FBElementTypeTransformer.h index b4097eee..a94ff62a 100644 --- a/WebDriverAgentLib/Utilities/FBElementTypeTransformer.h +++ b/WebDriverAgentLib/Utilities/FBElementTypeTransformer.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBElementTypeTransformer.m b/WebDriverAgentLib/Utilities/FBElementTypeTransformer.m index 7dc5b1e6..d3748a44 100644 --- a/WebDriverAgentLib/Utilities/FBElementTypeTransformer.m +++ b/WebDriverAgentLib/Utilities/FBElementTypeTransformer.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBElementTypeTransformer.h" diff --git a/WebDriverAgentLib/Utilities/FBErrorBuilder.h b/WebDriverAgentLib/Utilities/FBErrorBuilder.h index 7678daf1..8435eba9 100644 --- a/WebDriverAgentLib/Utilities/FBErrorBuilder.h +++ b/WebDriverAgentLib/Utilities/FBErrorBuilder.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBErrorBuilder.m b/WebDriverAgentLib/Utilities/FBErrorBuilder.m index cafaf503..3ee5d8fa 100644 --- a/WebDriverAgentLib/Utilities/FBErrorBuilder.m +++ b/WebDriverAgentLib/Utilities/FBErrorBuilder.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBErrorBuilder.h" diff --git a/WebDriverAgentLib/Utilities/FBFailureProofTestCase.h b/WebDriverAgentLib/Utilities/FBFailureProofTestCase.h index 5d744107..80d86483 100644 --- a/WebDriverAgentLib/Utilities/FBFailureProofTestCase.h +++ b/WebDriverAgentLib/Utilities/FBFailureProofTestCase.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBFailureProofTestCase.m b/WebDriverAgentLib/Utilities/FBFailureProofTestCase.m index 72d79ee1..ab91fd94 100644 --- a/WebDriverAgentLib/Utilities/FBFailureProofTestCase.m +++ b/WebDriverAgentLib/Utilities/FBFailureProofTestCase.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBFailureProofTestCase.h" diff --git a/WebDriverAgentLib/Utilities/FBImageProcessor.h b/WebDriverAgentLib/Utilities/FBImageProcessor.h index a350bd9c..e83b830f 100644 --- a/WebDriverAgentLib/Utilities/FBImageProcessor.h +++ b/WebDriverAgentLib/Utilities/FBImageProcessor.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBImageProcessor.m b/WebDriverAgentLib/Utilities/FBImageProcessor.m index 16601ce8..7d2ada75 100644 --- a/WebDriverAgentLib/Utilities/FBImageProcessor.m +++ b/WebDriverAgentLib/Utilities/FBImageProcessor.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBImageProcessor.h" diff --git a/WebDriverAgentLib/Utilities/FBImageUtils.h b/WebDriverAgentLib/Utilities/FBImageUtils.h index 15a04f6f..07501657 100644 --- a/WebDriverAgentLib/Utilities/FBImageUtils.h +++ b/WebDriverAgentLib/Utilities/FBImageUtils.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBImageUtils.m b/WebDriverAgentLib/Utilities/FBImageUtils.m index b1d2f9b5..d991cea1 100644 --- a/WebDriverAgentLib/Utilities/FBImageUtils.m +++ b/WebDriverAgentLib/Utilities/FBImageUtils.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBImageUtils.h" diff --git a/WebDriverAgentLib/Utilities/FBKeyboard.h b/WebDriverAgentLib/Utilities/FBKeyboard.h index fa1515e6..c3c5f8ec 100644 --- a/WebDriverAgentLib/Utilities/FBKeyboard.h +++ b/WebDriverAgentLib/Utilities/FBKeyboard.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBKeyboard.m b/WebDriverAgentLib/Utilities/FBKeyboard.m index d90a68e2..af3529eb 100644 --- a/WebDriverAgentLib/Utilities/FBKeyboard.m +++ b/WebDriverAgentLib/Utilities/FBKeyboard.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBKeyboard.h" diff --git a/WebDriverAgentLib/Utilities/FBLogger.h b/WebDriverAgentLib/Utilities/FBLogger.h index 3626fa52..c92b7ef7 100644 --- a/WebDriverAgentLib/Utilities/FBLogger.h +++ b/WebDriverAgentLib/Utilities/FBLogger.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBLogger.m b/WebDriverAgentLib/Utilities/FBLogger.m index 9466b86c..060b8f00 100644 --- a/WebDriverAgentLib/Utilities/FBLogger.m +++ b/WebDriverAgentLib/Utilities/FBLogger.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBLogger.h" diff --git a/WebDriverAgentLib/Utilities/FBMacros.h b/WebDriverAgentLib/Utilities/FBMacros.h index dae0c5fa..ba77c2b5 100644 --- a/WebDriverAgentLib/Utilities/FBMacros.h +++ b/WebDriverAgentLib/Utilities/FBMacros.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ // Typedef to help with storing constant strings for enums. diff --git a/WebDriverAgentLib/Utilities/FBMathUtils.h b/WebDriverAgentLib/Utilities/FBMathUtils.h index 2d52d3e6..2dbce05a 100644 --- a/WebDriverAgentLib/Utilities/FBMathUtils.h +++ b/WebDriverAgentLib/Utilities/FBMathUtils.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBMathUtils.m b/WebDriverAgentLib/Utilities/FBMathUtils.m index 44ee257d..87a7ecf6 100644 --- a/WebDriverAgentLib/Utilities/FBMathUtils.m +++ b/WebDriverAgentLib/Utilities/FBMathUtils.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBMathUtils.h" diff --git a/WebDriverAgentLib/Utilities/FBMjpegServer.h b/WebDriverAgentLib/Utilities/FBMjpegServer.h index 6ab15a30..294c399f 100644 --- a/WebDriverAgentLib/Utilities/FBMjpegServer.h +++ b/WebDriverAgentLib/Utilities/FBMjpegServer.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBTCPSocket.h" diff --git a/WebDriverAgentLib/Utilities/FBMjpegServer.m b/WebDriverAgentLib/Utilities/FBMjpegServer.m index 691e5774..4c786ba0 100644 --- a/WebDriverAgentLib/Utilities/FBMjpegServer.m +++ b/WebDriverAgentLib/Utilities/FBMjpegServer.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBMjpegServer.h" diff --git a/WebDriverAgentLib/Utilities/FBNotificationsHelper.h b/WebDriverAgentLib/Utilities/FBNotificationsHelper.h index b0ca35b3..b337cb11 100644 --- a/WebDriverAgentLib/Utilities/FBNotificationsHelper.h +++ b/WebDriverAgentLib/Utilities/FBNotificationsHelper.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBNotificationsHelper.m b/WebDriverAgentLib/Utilities/FBNotificationsHelper.m index 60cc509d..45704788 100644 --- a/WebDriverAgentLib/Utilities/FBNotificationsHelper.m +++ b/WebDriverAgentLib/Utilities/FBNotificationsHelper.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBNotificationsHelper.h" diff --git a/WebDriverAgentLib/Utilities/FBPasteboard.h b/WebDriverAgentLib/Utilities/FBPasteboard.h index 9595162d..f61d7d64 100644 --- a/WebDriverAgentLib/Utilities/FBPasteboard.h +++ b/WebDriverAgentLib/Utilities/FBPasteboard.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBPasteboard.m b/WebDriverAgentLib/Utilities/FBPasteboard.m index 0171b259..08e4e9f3 100644 --- a/WebDriverAgentLib/Utilities/FBPasteboard.m +++ b/WebDriverAgentLib/Utilities/FBPasteboard.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBPasteboard.h" diff --git a/WebDriverAgentLib/Utilities/FBProtocolHelpers.h b/WebDriverAgentLib/Utilities/FBProtocolHelpers.h index eff0a518..e25573e7 100644 --- a/WebDriverAgentLib/Utilities/FBProtocolHelpers.h +++ b/WebDriverAgentLib/Utilities/FBProtocolHelpers.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBProtocolHelpers.m b/WebDriverAgentLib/Utilities/FBProtocolHelpers.m index 3cd03758..a463294a 100644 --- a/WebDriverAgentLib/Utilities/FBProtocolHelpers.m +++ b/WebDriverAgentLib/Utilities/FBProtocolHelpers.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBProtocolHelpers.h" diff --git a/WebDriverAgentLib/Utilities/FBReflectionUtils.h b/WebDriverAgentLib/Utilities/FBReflectionUtils.h index 0e4cca31..262702a0 100644 --- a/WebDriverAgentLib/Utilities/FBReflectionUtils.h +++ b/WebDriverAgentLib/Utilities/FBReflectionUtils.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBReflectionUtils.m b/WebDriverAgentLib/Utilities/FBReflectionUtils.m index 9114c312..8ef8419f 100644 --- a/WebDriverAgentLib/Utilities/FBReflectionUtils.m +++ b/WebDriverAgentLib/Utilities/FBReflectionUtils.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBReflectionUtils.h" diff --git a/WebDriverAgentLib/Utilities/FBRunLoopSpinner.h b/WebDriverAgentLib/Utilities/FBRunLoopSpinner.h index bc6b543c..5f8faf52 100644 --- a/WebDriverAgentLib/Utilities/FBRunLoopSpinner.h +++ b/WebDriverAgentLib/Utilities/FBRunLoopSpinner.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBRunLoopSpinner.m b/WebDriverAgentLib/Utilities/FBRunLoopSpinner.m index 38623873..09123254 100644 --- a/WebDriverAgentLib/Utilities/FBRunLoopSpinner.m +++ b/WebDriverAgentLib/Utilities/FBRunLoopSpinner.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBRunLoopSpinner.h" diff --git a/WebDriverAgentLib/Utilities/FBRuntimeUtils.h b/WebDriverAgentLib/Utilities/FBRuntimeUtils.h index 8e54ed4c..b16b123a 100644 --- a/WebDriverAgentLib/Utilities/FBRuntimeUtils.h +++ b/WebDriverAgentLib/Utilities/FBRuntimeUtils.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBRuntimeUtils.m b/WebDriverAgentLib/Utilities/FBRuntimeUtils.m index bb08de7e..6904cf76 100644 --- a/WebDriverAgentLib/Utilities/FBRuntimeUtils.m +++ b/WebDriverAgentLib/Utilities/FBRuntimeUtils.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBRuntimeUtils.h" diff --git a/WebDriverAgentLib/Utilities/FBScreen.h b/WebDriverAgentLib/Utilities/FBScreen.h index 61dc4aeb..87c22c7c 100644 --- a/WebDriverAgentLib/Utilities/FBScreen.h +++ b/WebDriverAgentLib/Utilities/FBScreen.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -18,11 +17,6 @@ NS_ASSUME_NONNULL_BEGIN */ + (double)scale; -/** - The absolute size of application's status bar or CGSizeZero if it's hidden or does not exist - */ -+ (CGSize)statusBarSizeForApplication:(XCUIApplication *)application; - @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBScreen.m b/WebDriverAgentLib/Utilities/FBScreen.m index 8ebe080d..dc653640 100644 --- a/WebDriverAgentLib/Utilities/FBScreen.m +++ b/WebDriverAgentLib/Utilities/FBScreen.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBScreen.h" @@ -19,17 +18,4 @@ + (double)scale return [XCUIScreen.mainScreen scale]; } -+ (CGSize)statusBarSizeForApplication:(XCUIApplication *)application -{ - XCUIApplication *app = XCUIApplication.fb_systemApplication; - // Since iOS 13 the status bar is no longer part of the application, it’s part of the SpringBoard - XCUIElement *mainStatusBar = app.statusBars.allElementsBoundByIndex.firstObject; - if (nil == mainStatusBar) { - return CGSizeZero; - } - CGSize result = mainStatusBar.frame.size; - // Workaround for https://github.com/appium/appium/issues/15961 - return CGSizeMake(MAX(result.width, result.height), MIN(result.width, result.height)); -} - @end diff --git a/WebDriverAgentLib/Utilities/FBScreenshot.h b/WebDriverAgentLib/Utilities/FBScreenshot.h index 74e6b588..b0fdfbe7 100644 --- a/WebDriverAgentLib/Utilities/FBScreenshot.h +++ b/WebDriverAgentLib/Utilities/FBScreenshot.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBScreenshot.m b/WebDriverAgentLib/Utilities/FBScreenshot.m index 3d9716de..f13f9673 100644 --- a/WebDriverAgentLib/Utilities/FBScreenshot.m +++ b/WebDriverAgentLib/Utilities/FBScreenshot.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBScreenshot.h" @@ -28,7 +27,7 @@ NSString *formatTimeInterval(NSTimeInterval interval) { NSUInteger milliseconds = (NSUInteger)(interval * 1000); - return [NSString stringWithFormat:@"%ld ms", milliseconds]; + return [NSString stringWithFormat:@"%lu ms", milliseconds]; } @implementation FBScreenshot diff --git a/WebDriverAgentLib/Utilities/FBSettings.h b/WebDriverAgentLib/Utilities/FBSettings.h index dd82d740..b98a070b 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.h +++ b/WebDriverAgentLib/Utilities/FBSettings.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -22,9 +21,6 @@ extern NSString* const FB_SETTING_MJPEG_SCALING_FACTOR; extern NSString* const FB_SETTING_SCREENSHOT_QUALITY; extern NSString* const FB_SETTING_KEYBOARD_AUTOCORRECTION; extern NSString* const FB_SETTING_KEYBOARD_PREDICTION; -// This setting is deprecated. Please use CUSTOM_SNAPSHOT_TIMEOUT instead -extern NSString* const FB_SETTING_SNAPSHOT_TIMEOUT; -extern NSString* const FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT; extern NSString* const FB_SETTING_SNAPSHOT_MAX_DEPTH; extern NSString* const FB_SETTING_USE_FIRST_MATCH; extern NSString* const FB_SETTING_BOUND_ELEMENTS_BY_INDEX; @@ -38,6 +34,13 @@ extern NSString* const FB_SETTING_DISMISS_ALERT_BUTTON_SELECTOR; extern NSString* const FB_SETTING_SCREENSHOT_ORIENTATION; extern NSString* const FB_SETTING_WAIT_FOR_IDLE_TIMEOUT; extern NSString* const FB_SETTING_ANIMATION_COOL_OFF_TIMEOUT; - +extern NSString* const FB_SETTING_MAX_TYPING_FREQUENCY; +extern NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS; +extern NSString* const FB_SETTING_USE_CLEAR_TEXT_SHORTCUT; +extern NSString* const FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE; +extern NSString* const FB_SETTING_AUTO_CLICK_ALERT_SELECTOR; +extern NSString *const FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE; +extern NSString *const FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE; +extern NSString *const FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE; NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBSettings.m b/WebDriverAgentLib/Utilities/FBSettings.m index 6b12a4cd..17b8ab79 100644 --- a/WebDriverAgentLib/Utilities/FBSettings.m +++ b/WebDriverAgentLib/Utilities/FBSettings.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBSettings.h" @@ -18,8 +17,6 @@ NSString* const FB_SETTING_SCREENSHOT_QUALITY = @"screenshotQuality"; NSString* const FB_SETTING_KEYBOARD_AUTOCORRECTION = @"keyboardAutocorrection"; NSString* const FB_SETTING_KEYBOARD_PREDICTION = @"keyboardPrediction"; -NSString* const FB_SETTING_SNAPSHOT_TIMEOUT = @"snapshotTimeout"; -NSString* const FB_SETTING_CUSTOM_SNAPSHOT_TIMEOUT = @"customSnapshotTimeout"; NSString* const FB_SETTING_SNAPSHOT_MAX_DEPTH = @"snapshotMaxDepth"; NSString* const FB_SETTING_USE_FIRST_MATCH = @"useFirstMatch"; NSString* const FB_SETTING_BOUND_ELEMENTS_BY_INDEX = @"boundElementsByIndex"; @@ -33,3 +30,11 @@ NSString* const FB_SETTING_SCREENSHOT_ORIENTATION = @"screenshotOrientation"; NSString* const FB_SETTING_WAIT_FOR_IDLE_TIMEOUT = @"waitForIdleTimeout"; NSString* const FB_SETTING_ANIMATION_COOL_OFF_TIMEOUT = @"animationCoolOffTimeout"; +NSString* const FB_SETTING_MAX_TYPING_FREQUENCY = @"maxTypingFrequency"; +NSString* const FB_SETTING_RESPECT_SYSTEM_ALERTS = @"respectSystemAlerts"; +NSString* const FB_SETTING_USE_CLEAR_TEXT_SHORTCUT = @"useClearTextShortcut"; +NSString* const FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE = @"limitXPathContextScope"; +NSString* const FB_SETTING_AUTO_CLICK_ALERT_SELECTOR = @"autoClickAlertSelector"; +NSString* const FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE = @"includeHittableInPageSource"; +NSString* const FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE = @"includeNativeFrameInPageSource"; +NSString* const FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE = @"includeMinMaxValueInPageSource"; diff --git a/WebDriverAgentLib/Utilities/FBTVNavigationTracker-Private.h b/WebDriverAgentLib/Utilities/FBTVNavigationTracker-Private.h index 2496ccbd..8b7f775d 100644 --- a/WebDriverAgentLib/Utilities/FBTVNavigationTracker-Private.h +++ b/WebDriverAgentLib/Utilities/FBTVNavigationTracker-Private.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBTVNavigationTracker.h b/WebDriverAgentLib/Utilities/FBTVNavigationTracker.h index 9e539f9e..3a80583b 100644 --- a/WebDriverAgentLib/Utilities/FBTVNavigationTracker.h +++ b/WebDriverAgentLib/Utilities/FBTVNavigationTracker.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m b/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m index 11becfa7..19fa4a0b 100644 --- a/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m +++ b/WebDriverAgentLib/Utilities/FBTVNavigationTracker.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBTVNavigationTracker.h" @@ -57,9 +56,7 @@ - (instancetype)initWithTargetElement:(XCUIElement *)targetElement self = [super init]; if (self) { _targetElement = targetElement; - CGRect frame = targetElement.fb_isResolvedFromCache.boolValue - ? [FBXCElementSnapshotWrapper ensureWrapped:targetElement.lastSnapshot].wdFrame - : targetElement.wdFrame; + CGRect frame = targetElement.wdFrame; _targetCenter = FBRectGetCenter(frame); _navigationItems = [NSMutableDictionary dictionary]; } diff --git a/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.h b/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.h index eabf476f..f640405b 100644 --- a/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.h +++ b/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.m b/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.m index f877b67c..a8679a87 100644 --- a/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.m +++ b/WebDriverAgentLib/Utilities/FBUnattachedAppLauncher.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBUnattachedAppLauncher.h" diff --git a/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.h b/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.h index afd8249f..3add9b1b 100644 --- a/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.h +++ b/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the -* LICENSE file in the root directory of this source tree. An additional grant -* of patent rights can be found in the PATENTS file in the same directory. +* LICENSE file in the root directory of this source tree. */ #import @@ -30,19 +29,14 @@ NSString *_Nullable FBRequireValue(NSDictionary *actionItem, NSE */ NSNumber *_Nullable FBOptDuration(NSDictionary *actionItem, NSNumber *_Nullable defaultValue, NSError **error); -/** - * Checks whether the given key action value is a W3C meta modifier - * @param value key action value - * @returns YES if the value is a meta modifier - */ -BOOL FBIsMetaModifier(NSString *value); - /** * Maps W3C meta modifier to XCUITest compatible-one + * See https://w3c.github.io/webdriver/#keyboard-actions * * @param value key action value - * @returns the mapped modifier value or 0 in case of failure + * @returns the mapped modifier value or the same input character + * if no mapped value could be found for it. */ -NSUInteger FBToMetaModifier(NSString *value); +NSString * FBMapIfSpecialCharacter(NSString *value); NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.m b/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.m index bcbf5a78..f7a052d4 100644 --- a/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.m +++ b/WebDriverAgentLib/Utilities/FBW3CActionsHelpers.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the -* LICENSE file in the root directory of this source tree. An additional grant -* of patent rights can be found in the PATENTS file in the same directory. +* LICENSE file in the root directory of this source tree. */ #import "FBW3CActionsHelpers.h" @@ -53,32 +52,68 @@ return durationObj; } -BOOL FBIsMetaModifier(NSString *value) +NSString *FBMapIfSpecialCharacter(NSString *value) { - unichar charCode = [value characterAtIndex:0]; - return charCode >= 0xE000 && charCode <= 0xF8FF; -} - -NSUInteger FBToMetaModifier(NSString *value) -{ - if (!FBIsMetaModifier(value)) { - return 0; + if (0 == [value length]) { + return value; } unichar charCode = [value characterAtIndex:0]; switch (charCode) { case 0xE000: - return XCUIKeyModifierNone; - case 0xE03D: - return XCUIKeyModifierCommand; - case 0xE009: - return XCUIKeyModifierControl; - case 0xE00A: - return XCUIKeyModifierOption; - case 0xE008: - return XCUIKeyModifierShift; + return @""; + case 0xE003: + return [NSString stringWithFormat:@"%C", 0x0008]; + case 0xE004: + return [NSString stringWithFormat:@"%C", 0x0009]; + case 0xE006: + return [NSString stringWithFormat:@"%C", 0x000D]; + case 0xE007: + return [NSString stringWithFormat:@"%C", 0x000A]; + case 0xE00C: + return [NSString stringWithFormat:@"%C", 0x001B]; + case 0xE00D: + case 0xE05D: + return @" "; + case 0xE017: + return [NSString stringWithFormat:@"%C", 0x007F]; + case 0xE018: + return @";"; + case 0xE019: + return @"="; + case 0xE01A: + return @"0"; + case 0xE01B: + return @"1"; + case 0xE01C: + return @"2"; + case 0xE01D: + return @"3"; + case 0xE01E: + return @"4"; + case 0xE01F: + return @"5"; + case 0xE020: + return @"6"; + case 0xE021: + return @"7"; + case 0xE022: + return @"8"; + case 0xE023: + return @"9"; + case 0xE024: + return @"*"; + case 0xE025: + return @"+"; + case 0xE026: + return @","; + case 0xE027: + return @"-"; + case 0xE028: + return @"."; + case 0xE029: + return @"/"; default: - [FBLogger logFmt:@"Skipping the unsupported meta modifier with code %@", @(charCode)]; - return 0; + return charCode >= 0xE000 && charCode <= 0xE05D ? @"" : value; } } diff --git a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.h b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.h index e5ed479a..746c38e3 100644 --- a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.h +++ b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBBaseActionsSynthesizer.h" diff --git a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m index dc506056..ef17e035 100644 --- a/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +++ b/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBW3CActionsSynthesizer.h" @@ -410,17 +409,12 @@ - (BOOL)hasDownPairInItems:(NSArray *)allItems currentItemIndex:(NSUInteger)currentItemIndex { NSInteger balance = 1; - BOOL isSelfMetaModifier = FBIsMetaModifier(self.value); for (NSInteger index = currentItemIndex - 1; index >= 0; index--) { FBW3CKeyItem *item = [allItems objectAtIndex:index]; BOOL isKeyDown = [item isKindOfClass:FBKeyDownItem.class]; BOOL isKeyUp = !isKeyDown && [item isKindOfClass:FBKeyUpItem.class]; if (!isKeyUp && !isKeyDown) { - if (isSelfMetaModifier) { - continue; - } else { - break; - } + break; } NSString *value = [item performSelector:@selector(value)]; @@ -434,32 +428,6 @@ - (BOOL)hasDownPairInItems:(NSArray *)allItems return 0 == balance; } -- (NSUInteger)collectModifersWithItems:(NSArray *)allItems - currentItemIndex:(NSUInteger)currentItemIndex -{ - NSUInteger modifiers = 0; - for (NSUInteger index = 0; index < currentItemIndex; index++) { - FBW3CKeyItem *item = [allItems objectAtIndex:index]; - BOOL isKeyDown = [item isKindOfClass:FBKeyDownItem.class]; - BOOL isKeyUp = !isKeyDown && [item isKindOfClass:FBKeyUpItem.class]; - if (!isKeyUp && !isKeyDown) { - continue; - } - - NSString *value = [item performSelector:@selector(value)]; - NSUInteger modifier = FBToMetaModifier(value); - if (modifier > 0) { - if (isKeyDown) { - modifiers |= modifier; - } else if (item.offset < self.offset) { - // only cancel the modifier if it is not in the same group - modifiers &= ~modifier; - } - } - } - return modifiers; -} - - (NSString *)collectTextWithItems:(NSArray *)allItems currentItemIndex:(NSUInteger)currentItemIndex { @@ -473,12 +441,8 @@ - (NSString *)collectTextWithItems:(NSArray *)allItems } NSString *value = [item performSelector:@selector(value)]; - if (FBIsMetaModifier(value)) { - continue; - } - if (isKeyUp) { - [result addObject:value]; + [result addObject:FBMapIfSpecialCharacter(value)]; } } return [result.reverseObjectEnumerator.allObjects componentsJoinedByString:@""]; @@ -497,10 +461,6 @@ - (NSString *)collectTextWithItems:(NSArray *)allItems return nil; } - if (FBIsMetaModifier(self.value)) { - return @[]; - } - BOOL isLastKeyUpInGroup = currentItemIndex == allItems.count - 1 || [[allItems objectAtIndex:currentItemIndex + 1] isKindOfClass:FBKeyPauseItem.class]; if (!isLastKeyUpInGroup) { @@ -510,10 +470,6 @@ - (NSString *)collectTextWithItems:(NSArray *)allItems NSString *text = [self collectTextWithItems:allItems currentItemIndex:currentItemIndex]; NSTimeInterval offset = FBMillisToSeconds(self.offset); XCPointerEventPath *resultPath = [[XCPointerEventPath alloc] initForTextInput]; - // TODO: Figure out how meta modifiers could be applied - // TODO: The current approach throws zero division error on execution - // NSUInteger modifiers = [self collectModifersWithItems:allItems currentItemIndex:currentItemIndex]; - // [resultPath setModifiers:modifiers mergeWithCurrentModifierFlags:NO atOffset:0]; [resultPath typeText:text atOffset:offset typingSpeed:FBConfiguration.maxTypingFrequency @@ -555,17 +511,12 @@ - (BOOL)hasUpPairInItems:(NSArray *)allItems currentItemIndex:(NSUInteger)currentItemIndex { NSInteger balance = 1; - BOOL isSelfMetaModifier = FBIsMetaModifier(self.value); for (NSUInteger index = currentItemIndex + 1; index < allItems.count; index++) { FBW3CKeyItem *item = [allItems objectAtIndex:index]; BOOL isKeyDown = [item isKindOfClass:FBKeyDownItem.class]; BOOL isKeyUp = !isKeyDown && [item isKindOfClass:FBKeyUpItem.class]; if (!isKeyUp && !isKeyDown) { - if (isSelfMetaModifier) { - continue; - } else { - break; - } + break; } NSString *value = [item performSelector:@selector(value)]; @@ -709,7 +660,7 @@ @implementation FBW3CActionsSynthesizer if ([origin isKindOfClass:XCUIElement.class]) { instance = origin; } else if ([origin isKindOfClass:NSString.class]) { - instance = [self.elementCache elementForUUID:(NSString *)origin]; + instance = [self.elementCache elementForUUID:(NSString *)origin checkStaleness:YES]; } else { [result addObject:actionItem]; continue; @@ -819,7 +770,7 @@ @implementation FBW3CActionsSynthesizer NSArray *> *actionItems = [actionDescription objectForKey:FB_KEY_ACTIONS]; if (nil == actionItems || 0 == actionItems.count) { - NSString *description = [NSString stringWithFormat:@"It is mandatory to have at least one gesture item defined for each action. Action with id '%@' contains none", actionId]; + NSString *description = [NSString stringWithFormat:@"It is mandatory to have at least one gesture item defined for each action. Action with id '%@' contains none", actionId]; if (error) { *error = [[FBErrorBuilder.builder withDescription:description] build]; } @@ -900,7 +851,20 @@ - (nullable XCSynthesizedEventRecord *)synthesizeWithError:(NSError **)error *error = [[FBErrorBuilder.builder withDescription:description] build]; } return nil; + } + NSArray *> *actionItems = [action objectForKey:FB_KEY_ACTIONS]; + if (nil == actionItems) { + NSString *description = [NSString stringWithFormat:@"It is mandatory to have at least one item defined for each action. Action with id '%@' contains none", actionId]; + if (error) { + *error = [[FBErrorBuilder.builder withDescription:description] build]; + } + return nil; } + if (0 == actionItems.count) { + [FBLogger logFmt:@"Action items in the action id '%@' had an empty array. Skipping the action.", actionId]; + continue; + } + [actionIds addObject:actionId]; [actionsMapping setObject:action forKey:actionId]; } diff --git a/WebDriverAgentLib/Utilities/FBWebServerParams.h b/WebDriverAgentLib/Utilities/FBWebServerParams.h new file mode 100644 index 00000000..aba0fa34 --- /dev/null +++ b/WebDriverAgentLib/Utilities/FBWebServerParams.h @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FBWebServerParams : NSObject + +/** The local port number WDA server is running on */ +@property (nonatomic, nullable) NSNumber *port; + ++ (id)sharedInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/FBWebServerParams.m b/WebDriverAgentLib/Utilities/FBWebServerParams.m new file mode 100644 index 00000000..9ced0a38 --- /dev/null +++ b/WebDriverAgentLib/Utilities/FBWebServerParams.m @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FBWebServerParams.h" + +@implementation FBWebServerParams + ++ (instancetype)sharedInstance +{ + static FBWebServerParams *instance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + }); + return instance; +} + +@end diff --git a/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h b/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h index cf6f497a..b216e303 100644 --- a/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h +++ b/WebDriverAgentLib/Utilities/FBXCAXClientProxy.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -27,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN - (nullable id)snapshotForElement:(id)element attributes:(nullable NSArray *)attributes - maxDepth:(nullable NSNumber *)maxDepth + inDepth:(BOOL)inDepth error:(NSError **)error; - (NSArray> *)activeApplications; @@ -39,10 +38,11 @@ NS_ASSUME_NONNULL_BEGIN - (void)notifyWhenNoAnimationsAreActiveForApplication:(XCUIApplication *)application reply:(void (^)(void))reply; -- (NSDictionary *)attributesForElement:(id)element - attributes:(NSArray *)attributes; +- (nullable NSDictionary *)attributesForElement:(id)element + attributes:(NSArray *)attributes + error:(NSError**)error; -- (XCUIApplication *)monitoredApplicationWithProcessIdentifier:(int)pid; +- (nullable XCUIApplication *)monitoredApplicationWithProcessIdentifier:(int)pid; @end diff --git a/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m b/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m index 907bb25b..f84f803f 100644 --- a/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m +++ b/WebDriverAgentLib/Utilities/FBXCAXClientProxy.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBXCAXClientProxy.h" @@ -14,9 +13,16 @@ #import "FBMacros.h" #import "XCAXClient_iOS+FBSnapshotReqParams.h" #import "XCUIDevice.h" +#import "XCUIApplication.h" static id FBAXClient = nil; +@interface FBXCAXClientProxy () + +@property (nonatomic) NSMutableDictionary *appsCache; + +@end + @implementation FBXCAXClientProxy + (instancetype)sharedClient @@ -25,6 +31,7 @@ + (instancetype)sharedClient static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; + instance.appsCache = [NSMutableDictionary dictionary]; FBAXClient = [XCUIDevice.sharedDevice accessibilityInterface]; }); return instance; @@ -37,12 +44,12 @@ - (BOOL)setAXTimeout:(NSTimeInterval)timeout error:(NSError **)error - (id)snapshotForElement:(id)element attributes:(NSArray *)attributes - maxDepth:(nullable NSNumber *)maxDepth + inDepth:(BOOL)inDepth error:(NSError **)error { NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithDictionary:self.defaultParameters]; - if (nil != maxDepth) { - parameters[FBSnapshotMaxDepthKey] = maxDepth; + if (!inDepth) { + parameters[FBSnapshotMaxDepthKey] = @1; } id result = [FBAXClient requestSnapshotForElement:element @@ -76,20 +83,37 @@ - (void)notifyWhenNoAnimationsAreActiveForApplication:(XCUIApplication *)applica - (NSDictionary *)attributesForElement:(id)element attributes:(NSArray *)attributes + error:(NSError**)error; { - NSError *error = nil; - NSDictionary* result = [FBAXClient attributesForElement:element - attributes:attributes - error:&error]; - if (error) { - [FBLogger logFmt:@"Cannot retrieve element attribute(s) %@. Original error: %@", attributes, error.description]; - } - return result; + return [FBAXClient attributesForElement:element + attributes:attributes + error:error]; } - (XCUIApplication *)monitoredApplicationWithProcessIdentifier:(int)pid { - return [[FBAXClient applicationProcessTracker] monitoredApplicationWithProcessIdentifier:pid]; + NSMutableSet *terminatedAppIds = [NSMutableSet set]; + for (NSNumber *appPid in self.appsCache) { + if (![self.appsCache[appPid] running]) { + [terminatedAppIds addObject:appPid]; + } + } + for (NSNumber *appPid in terminatedAppIds) { + [self.appsCache removeObjectForKey:appPid]; + } + + XCUIApplication *result = [self.appsCache objectForKey:@(pid)]; + if (nil != result) { + return result; + } + + XCUIApplication *app = [[FBAXClient applicationProcessTracker] + monitoredApplicationWithProcessIdentifier:pid]; + if (nil == app) { + return nil; + } + [self.appsCache setObject:app forKey:@(pid)]; + return app; } @end diff --git a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h index 18761248..41514a5c 100644 --- a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h +++ b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m index f71e1bd3..e29b94e9 100644 --- a/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m +++ b/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBXCTestDaemonsProxy.h" @@ -73,9 +72,12 @@ + (void)swizzleLaunchApp { [FBLogger log:@"Could not find method -[XCTRunnerDaemonSession launchApplicationWithPath:]"]; return; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-function-type-strict" // Workaround for https://github.com/appium/WebDriverAgent/issues/702 originalLaunchAppMethod = (void(*)(id, SEL, NSString*, NSString*, NSArray*, NSDictionary*, void (^)(_Bool, NSError *))) method_getImplementation(original); method_setImplementation(original, (IMP)swizzledLaunchApp); +#pragma clang diagnostic pop } + (id)testRunnerProxy diff --git a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h index 0a7dd9a0..75d1ee20 100644 --- a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h +++ b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.h @@ -3,13 +3,14 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import #import "XCPointerEvent.h" +@class FBXCElementSnapshot; + /** The version of testmanagerd process which is running on the device. @@ -46,7 +47,7 @@ NS_ASSUME_NONNULL_BEGIN @param error The error instance if there was a failure while retrieveing the snapshot @returns The cached unqiue snapshot or nil if the element is stale */ -- (nullable XCElementSnapshot *)fb_uniqueSnapshotWithError:(NSError **)error; +- (nullable id)fb_uniqueSnapshotWithError:(NSError **)error; @end diff --git a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m index b13a79e5..f2cf03a2 100644 --- a/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m +++ b/WebDriverAgentLib/Utilities/FBXCodeCompatibility.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBXCodeCompatibility.h" @@ -20,9 +19,9 @@ @implementation XCUIElementQuery (FBCompatibility) -- (XCElementSnapshot *)fb_uniqueSnapshotWithError:(NSError **)error +- (id)fb_uniqueSnapshotWithError:(NSError **)error { - return [self uniqueMatchingSnapshotWithError:error]; + return (id)[self uniqueMatchingSnapshotWithError:error]; } - (XCUIElement *)fb_firstMatch diff --git a/WebDriverAgentLib/Utilities/FBXMLGenerationOptions.h b/WebDriverAgentLib/Utilities/FBXMLGenerationOptions.h index 0fd71e13..8a014c12 100644 --- a/WebDriverAgentLib/Utilities/FBXMLGenerationOptions.h +++ b/WebDriverAgentLib/Utilities/FBXMLGenerationOptions.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/FBXMLGenerationOptions.m b/WebDriverAgentLib/Utilities/FBXMLGenerationOptions.m index 23bfa589..40dcebd2 100644 --- a/WebDriverAgentLib/Utilities/FBXMLGenerationOptions.m +++ b/WebDriverAgentLib/Utilities/FBXMLGenerationOptions.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBXMLGenerationOptions.h" diff --git a/WebDriverAgentLib/Utilities/FBXPath-Private.h b/WebDriverAgentLib/Utilities/FBXPath-Private.h index 31bb403b..db9732c4 100644 --- a/WebDriverAgentLib/Utilities/FBXPath-Private.h +++ b/WebDriverAgentLib/Utilities/FBXPath-Private.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -25,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN If `query` argument is assigned then `excludedAttributes` argument is effectively ignored. @return zero if the method has completed successfully */ -+ (int)xmlRepresentationWithRootElement:(id)root ++ (int)xmlRepresentationWithRootElement:(id)root writer:(xmlTextWriterPtr)writer elementStore:(nullable NSMutableDictionary *)elementStore query:(nullable NSString*)query @@ -45,9 +44,12 @@ NS_ASSUME_NONNULL_BEGIN @param xpathQuery actual query. Should be valid XPath 1.0-compatible expression @param document libxml2-compatible document pointer + @param contextNode Optonal context node instance @return pointer to a libxml2-compatible structure with set of matched nodes or NULL in case of failure */ -+ (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery document:(xmlDocPtr)doc; ++ (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery + document:(xmlDocPtr)doc + contextNode:(nullable xmlNodePtr)contextNode; @end diff --git a/WebDriverAgentLib/Utilities/FBXPath.h b/WebDriverAgentLib/Utilities/FBXPath.h index 50c85197..1135c722 100644 --- a/WebDriverAgentLib/Utilities/FBXPath.h +++ b/WebDriverAgentLib/Utilities/FBXPath.h @@ -3,13 +3,12 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import #import -#import "FBXCElementSnapshot.h" +#import #ifdef __clang__ #pragma clang diagnostic push diff --git a/WebDriverAgentLib/Utilities/FBXPath.m b/WebDriverAgentLib/Utilities/FBXPath.m index eae3ee43..79e8f75f 100644 --- a/WebDriverAgentLib/Utilities/FBXPath.m +++ b/WebDriverAgentLib/Utilities/FBXPath.m @@ -3,24 +3,28 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBXPath.h" #import "FBConfiguration.h" #import "FBExceptions.h" +#import "FBElementUtils.h" #import "FBLogger.h" #import "FBMacros.h" #import "FBXMLGenerationOptions.h" #import "FBXCElementSnapshotWrapper+Helpers.h" #import "NSString+FBXMLSafeString.h" +#import "XCUIApplication.h" #import "XCUIElement.h" #import "XCUIElement+FBCaching.h" #import "XCUIElement+FBUtilities.h" #import "XCUIElement+FBWebDriverAttributes.h" #import "XCTestPrivateSymbols.h" +#import "FBElementHelpers.h" +#import "FBXCAXClientProxy.h" +#import "FBXCAccessibilityElement.h" @interface FBElementAttribute : NSObject @@ -31,6 +35,7 @@ + (nonnull NSString *)name; + (nullable NSString *)valueForElement:(id)element; + (int)recordWithWriter:(xmlTextWriterPtr)writer forElement:(id)element; ++ (int)recordWithWriter:(xmlTextWriterPtr)writer forValue:(nullable NSString *)value; + (NSArray *)supportedAttributes; @@ -96,7 +101,33 @@ @interface FBInternalIndexAttribute : FBElementAttribute @property (nonatomic, nonnull, readonly) NSString* indexValue; -+ (int)recordWithWriter:(xmlTextWriterPtr)writer forValue:(NSString *)value; +@end + +@interface FBApplicationBundleIdAttribute : FBElementAttribute + +@end + +@interface FBApplicationPidAttribute : FBElementAttribute + +@end + +@interface FBPlaceholderValueAttribute : FBElementAttribute + +@end + +@interface FBNativeFrameAttribute : FBElementAttribute + +@end + +@interface FBTraitsAttribute : FBElementAttribute + +@end + +@interface FBMinValueAttribute : FBElementAttribute + +@end + +@interface FBMaxValueAttribute : FBElementAttribute @end @@ -141,7 +172,11 @@ + (nullable NSString *)xmlStringWithRootElement:(id)root } if (rc >= 0) { - rc = [self xmlRepresentationWithRootElement:root + [self waitUntilStableWithElement:root]; + // If 'includeHittableInPageSource' setting is enabled, then use native snapshots + // to calculate a more accurate value for the 'hittable' attribute. + rc = [self xmlRepresentationWithRootElement:[self snapshotWithRoot:root + useNative:FBConfiguration.includeHittableInPageSource] writer:writer elementStore:nil query:nil @@ -189,10 +224,35 @@ + (nullable NSString *)xmlStringWithRootElement:(id)root } NSMutableDictionary *elementStore = [NSMutableDictionary dictionary]; int rc = xmlTextWriterStartDocument(writer, NULL, _UTF8Encoding, NULL); + id lookupScopeSnapshot = nil; + id contextRootSnapshot = nil; + BOOL useNativeSnapshot = nil == xpathQuery + ? NO + : [[self.class elementAttributesWithXPathQuery:xpathQuery] containsObject:FBHittableAttribute.class]; if (rc < 0) { [FBLogger logFmt:@"Failed to invoke libxml2>xmlTextWriterStartDocument. Error code: %d", rc]; } else { - rc = [self xmlRepresentationWithRootElement:root + [self waitUntilStableWithElement:root]; + if (FBConfiguration.limitXpathContextScope) { + lookupScopeSnapshot = [self snapshotWithRoot:root useNative:useNativeSnapshot]; + } else { + if ([root isKindOfClass:XCUIElement.class]) { + lookupScopeSnapshot = [self snapshotWithRoot:[(XCUIElement *)root application] + useNative:useNativeSnapshot]; + contextRootSnapshot = [root isKindOfClass:XCUIApplication.class] + ? nil + : ([(XCUIElement *)root lastSnapshot] ?: [self snapshotWithRoot:(XCUIElement *)root + useNative:useNativeSnapshot]); + } else { + lookupScopeSnapshot = (id)root; + contextRootSnapshot = nil == lookupScopeSnapshot.parent ? nil : (id)root; + while (nil != lookupScopeSnapshot.parent) { + lookupScopeSnapshot = lookupScopeSnapshot.parent; + } + } + } + + rc = [self xmlRepresentationWithRootElement:lookupScopeSnapshot writer:writer elementStore:elementStore query:xpathQuery @@ -210,7 +270,22 @@ + (nullable NSString *)xmlStringWithRootElement:(id)root return [self throwException:FBXPathQueryEvaluationException forQuery:xpathQuery]; } - xmlXPathObjectPtr queryResult = [self evaluate:xpathQuery document:doc]; + xmlXPathObjectPtr contextNodeQueryResult = [self matchNodeInDocument:doc + elementStore:elementStore.copy + forSnapshot:contextRootSnapshot]; + xmlNodePtr contextNode = NULL; + if (NULL != contextNodeQueryResult) { + xmlNodeSetPtr nodeSet = contextNodeQueryResult->nodesetval; + if (!xmlXPathNodeSetIsEmpty(nodeSet)) { + contextNode = nodeSet->nodeTab[0]; + } + } + xmlXPathObjectPtr queryResult = [self evaluate:xpathQuery + document:doc + contextNode:contextNode]; + if (NULL != contextNodeQueryResult) { + xmlXPathFreeObject(contextNodeQueryResult); + } if (NULL == queryResult) { xmlFreeTextWriter(writer); xmlFreeDoc(doc); @@ -252,6 +327,36 @@ + (NSArray *)collectMatchingSnapshots:(xmlNodeSetPtr)nodeSet return matchingSnapshots.copy; } ++ (nullable xmlXPathObjectPtr)matchNodeInDocument:(xmlDocPtr)doc + elementStore:(NSDictionary> *)elementStore + forSnapshot:(nullable id)snapshot +{ + if (nil == snapshot) { + return NULL; + } + + NSString *contextRootUid = [FBElementUtils uidWithAccessibilityElement:[(id)snapshot accessibilityElement]]; + if (nil == contextRootUid) { + return NULL; + } + + for (NSString *key in elementStore) { + id value = [elementStore objectForKey:key]; + NSString *snapshotUid = [FBElementUtils uidWithAccessibilityElement:[value accessibilityElement]]; + if (nil == snapshotUid || ![snapshotUid isEqualToString:contextRootUid]) { + continue; + } + NSString *indexQuery = [NSString stringWithFormat:@"//*[@%@=\"%@\"]", kXMLIndexPathKey, key]; + xmlXPathObjectPtr queryResult = [self evaluate:indexQuery + document:doc + contextNode:NULL]; + if (NULL != queryResult) { + return queryResult; + } + } + return NULL; +} + + (NSSet *)elementAttributesWithXPathQuery:(NSString *)query { if ([query rangeOfString:@"[^\\w@]@\\*[^\\w]" options:NSRegularExpressionSearch].location != NSNotFound) { @@ -267,7 +372,7 @@ + (NSArray *)collectMatchingSnapshots:(xmlNodeSetPtr)nodeSet return result.copy; } -+ (int)xmlRepresentationWithRootElement:(id)root ++ (int)xmlRepresentationWithRootElement:(id)root writer:(xmlTextWriterPtr)writer elementStore:(nullable NSMutableDictionary *)elementStore query:(nullable NSString*)query @@ -278,9 +383,20 @@ + (int)xmlRepresentationWithRootElement:(id)root NSMutableSet *includedAttributes; if (nil == query) { includedAttributes = [NSMutableSet setWithArray:FBElementAttribute.supportedAttributes]; - // The hittable attribute is expensive to calculate for each snapshot item - // thus we only include it when requested by an xPath query - [includedAttributes removeObject:FBHittableAttribute.class]; + if (!FBConfiguration.includeHittableInPageSource) { + // The hittable attribute is expensive to calculate for each snapshot item + // thus we only include it when requested explicitly + [includedAttributes removeObject:FBHittableAttribute.class]; + } + if (!FBConfiguration.includeNativeFrameInPageSource) { + // Include nativeFrame only when requested + [includedAttributes removeObject:FBNativeFrameAttribute.class]; + } + if (!FBConfiguration.includeMinMaxValueInPageSource) { + // minValue/maxValue are retrieved from private APIs and may be slow on deep trees + [includedAttributes removeObject:FBMinValueAttribute.class]; + [includedAttributes removeObject:FBMaxValueAttribute.class]; + } if (nil != excludedAttributes) { for (NSString *excludedAttributeName in excludedAttributes) { for (Class supportedAttribute in FBElementAttribute.supportedAttributes) { @@ -308,14 +424,16 @@ + (int)xmlRepresentationWithRootElement:(id)root return 0; } -+ (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery document:(xmlDocPtr)doc ++ (xmlXPathObjectPtr)evaluate:(NSString *)xpathQuery + document:(xmlDocPtr)doc + contextNode:(nullable xmlNodePtr)contextNode { xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc); if (NULL == xpathCtx) { [FBLogger logFmt:@"Failed to invoke libxml2>xmlXPathNewContext for XPath query \"%@\"", xpathQuery]; return NULL; } - xpathCtx->node = doc->children; + xpathCtx->node = NULL == contextNode ? doc->children : contextNode; xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression((const xmlChar *)[xpathQuery UTF8String], xpathCtx); if (NULL == xpathObj) { @@ -342,6 +460,16 @@ + (int)recordElementAttributes:(xmlTextWriterPtr)writer if (includedAttributes && ![includedAttributes containsObject:attributeCls]) { continue; } + // Text-input placeholder (only for elements that support inner text) + if ((attributeCls == FBPlaceholderValueAttribute.class) && + !FBDoesElementSupportInnerText(element.elementType)) { + continue; + } + // Only for elements that support min/max value + if ((attributeCls == FBMinValueAttribute.class || attributeCls == FBMaxValueAttribute.class) && + !FBDoesElementSupportMinMaxValue(element.elementType)) { + continue; + } int rc = [attributeCls recordWithWriter:writer forElement:[FBXCElementSnapshotWrapper ensureWrapped:element]]; if (rc < 0) { @@ -353,10 +481,31 @@ + (int)recordElementAttributes:(xmlTextWriterPtr)writer // index path is the special case return [FBInternalIndexAttribute recordWithWriter:writer forValue:indexPath]; } + if (element.elementType == XCUIElementTypeApplication) { + // only record process identifier and bundle identifier for the application element + int pid = [element.accessibilityElement processIdentifier]; + if (pid > 0) { + int rc = [FBApplicationPidAttribute recordWithWriter:writer + forValue:[NSString stringWithFormat:@"%d", pid]]; + if (rc < 0) { + return rc; + } + XCUIApplication *app = [[FBXCAXClientProxy sharedClient] + monitoredApplicationWithProcessIdentifier:pid]; + NSString *bundleID = [app bundleID]; + if (nil != bundleID) { + rc = [FBApplicationBundleIdAttribute recordWithWriter:writer + forValue:bundleID]; + if (rc < 0) { + return rc; + } + } + } + } return 0; } -+ (int)writeXmlWithRootElement:(id)root ++ (int)writeXmlWithRootElement:(id)root indexPath:(nullable NSString *)indexPath elementStore:(nullable NSMutableDictionary *)elementStore includedAttributes:(nullable NSSet *)includedAttributes @@ -364,30 +513,13 @@ + (int)writeXmlWithRootElement:(id)root { NSAssert((indexPath == nil && elementStore == nil) || (indexPath != nil && elementStore != nil), @"Either both or none of indexPath and elementStore arguments should be equal to nil", nil); - id currentSnapshot; - NSArray> *children; - if ([root isKindOfClass:XCUIElement.class]) { - XCUIElement *element = (XCUIElement *)root; - NSMutableArray *snapshotAttributes = [NSMutableArray arrayWithArray:FBStandardAttributeNames()]; - if (nil == includedAttributes || [includedAttributes containsObject:FBVisibleAttribute.class]) { - [snapshotAttributes addObject:FB_XCAXAIsVisibleAttributeName]; - // If the app is not idle state while we retrieve the visiblity state - // then the snapshot retrieval operation might freeze and time out - [element.application fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; - } - currentSnapshot = [element fb_snapshotWithAttributes:snapshotAttributes.copy - maxDepth:nil]; - children = currentSnapshot.children; - } else { - currentSnapshot = (id)root; - children = currentSnapshot.children; - } + NSArray> *children = root.children; if (elementStore != nil && indexPath != nil && [indexPath isEqualToString:topNodeIndexPath]) { - [elementStore setObject:currentSnapshot forKey:topNodeIndexPath]; + [elementStore setObject:root forKey:topNodeIndexPath]; } - FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:currentSnapshot]; + FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:root]; int rc = xmlTextWriterStartElement(writer, (xmlChar *)[wrappedSnapshot.wdType UTF8String]); if (rc < 0) { [FBLogger logFmt:@"Failed to invoke libxml2>xmlTextWriterStartElement for the tag value '%@'. Error code: %d", wrappedSnapshot.wdType, rc]; @@ -395,7 +527,7 @@ + (int)writeXmlWithRootElement:(id)root } rc = [self recordElementAttributes:writer - forElement:currentSnapshot + forElement:root indexPath:indexPath includedAttributes:includedAttributes]; if (rc < 0) { @@ -403,18 +535,20 @@ + (int)writeXmlWithRootElement:(id)root } for (NSUInteger i = 0; i < [children count]; i++) { - id childSnapshot = [children objectAtIndex:i]; - NSString *newIndexPath = (indexPath != nil) ? [indexPath stringByAppendingFormat:@",%lu", (unsigned long)i] : nil; - if (elementStore != nil && newIndexPath != nil) { - [elementStore setObject:childSnapshot forKey:(id)newIndexPath]; - } - rc = [self writeXmlWithRootElement:[FBXCElementSnapshotWrapper ensureWrapped:childSnapshot] - indexPath:newIndexPath - elementStore:elementStore - includedAttributes:includedAttributes - writer:writer]; - if (rc < 0) { - return rc; + @autoreleasepool { + id childSnapshot = [children objectAtIndex:i]; + NSString *newIndexPath = (indexPath != nil) ? [indexPath stringByAppendingFormat:@",%lu", (unsigned long)i] : nil; + if (elementStore != nil && newIndexPath != nil) { + [elementStore setObject:childSnapshot forKey:(id)newIndexPath]; + } + rc = [self writeXmlWithRootElement:[FBXCElementSnapshotWrapper ensureWrapped:childSnapshot] + indexPath:newIndexPath + elementStore:elementStore + includedAttributes:includedAttributes + writer:writer]; + if (rc < 0) { + return rc; + } } } @@ -426,6 +560,30 @@ + (int)writeXmlWithRootElement:(id)root return 0; } ++ (id)snapshotWithRoot:(id)root + useNative:(BOOL)useNative +{ + if (![root isKindOfClass:XCUIElement.class]) { + return (id)root; + } + + if (useNative) { + return [(XCUIElement *)root fb_nativeSnapshot]; + } + return [root isKindOfClass:XCUIApplication.class] + ? [(XCUIElement *)root fb_standardSnapshot] + : [(XCUIElement *)root fb_customSnapshot]; +} + ++ (void)waitUntilStableWithElement:(id)root +{ + if ([root isKindOfClass:XCUIElement.class]) { + // If the app is not idle state while we retrieve the visiblity state + // then the snapshot retrieval operation might freeze and time out + [[(XCUIElement *)root application] fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout]; + } +} + @end @@ -457,6 +615,11 @@ + (NSString *)valueForElement:(id)element + (int)recordWithWriter:(xmlTextWriterPtr)writer forElement:(id)element { NSString *value = [self valueForElement:element]; + return [self recordWithWriter:writer forValue:value]; +} + ++ (int)recordWithWriter:(xmlTextWriterPtr)writer forValue:(nullable NSString *)value +{ if (nil == value) { // Skip the attribute if the value equals to nil return 0; @@ -490,6 +653,11 @@ + (int)recordWithWriter:(xmlTextWriterPtr)writer forElement:(id)eleme FBHeightAttribute.class, FBIndexAttribute.class, FBHittableAttribute.class, + FBPlaceholderValueAttribute.class, + FBTraitsAttribute.class, + FBNativeFrameAttribute.class, + FBMinValueAttribute.class, + FBMaxValueAttribute.class, ]; } @@ -697,18 +865,90 @@ + (NSString *)name return kXMLIndexPathKey; } -+ (int)recordWithWriter:(xmlTextWriterPtr)writer forValue:(NSString *)value +@end + +@implementation FBApplicationBundleIdAttribute : FBElementAttribute + ++ (NSString *)name { - if (nil == value) { - // Skip the attribute if the value equals to nil - return 0; - } - int rc = xmlTextWriterWriteAttribute(writer, - (xmlChar *)[[FBXPath safeXmlStringWithString:[self name]] UTF8String], - (xmlChar *)[[FBXPath safeXmlStringWithString:value] UTF8String]); - if (rc < 0) { - [FBLogger logFmt:@"Failed to invoke libxml2>xmlTextWriterWriteAttribute(%@='%@'). Error code: %d", [self name], value, rc]; - } - return rc; + return @"bundleId"; } + +@end + +@implementation FBApplicationPidAttribute : FBElementAttribute + ++ (NSString *)name +{ + return @"processId"; +} + +@end + +@implementation FBPlaceholderValueAttribute + ++ (NSString *)name +{ + return @"placeholderValue"; +} + ++ (NSString *)valueForElement:(id)element +{ + return element.wdPlaceholderValue; +} +@end + +@implementation FBNativeFrameAttribute + ++ (NSString *)name +{ + return @"nativeFrame"; +} + ++ (NSString *)valueForElement:(id)element +{ + return NSStringFromCGRect(element.wdNativeFrame); +} +@end + +@implementation FBTraitsAttribute + ++ (NSString *)name +{ + return @"traits"; +} + ++ (NSString *)valueForElement:(id)element +{ + return element.wdTraits; +} + +@end + +@implementation FBMinValueAttribute + ++ (NSString *)name +{ + return @"minValue"; +} + ++ (NSString *)valueForElement:(id)element +{ + return [element.wdMinValue stringValue]; +} + +@end + +@implementation FBMaxValueAttribute + ++ (NSString *)name +{ + return @"maxValue"; +} + ++ (NSString *)valueForElement:(id)element +{ + return [element.wdMaxValue stringValue]; +} + @end diff --git a/WebDriverAgentLib/Utilities/LRUCache/LRUCache.h b/WebDriverAgentLib/Utilities/LRUCache/LRUCache.h index 70614235..dbfb4cfb 100644 --- a/WebDriverAgentLib/Utilities/LRUCache/LRUCache.h +++ b/WebDriverAgentLib/Utilities/LRUCache/LRUCache.h @@ -54,6 +54,13 @@ NS_ASSUME_NONNULL_BEGIN */ - (NSArray *)allObjects; +/** + Removes the object associated with the specified key from the cache. + + @param key The key identifying the object to remove. + */ +- (void)removeObjectForKey:(id)key; + @end NS_ASSUME_NONNULL_END diff --git a/WebDriverAgentLib/Utilities/LRUCache/LRUCache.m b/WebDriverAgentLib/Utilities/LRUCache/LRUCache.m index 4f3a9ad0..731d7440 100644 --- a/WebDriverAgentLib/Utilities/LRUCache/LRUCache.m +++ b/WebDriverAgentLib/Utilities/LRUCache/LRUCache.m @@ -135,4 +135,12 @@ - (void)alignSize } } +- (void)removeObjectForKey:(id)key +{ + LRUCacheNode *node = self.store[key]; + if (node != nil) { + [self removeNode:node]; + } +} + @end diff --git a/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.h b/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.h index 89ce4ade..a7ad285d 100644 --- a/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.h +++ b/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m b/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m index 8a033e70..65af951a 100644 --- a/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m +++ b/WebDriverAgentLib/Utilities/NSPredicate+FBFormat.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "NSPredicate+FBFormat.h" @@ -59,8 +58,10 @@ + (instancetype)fb_snapshotBlockPredicateWithPredicate:(NSPredicate *)input NSPredicate *wdPredicate = [self.class fb_formatSearchPredicate:input]; return [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary * _Nullable bindings) { - FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:evaluatedObject]; - return [wdPredicate evaluateWithObject:wrappedSnapshot]; + @autoreleasepool { + FBXCElementSnapshotWrapper *wrappedSnapshot = [FBXCElementSnapshotWrapper ensureWrapped:evaluatedObject]; + return [wdPredicate evaluateWithObject:wrappedSnapshot]; + } }]; } diff --git a/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.h b/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.h index 87199ff3..853ba414 100644 --- a/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.h +++ b/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -19,6 +18,17 @@ extern NSString *FB_XCAXAIsVisibleAttributeName; extern NSNumber *FB_XCAXAIsElementAttribute; extern NSString *FB_XCAXAIsElementAttributeName; +/*! Accessibility identifier for visible frame attribute */ +extern NSString *FB_XCAXAVisibleFrameAttributeName; + +/*! Accessibility identifier для минимума */ +extern NSNumber *FB_XCAXACustomMinValueAttribute; +extern NSString *FB_XCAXACustomMinValueAttributeName; + +/*! Accessibility identifier для максимума */ +extern NSNumber *FB_XCAXACustomMaxValueAttribute; +extern NSString *FB_XCAXACustomMaxValueAttributeName; + /*! Getter for XCTest logger */ extern id (*XCDebugLogger)(void); diff --git a/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m b/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m index 861a7866..244e3fdb 100644 --- a/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m +++ b/WebDriverAgentLib/Utilities/XCTestPrivateSymbols.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCTestPrivateSymbols.h" @@ -18,6 +17,11 @@ NSString *FB_XCAXAIsVisibleAttributeName = @"XC_kAXXCAttributeIsVisible"; NSNumber *FB_XCAXAIsElementAttribute; NSString *FB_XCAXAIsElementAttributeName = @"XC_kAXXCAttributeIsElement"; +NSString *FB_XCAXAVisibleFrameAttributeName = @"XC_kAXXCAttributeVisibleFrame"; +NSNumber *FB_XCAXACustomMinValueAttribute; +NSString *FB_XCAXACustomMinValueAttributeName = @"XC_kAXXCAttributeMinValue"; +NSNumber *FB_XCAXACustomMaxValueAttribute; +NSString *FB_XCAXACustomMaxValueAttributeName = @"XC_kAXXCAttributeMaxValue"; void (*XCSetDebugLogger)(id ); id (*XCDebugLogger)(void); @@ -41,6 +45,16 @@ NSCAssert(FB_XCAXAIsVisibleAttribute != nil , @"Failed to retrieve FB_XCAXAIsVisibleAttribute", FB_XCAXAIsVisibleAttribute); NSCAssert(FB_XCAXAIsElementAttribute != nil , @"Failed to retrieve FB_XCAXAIsElementAttribute", FB_XCAXAIsElementAttribute); + + NSString *XC_kAXXCAttributeMinValue = *(NSString *__autoreleasing *)FBRetrieveXCTestSymbol([FB_XCAXACustomMinValueAttributeName UTF8String]); + NSString *XC_kAXXCAttributeMaxValue = *(NSString *__autoreleasing *)FBRetrieveXCTestSymbol([FB_XCAXACustomMaxValueAttributeName UTF8String]); + + NSArray *minMaxAttrs = XCAXAccessibilityAttributesForStringAttributes(@[XC_kAXXCAttributeMinValue, XC_kAXXCAttributeMaxValue]); + FB_XCAXACustomMinValueAttribute = minMaxAttrs[0]; + FB_XCAXACustomMaxValueAttribute = minMaxAttrs[1]; + + NSCAssert(FB_XCAXACustomMinValueAttribute != nil, @"Failed to retrieve FB_XCAXACustomMinValueAttribute", FB_XCAXACustomMinValueAttribute); + NSCAssert(FB_XCAXACustomMaxValueAttribute != nil, @"Failed to retrieve FB_XCAXACustomMaxValueAttribute", FB_XCAXACustomMaxValueAttribute); } void *FBRetrieveXCTestSymbol(const char *name) @@ -73,7 +87,9 @@ dispatch_once(&onceCustomAttributeNamesToken, ^{ customNames = @[ FB_XCAXAIsVisibleAttributeName, - FB_XCAXAIsElementAttributeName + FB_XCAXAIsElementAttributeName, + FB_XCAXACustomMinValueAttributeName, + FB_XCAXACustomMaxValueAttributeName ]; }); return customNames; diff --git a/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.h b/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.h index ed11a9a5..3cbb5efb 100644 --- a/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.h +++ b/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m b/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m index c50ca413..e41a0a78 100644 --- a/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m +++ b/WebDriverAgentLib/Utilities/XCUIApplicationProcessDelay.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "XCUIApplicationProcessDelay.h" @@ -61,7 +60,10 @@ + (void)swizzleSetEventLoopHasIdled { [FBLogger log:@"Could not find method -[XCUIApplicationProcess setEventLoopHasIdled:]"]; return; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-function-type-strict" orig_set_event_loop_has_idled = (void(*)(id, SEL, BOOL)) method_getImplementation(original); +#pragma clang diagnostic pop Method replace = class_getClassMethod([XCUIApplicationProcessDelay class], @selector(setEventLoopHasIdled:)); method_setImplementation(original, method_getImplementation(replace)); isSwizzled = YES; diff --git a/WebDriverAgentLib/WebDriverAgentLib.h b/WebDriverAgentLib/WebDriverAgentLib.h index f14994b8..d0e3f739 100644 --- a/WebDriverAgentLib/WebDriverAgentLib.h +++ b/WebDriverAgentLib/WebDriverAgentLib.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import @@ -15,6 +14,7 @@ FOUNDATION_EXPORT double WebDriverAgentLib_VersionNumber; //! Project version string for WebDriverAgentLib_. FOUNDATION_EXPORT const unsigned char WebDriverAgentLib_VersionString[]; +#import #import #import #import @@ -38,9 +38,17 @@ FOUNDATION_EXPORT const unsigned char WebDriverAgentLib_VersionString[]; #import #import #import +#import +#import +#import +#import +#import +#import +#import #import #import #import +#import #import #import #import diff --git a/WebDriverAgentRunner/UITestingUITests.m b/WebDriverAgentRunner/UITestingUITests.m index cc7c7807..ad2ff455 100644 --- a/WebDriverAgentRunner/UITestingUITests.m +++ b/WebDriverAgentRunner/UITestingUITests.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.h b/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.h index ae3920f7..847dbec8 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.h +++ b/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.h @@ -3,13 +3,13 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import +#import -@interface AppDelegate : UIResponder +@interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end diff --git a/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.m b/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.m index 0a0e1d46..3ac33aa2 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.m +++ b/WebDriverAgentTests/IntegrationApp/Classes/AppDelegate.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "AppDelegate.h" diff --git a/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.h b/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.h index c657ab61..e5b2088c 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.h +++ b/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.h @@ -3,11 +3,11 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import +#import @interface FBAlertViewController : UIViewController diff --git a/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.m b/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.m index c90b58ab..1f1c77e1 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.m +++ b/WebDriverAgentTests/IntegrationApp/Classes/FBAlertViewController.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBAlertViewController.h" @@ -37,7 +36,14 @@ - (IBAction)createAppSheet:(UIButton *)sender - (IBAction)createNotificationAlert:(UIButton *)sender { - [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert categories:nil]]; + UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; + [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound|UNAuthorizationOptionAlert|UNAuthorizationOptionBadge) + completionHandler:^(BOOL granted, NSError * _Nullable error) + { + dispatch_async(dispatch_get_main_queue(), ^{ + [[UIApplication sharedApplication] registerForRemoteNotifications]; + }); + }]; } - (IBAction)createCameraRollAccessAlert:(UIButton *)sender diff --git a/WebDriverAgentTests/IntegrationApp/Classes/FBNavigationController.h b/WebDriverAgentTests/IntegrationApp/Classes/FBNavigationController.h index c83f8d26..e9a6b8d9 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/FBNavigationController.h +++ b/WebDriverAgentTests/IntegrationApp/Classes/FBNavigationController.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentTests/IntegrationApp/Classes/FBNavigationController.m b/WebDriverAgentTests/IntegrationApp/Classes/FBNavigationController.m index f404c0ba..3b0bec26 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/FBNavigationController.m +++ b/WebDriverAgentTests/IntegrationApp/Classes/FBNavigationController.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBNavigationController.h" diff --git a/WebDriverAgentTests/IntegrationApp/Classes/FBScrollViewController.h b/WebDriverAgentTests/IntegrationApp/Classes/FBScrollViewController.h index 4c79fb0f..7cd517b4 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/FBScrollViewController.h +++ b/WebDriverAgentTests/IntegrationApp/Classes/FBScrollViewController.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentTests/IntegrationApp/Classes/FBScrollViewController.m b/WebDriverAgentTests/IntegrationApp/Classes/FBScrollViewController.m index 4a49f9ce..a8fe7977 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/FBScrollViewController.m +++ b/WebDriverAgentTests/IntegrationApp/Classes/FBScrollViewController.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBScrollViewController.h" diff --git a/WebDriverAgentTests/IntegrationApp/Classes/FBTableDataSource.h b/WebDriverAgentTests/IntegrationApp/Classes/FBTableDataSource.h index 28cbe478..d82f8b65 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/FBTableDataSource.h +++ b/WebDriverAgentTests/IntegrationApp/Classes/FBTableDataSource.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentTests/IntegrationApp/Classes/FBTableDataSource.m b/WebDriverAgentTests/IntegrationApp/Classes/FBTableDataSource.m index ba28aed7..335f28af 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/FBTableDataSource.m +++ b/WebDriverAgentTests/IntegrationApp/Classes/FBTableDataSource.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "FBTableDataSource.h" diff --git a/WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.h b/WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.h index 3a312cb8..ed6a9cd6 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.h +++ b/WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the -* LICENSE file in the root directory of this source tree. An additional grant -* of patent rights can be found in the PATENTS file in the same directory. +* LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.m b/WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.m index 539add43..ed796940 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.m +++ b/WebDriverAgentTests/IntegrationApp/Classes/TouchSpotView.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the -* LICENSE file in the root directory of this source tree. An additional grant -* of patent rights can be found in the PATENTS file in the same directory. +* LICENSE file in the root directory of this source tree. */ #import "TouchSpotView.h" diff --git a/WebDriverAgentTests/IntegrationApp/Classes/TouchViewController.h b/WebDriverAgentTests/IntegrationApp/Classes/TouchViewController.h index 33bd0859..7125306a 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/TouchViewController.h +++ b/WebDriverAgentTests/IntegrationApp/Classes/TouchViewController.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the -* LICENSE file in the root directory of this source tree. An additional grant -* of patent rights can be found in the PATENTS file in the same directory. +* LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentTests/IntegrationApp/Classes/TouchViewController.m b/WebDriverAgentTests/IntegrationApp/Classes/TouchViewController.m index 1fd07671..25b3f993 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/TouchViewController.m +++ b/WebDriverAgentTests/IntegrationApp/Classes/TouchViewController.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the -* LICENSE file in the root directory of this source tree. An additional grant -* of patent rights can be found in the PATENTS file in the same directory. +* LICENSE file in the root directory of this source tree. */ #import "TouchViewController.h" diff --git a/WebDriverAgentTests/IntegrationApp/Classes/TouchableView.h b/WebDriverAgentTests/IntegrationApp/Classes/TouchableView.h index 46111c01..53d0c183 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/TouchableView.h +++ b/WebDriverAgentTests/IntegrationApp/Classes/TouchableView.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the -* LICENSE file in the root directory of this source tree. An additional grant -* of patent rights can be found in the PATENTS file in the same directory. +* LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentTests/IntegrationApp/Classes/TouchableView.m b/WebDriverAgentTests/IntegrationApp/Classes/TouchableView.m index 55b2fd11..9e7412ab 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/TouchableView.m +++ b/WebDriverAgentTests/IntegrationApp/Classes/TouchableView.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the -* LICENSE file in the root directory of this source tree. An additional grant -* of patent rights can be found in the PATENTS file in the same directory. +* LICENSE file in the root directory of this source tree. */ #import "TouchableView.h" diff --git a/WebDriverAgentTests/IntegrationApp/Classes/ViewController.h b/WebDriverAgentTests/IntegrationApp/Classes/ViewController.h index e4df859a..93496048 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/ViewController.h +++ b/WebDriverAgentTests/IntegrationApp/Classes/ViewController.h @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import diff --git a/WebDriverAgentTests/IntegrationApp/Classes/ViewController.m b/WebDriverAgentTests/IntegrationApp/Classes/ViewController.m index 6a0d0441..1267c28b 100644 --- a/WebDriverAgentTests/IntegrationApp/Classes/ViewController.m +++ b/WebDriverAgentTests/IntegrationApp/Classes/ViewController.m @@ -3,8 +3,7 @@ * All rights reserved. * * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. + * LICENSE file in the root directory of this source tree. */ #import "ViewController.h" @@ -37,7 +36,7 @@ - (void)viewDidLayoutSubviews - (void)updateOrentationLabel { NSString *orientation = nil; - switch (self.interfaceOrientation) { + switch (UIDevice.currentDevice.orientation) { case UIInterfaceOrientationPortrait: orientation = @"Portrait"; break; @@ -50,6 +49,12 @@ - (void)updateOrentationLabel case UIInterfaceOrientationLandscapeRight: orientation = @"LandscapeRight"; break; + case UIDeviceOrientationFaceUp: + orientation = @"FaceUp"; + break; + case UIDeviceOrientationFaceDown: + orientation = @"FaceDown"; + break; case UIInterfaceOrientationUnknown: orientation = @"Unknown"; break; diff --git a/WebDriverAgentTests/IntegrationApp/Info.plist b/WebDriverAgentTests/IntegrationApp/Info.plist index 2f4f1752..2dfb754c 100644 --- a/WebDriverAgentTests/IntegrationApp/Info.plist +++ b/WebDriverAgentTests/IntegrationApp/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.facebook.wda.integrationApp + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -22,12 +22,12 @@ 1 LSRequiresIPhoneOS + NSLocationAlwaysAndWhenInUseUsageDescription + Yo Yo NSLocationAlwaysUsageDescription Yo Yo NSLocationWhenInUseUsageDescription Yo Yo - NSLocationAlwaysAndWhenInUseUsageDescription - Yo Yo NSPhotoLibraryUsageDescription Yo Yo UILaunchStoryboardName diff --git a/WebDriverAgentTests/IntegrationApp/Resources/Base.lproj/Main.storyboard b/WebDriverAgentTests/IntegrationApp/Resources/Base.lproj/Main.storyboard index db522104..5fb805f2 100644 --- a/WebDriverAgentTests/IntegrationApp/Resources/Base.lproj/Main.storyboard +++ b/WebDriverAgentTests/IntegrationApp/Resources/Base.lproj/Main.storyboard @@ -1,9 +1,10 @@ - + - + + @@ -19,7 +20,7 @@ - - - - - - - - - -