Skip to content

Commit

Permalink
[auick_action_ios] Retries multiple times to not fail ci when there i…
Browse files Browse the repository at this point in the history
…s a flake (#3823)

The only way that we found to test quick action menu is to long press for a x second. Previously, we pressed it for 2 seconds but it is sometimes too long and the quick action menu is disappeared.

In this PR, we:
1. Reduce the press time to 1.5 seconds.
2. Retry 3 times.

fixes flutter/flutter#125509
  • Loading branch information
Chris Yang authored Apr 27, 2023
1 parent c11149c commit cf8dd12
Showing 1 changed file with 50 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@
import XCTest

private let elementWaitingTime: TimeInterval = 30
// The duration in when pressing the app icon to open the
// quick action menu. This duration is undocumented by Apple.
// The duration will be adjusted with `pressDurationRetryAdjustment` if
// this duration does not result in the quick action menu opened.
private let quickActionPressDuration: TimeInterval = 1.5
// If the previous try to open quick action menu did not work,
// a new try with adjust the press time by this value.
// The adjusment could be + or - depends on the result of the previous try.
private let pressDurationRetryAdjustment: TimeInterval = 0.2
// Max number of tries to open the quick action menu if failed.
// This is to deflake a situation where the quick action menu is not present after
// the long press.
// See: https://github.com/flutter/flutter/issues/125509
private let quickActionMaxRetries: Int = 4;

class RunnerUITests: XCTestCase {

Expand All @@ -25,22 +39,8 @@ class RunnerUITests: XCTestCase {
func testQuickActionWithFreshStart() {
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let quickActionsAppIcon = springboard.icons["quick_actions_example"]
if !quickActionsAppIcon.waitForExistence(timeout: elementWaitingTime) {
XCTFail(
"Failed due to not able to find the example app from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)"
)
}

quickActionsAppIcon.press(forDuration: 2)

let actionTwo = springboard.buttons["Action two"]
if !actionTwo.waitForExistence(timeout: elementWaitingTime) {
XCTFail(
"Failed due to not able to find the actionTwo button from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)"
)
}

actionTwo.tap()
findAndTapQuickActionButton(buttonName: "Action two", quickActionsAppIcon: quickActionsAppIcon, springboard: springboard);

let actionTwoConfirmation = exampleApp.otherElements["action_two"]
if !actionTwoConfirmation.waitForExistence(timeout: elementWaitingTime) {
Expand Down Expand Up @@ -73,24 +73,50 @@ class RunnerUITests: XCTestCase {
)
}

quickActionsAppIcon.press(forDuration: 2)
findAndTapQuickActionButton(buttonName: "Action one", quickActionsAppIcon: quickActionsAppIcon, springboard: springboard);

let actionOne = springboard.buttons["Action one"]
if !actionOne.waitForExistence(timeout: elementWaitingTime) {
let actionOneConfirmation = exampleApp.otherElements["action_one"]
if !actionOneConfirmation.waitForExistence(timeout: elementWaitingTime) {
XCTFail(
"Failed due to not able to find the actionOne button from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)"
"Failed due to not able to find the actionOneConfirmation in the app with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)"
)
}

actionOne.tap()
XCTAssert(actionOneConfirmation.exists)
}

let actionOneConfirmation = exampleApp.otherElements["action_one"]
if !actionOneConfirmation.waitForExistence(timeout: elementWaitingTime) {
private func findAndTapQuickActionButton(buttonName: String, quickActionsAppIcon: XCUIElement, springboard: XCUIElement) {
var actionButton: XCUIElement?
var pressDuration = quickActionPressDuration
for _ in 1...quickActionMaxRetries {
if !quickActionsAppIcon.waitForExistence(timeout: elementWaitingTime) {
XCTFail(
"Failed due to not able to find the example app from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)"
)
}
quickActionsAppIcon.press(forDuration: pressDuration)
actionButton = springboard.buttons[buttonName]
if actionButton!.waitForExistence(timeout: elementWaitingTime) {
// find the button, exit the retry loop.
break
}
let deleteButton = springboard.buttons["DeleteButton"]
if deleteButton.waitForExistence(timeout: elementWaitingTime) {
// Found delete button instead, we pressed too long, reduce the press time.
pressDuration -= pressDurationRetryAdjustment
} else {
// Neither action button nor delete button was found, we need a longer press.
pressDuration += pressDurationRetryAdjustment
}
// Reset to previous state.
XCUIDevice.shared.press(XCUIDevice.Button.home)
}
if (!actionButton!.exists) {
XCTFail(
"Failed due to not able to find the actionOneConfirmation in the app with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)"
"Failed due to not able to find the \(buttonName) button from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)"
)
}

XCTAssert(actionOneConfirmation.exists)
actionButton!.tap();
}
}

0 comments on commit cf8dd12

Please sign in to comment.