From c28317a766e61fe3846c58681c97d1b0b29c772c Mon Sep 17 00:00:00 2001 From: Kyle Date: Mon, 19 Oct 2026 15:39:13 +0800 Subject: [PATCH 1/2] fix: preserve content when applying transitions --- .../Animation/Transition/Transition.swift | 8 ++- .../Transition/TransitionTests.swift | 65 +++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 Tests/OpenSwiftUICoreTests/Animation/Transition/TransitionTests.swift diff --git a/Sources/OpenSwiftUICore/Animation/Transition/Transition.swift b/Sources/OpenSwiftUICore/Animation/Transition/Transition.swift index 586931d84..6828c6b20 100644 --- a/Sources/OpenSwiftUICore/Animation/Transition/Transition.swift +++ b/Sources/OpenSwiftUICore/Animation/Transition/Transition.swift @@ -153,10 +153,14 @@ package struct ApplyTransitionModifier: PrimitiveViewModifier, M inputs: _ViewInputs, body: @escaping (_Graph, _ViewInputs) -> _ViewOutputs ) -> _ViewOutputs { - .init() + TransitionType.makeView( + view: _GraphValue(Child(modifier: modifier.value)), + inputs: inputs, + body: body + ) } - nonisolated package static func _viewListCount( + nonisolated package static func viewListCount( inputs: _ViewListCountInputs, body: (_ViewListCountInputs) -> Int? ) -> Int? { diff --git a/Tests/OpenSwiftUICoreTests/Animation/Transition/TransitionTests.swift b/Tests/OpenSwiftUICoreTests/Animation/Transition/TransitionTests.swift new file mode 100644 index 000000000..9d4152f9d --- /dev/null +++ b/Tests/OpenSwiftUICoreTests/Animation/Transition/TransitionTests.swift @@ -0,0 +1,65 @@ +// +// TransitionTests.swift +// OpenSwiftUICoreTests + +import Foundation +import OpenAttributeGraphShims +@_spi(ForOpenSwiftUIOnly) @testable import OpenSwiftUICore +import Testing + +@MainActor +@Suite(.disabled(if: attributeGraphVendor == .oag)) +struct TransitionTests { + @Test + func viewListCountWitnessPreservesBodyCount() { + var bodyCalls = 0 + let count = viewListCount( + ApplyTransitionModifier.self, + inputs: _ViewListCountInputs(.init(.invalid)) + ) { _ in + bodyCalls += 1 + return 2 + } + #expect(count == 2) + #expect(bodyCalls == 1) + } + + @Test(arguments: [TransitionPhase.willAppear, .identity, .didDisappear]) + func combinedTransitionPreservesContentLayout(phase: TransitionPhase) { + checkLayout( + transition: MoveTransition(edge: .leading).combined(with: .opacity), + phase: phase + ) + } + + @Test(arguments: [TransitionPhase.willAppear, .identity, .didDisappear]) + func asymmetricTransitionPreservesContentLayout(phase: TransitionPhase) { + checkLayout( + transition: AsymmetricTransition( + insertion: MoveTransition(edge: .leading).combined(with: .opacity), + removal: OpacityTransition() + ), + phase: phase + ) + } + + private func checkLayout(transition: T, phase: TransitionPhase) { + let content = Color.red + .frame(width: 32, height: 48) + .modifier(ApplyTransitionModifier(transition: transition, phase: phase)) + Update.perform { + let graph = ViewGraph(rootViewType: type(of: content), requestedOutputs: .layout) + defer { graph.invalidate() } + graph.setRootView(content) + #expect(graph.sizeThatFits(.unspecified) == CGSize(width: 32, height: 48)) + } + } + + private func viewListCount( + _ modifier: M.Type, + inputs: _ViewListCountInputs, + body: (_ViewListCountInputs) -> Int? + ) -> Int? { + M._viewListCount(inputs: inputs, body: body) + } +} From e223e7b9267706e4396e9574da5865a6d09e3901 Mon Sep 17 00:00:00 2001 From: Kyle Date: Mon, 19 Oct 2026 23:15:15 +0800 Subject: [PATCH 2/2] test: tag transition regression tests as aigc --- .../Animation/Transition/TransitionTests.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/OpenSwiftUICoreTests/Animation/Transition/TransitionTests.swift b/Tests/OpenSwiftUICoreTests/Animation/Transition/TransitionTests.swift index 9d4152f9d..5f43a1170 100644 --- a/Tests/OpenSwiftUICoreTests/Animation/Transition/TransitionTests.swift +++ b/Tests/OpenSwiftUICoreTests/Animation/Transition/TransitionTests.swift @@ -5,10 +5,11 @@ import Foundation import OpenAttributeGraphShims @_spi(ForOpenSwiftUIOnly) @testable import OpenSwiftUICore +import OpenSwiftUITestsSupport import Testing @MainActor -@Suite(.disabled(if: attributeGraphVendor == .oag)) +@Suite(.tags(.aigc), .disabled(if: attributeGraphVendor == .oag)) struct TransitionTests { @Test func viewListCountWitnessPreservesBodyCount() {