Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// ObservationUXTests.swift
// OpenSwiftUIUXTests

#if OPENSWIFTUI
import OpenObservation
import OpenSwiftUI
#else
import Observation
import SwiftUI
#endif
import Testing

@MainActor
@Suite
struct ObservationUXTests {
@Test
func stateModelMutationUpdatesBody() async throws {
var displayedCounts: [Int] = []
let content = CounterView { displayedCounts.append($0) }

try await withUXTestHost(of: content) { host in
try await host.waitUntil(displayedCounts == [0])
for count in 1...2 {
try await host.tap()
try await host.waitUntil(displayedCounts.last == count)
#expect(displayedCounts == Array(0...count))
}
}
}
}

@Observable
private final class CounterModel {
var count = 0
}

private struct CounterView: View {
@State private var model = CounterModel()
let onChange: (Int) -> Void

var body: some View {
let count = model.count
Text("\(count)")
.onTapGesture {
model.count += 1
}
.onChange(of: count, initial: true) { _, newValue in
onChange(newValue)
}
}
}
1 change: 1 addition & 0 deletions Example/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ let targets: [Target] = [
dependencies: [
.target(name: "TestingHost"),
.external(name: "Hammer"),
.external(name: "OpenSwiftUITestsSupport"),
] + privateFrameworkDependencies,
settings: settings(base: uxTestsSettings, xcconfig: "../Configurations/OpenSwiftUIUXTests.xcconfig")
),
Expand Down
54 changes: 39 additions & 15 deletions Example/Shared/Data/ObservationExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,55 @@ import Observation
import SwiftUI
#endif

struct ObservationExample: View {
var body: some View {
VStack {
ObservationColorExample()
Divider()
ObservationCounterExample()
}
}
}

@Observable
private class Model {
private class ColorModel {
var showRed = false
}

struct ObservationExample: View {
@State private var model = Model()

private var showRed: Bool {
get { model.showRed }
nonmutating set { model.showRed = newValue }
}
struct ObservationColorExample: View {
@State private var model = ColorModel()

var body: some View {
VStack {
Color(platformColor: showRed ? .red : .blue)
.frame(width: showRed ? 200 : 400, height: showRed ? 200 : 400)
}
.animation(.spring, value: showRed)
.onTapGesture {
showRed.toggle()
Color(model.showRed ? .red : .blue)
Text("Toggle")
.onTapGesture {
model.showRed.toggle()
}
}
}
}

#Preview {
ObservationExample()
ObservationColorExample()
}

@Observable
private final class CounterModel {
var count = 0
}

struct ObservationCounterExample: View {
@State private var model = CounterModel()

var body: some View {
Text("Tap to increase: \(model.count)")
.onTapGesture {
model.count += 1
}
}
}

#Preview {
ObservationCounterExample()
}
2 changes: 1 addition & 1 deletion Example/Tuist/Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 11 additions & 4 deletions Example/Tuist/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,11 @@ var packageProductTypes: [String: ProjectDescription.Product] = [
"OpenSwiftUITestsSupport": ProjectDescription.Product.staticFramework,
"OpenSwiftUISymbolDualTestsSupport": ProjectDescription.Product.staticFramework,
"OpenAttributeGraphShims": ProjectDescription.Product.staticFramework,
"OpenCoreGraphicsShims": ProjectDescription.Product.staticFramework,
"OpenObservation": ProjectDescription.Product.staticFramework,
"OpenQuartzCoreShims": ProjectDescription.Product.staticFramework,
"OpenRenderBoxShims": ProjectDescription.Product.staticFramework,
"OpenCoreGraphicsShims": ProjectDescription.Product.framework,
"OpenObservation": ProjectDescription.Product.framework,
"OpenObservationCxx": ProjectDescription.Product.staticFramework,
"OpenQuartzCoreShims": ProjectDescription.Product.framework,
"OpenRenderBoxShims": ProjectDescription.Product.framework,
"SymbolLocator": ProjectDescription.Product.staticFramework,
]

Expand Down Expand Up @@ -146,6 +147,12 @@ let packageSettings = PackageSettings(
defaultSettings: .essential,
defaultConfiguration: "OpenSwiftUIDebug"
),
"OpenSwiftUITestsSupport": .settings(
base: ["ENABLE_TESTING_SEARCH_PATHS": "YES"],
configurations: openSwiftUIPackageConfigurations,
defaultSettings: .essential,
defaultConfiguration: "OpenSwiftUIDebug"
),
"OpenSwiftUI": .settings(
base: openSwiftUITargetSettings,
configurations: openSwiftUIPackageConfigurations,
Expand Down
4 changes: 2 additions & 2 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ private func installObservationSlow<T>(
accessList: ObservationTracking._AccessList,
attribute: Attribute<T>
) {
guard let subgraph = attribute.identifier.subgraph2 else {
guard let subgraph = attribute.identifier.subgraphOrNil else {
return
}
let weakViewGraph = WeakUncheckedSendable(ViewGraph.current)
Expand Down
Loading