Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UI Test suite #314

Merged
merged 16 commits into from
Jul 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ jobs:
run: fastlane test platform:${{ matrix.platform[0] }} version:${{ matrix.platform[1] }} scheme:Introspect

- if: ${{ join(matrix.platform, ' ') != 'macos 11' }}
name: Run Tests (SwiftUIIntrospect, Debug)
name: Run Tests (SwiftUIIntrospect)
run: fastlane test platform:${{ matrix.platform[0] }} version:${{ matrix.platform[1] }} scheme:SwiftUIIntrospectTests configuration:Debug

- if: ${{ join(matrix.platform, ' ') != 'macos 11' }}
name: Run Tests (SwiftUIIntrospect, Release)
run: fastlane test platform:${{ matrix.platform[0] }} version:${{ matrix.platform[1] }} scheme:SwiftUIIntrospectTests configuration:Release
- if: ${{ matrix.platform[0] == 'ios' && matrix.platform[1] >= '14' && matrix.platform[1] <= '16' }}
name: Run UI Tests (SwiftUIIntrospect)
run: fastlane test platform:${{ matrix.platform[0] }} version:${{ matrix.platform[1] }} scheme:SwiftUIIntrospectUITests configuration:Debug
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"pins" : [
{
"identity" : "simulatorstatusmagic",
"kind" : "remoteSourceControl",
"location" : "https://github.com/shinydevelopment/SimulatorStatusMagic",
"state" : {
"revision" : "76095ec820674457a11dc3cc621d8a5c369eea0e",
"version" : "2.7.0"
}
},
{
"identity" : "swift-snapshot-testing",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-snapshot-testing.git",
"state" : {
"revision" : "dc46eeb3928a75390651fac6c1ef7f93ad59a73b",
"version" : "1.11.1"
}
}
],
"version" : 2
}
602 changes: 589 additions & 13 deletions Tests/Tests.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1500"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D58D833E2A66C5EC00A203BE"
BuildableName = "UITestsHostApp.app"
BlueprintName = "UITestsHostApp"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:UITests/UITests.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D58D833E2A66C5EC00A203BE"
BuildableName = "UITestsHostApp.app"
BlueprintName = "UITestsHostApp"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D58D833E2A66C5EC00A203BE"
BuildableName = "UITestsHostApp.app"
BlueprintName = "UITestsHostApp"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
30 changes: 30 additions & 0 deletions Tests/UITests/StatusBarStyleUITests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import SnapshotTesting
import XCTest

final class StatusBarStyleUITests: UITestCase {
override var testCase: TestCase {
.statusBarStyle
}

func test() throws {
guard #unavailable(iOS 17) else {
throw XCTSkip("SimulatorStatusMagic stopped working in iOS 17, so we can no longer consistently compare status bar screenshots")
}

app.buttons["Navigate To Detail"].tap()
app.buttons["Navigate To Detail"].tap()
app.buttons["Navigate Back"].tap()

let iOSDevice = UIDevice.current.userInterfaceIdiom == .pad ? "ipad" : "iphone"
let iOSVersion = ProcessInfo().operatingSystemVersion
func screenshotName(_ number: Int) -> String {
"\(iOSDevice)-ios-\(iOSVersion.majorVersion)-screenshot-\(number)"
}

assertSnapshot(
matching: app.windows.firstMatch.screenshot().image,
as: .image(perceptualPrecision: 0.95),
named: screenshotName(1)
)
}
}
21 changes: 21 additions & 0 deletions Tests/UITests/UITestCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import SimulatorStatusMagic
import XCTest

class UITestCase: XCTestCase {
var testCase: TestCase {
preconditionFailure("Please override this property")
}

let app = XCUIApplication()

override func invokeTest() {
SDStatusBarManager.sharedInstance().enableOverrides()

continueAfterFailure = false

app.launchEnvironment["testCase"] = testCase.rawValue
app.launch()

super.invokeTest()
}
}
24 changes: 24 additions & 0 deletions Tests/UITests/UITests.xctestplan
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"configurations" : [
{
"id" : "DD0EEECD-4762-4A68-91A8-F7B5A2209B45",
"name" : "Test Scheme Action",
"options" : {

}
}
],
"defaultOptions" : {

},
"testTargets" : [
{
"target" : {
"containerPath" : "container:Tests.xcodeproj",
"identifier" : "D58D832A2A66BDD500A203BE",
"name" : "UITests"
}
}
],
"version" : 1
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
6 changes: 6 additions & 0 deletions Tests/UITestsHostApp/Assets.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
8 changes: 8 additions & 0 deletions Tests/UITestsHostApp/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
32 changes: 32 additions & 0 deletions Tests/UITestsHostApp/StatusBarStyle/HostingController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// HostingController.swift
// Blago
//
// Created by Dmytro Chumakov on 04.05.2023.
//

import SwiftUI

final class HostingController<ContentView>: UIHostingController<ContentView> where ContentView: View {

var statusBarStyle: UIStatusBarStyle = .darkContent
var isInteractivePopGestureEnabled = true

override var preferredStatusBarStyle: UIStatusBarStyle {
statusBarStyle
}

override func viewDidLoad() {
super.viewDidLoad()
navigationController?.interactivePopGestureRecognizer?.isEnabled = isInteractivePopGestureEnabled
}

override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()

guard #available(iOS 16, *) else {
navigationController?.setNavigationBarHidden(true, animated: false)
return
}
}
}
44 changes: 44 additions & 0 deletions Tests/UITestsHostApp/StatusBarStyle/NavigationView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

//
// NavigationController.swift
// Blago
//
// Created by Dmytro Chumakov on 11.05.2023.
//

import UIKit

// MARK: - NavigationController

final class NavigationController: UINavigationController {

static var shared: UINavigationController?

// MARK: Lifecycle

override init(rootViewController: UIViewController) {
super.init(rootViewController: rootViewController)
setNavigationBarHidden(true, animated: false)
}

required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override var preferredStatusBarStyle: UIStatusBarStyle {
topViewController?.preferredStatusBarStyle ?? .default
}

override func viewDidLoad() {
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = self
}
}

// MARK: UIGestureRecognizerDelegate

extension NavigationController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_: UIGestureRecognizer) -> Bool {
viewControllers.count > 1
}
}
52 changes: 52 additions & 0 deletions Tests/UITestsHostApp/StatusBarStyle/RootView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// RootView.swift
// Showcase
//
// Created by Orackle on 14.07.2023.
//

import SwiftUI
import SwiftUIIntrospect

struct RootView: View {

var body: some View {
VStack {
Button("Navigate To Detail", action: navigateToDetail)
}
}

private func navigateToDetail() {
let controller = HostingController(rootView: DetailView())
controller.statusBarStyle = .lightContent
NavigationController.shared?.pushViewController(controller, animated: true)
}
}

struct DetailView: View {
@Environment(\.presentationMode) var dismiss

var body: some View {
ZStack {
Color.red.edgesIgnoringSafeArea(.all)

VStack {
Button("Navigate To Detail", action: navigateToDetail)
Button("Navigate Back", action: goBack)
}
}
.introspect(.viewController, on: .iOS(.v13, .v14, .v15, .v16)) { viewController in
/// some customizations there
}
}

private func goBack() {
dismiss.wrappedValue.dismiss()
}

private func navigateToDetail() {
let controller = HostingController(rootView: DetailView())
controller.statusBarStyle = .lightContent
NavigationController.shared?.pushViewController(controller, animated: true)
}
}
3 changes: 3 additions & 0 deletions Tests/UITestsHostApp/TestCases.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public enum TestCase: String {
case statusBarStyle = "Status Bar Style"
}
Loading