Skip to content

Commit

Permalink
fixing push notification integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ruisebas committed May 2, 2024
1 parent 8bba829 commit a9f6505
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 33 deletions.
58 changes: 38 additions & 20 deletions .github/composite_actions/get_platform_parameters/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ outputs:
destination:
description: "The destination associated with the given platform and Xcode version"
value: ${{ steps.get-destination.outputs.destination }}
device:
description: "The device name used in the destination"
value: ${{ steps.get-destination.outputs.device }}
sdk:
description: "The SDK associated with the given platform"
value: ${{ steps.get-sdk.outputs.sdk }}
Expand Down Expand Up @@ -61,28 +64,42 @@ runs:
INPUT_DESTINATION='${{ inputs.destination }}'
INPUT_XCODE_VERSION=${{ inputs.xcode_version }}
DESTINATION_MAPPING='{
"minimum": {
"iOS": "platform=iOS Simulator,name=iPhone 14,OS=17.0.1",
"tvOS": "platform=tvOS Simulator,name=Apple TV 4K (3rd generation),OS=17.0",
"watchOS": "platform=watchOS Simulator,name=Apple Watch Series 8 (45mm),OS=10.0",
"macOS": "platform=macOS,arch=x86_64"
},
"latest": {
"iOS": "platform=iOS Simulator,name=iPhone 15,OS=17.4",
"tvOS": "platform=tvOS Simulator,name=Apple TV 4K (3rd generation),OS=17.4",
"watchOS": "platform=watchOS Simulator,name=Apple Watch Series 8 (45mm),OS=10.4",
"macOS": "platform=macOS,arch=x86_64"
}
}'
case $INPUT_PLATFORM/$INPUT_XCODE_VERSION in
iOS/latest)
DEVICE="iPhone 15"
OS_VERSION="17.4"
;;
iOS/*)
DEVICE="iPhone 14"
OS_VERSION="17.0.1"
;;
tvOS/latest)
DEVICE="Apple TV 4K (3rd generation)"
OS_VERSION="17.4"
;;
tvOS/*)
DEVICE="Apple TV 4K (3rd generation)"
OS_VERSION="17.0"
;;
watchOS/latest)
DEVICE="Apple Watch Series 9 (45mm)"
OS_VERSION="10.4"
;;
watchOS/*)
DEVICE="Apple Watch Series 8 (45mm)"
OS_VERSION="10.0"
;;
esac
DESTINATION_MAPPING="{
\"iOS\": \"platform=iOS Simulator,name=$DEVICE,OS=$OS_VERSION\",
\"tvOS\": \"platform=tvOS Simulator,name=$DEVICE,OS=$OS_VERSION\",
\"watchOS\": \"platform=watchOS Simulator,name=$DEVICE,OS=$OS_VERSION\",
\"macOS\": \"platform=macOS,arch=arm64\"
}"
if [ -z "$INPUT_DESTINATION" ]; then
case $INPUT_XCODE_VERSION in
latest|minimum)
DESTINATION=$(echo $DESTINATION_MAPPING | jq -r ".\"$INPUT_XCODE_VERSION\".$INPUT_PLATFORM") ;;
*)
DESTINATION=$(echo $DESTINATION_MAPPING | jq -r ".\"minimum\".$INPUT_PLATFORM") ;;
esac
DESTINATION=$(echo $DESTINATION_MAPPING | jq -r ".$INPUT_PLATFORM")
else
DESTINATION=$INPUT_DESTINATION
fi
Expand All @@ -92,6 +109,7 @@ runs:
exit 1
fi
echo "destination=$DESTINATION" >> $GITHUB_OUTPUT
echo "device=$DEVICE" >> $GITHUB_OUTPUT
shell: bash

- id: get-sdk
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/canary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ jobs:
matrix:
include:
- os: macos-latest
xcode-version: 14.3.1
device: iPhone 14 Pro
version: 16.4
xcode-version: 15.3.0
device: iPhone 15
version: 17.4
- os: macos-latest
xcode-version: 14.1
device: iPhone 13 Pro
version: 16.1
xcode-version: 15.0.1
device: iPhone 14
version: 17.0.1
name: Canary Test - Xcode ${{ matrix.xcode-version }}
runs-on: ${{ matrix.os }}
steps:
Expand All @@ -39,7 +39,7 @@ jobs:
run: amplify init --quickstart --frontend ios

- name: Setup Ruby
uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # v1.152.0
uses: ruby/setup-ruby@22fdc77bf4148f810455b226c90fb81b5cbc00a7 # v1.171.0
with:
ruby-version: '3.2.1'
bundler-cache: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,19 @@ app.post('/uninstall', async (req, res) => {
}
})

app.post('/boot', async (req, res) => {
console.log("POST /boot ")
const { deviceId } = req.body
try {
const cmd = `xcrun simctl --set testing bootstatus ${deviceId} -b`
await run(cmd)
res.send("Done")
} catch (error) {
console.error("Failed to boot the device", error)
res.sendStatus(500)
}
})

app.listen(9293, () => {
console.log("Starting server")
})
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,23 @@ enum LocalServer {

case notifications(PinpointNotification)
case uninstall(String)
case boot(String)
}

extension LocalServer {
var httpMethod: String {
switch self {
case .notifications: return "POST"
case .uninstall: return "POST"
case .boot: return "POST"
}
}

var path: String {
switch self {
case .notifications: return "/notifications"
case .uninstall: return "/uninstall"
case .boot: return "/boot"
}
}

Expand All @@ -36,12 +39,14 @@ extension LocalServer {
return try? JSONEncoder().encode(notification)
case let .uninstall(deviceId):
return try? JSONEncoder().encode(["deviceId": deviceId])
case let .boot(deviceId):
return try? JSONEncoder().encode(["deviceId": deviceId])
}
}

var additionalRequestHeaders: [String: String]? {
switch self {
case .notifications, .uninstall:
case .notifications, .uninstall, .boot:
return ["Content-Type": "application/json"]
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ final class PushNotificationHostAppUITests: XCTestCase {
return identifier
}()

override func setUpWithError() throws {
@MainActor
override func setUp() async throws {
continueAfterFailure = false
try await bootDevice()
#if os(iOS)
XCUIDevice.shared.orientation = .portrait
#endif
Expand Down Expand Up @@ -64,7 +66,12 @@ final class PushNotificationHostAppUITests: XCTestCase {

let identifyUserButton = app.buttons["Identify User"]
if identifyUserButton.waitForExistence(timeout: timeout) {
#if os(tvOS)
identifyUserButton.select(direction: .vertical)
#else
identifyUserButton.tap()
#endif

} else {
XCTFail("Failed to find 'Identify User' button")
}
Expand All @@ -84,7 +91,12 @@ final class PushNotificationHostAppUITests: XCTestCase {

let registerDeviceButton = app.buttons["Register Device"]
if registerDeviceButton.waitForExistence(timeout: timeout) {
#if os(tvOS)
registerDeviceButton.select(direction: .vertical)
#else
registerDeviceButton.tap()
#endif

} else {
XCTFail("Failed to find 'Register Device' button")
}
Expand Down Expand Up @@ -235,7 +247,12 @@ final class PushNotificationHostAppUITests: XCTestCase {
private func initAmplify() {
let initAmplifyButton = app.buttons["Init Amplify"]
if initAmplifyButton.waitForExistence(timeout: timeout) {
#if os(tvOS)
initAmplifyButton.select(direction: .vertical)
#else
initAmplifyButton.tap()
#endif

} else {
XCTFail("Failed to find `Init Amplify` button")
}
Expand All @@ -249,7 +266,14 @@ final class PushNotificationHostAppUITests: XCTestCase {
#endif
if alert.waitForExistence(timeout: timeout) {
XCTAssertTrue(anyElementContains(text: "Would Like to Send You Notifications", scope: alert).exists)
#if os(tvOS)
alert.buttons["Allow"].firstMatch.select(direction: .horizontal)
#elseif os(watchOS)
alert.swipeUp()
alert.buttons["Allow"].tap()
#else
alert.buttons["Allow"].tap()
#endif
}
}

Expand Down Expand Up @@ -282,6 +306,12 @@ final class PushNotificationHostAppUITests: XCTestCase {
XCTAssertTrue((response as! HTTPURLResponse).statusCode < 300, "Failed to uninstall the App")
}

private func bootDevice() async throws {
let request = LocalServer.boot(deviceIdentifier!).urlRequest
let (_, response) = try await URLSession.shared.data(for: request)
XCTAssertTrue((response as! HTTPURLResponse).statusCode < 300, "Failed to boot the device")
}

private func pressHomeButton() {
XCUIDevice.shared.press(XCUIDevice.Button.home)
let springboard = XCUIApplication.homeScreen
Expand Down Expand Up @@ -314,18 +344,41 @@ final class PushNotificationHostAppUITests: XCTestCase {

#if os(tvOS)
extension XCUIElement {
func tap() {
XCUIRemote.shared.select(self)
func select(direction: Direction) {
XCUIRemote.shared.select(self, direction: direction)
}
}

enum Direction {
case horizontal
case vertical

func next() -> XCUIRemote.Button {
switch self {
case .horizontal:
return .right
case .vertical:
return .down
}
}

func previous() -> XCUIRemote.Button {
switch self {
case .horizontal:
return .left
case .vertical:
return .up
}
}
}

extension XCUIRemote {
func select(_ element: XCUIElement) {
func select(_ element: XCUIElement, direction: Direction) {
let app = XCUIApplication()
var isEndReached = false
while !element.hasFocus {
let previousElement = app.focusedElement
press(isEndReached ? .up : .down)
press(isEndReached ? direction.previous() : direction.next())
if previousElement == app.focusedElement {
if isEndReached {
XCTFail("Element \(element) was not found.")
Expand Down

0 comments on commit a9f6505

Please sign in to comment.