Skip to content

FIX: Incorrect behavior of .with(delay:) for ActionGroup#128

Open
killlilwinters wants to merge 6 commits into
1.5.2from
feature/incorrect-behavior-of-with-delay-for-actiongroup-guid_869dxz026
Open

FIX: Incorrect behavior of .with(delay:) for ActionGroup#128
killlilwinters wants to merge 6 commits into
1.5.2from
feature/incorrect-behavior-of-with-delay-for-actiongroup-guid_869dxz026

Conversation

@killlilwinters

@killlilwinters killlilwinters commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Description

This merge request fixes metadata loss when decorating nested ActionGroups. Previously, applying modifiers such as .with(animation:), .with(delay:), .silent(), or .binded(...) to a group only mapped the top-level internal actions. If a child action inside that group was itself wrapped in another ActionGroup, the modifier could be applied incorrectly to the wrapper or flatten the structure in a way that dropped child-level behavior.

The change is necessary because delayed and animated actions can be composed together, and nested groups must preserve both parent-applied metadata and child-specific metadata. The added test demonstrates the concrete failure case: a delayed group containing a child action with animation should still execute with the delay while keeping the child animation intact.

An alternative would have been to special-case each modifier’s group handling separately, but introducing a shared recursive mapping mechanism keeps the behavior consistent across all action decorators.

Changes Made

  • Added a recursive traversal utility to ActionGroup:

    • recursiveMap(_:) walks nested ActionGroups and applies transforms only to leaf InternalActions.
    • This centralizes nested-group handling instead of relying on shallow _actions.map(...).
  • Updated action decorators in Action.swift to use recursive mapping for grouped actions:

    • .with(animation:)
    • .silent()
    • .binded(...)
    • .with(delay:)
  • Added a regression test covering nested delay + animation composition:

    • Verifies that an action inside a delayed ActionGroup can retain its own animation.
    • Confirms ordering by dispatching an immediate “sentinel” update first, then asserting the delayed action applies afterward.
  • Increased the DelayedActionTests suite constraints with a 1-minute time limit to better bound async timing-based test execution.

ClickUp task

https://app.clickup.com/t/869dxz026

@killlilwinters killlilwinters added this to the 1.5.2 milestone Jun 30, 2026
@killlilwinters killlilwinters self-assigned this Jun 30, 2026
@killlilwinters killlilwinters added the bug Something isn't working label Jun 30, 2026
@killlilwinters killlilwinters linked an issue Jun 30, 2026 that may be closed by this pull request
Comment thread Tests/SwiftUI-UDF-Tests/Actions/DelayedActionTests.swift
Comment thread Tests/SwiftUI-UDF-Tests/Actions/DelayedActionTests.swift
Comment thread Tests/SwiftUI-UDF-Tests/Actions/DelayedActionTests.swift

var actions: [LoggingAction] {
lock.withLock { $0 }
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

нащо lock? ми ж в кожному тесті створюємо свій екземпляр ActionCollectorLogger

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В принципі якщо його прибрати то тести фейлитись не будуть але так як у нас тут EnvStore потік та потік наших тестів одночасно оперують над масивом то теоретично може бути race, ThreadSanitizer на це скаржився.

WARNING: ThreadSanitizer: Swift access race (pid=49329)
  Modifying access of Swift variable at 0x00010e9045f0 by thread T4:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect behavior of .with(delay:) for ActionGroup

3 participants