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
4 changes: 4 additions & 0 deletions Configurations/OpenSwiftUIUITests.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ CODE_SIGN_ENTITLEMENTS = TestingHost/TestingHost.entitlements

// Remove -module_alias Testing=_Testing_Unavailable
OTHER_SWIFT_FLAGS = $(OPENSWIFTUI_AVAILABILITY_MACRO)

CLANG_ENABLE_MODULES = YES;

SWIFT_OBJC_BRIDGING_HEADER = OpenSwiftUIUITests/OpenSwiftUIUITests-Bridging-Header.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// AnimationCompletionUITests.swift
// OpenSwiftUIUITests

import Testing
import SnapshotTesting

@MainActor
@Suite(.snapshots(record: .never, diffTool: diffTool))
struct AnimationCompletionUITests {
@Test
func logicalAndRemovedComplete() {
struct ContentView: AnimationTestView {
nonisolated static var model: AnimationTestModel {
AnimationTestModel(duration: 3, count: 3)
}

@State private var opacity = 1.0
@State private var scale = 1.0

@State private var showGreen = false
@State private var showBlue = false

var body: some View {
ZStack {
Color.red
.frame(width: 100 * scale, height: 100 * scale)
.opacity(opacity)
if showGreen { Color.green.frame(width: 20, height: 20) }
if showBlue { Color.blue.frame(width: 10, height: 10) }
}
.onAppear {
let animation = Animation.linear(duration: 2)
.logicallyComplete(after: 1)
withAnimation(animation, completionCriteria: .logicallyComplete) {
opacity = 0.1
} completion: {
showGreen.toggle()
}
withAnimation(animation, completionCriteria: .removed) {
scale = 0.1
} completion: {
showBlue.toggle()
}
}
}
}
// When run seperately, precision: 1.0 works fine
// but in the full suite, it will hit the same issue of #340
withKnownIssue("#340", isIntermittent: true) {
openSwiftUIAssertAnimationSnapshot(
of: ContentView()
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//
// BezierAnimationUITests.swift
// OpenSwiftUIUITests

import Testing
import SnapshotTesting

@MainActor
@Suite(.snapshots(record: .never, diffTool: diffTool))
struct BezierAnimationUITests {
@Test
func colorRow() {
struct ContentView: AnimationTestView {
nonisolated static var model: AnimationTestModel {
AnimationTestModel(duration: 2, count: 5)
}

@State private var animate = false
private var animationDuration: Double { Self.model.duration }

var body: some View {
VStack(spacing: 10) {
AnimationRow(
color: .blue,
animate: animate,
animation: .linear(duration: animationDuration)
)
AnimationRow(
color: .green,
animate: animate,
animation: .easeIn(duration: animationDuration)
)
AnimationRow(
color: .red,
animate: animate,
animation: .easeOut(duration: animationDuration)
)
AnimationRow(
color: .orange,
animate: animate,
animation: .easeInOut(duration: animationDuration)
)
AnimationRow(
color: .purple,
animate: animate,
animation: .timingCurve(0.68, -0.6, 0.32, 1.6, duration: animationDuration)
)
}
.padding()
.frame(width: 200, height: 200)
.onAppear {
animate.toggle()
}
}
struct AnimationRow: View {
let color: Color
let animate: Bool
let animation: Animation

private let squareSize: CGFloat = 20.0

var body: some View {
GeometryReader { geometry in
ZStack(alignment: .leading) {
Color.black.opacity(0.1)
color
// TODO: Color interpolation not aligned yet
// Color(animate ? color : .gray)
.frame(width: squareSize, height: squareSize)
.offset(x: animate ? geometry.size.width - squareSize : 0)
}
}
.frame(height: squareSize)
.animation(animation, value: animate)
}
}
}
// When run seperately, precision: 1.0 works fine
// but in the full suite, it will hit the same issue of #340
withKnownIssue("$340", isIntermittent: true) {
openSwiftUIAssertAnimationSnapshot(
of: ContentView(),
)
}
}
}
4 changes: 3 additions & 1 deletion Example/OpenSwiftUIUITests/Graphic/Color/ColorUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ struct ColorUITests {
}
}
}
openSwiftUIAssertAnimationSnapshot(of: ContentView())
withKnownIssue("#340", isIntermittent: true) {
openSwiftUIAssertAnimationSnapshot(of: ContentView())
}
}

// FIXME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct DynamicLayoutViewUITests {
@Test
func dynamicLayout() {
struct ContentView: View {
@State var show = false
@State private var show = false
var body: some View {
VStack {
Color.red
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//

#import "AnimationDebugControllerHelper.h"
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// OpenSwiftUIUITests

import Foundation
import OpenSwiftUI_SPI

struct AnimationTestModel: Hashable {
var intervals: [Double]
Expand Down Expand Up @@ -99,17 +98,23 @@ final class AnimationDebugController<V>: PlatformHostingController<V> where V: V
// Avoid generic parameter casting
private protocol AnimationDebuggableController: PlatformViewController {
var disableLayoutSubview: Bool { get set }

func advance(interval: Double)
}

extension AnimationDebugController: AnimationDebuggableController {}

extension PlatformView {
// Fix swift-snapshot-testing trigger extra layoutSubviews and advance time issue
@objc func swizzled_layoutSubviews() {
guard let vc = _viewControllerForAncestor as? AnimationDebuggableController else {
swizzled_layoutSubviews()
return
}
guard !vc.disableLayoutSubview else {
// superLayoutSubviews(type(of: self))
// Fix swift-snapshot-testing set initialFrame as .zero and then trigger setProposedSize(.zero) causing DisplayList layout issue (View is placed at topLeft instead of center)
vc.advance(interval: .zero)
return
}
swizzled_layoutSubviews()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// AnimationDebugControllerHelper.h
// OpenSwiftUIUITests

#import <Foundation/Foundation.h>

#if TARGET_OS_IPHONE

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIView (OpenSwiftUIUITests)
@property(nonatomic, readonly, nullable) UIViewController *_viewControllerForAncestor;
@end

void superLayoutSubviews(Class cls);

NS_ASSUME_NONNULL_END


#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// AnimationDebugControllerHelper.m
// OpenSwiftUIUITests

#import "AnimationDebugControllerHelper.h"
#import <objc/runtime.h>
#import <objc/message.h>

#if TARGET_OS_IPHONE

void superLayoutSubviews(Class cls) {
((void (*)(struct objc_super *, SEL))(void *)objc_msgSendSuper)(&((struct objc_super){(id)cls, (id)class_getSuperclass(cls)}), sel_registerName("layoutSubviews"));
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,32 @@ struct ForEachUITests {
}
openSwiftUIAssertSnapshot(of: ContentView())
}

@Test
func insertAnimation() {
struct ContentView: AnimationTestView {
nonisolated static var model: AnimationTestModel {
AnimationTestModel(duration: 1.0, count: 5)
}

@State private var opacities = [0, 0.5, 1.0]

var body: some View {
VStack(spacing: 0) {
ForEach(opacities, id: \.self) { opacity in
Color.red.opacity(opacity)
}
}.onAppear {
withAnimation(.spring(duration: Self.model.duration)) {
opacities.insert(0.25, at: 1)
opacities.insert(0.75, at: 3)
}
}
}
}
withKnownIssue("#632") {
Issue.record("AttributeGraph precondition failure: accessing attribute in a different namespace: 36376.")
// openSwiftUIAssertAnimationSnapshot(of: ContentView())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import SwiftUI
#endif

struct DynamicLayoutViewExample: View {
@State var show = false
@State private var show = false
var body: some View {
VStack {
Color.red
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,8 @@ struct ForEachKeyPathExample: View {
}
}

// TODO: Animation test case
struct ForEachDynamicView: View {
@State var opacities = [0, 0.5, 1.0]
@State private var opacities = [0, 0.5, 1.0]

var body: some View {
VStack(spacing: 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ struct AnimationCompletionCompatibilityTests {
)
)
}
#expect(Helper.values == [1, 2])
withKnownIssue(isIntermittent: true) {
#expect(Helper.values == [1, 2])
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ struct ChangedBodyPropertyCompatibilityTests {
@Test
func statePropertyView() throws {
struct ContentView: View {
@State var name = ""
@State private var name = ""
var body: some View {
let _ = Self._logChanges()
AnyView(EmptyView())
Expand Down
Loading