Skip to content

Commit

Permalink
add launch argument tests
Browse files Browse the repository at this point in the history
  • Loading branch information
shamanec committed Jul 24, 2023
1 parent 06c191b commit ab9ccb6
Show file tree
Hide file tree
Showing 11 changed files with 140 additions and 26 deletions.
4 changes: 4 additions & 0 deletions xcuitest-sample-proj.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
FF79C2832A66F54E00BBC60A /* BaseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF79C2822A66F54E00BBC60A /* BaseTest.swift */; };
FF79C2862A66F72200BBC60A /* TestConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF79C2852A66F72200BBC60A /* TestConstants.swift */; };
FF79C2892A66F9F500BBC60A /* Interactions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF79C2882A66F9F500BBC60A /* Interactions.swift */; };
FF7C55402A6EF2DA00102A71 /* LaunchArgumentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF7C553F2A6EF2DA00102A71 /* LaunchArgumentTests.swift */; };
FF86799B2A69699D00C4A1A7 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF86799A2A69699D00C4A1A7 /* AppDelegate.swift */; };
FF86799E2A696BDC00C4A1A7 /* CarouselItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF86799D2A696BDC00C4A1A7 /* CarouselItemView.swift */; };
FFF0348F2A6CFA6500A33E97 /* FirstPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFF0348E2A6CFA6500A33E97 /* FirstPage.swift */; };
Expand Down Expand Up @@ -59,6 +60,7 @@
FF79C2822A66F54E00BBC60A /* BaseTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTest.swift; sourceTree = "<group>"; };
FF79C2852A66F72200BBC60A /* TestConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestConstants.swift; sourceTree = "<group>"; };
FF79C2882A66F9F500BBC60A /* Interactions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Interactions.swift; sourceTree = "<group>"; };
FF7C553F2A6EF2DA00102A71 /* LaunchArgumentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchArgumentTests.swift; sourceTree = "<group>"; };
FF86799A2A69699D00C4A1A7 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
FF86799D2A696BDC00C4A1A7 /* CarouselItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselItemView.swift; sourceTree = "<group>"; };
FFF0348E2A6CFA6500A33E97 /* FirstPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstPage.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -156,6 +158,7 @@
FF79C27D2A66F31800BBC60A /* Extensions */,
FF79C2022A66F1B700BBC60A /* SampleAppUITests.swift */,
FFF034A22A6D687400A33E97 /* README.md */,
FF7C553F2A6EF2DA00102A71 /* LaunchArgumentTests.swift */,
);
path = "xcuitest-sample-projUITests";
sourceTree = "<group>";
Expand Down Expand Up @@ -364,6 +367,7 @@
FFF0349B2A6D227100A33E97 /* XCUIApplication+Extensions.swift in Sources */,
FFF0348F2A6CFA6500A33E97 /* FirstPage.swift in Sources */,
FF79C2862A66F72200BBC60A /* TestConstants.swift in Sources */,
FF7C55402A6EF2DA00102A71 /* LaunchArgumentTests.swift in Sources */,
FF79C27F2A66F3A000BBC60A /* XCUIElement+Extensions.swift in Sources */,
FFF034A12A6D56DF00A33E97 /* ThirdPage.swift in Sources */,
FF79C2812A66F45200BBC60A /* XCUIElementQuery+Extensions.swift in Sources */,
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@
ReferencedContainer = "container:xcuitest-sample-proj.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "-showCustomText"
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,75 @@
filePath = "xcuitest-sample-projUITests/Foundations/BaseTest.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "63"
endingLineNumber = "63"
startingLineNumber = "67"
endingLineNumber = "67"
landmarkName = "handleCameraAlert(allow:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "7B4B5838-F991-466B-AFAE-78221901506B"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "xcuitest-sample-projUITests/SampleAppUITests.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "77"
endingLineNumber = "77"
landmarkName = "testAllowCameraPermissions()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "C838D7E2-CAEA-4D0A-BE2E-BD15A9F56DF0"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "xcuitest-sample-projUITests/Foundations/BaseTest.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "29"
endingLineNumber = "29"
landmarkName = "setUp()"
landmarkType = "7">
<Locations>
<Location
uuid = "C838D7E2-CAEA-4D0A-BE2E-BD15A9F56DF0 - e56f399342f491cb"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "xcuitest_sample_projUITests.BaseTest.setUp() -&gt; ()"
moduleName = "xcuitest-sample-projUITests"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/shamanec/repo/xcuitest-sample-proj/xcuitest-sample-projUITests/Foundations/BaseTest.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "29"
endingLineNumber = "29"
offsetFromSymbolStart = "332">
</Location>
<Location
uuid = "C838D7E2-CAEA-4D0A-BE2E-BD15A9F56DF0 - e56f399342f491cb"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "xcuitest_sample_projUITests.BaseTest.setUp() -&gt; ()"
moduleName = "xcuitest-sample-projUITests"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/shamanec/repo/xcuitest-sample-proj/xcuitest-sample-projUITests/Foundations/BaseTest.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "29"
endingLineNumber = "29"
offsetFromSymbolStart = "380">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>
19 changes: 18 additions & 1 deletion xcuitest-sample-proj/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct TabBarView: View {
}

struct CarouselView: View {
@StateObject var viewModel = ArgumentTextViewModel()
@State private var isButtonVisible = true
@State private var text: String = ""

Expand Down Expand Up @@ -73,8 +74,19 @@ struct CarouselView: View {
.frame(width: 200, height: 50)
.textFieldStyle(RoundedBorderTextFieldStyle())
.accessibilityIdentifier("text-field")

Text("Argument:\(viewModel.displayText)")
.foregroundColor(.gray)
.padding(.top, 8)
.accessibilityIdentifier("argument-text")
.onAppear {
// Check if the launch arguments contain the specific argument you provided
if CommandLine.arguments.contains("-showCustomText") {
// Perform any action based on the launch argument, e.g., update ViewModel
viewModel.displayText = "Custom"
}
}
}

}

private func hideButtonAfterDelay() {
Expand Down Expand Up @@ -109,3 +121,8 @@ struct LoadingElementsView: View {
}
}
}

// Your ViewModel
class ArgumentTextViewModel: ObservableObject {
@Published var displayText: String = "Default"
}
31 changes: 15 additions & 16 deletions xcuitest-sample-projUITests/Foundations/BaseTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import XCTest

class BaseTest: XCTestCase {
private let app = XCUIApplication()

private let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
private let device = XCUIDevice.shared

Expand All @@ -27,6 +26,7 @@ class BaseTest: XCTestCase {
// Fail-fast tests
continueAfterFailure = false
// Start the AUT
app.launchArguments = launchArguments()
app.launch()
}

Expand All @@ -38,6 +38,11 @@ class BaseTest: XCTestCase {
app.terminate()
}

func launchArguments() -> [String] {
// Override this method in subclasses to provide custom launch arguments
return []
}

func getApp() -> XCUIApplication {
return self.app
}
Expand All @@ -54,8 +59,7 @@ class BaseTest: XCTestCase {
print(app.debugDescription)
}

///===========================

/// Accept or deny camera permissions
func handleCameraAlert(allow: Bool) {
// Add UI interruption monitor to handle system alerts
addUIInterruptionMonitor(withDescription: "System Alert") { (alert) -> Bool in
Expand All @@ -79,7 +83,7 @@ class BaseTest: XCTestCase {
device.press(.home)
}

/// This function allows to delete the app between tests
/// This function allows to delete the app between tests - to trigger permission alerts again for example
func deleteApp() {
app.terminate()
pressHomeButton()
Expand All @@ -91,21 +95,21 @@ class BaseTest: XCTestCase {
usleep(500_000) // 0.5 seconds
springboard.swipeLeft()
}

let appName = "SampleApp"
let icon = springboard.icons[appName]
let iconExists = Elements.waitForElement(icon, TestConstants.Timeout.short)

guard iconExists else { return }

icon.press(forDuration: TestConstants.Timeout.short)

let editHomeScreenAlert = springboard.alerts["Edit Home Screens"]
if Elements.waitForElement(editHomeScreenAlert, 1) {
let editHomeScreenAlertButton = editHomeScreenAlert.buttons["OK"]
editHomeScreenAlertButton.tap()
}

let deleteAppButton = springboard.icons[appName].buttons["DeleteButton"]
deleteAppButton.tap()

Expand All @@ -117,24 +121,19 @@ class BaseTest: XCTestCase {
pressHomeButton()
}

///
private var cleanedTestName: String? {
let testName = self.name
do {
// The pattern (?<= )(.*?)(?=]) is a positive lookbehind (?<= ), followed by a non-greedy capture group (.*?), and finally, a positive lookahead (?=]).
// This regular expression is designed to match the text between a space and a closing square bracket ("]")
let regex = try NSRegularExpression(pattern: "(?<= )(.*?)(?=])")
guard let match = regex.firstMatch(in: testName, range: NSRange(testName.startIndex..., in: testName)),
let range = Range(match.range(at: 1), in: testName) else { return nil }
let range = Range(match.range(at: 1), in: testName) else { return nil }
return String(testName[range])
} catch let error as NSError {
print("[UITest] invalid regex: \(error.localizedDescription)")
return nil
}
}

func waitForElementHittableAttributeToBe(_ element: XCUIElement, _ timeoutValue: Double, _ visibility: Bool) {
let predicate = "hittable == \(String(visibility))"
let isDisplayedPredicate = NSPredicate(format: predicate)
let expectation = [XCTNSPredicateExpectation(predicate: isDisplayedPredicate, object: element)]
let result = XCTWaiter().wait(for: expectation, timeout: timeoutValue)
XCTAssertEqual(result, .completed, "Element \(element) is not displayed and/or hittable")
}
}
5 changes: 3 additions & 2 deletions xcuitest-sample-projUITests/Helpers/Elements.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@ class Elements {
XCTAssertTrue(result, "\(firstElement) is not in `\(relativePosition)` relative position to \(secondElement)")
}

// MARK: - Wait functions

/// Wait for element to exist
static func waitForElement(_ element: XCUIElement, _ timeoutValue: Double) -> Bool {
return element.waitForExistence(timeout: timeoutValue)
}

// MARK: - Wait functions

/// Wait until XCUIElement disappears
///
/// - Parameters:
Expand Down
19 changes: 19 additions & 0 deletions xcuitest-sample-projUITests/LaunchArgumentTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// LaunchArgumentTests.swift
// xcuitest-sample-projUITests
//
// Created by Nikola Shabanov on 24.07.23.
//

import XCTest

class LaunchArgumentTests: BaseTest {
override func launchArguments() -> [String] {
return ["-showCustomText"]
}

func testLaunchArgument() {
let firstPage = FirstPage(app: getApp())
XCTAssertEqual(firstPage.argumentText.label, "Argument:Custom")
}
}
1 change: 1 addition & 0 deletions xcuitest-sample-projUITests/Pages/FirstPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ class FirstPage: BasePage {
var carouselItems: XCUIElementQuery { carousel.staticTexts }
var disappearingButton: XCUIElement { app.buttons["disappearing-button"] }
var textField: XCUIElement { app.textFields["text-field"] }
var argumentText: XCUIElement { app.staticTexts["argument-text"] }
}
2 changes: 1 addition & 1 deletion xcuitest-sample-projUITests/Pages/ThirdPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import XCTest

class ThirdPage: BasePage {
var permissionState: XCUIElement { app.staticTexts["permission-state"] }
private var permissionState: XCUIElement { app.staticTexts["permission-state"] }

func getPermissionState() -> String {
return permissionState.label
Expand Down
11 changes: 7 additions & 4 deletions xcuitest-sample-projUITests/SampleAppUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,7 @@ final class SampleAppUITests: BaseTest {
navigation.openThirdPage()
XCTAssertTrue(getSpringboardApp().alerts.count == 0)
let thirdPage = ThirdPage(app: getApp())
let state = thirdPage.getPermissionState()
XCTAssertEqual(state, "Allowed")
XCTAssertEqual(thirdPage.getPermissionState(), "Allowed")
}

func testDenyCameraPermissions() {
Expand All @@ -89,7 +88,11 @@ final class SampleAppUITests: BaseTest {
navigation.openThirdPage()
XCTAssertTrue(getSpringboardApp().alerts.count == 0)
let thirdPage = ThirdPage(app: getApp())
let state = thirdPage.getPermissionState()
XCTAssertEqual(state, "Denied")
XCTAssertEqual(thirdPage.getPermissionState(), "Denied")
}

func testLaunchArgumentNotProvided() {
let firstPage = FirstPage(app: getApp())
XCTAssertEqual(firstPage.argumentText.label, "Argument:Default")
}
}

0 comments on commit ab9ccb6

Please sign in to comment.