Skip to content

Commit cf8dd12

Browse files
author
Chris Yang
authored
[auick_action_ios] Retries multiple times to not fail ci when there is 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
1 parent c11149c commit cf8dd12

File tree

1 file changed

+50
-24
lines changed

1 file changed

+50
-24
lines changed

packages/quick_actions/quick_actions_ios/example/ios/RunnerUITests/RunnerUITests.swift

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,20 @@
55
import XCTest
66

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

923
class RunnerUITests: XCTestCase {
1024

@@ -25,22 +39,8 @@ class RunnerUITests: XCTestCase {
2539
func testQuickActionWithFreshStart() {
2640
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
2741
let quickActionsAppIcon = springboard.icons["quick_actions_example"]
28-
if !quickActionsAppIcon.waitForExistence(timeout: elementWaitingTime) {
29-
XCTFail(
30-
"Failed due to not able to find the example app from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)"
31-
)
32-
}
33-
34-
quickActionsAppIcon.press(forDuration: 2)
35-
36-
let actionTwo = springboard.buttons["Action two"]
37-
if !actionTwo.waitForExistence(timeout: elementWaitingTime) {
38-
XCTFail(
39-
"Failed due to not able to find the actionTwo button from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)"
40-
)
41-
}
4242

43-
actionTwo.tap()
43+
findAndTapQuickActionButton(buttonName: "Action two", quickActionsAppIcon: quickActionsAppIcon, springboard: springboard);
4444

4545
let actionTwoConfirmation = exampleApp.otherElements["action_two"]
4646
if !actionTwoConfirmation.waitForExistence(timeout: elementWaitingTime) {
@@ -73,24 +73,50 @@ class RunnerUITests: XCTestCase {
7373
)
7474
}
7575

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

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

85-
actionOne.tap()
85+
XCTAssert(actionOneConfirmation.exists)
86+
}
8687

87-
let actionOneConfirmation = exampleApp.otherElements["action_one"]
88-
if !actionOneConfirmation.waitForExistence(timeout: elementWaitingTime) {
88+
private func findAndTapQuickActionButton(buttonName: String, quickActionsAppIcon: XCUIElement, springboard: XCUIElement) {
89+
var actionButton: XCUIElement?
90+
var pressDuration = quickActionPressDuration
91+
for _ in 1...quickActionMaxRetries {
92+
if !quickActionsAppIcon.waitForExistence(timeout: elementWaitingTime) {
93+
XCTFail(
94+
"Failed due to not able to find the example app from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)"
95+
)
96+
}
97+
quickActionsAppIcon.press(forDuration: pressDuration)
98+
actionButton = springboard.buttons[buttonName]
99+
if actionButton!.waitForExistence(timeout: elementWaitingTime) {
100+
// find the button, exit the retry loop.
101+
break
102+
}
103+
let deleteButton = springboard.buttons["DeleteButton"]
104+
if deleteButton.waitForExistence(timeout: elementWaitingTime) {
105+
// Found delete button instead, we pressed too long, reduce the press time.
106+
pressDuration -= pressDurationRetryAdjustment
107+
} else {
108+
// Neither action button nor delete button was found, we need a longer press.
109+
pressDuration += pressDurationRetryAdjustment
110+
}
111+
// Reset to previous state.
112+
XCUIDevice.shared.press(XCUIDevice.Button.home)
113+
}
114+
if (!actionButton!.exists) {
89115
XCTFail(
90-
"Failed due to not able to find the actionOneConfirmation in the app with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)"
116+
"Failed due to not able to find the \(buttonName) button from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)"
91117
)
92118
}
93119

94-
XCTAssert(actionOneConfirmation.exists)
120+
actionButton!.tap();
95121
}
96122
}

0 commit comments

Comments
 (0)