Xcode 7 UI Testing not recording swipes - ios

I have a collection view in my app, which is inside a table view cell (yes I know it's weird), and I want to UI Test the scrolling of the collection view. I use the recording button for this, however Xcode identifies the swiping on my collection view as taps. If I manually change the generated UI Test code from [collectionview tap] to [collectionview scrollLeft], it works, but Xcode won't generate the code for swiping automatically.
What could be the problem?

Xcode only recognises a gesture as a swipe if your trajectory with the gesture is fast, straight and true to the (up/down/left/right) direction you are swiping in.
My guess is that this prevents recording drag or tap-and-hold gestures as swipes, since these are unsupported by the recording tool. If you were going for either of those, a tap gesture would be closer.
As a workaround, take note of where you expected a swipe and switch the gesture as you have been doing when your swipes aren't recorded.

I believe you should file a bug with Apple and include a sample project.
It may be hard for the recording system to differentiate between a tap, a long press, and a swipe. While I've seen the recording of tap events to be reliable, I find I'm manually typing any steps for swipes or typeText. Generally I use the UI test recording feature to help with identification of particular elements, which I then work with in code to specify the user interactions and asserts.
If you want to create a sample project on github or somewhere with your collectionView-inside-tableViewCell configuration, I'd be willing to take a look.
EDIT: After trying your example project, I was sometimes able to get Xcode to record swipeLeft and swipeRight events from the first cell. It's not the most elegant approach, but with the trackpad on my MacBook Air, I start a horizontal swipe with one finger without pressing the mouse button, and then press the button with another finger while the first finger is still swiping.
There were some instances when Xcode recorded this simply as a tap, and at least one instance where it recorded a twoFingerTap.

Related

Performing a multi-finger swipe using XCUITest

I am working with an app that supports swipe gestures with multi-fingers (2 finger down swipe, etc.), and would like to simulate this in XCUITests. I see that XCUIElement contains a bunch of functions like SwipeUp() and SwipeLeft(), however they all see to be for only single fingers. I don't see any other APIs that look like they would allow simulating a two-finger down swipe, for instance.
Does anyone know of a way to do this?
Unfortunately, there isn’t a solution for this until we’re given a specific call for it; the existing gestures are all synchronous so you can’t simulate individual fingers doing different things at the same time.
There are pinch and rotate functions, but they can’t be made to do what you’re looking for.

Register multi-touch as a single touch?

Is there a way to register multi-touch as a single touch? Say if I use three fingers to tap a large button, can it be registered as simply one tap of the button? -- the current default appears to treat it as a multi-touch, and as a result ignores the button-pressing altogether. Similarly, if I use my palm to tap a large button, the button isn't pressed either.
I noticed in iphone Accessibility Settings -> Touch Accommodations, one could set "Ignore Repeat" and "Use Initial Touch Location" for tap assistance. Of course, if those are turned on, it affects the entire phone instead of just one app. But would that be the direction to approach this problem?
BTW I don't actually need multi-touch in my app. So if turning off multi-touch can be more simply done on the whole-app level instead of button-by-button, it would suit this case very well.
Thank you #DonMag for providing a hint.
So, if yours is an ios app from Capacitor, here is how to change your javascript code:
Change your button onClick events into "onTouchStart"
Use a state variable to keep track of whether "onTouchStart" is triggered and the resulting logic is executing. During that execution, prevent more touch events to have further effect on the button. This is to prevent the button from being pressed in quick succession by multiple touches that come from, say, your three-finger tap or palm tap. Only after the execution is finished do you revert the state variable back to the original value, so that the button is ready to be pressed again.
If there is an answer that's more suitable for the native Swift bundle I'll accept that as the answer. The above is just to help anyone who may encounter the same problem as mine.

How can I "mock" the UI of an iOS app?

I am trying to take screenshots of my iOS app. Before taking a screenshot, I need to get the app to an appropriate state. To get to an appropriate state, a lot of swiping is required.
This would have been fine if I have actual devices, but I don't. So I need to perform swipes on a simulator using a trackpad. I find this very hard, and sometimes I can't swipe properly so the gesture is not recognised.
I thought of using the UI Testing library to programmatically perform swipes. However, my app is actually a game, and random events happen. Writing code to handle these random events would not be worth the time. It would be best if I am in control of the swiping.
I have also thought of adding buttons on the UI of the app. When they are pressed a swipe is simulated. Then I can just click those buttons instead of swiping with my trackpad, which is way easier. However, these buttons will then appear on the screenshot, which I obviously don't want users to see.
Also note that I can't use a tap gesture recogniser as a replacement for the swipe gesture recognisers, because I need to detect swipes in all four directions and do different things depending on the direction.
Essentially, how can I perform a "swipe" more easily on the simulator? It would be great if I can do this by pressing keys on my keyboard, or maybe there is a feature in Xcode that allows me to do this which I am not aware of?
I suggest you automate the UI test.
Recording a test from live actions is a standard Xcode UI test feature. Fastlane is the icing on the cake to automate the capture of screenshots too.
Fastlane has the tools to automatically run a UI test and capture screenshots in all device resolutions. You can even record the actions by recording a UI test and play it back.
Check it out here:
Fastlane Screenshot
Even if you do not wish to use Fastlane, you can record the gestures in a unit test and have it pause.

How to childproof an iOS app by requiring "exit" button to be pushed multiple times before exit

I'm quite new to xCode and am trying to build a simple children's app. I have a young child and have experience with her playing with some apps where it's too easy to exit the screen - either with the main iPhone button or by swiping/pushing a button to exit the app. I know there are workarounds to this through the settings on iPhone, however I want to make my app so it is more childproof upfront with regards to exiting the app too easily.
My app is structured with a main menu for parents to access the settings/help and has a play button to enter the kids zone. Once the play button is pressed, a new view controller comes up which is where I'd like to add the code to press the exit button multiple times in a row to get back to the main menu and to disable the iPhone's main button from exiting the app.
If anyone has a suggestion on how to go about this I'd sure appreciate your help!
Cool concept! I'll suggest you use a UITapGestureRecognizer. Many subclasses of UIView accept gesture recognizers so you could simply do the following:
let tap = UITapGestureRecognizer(target: self, action: #selector(theMethodToExit))
tap.numberOfTapsRequired = 4
self.theTappingButton.addGestureRecognizer(tap)
where theMethodToExit is the method you will call to exit from the app and theTappingButton is the UIView or UIView subclass.
I'm not sure if you can attach a gesture recognizer to a UIButton, but it might be worth trying. If not, you can mimic the the behavior of a UIButton with a UIView.
Unfortunately you won't be able to disable the home button from being pressed, though you can provide a tutorial to parents for how to lock the app on the screen.

How to receive a touch ended event if a finger is already touching the screen when the app loads

I need to track if the user is touching the screen across multiple views and separate screens throughout my app. I have already created a window delegate method to receive every type of touch event. The problem is that if I keep one finger on the first screen and tap a button with a separate finger that takes me to the second screen, when I release my original finger no event is fired.
This problem is the same if you were to hold your finger on the screen before the app loads and then release it once it's started, no event is fired for the touch ending.
I presume there is some in built system in iOS that states you have to start a new touch once the app has started or the screen/view has changed, so if you release a finger that was already touching nothing happens.
Is there a way to detect this? I really need to keep a constant accurate number of touches on the screen throughout the different screens/views within my app, especially if the user takes their finger(s) off the screen.

Resources