Upload photo from a web app in IOS 14 Safari

Hi all,

I’m using Safari on the IOS 14 iPhone simulator to test a React web application. It’s working fine except for when it comes to upload a photo from the photo gallery.

The webapp is using a input type file to prompt the user to select from the gallery:

<input class="jss124" type="file" accept="image/*" multiple="">

My problem is that the native photo gallery picker pops up and I seem to have no way to control the picker to select a photo.

Any thoughts about how this can be accomplished?

Thanks,
Simon.

It might be this picker belongs to a different app, so you need to customize activeAppDetectionPoint setting in order to “switch” to it. Check https://appiumpro.com/editions/13-switching-between-ios-apps-during-a-test and https://appiumpro.com/editions/109-working-with-ipados-multitasking-split-view for more details

I remember similar was need about 5y ago. I did:

  1. remove all photos from simulator (or clear data on Simulator)
  2. add needed photo to simulator
  3. now open and select your only ONE image :slight_smile:

Ok…for the next person that comes along. This took me literally two days to find a working solution.

The strategy is to

  1. Switch context from the webapp context to the NATIVE_APP context
  2. Locate the native XCUIButton using the accessability id of ‘Choose Files’ and then a TouchAction.tap and sleep for 2 seconds
  3. Locate the native XCUIButton using the accessability id of ‘Photo Library’ and again, a TouchAction.tap and sleep for 2 seconds
  4. Find the photo using the accessability id of the photo name; e.g. ‘Photo, March 31, 2018, 5:14 AM’ and then a TouchAction.tap and sleep for 2 seconds
  5. Find the Add button using the accessability id of ‘Add’ and a TouchAction.tap and sleep for 2 seconds
  6. Switch back to the web application context.

Here’s the python code:

    contexts = self.driver.contexts
    LOGGER.info('Contexts {}'.format(','.join(contexts)))
    LOGGER.info('Switching to context {}'.format(self.driver.contexts[0]))
    orig_context = self.driver.context
    self.driver.switch_to.context('NATIVE_APP')
    time.sleep(2)

    LOGGER.info('Searching for Choose Files')
    el = self.driver.find_elements_by_accessibility_id('Choose Files')[0]
    assert(el)
    TouchAction(self.driver).tap(el).perform()
    time.sleep(2)

    LOGGER.info('Searching for Photo Library button')
    el = self.driver.find_elements_by_accessibility_id('Photo Library')[0]
    assert(el)
    TouchAction(self.driver).tap(el).perform()
    time.sleep(2)
    
    LOGGER.info('Searching for Photo')
    el = self.driver.find_elements_by_accessibility_id('Photo, March 31, 2018, 5:14 AM')[0]
    assert(el)
    TouchAction(self.driver).tap(el).perform()
    time.sleep(2)
    
    LOGGER.info('Add photo')
    el = self.driver.find_elements_by_accessibility_id('Add')[0]
    assert(el)
    TouchAction(self.driver).tap(el).perform()
    time.sleep(2)
    

    LOGGER.info('Switching to context {}'.format(orig_context))
    self.driver.switch_to.context(orig_context)
    return self

hardcoded sleeps are evil. Try to replace them with explicit waits