Skip to content

Commit

Permalink
more updates
Browse files Browse the repository at this point in the history
  • Loading branch information
shamanec committed Jul 23, 2023
1 parent 793aa5b commit 57ca60d
Show file tree
Hide file tree
Showing 13 changed files with 153 additions and 48 deletions.
24 changes: 20 additions & 4 deletions xcuitest-sample-proj.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@
FF79C2032A66F1B700BBC60A /* xcuitest_sample_projUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF79C2022A66F1B700BBC60A /* xcuitest_sample_projUITests.swift */; };
FF79C27F2A66F3A000BBC60A /* XCUIElement+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF79C27E2A66F3A000BBC60A /* XCUIElement+Extensions.swift */; };
FF79C2812A66F45200BBC60A /* XCUIElementQuery+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF79C2802A66F45200BBC60A /* XCUIElementQuery+Extensions.swift */; };
FF79C2832A66F54E00BBC60A /* Base.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF79C2822A66F54E00BBC60A /* Base.swift */; };
FF79C2832A66F54E00BBC60A /* BaseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF79C2822A66F54E00BBC60A /* BaseTest.swift */; };
FF79C2862A66F72200BBC60A /* TestConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF79C2852A66F72200BBC60A /* TestConstants.swift */; };
FF79C2892A66F9F500BBC60A /* InteractionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF79C2882A66F9F500BBC60A /* InteractionHelper.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 */; };
FFF034912A6CFA8B00A33E97 /* BasePage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFF034902A6CFA8B00A33E97 /* BasePage.swift */; };
FFF034932A6CFEA200A33E97 /* SecondPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFF034922A6CFEA200A33E97 /* SecondPage.swift */; };
FFF034952A6D027B00A33E97 /* TabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFF034942A6D027B00A33E97 /* TabBar.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -49,11 +53,15 @@
FF79C2022A66F1B700BBC60A /* xcuitest_sample_projUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = xcuitest_sample_projUITests.swift; sourceTree = "<group>"; };
FF79C27E2A66F3A000BBC60A /* XCUIElement+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCUIElement+Extensions.swift"; sourceTree = "<group>"; };
FF79C2802A66F45200BBC60A /* XCUIElementQuery+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCUIElementQuery+Extensions.swift"; sourceTree = "<group>"; };
FF79C2822A66F54E00BBC60A /* Base.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Base.swift; sourceTree = "<group>"; };
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 /* InteractionHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractionHelper.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>"; };
FFF034902A6CFA8B00A33E97 /* BasePage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasePage.swift; sourceTree = "<group>"; };
FFF034922A6CFEA200A33E97 /* SecondPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondPage.swift; sourceTree = "<group>"; };
FFF034942A6D027B00A33E97 /* TabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBar.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -84,6 +92,10 @@
FF4D5CAB2A67FDA300B52624 /* Pages */ = {
isa = PBXGroup;
children = (
FFF0348E2A6CFA6500A33E97 /* FirstPage.swift */,
FFF034902A6CFA8B00A33E97 /* BasePage.swift */,
FFF034922A6CFEA200A33E97 /* SecondPage.swift */,
FFF034942A6D027B00A33E97 /* TabBar.swift */,
);
path = Pages;
sourceTree = "<group>";
Expand Down Expand Up @@ -134,7 +146,7 @@
FF79C2842A66F71100BBC60A /* Props */,
FF79C27D2A66F31800BBC60A /* Extensions */,
FF79C2022A66F1B700BBC60A /* xcuitest_sample_projUITests.swift */,
FF79C2822A66F54E00BBC60A /* Base.swift */,
FF79C2822A66F54E00BBC60A /* BaseTest.swift */,
);
path = "xcuitest-sample-projUITests";
sourceTree = "<group>";
Expand Down Expand Up @@ -320,14 +332,18 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FF79C2832A66F54E00BBC60A /* Base.swift in Sources */,
FF79C2832A66F54E00BBC60A /* BaseTest.swift in Sources */,
FFF034932A6CFEA200A33E97 /* SecondPage.swift in Sources */,
FF79C2032A66F1B700BBC60A /* xcuitest_sample_projUITests.swift in Sources */,
FFF034952A6D027B00A33E97 /* TabBar.swift in Sources */,
FF79C2892A66F9F500BBC60A /* InteractionHelper.swift in Sources */,
FF4D5CB42A68146700B52624 /* Utils.swift in Sources */,
FF4D5CB02A68033C00B52624 /* ElementsHelper.swift in Sources */,
FFF0348F2A6CFA6500A33E97 /* FirstPage.swift in Sources */,
FF79C2862A66F72200BBC60A /* TestConstants.swift in Sources */,
FF79C27F2A66F3A000BBC60A /* XCUIElement+Extensions.swift in Sources */,
FF79C2812A66F45200BBC60A /* XCUIElementQuery+Extensions.swift in Sources */,
FFF034912A6CFA8B00A33E97 /* BasePage.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,37 @@
landmarkType = "3">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "3CA2097F-D0BD-4406-BE38-0BAA50C03851"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "xcuitest-sample-projUITests/xcuitest_sample_projUITests.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "52"
endingLineNumber = "52"
landmarkName = "testWaitForQueryHaveNumberOfElements()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "9EAF10C9-7D19-44BE-BCB4-4F11241BF119"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "xcuitest-sample-projUITests/xcuitest_sample_projUITests.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "36"
endingLineNumber = "36"
landmarkName = "testGetLastMatchFromQuery()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>
2 changes: 1 addition & 1 deletion xcuitest-sample-proj/Views/CarouselItemView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ struct CarouselItemView: View {
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
.accessibilityIdentifier("carousel_item\(item)")
.accessibilityIdentifier("carousel_item")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@

import XCTest

class Base: XCTestCase {
class BaseTest: XCTestCase {
private let defaultLoadingTime = 30.0
static var isReflectionIdleEnabled = false

public let app = XCUIApplication()
// Below for the developed app target
// let app = XCUIApplication()
private let app = XCUIApplication()

override func setUp() {
// Fail-fast tests
Expand All @@ -26,6 +23,18 @@ class Base: XCTestCase {
app.terminate()
}

func getApp() -> XCUIApplication {
return self.app
}

func getExternalApp(bundleIdentifier: String) -> XCUIApplication {
return XCUIApplication(bundleIdentifier: bundleIdentifier)
}

func printPageSource() {
print(app.debugDescription)
}

public func waitForPageLoading(element: XCUIElement) {
XCTAssertTrue(element.waitForExistence(timeout: defaultLoadingTime))
}
Expand All @@ -41,10 +50,10 @@ class Base: XCTestCase {
return
}

if state != Base.isReflectionIdleEnabled {
if state != BaseTest.isReflectionIdleEnabled {
method_exchangeImplementations(current, replaced)
print("[UITest] reflection idle hack " + (state ? "set" : "unset"))
Base.isReflectionIdleEnabled = state
BaseTest.isReflectionIdleEnabled = state
}
}

Expand Down
10 changes: 5 additions & 5 deletions xcuitest-sample-projUITests/Helpers/ElementsHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class ElementsHelper: XCTest {
/// - timeoutValue: How long to wait until the condition is met
/// - elementsCount: Minimum number of elements to expect in the XCUIElementQuery
/// - Returns: Boolean value if the condition was met and the query has at least the X number of elements
class func waitUntilTableFilled(elements: XCUIElementQuery,
class func waitUntilTableFilled(_ elements: XCUIElementQuery,
_ elementsCount: Int = 1,
_ timeoutValue: Double = TestConstants.Timeout.medium) {
var result = false
Expand Down Expand Up @@ -48,7 +48,7 @@ class ElementsHelper: XCTest {
/// - Parameters:
/// - element: XCUIElement that will be polled until it disappears
/// - timeoutValue: How long to poll the XCUIElement until it disappears
class func waitUntilElementDisappears(element: XCUIElement, timeoutValue: Double) {
class func waitUntilElementDisappears(_ element: XCUIElement, _ timeoutValue: Double) {
let startTime = Date().timeIntervalSince1970
var elementVisible = true

Expand All @@ -68,9 +68,9 @@ class ElementsHelper: XCTest {
/// - firstElement: The element for which we validate the position
/// - secondElement: The element against which we validate the first element position
/// - relativePosition: The expected position of the first element relative to the second element
class func validateElementToElementPosition(firstElement: XCUIElement,
secondElement: XCUIElement,
relativePosition: TestConstants.ElementPosition) {
class func validateElementToElementPosition(_ firstElement: XCUIElement,
_ secondElement: XCUIElement,
_ relativePosition: TestConstants.ElementPosition) {
var result = false
switch relativePosition {
case .leftOf:
Expand Down
5 changes: 1 addition & 4 deletions xcuitest-sample-projUITests/Helpers/InteractionHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
import XCTest

class InteractionHelper {

private static let app = XCUIApplication()

/// Gentler swipe alternative allowing swipe in specified XCUIElement
///
/// **Examples**
Expand Down Expand Up @@ -50,7 +47,7 @@ class InteractionHelper {
/// - direction: The direction of the swipe gesture, refer to `TestConstants` class for available options
/// - swipeAdjustment: CGFloat value for the size of the swipe gesture, refer to `TestConstants` class for available options
static func performGentleSwipe(_ direction: TestConstants.Direction, _ swipeAdjustment: CGFloat = TestConstants.SwipeAdjustment.normal) {
performGentleSwipe(app, direction, swipeAdjustment)
performGentleSwipe(BaseTest().getApp(), direction, swipeAdjustment)
}

/// Perform multiple gentle swipes
Expand Down
1 change: 0 additions & 1 deletion xcuitest-sample-projUITests/Helpers/Utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@
import Foundation

class Utils {

}
8 changes: 4 additions & 4 deletions xcuitest-sample-projUITests/Pages/BasePage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
// BasePage.swift
// xcuitest-sample-projUITests
//
// Created by Nikola Shabanov on 19.07.23.
// Created by Nikola Shabanov on 23.07.23.
//

import XCTest

class BasePage {
let app = XCUIApplication(bundleIdentifier: "com.apple.Preferences")
let app: XCUIApplication

func navigateBack() {
app.navigationBars.buttons.element(boundBy: 0).tap()
init() {
self.app = BaseTest().getApp()
}
}
14 changes: 14 additions & 0 deletions xcuitest-sample-projUITests/Pages/FirstPage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// FirstPage.swift
// xcuitest-sample-projUITests
//
// Created by Nikola Shabanov on 23.07.23.
//

import XCTest

class FirstPage: BasePage {
var carousel: XCUIElement { app.scrollViews.matching(identifier: "carousel-view").firstMatch }
var carouselItems: XCUIElementQuery { carousel.staticTexts }
var disappearingButton: XCUIElement { app.buttons["disappearing-button"] }
}
12 changes: 12 additions & 0 deletions xcuitest-sample-projUITests/Pages/SecondPage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// SecondPage.swift
// xcuitest-sample-projUITests
//
// Created by Nikola Shabanov on 23.07.23.
//

import XCTest

class SecondPage: BasePage {
var loadingElements: XCUIElementQuery { app.staticTexts.matching(identifier: "loaded-el") }
}
22 changes: 22 additions & 0 deletions xcuitest-sample-projUITests/Pages/TabBar.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// TabBar.swift
// xcuitest-sample-projUITests
//
// Created by Nikola Shabanov on 23.07.23.
//

import XCTest

class TabBar: BasePage {
private var defaultTabBar: XCUIElement { app }
private var firstPageButton: XCUIElement { defaultTabBar.buttons["Carousel"] }
private var secondPageButton: XCUIElement { defaultTabBar.buttons["Loading"] }

func openFirstPage() {
firstPageButton.tap()
}

func openSecondPage() {
secondPageButton.tap()
}
}
48 changes: 26 additions & 22 deletions xcuitest-sample-projUITests/xcuitest_sample_projUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,50 +7,54 @@

import XCTest

final class xcuitest_sample_projUITests: Base {
final class xcuitest_sample_projUITests: BaseTest {
let firstPage = FirstPage()
let secondPage = SecondPage()
let tabBar = TabBar()

func testGentleSwipeUntil() {
print(app.debugDescription)
InteractionHelper.performGentleSwipeUntil(app.scrollViews["carousel-view"], .left, 5, until: app.staticTexts["carousel_item10"].exists)
printPageSource()
InteractionHelper.performGentleSwipeUntil(firstPage.carousel, .left, 5, until: firstPage.carouselItems.element(matching: NSPredicate(format: "label CONTAINS[c] 'Item 10'")).exists)
}

func testGenericSwipeUntil() {
InteractionHelper.performSwipeUntil(app.scrollViews["carousel-view"], .left, 3, until: app.staticTexts["carousel_item10"].exists)
InteractionHelper.performSwipeUntil(firstPage.carousel, .left, 3, until: firstPage.carouselItems["Item 10"].exists)
}

func testElementToElementPositionPass() {
// This should pass
ElementsHelper.validateElementToElementPosition(firstElement: app.staticTexts["carousel_item2"], secondElement: app.staticTexts["carousel_item3"], relativePosition: .leftOf)
ElementsHelper.validateElementToElementPosition(firstPage.carouselItems["Item 2"], firstPage.carouselItems["Item 3"], .leftOf)
}

func testElementToElementPositionFail() {
// This should fail
ElementsHelper.validateElementToElementPosition(firstElement: app.staticTexts["carousel_item2"], secondElement: app.staticTexts["carousel_item3"], relativePosition: .rightOf)
ElementsHelper.validateElementToElementPosition(firstPage.carouselItems["Item 2"], firstPage.carouselItems["Item 3"], .rightOf)
}

func testGetLastMatchFromQuery() {
let text = firstPage.carouselItems.lastMatch.label
print("The label of the last matching element in the carousel is `\(text)`")
}

func testElementDisappearsSameScreen() {
app.buttons["Disappear"].tap()
let disappearingButton = app.buttons.element(matching: .button, identifier: "disappearing-button")
XCTAssertTrue(disappearingButton.isVisible)
disappearingButton.tap()
ElementsHelper.waitUntilElementDisappears(element: disappearingButton, timeoutValue: 6)
XCTAssertFalse(disappearingButton.isVisible)
XCTAssertTrue(firstPage.disappearingButton.isVisible)
firstPage.disappearingButton.tap()
ElementsHelper.waitUntilElementDisappears(firstPage.disappearingButton, 6)
XCTAssertFalse(firstPage.disappearingButton.isVisible)
}

func testElementNotExistChangeScreens() {
app.buttons["Disappear"].tap()
let button = app.buttons.element(matching: .button, identifier: "disappearing-button")
XCTAssertTrue(button.isVisible)
app.buttons["Carousel"].tap()
XCTAssertFalse(button.exists)
XCTAssertTrue(firstPage.disappearingButton.isVisible)
tabBar.openSecondPage()
XCTAssertFalse(firstPage.disappearingButton.exists)
}

func testWaitForQueryHaveNumberOfElements() {
app.buttons["Loading"].tap()
let elements = app.staticTexts.matching(identifier: "loaded-el")
// Wait for 11 seconds to have 5 elements, should pass
ElementsHelper.waitUntilTableFilled(elements: elements, 11, TestConstants.Timeout.medium)
tabBar.openSecondPage()
let elements = secondPage.loadingElements
// Wait for 10 seconds to have 5 elements, should pass
ElementsHelper.waitUntilTableFilled(elements, 5, TestConstants.Timeout.medium)
// Wait 5 more seconds to have 6 elements, should fail because only 5 in total will be loaded
ElementsHelper.waitUntilTableFilled(elements: elements, 6, TestConstants.Timeout.short)
ElementsHelper.waitUntilTableFilled(elements, 6, TestConstants.Timeout.short)
}
}

0 comments on commit 57ca60d

Please sign in to comment.