skip to content

In Appium on iOS, why does mobile: resetPermission work on a real device when mobile: setPermission does not?

level: middleimportance: must knowfreq 50%

answer

  1. not all three behave the same
  2. one runs on the host, one on device
  3. the agent is already installed there
  4. clearing is cheaper than setting

basics

~10 s

Because they run on different machinery. The XCUITest driver's mobile: setPermission and mobile: getPermission drive Simulator-only facilities on the host, while mobile: resetPermission proxies to WebDriverAgent's /wda/resetAppAuth, which runs on the device itself.

solid answer

~40 s

The XCUITest driver ships three permission methods and they are not equally portable. `mobile: setPermission` and `mobile: getPermission` write and read a chosen value for a bundle by driving Simulator tooling that lives on the **host**, so on a plugged-in iPhone there is nothing for them to talk to and they throw. `mobile: resetPermission` takes a different route: it proxies to **WebDriverAgent**, the XCTest agent the driver has already built and installed on the target, and asks it to clear the app's stored authorization through `/wda/resetAppAuth`. That runs inside the device's own test session, so it works on Simulators and real hardware alike. The price is expressiveness — reset can only return a permission to undecided, never to granted or denied.

go deeper

for a junior

Remember that the three Apple permission methods are not interchangeable: only mobile: resetPermission runs on a real device, and it clears a decision rather than setting one.

for a middle

Explain the mechanism split. Setting a value needs host-side Simulator tooling, while resetting is proxied to WebDriverAgent on the target, which is why one crosses to hardware and the other does not.

for a senior

Show how you turn this into suite behaviour: reset as a teardown step on shared devices, an explicit skip when a case needs a state the target cannot reach, and no silent fallbacks.

for a principal

Argue where the boundary belongs. If a precondition is reachable on some targets and not others, that asymmetry should be a declared capability of the fleet rather than an exception caught inside a helper.

## Three methods, two mechanisms The XCUITest driver's permission surface looks uniform from a test's point of view — three `mobile:` execute methods with matching names — and it is not. `mobile: setPermission` and `mobile: getPermission` are **Simulator-only**. `mobile: resetPermission` runs on **both a Simulator and a real device**. The difference is not a policy choice or a missing feature request; it falls straight out of where each one does its work. Setting a permission to a chosen value means editing the privacy store the operating system consults when an app asks for a resource. On a Simulator that store lives on your Mac, and the host tooling the driver already uses to manage Simulators can write it. There is no equivalent doorway into a real iPhone: the OS does not expose a host-side hook that lets a development machine stamp an arbitrary authorization into it. So `mobile: setPermission` has nothing to drive on hardware and reports a failure rather than pretending. Resetting is a different act with a different owner. Clearing an application's stored authorization is something the test harness running **on** the device is allowed to do for the app it is testing. The XCUITest driver already has such a harness present — **WebDriverAgent**, the XCTest-based agent it builds, installs and launches as part of starting a session. `mobile: resetPermission` therefore needs no host tooling: it proxies the request to WebDriverAgent's `/wda/resetAppAuth`, which performs the reset from inside the device's own test session. Simulators run WebDriverAgent too, so the same path serves both. ## The capability ladder this produces | Target | Set a value | Read a value | Clear the decision | |---|---|---|---| | Android emulator or real device | `mobile: changePermissions` | `mobile: getPermissions` | revoke via `mobile: changePermissions` | | Apple Simulator | `mobile: setPermission` | `mobile: getPermission` | `mobile: resetPermission` | | Apple real device | not available | not available | `mobile: resetPermission` | Read the bottom row carefully, because it is the fact that changes suite design. On a real iPhone an Appium session cannot put a permission into granted or denied, and cannot even ask what it currently is. It can only push it back to **undecided**, after which the operating system will ask the next time the application needs the resource. ## What undecided actually buys you Being able to reset is worth more than it first appears, because undecided is a real and useful starting state: - It makes runs **repeatable**. A device that has answered a prompt once stays answered; resetting between cases removes the order dependency where case 12 passes only because case 3 granted something. - It restores the prompt, which is the only route to a granted or denied state on hardware — you reach the state through the dialog rather than around it. - It is per-application, so resetting the vineyard harvest-log app's camera decision does not disturb anything else on a shared device. - It is the correct **teardown** step on a shared real-device fleet, so the next tenant does not inherit your run's answers. What it cannot do is skip the dialog. If a case needs the app to start with camera access already denied, reset gets you to a prompt, not to a denial. ## Reading it correctly, and the over-broad version A tempting shorthand is that iOS permission commands are Simulator-only. That is over-broad and it will cost you in an interview, because a third of the surface contradicts it. The precise statement names the method, not the platform: 1. `mobile: setPermission` — Simulator only. 2. `mobile: getPermission` — Simulator only. 3. `mobile: resetPermission` — Simulator and real device, via WebDriverAgent's `/wda/resetAppAuth`. The same discipline applies in the other direction. Android's `mobile: changePermissions` really does work on emulators and real devices equally, so the asymmetry is genuinely Apple's and not a general rule about virtual versus physical targets. ## Designing around it On a vineyard harvest-log suite that runs Simulators locally and real iPhones in a shared fleet, the seam is not where most people put it. The temptation is to write one helper that calls `mobile: setPermission` and catches the error on hardware. Better is to decide up front which states each target can reach, declare that, and let a case that needs an unreachable state be skipped with a reason rather than fail obscurely three screens later. A permission precondition that silently does not hold is the raw material of a flaky suite, and reset-plus-prompt is a genuinely different flow from seed-and-proceed — not a fallback that can quietly substitute for it.

  • What state does mobile: resetPermission leave a permission in?
    Undecided. It clears the application's stored authorization, so the operating system raises its prompt again the next time the app needs the resource. It does not grant and it does not deny — reaching either of those on real Apple hardware means going through the dialog, because no Appium command can write the value directly there.
  • Why does WebDriverAgent being installed on the device matter to this answer?
    Because it is what makes the reset possible without host tooling. The XCUITest driver builds, installs and launches WebDriverAgent as part of starting a session, so there is already an XCTest process on the target entitled to clear the app under test's authorization. `mobile: resetPermission` simply proxies to its `/wda/resetAppAuth` route.

A Simulator lets you write the answer straight into the system's ledger; a real device only lets you tear the page out, so the system has to ask the question again.

saying these in an interview costs you the question

  • Says all iOS permission commands are Simulator-only
  • Thinks reset can set a permission to granted
  • Claims Android has the same virtual-versus-physical split
  • Assumes resetting also dismisses an on-screen prompt
  • Treats the throw on real hardware as a driver bug