Skip to content

AXComponentKit 2.0: Swift 6, @AXScreen macro, dynamic component enhancements - #4

Open
Chris Stroud (Clstroud) wants to merge 8 commits into
mainfrom
enhancement/wip-modernization
Open

AXComponentKit 2.0: Swift 6, @AXScreen macro, dynamic component enhancements#4
Chris Stroud (Clstroud) wants to merge 8 commits into
mainfrom
enhancement/wip-modernization

Conversation

@Clstroud

@ClstroudChris Stroud (Clstroud) commented May 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

Major modernization of AXComponentKit, bringing it to Swift 6.0 with full strict concurrency compliance, a new @AXScreen macro, enhanced dynamic component APIs, and comprehensive documentation.

Changes

Core Library

  • Swift 6 / iOS 16+: Bumped swift-tools-version to 6.0, minimum deployment to iOS 16 / macOS 13. Full strict concurrency (Sendable, @MainActor) compliance throughout.
  • @AXScreen macro: Auto-generates screenIdentifier from PascalCase struct names. Optional — manual AXScreen conformance still works.
  • AXIdentifierConvertible protocol: Collapsed 4× generic overload explosion into a single protocol-based API.
  • Navigator ergonomics: AXScreen.navigator static property, performNavigationnavigate rename, tap() convenience methods.
  • Animation suppression: First-class .automationOptimized() view modifier and AXAutomation.suppressAnimationsIfNeeded() for UIKit — no-op in production.
  • AXFailure refactor: Avoids double failure output on assertion failures.
  • VoiceOver fix: Accessibility modifiers no longer interfere with VoiceOver navigation.
  • Scroll reliability: Tighter gesture ranges and restored press duration for consistent scrolling.
  • XCTestCase async setUp bridge removed: Deprecated in favor of native setUp() async throws.

Dynamic Component Enhancements (new in this PR)

  • Optional-value automationComponent: When value is nil, no identifier is applied — useful for loading/placeholder states.
  • Prefixed automationComponent: Adds a custom prefix to distinguish elements sharing a component definition (e.g. "featured-catalog-category_electronics").
  • firstElement(anyOf:) / tapFirst(anyOf:): Query/tap the first element matching a dynamic component's prefix when the exact value is unknown at test time.
  • AXDynamicComponent.prefix made public: Enables downstream prefix-based queries.
  • Navigator screen-appear logging: NSLog breadcrumb on screen transitions for debugging.

Sample App

  • Expanded from 2-tab to 4-tab comprehensive demo (catalog, profile, settings).
  • Deep navigation test coverage (catalog → category → item detail).
  • Capability protocols (DismissibleScreen, NavigationScreen).
  • Converted to xctestplan format.

Documentation

  • Comprehensive README with installation, quick start, animation suppression, and dynamic component examples.
  • Updated all DocC articles: IntegratingWithViews, WritingYourFirstTest, NavigatorFundamentals, CustomNavigatorOperations, ScreenModels, Overview, Philosophy.
  • Version references bumped to 2.0.0.

Test plan

  • AXComponentKit target builds for iOS Simulator
  • AXComponentKitTestSupport target builds for iOS Simulator
  • Sample app builds and runs on simulator
  • Sample app UI tests pass with xctestplan

@moyerr

Copy link
Copy Markdown
Collaborator

Copilot Please review

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR modernizes AXComponentKit for Swift 6 with stricter concurrency semantics, introduces an optional @AXScreen macro for auto-synthesized screen identifiers/conformance, and expands the dynamic component + navigator APIs to improve UI test ergonomics and reliability (along with significant documentation and sample app updates).

Changes:

  • Added @AXScreen macro support (new macro targets + swift-syntax dependency) and migrated screen models toward Sendable/@MainActor usage.
  • Simplified dynamic component APIs around AXIdentifierConvertible, added optional/prefixed dynamic identifiers, and added prefix-based “first match” querying helpers.
  • Updated navigator/test support ergonomics (e.g., navigator property, navigate rename, animation suppression helpers), plus refreshed sample app UI tests and DocC/README.

Reviewed changes

Copilot reviewed 80 out of 80 changed files in this pull request and generated 23 comments.

Show a summary per file
FileDescription
Sources/AXComponentKitTestSupport/XCTestCase+AsyncSetup.swiftRemoved legacy async setUp(completion:) helper.
Sources/AXComponentKitTestSupport/Navigation/ScrollTransaction.swiftAdjusted scroll gesture coordinate ranges.
Sources/AXComponentKitTestSupport/Navigation/AXTabComponent.swiftMade tab component Sendable; exposed name.
Sources/AXComponentKitTestSupport/Navigation/AXTabBarNavigable.swiftUpdated tab navigation to use renamed navigator API.
Sources/AXComponentKitTestSupport/Navigation/AXScreenNavigator+Scrolling.swiftSimplified dynamic scroll overloads; tweaked timing/velocity.
Sources/AXComponentKitTestSupport/Navigation/AXScreenNavigator.swiftAdded AXScreen.navigator; renamed navigation API; added breadcrumb log.
Sources/AXComponentKitTestSupport/Launch/XCUIApplication+AutomationLaunch.swiftAdded automation-configured app launch helpers.
Sources/AXComponentKitTestSupport/Existence/XCUIElement+Existence.swiftImproved existence waiting; routed failures through AXFailure.fail.
Sources/AXComponentKitTestSupport/Element Querying/AXScreenModel+Tap.swiftAdded AXScreen.tap(...) convenience helpers.
Sources/AXComponentKitTestSupport/Element Querying/AXScreenModel+TabComponents.swiftHardened tab item label predicate construction.
Sources/AXComponentKitTestSupport/Element Querying/AXScreenModel+FirstDynamicElement.swiftAdded prefix-based “first dynamic element” query/tap helpers.
Sources/AXComponentKitTestSupport/Element Querying/AXScreenModel+DynamicElements.swiftConsolidated dynamic element querying around AXIdentifierConvertible.
Sources/AXComponentKitTestSupport/Element Querying/AXScreenModel+AssumedElements.swiftConsolidated assumed-element APIs around AXIdentifierConvertible.
Sources/AXComponentKitTestSupport/AXFailure.swiftRefactored failure reporting to central fail(...) helper.
Sources/AXComponentKitTestSupport/AXComponentKitTestSupport.docc/WritingYourFirstTest.mdUpdated examples to async setUp and new APIs.
Sources/AXComponentKitTestSupport/AXComponentKitTestSupport.docc/NavigatorFundamentals.mdUpdated docs for navigator and navigate rename.
Sources/AXComponentKitTestSupport/AXComponentKitTestSupport.docc/CustomNavigatorOperations.mdUpdated docs for new navigator call patterns.
Sources/AXComponentKitMacroSupport/Exports.swiftRe-exported AXComponentKit from macro support product.
Sources/AXComponentKitMacroSupport/AXScreenMacroDeclaration.swiftDeclared @AXScreen macros (default/custom identifier).
Sources/AXComponentKitMacros/Plugin.swiftAdded Swift compiler plugin entry point.
Sources/AXComponentKitMacros/AXScreenMacro.swiftImplemented macro expansion + identifier derivation.
Sources/AXComponentKit/Screen Models/AXScreenModel+Components.swiftSimplified dynamic component resolution API surface.
Sources/AXComponentKit/Screen Models/AXScreen.swiftMade AXScreenSendable.
Sources/AXComponentKit/Extensions/Temporal/Measurement+TimeInterval.swiftRemoved explicit Measurement: Sendable conformance.
Sources/AXComponentKit/Extensions/App UI/View+ScreenIdentityModifier.swiftAdjusted accessibility wrapping to avoid VoiceOver interference.
Sources/AXComponentKit/Extensions/App UI/View+AXScrollView.swiftAdjusted accessibility wrapping for scroll views.
Sources/AXComponentKit/Extensions/App UI/View+AXDynamicComponent.swiftAdded optional/prefixed dynamic identifier modifiers; unified constraints.
Sources/AXComponentKit/Extensions/App UI/View+AXComponent.swiftRemoved optional component overload that emitted "undefined".
Sources/AXComponentKit/Extensions/App UI/View+AnimationSuppression.swiftAdded .automationOptimized() view modifier.
Sources/AXComponentKit/Configuration/AXAutomation.swiftAdded automation runner detection + animation suppression entry point.
Sources/AXComponentKit/Configuration/AnimationSuppressor.swiftImplemented UIKit/Core Animation suppression mechanics.
Sources/AXComponentKit/AXComponentKit.docc/ScreenModels.mdDocumented @AXScreen macro + AXIdentifierConvertible guidance.
Sources/AXComponentKit/AXComponentKit.docc/Overview.mdFilled in framework overview and setup guidance.
Sources/AXComponentKit/AXComponentKit.docc/IntegratingWithViews.mdDocumented optional/prefixed dynamics + animation suppression usage.
Sources/AXComponentKit/AX Components/Static Components/AXScrollView.swiftMarked AXScrollView as Sendable.
Sources/AXComponentKit/AX Components/Static Components/AXComponent.swiftMarked AXComponent as Sendable.
Sources/AXComponentKit/AX Components/Dynamic Components/AXIdentifierConvertible.swiftAdded AXIdentifierConvertible + stdlib conformances.
Sources/AXComponentKit/AX Components/Dynamic Components/AXDynamicValue.swiftMade AXDynamicValue refine AXIdentifierConvertible.
Sources/AXComponentKit/AX Components/Dynamic Components/AXDynamicComponent.swiftConstrained dynamic values to AXIdentifierConvertible; made prefix public.
README.mdReplaced stub with full README + examples.
Package.swiftBumped tools/platforms; added macro targets + swift-syntax dependency.
AXComponentKitSample/UITests/SettingsScreenTests.swiftAdded Settings UI tests using new APIs.
AXComponentKitSample/UITests/SecondTabScreenTests.swiftUpdated sample tests to async setUp + navigator APIs.
AXComponentKitSample/UITests/Screens+TestSupport/ShareScreen+TestSupport.swiftAdded Share screen capability conformance.
AXComponentKitSample/UITests/Screens+TestSupport/SettingsScreen+TestSupport.swiftAdded Settings screen capability conformance.
AXComponentKitSample/UITests/Screens+TestSupport/SettingsScreen+Navigator.swiftAdded Settings→Profile navigator op.
AXComponentKitSample/UITests/Screens+TestSupport/SecondTabScreen+Navigator.swiftUpdated navigator op to renamed navigate.
AXComponentKitSample/UITests/Screens+TestSupport/ProfileScreen+TestSupport.swiftAdded dismissible conformance mapping.
AXComponentKitSample/UITests/Screens+TestSupport/ProfileScreen+Navigator.swiftAdded profile save navigator op.
AXComponentKitSample/UITests/Screens+TestSupport/ItemDetailScreen+Navigator.swiftAdded item detail → share navigator op.
AXComponentKitSample/UITests/Screens+TestSupport/FirstTabScreen+Navigator.swiftUpdated First tab navigator to new tap/navigate API.
AXComponentKitSample/UITests/Screens+TestSupport/CategoryDetailScreen+Navigator.swiftAdded category detail → item navigator op.
AXComponentKitSample/UITests/Screens+TestSupport/CatalogScreen+TestSupport.swiftAdded Catalog screen tab capability conformance.
AXComponentKitSample/UITests/Screens+TestSupport/CatalogScreen+Navigator.swiftAdded catalog → category navigator op.
AXComponentKitSample/UITests/FirstTabScreenTests.swiftUpdated sample tests to async setUp + navigator APIs.
AXComponentKitSample/UITests/DeepNavigationTests.swiftAdded deep navigation chain tests.
AXComponentKitSample/UITests/CatalogScreenTests.swiftAdded catalog tests covering dynamic components.
AXComponentKitSample/UITests/Capabilities/RootTabBarNavigable.swiftExpanded sample tab capabilities (settings/catalog).
AXComponentKitSample/UITests/Capabilities/DismissibleScreen.swiftAdded dismissible capability + navigator dismiss helper.
AXComponentKitSample/UITests/AXComponentKitSample.xctestplanAdded xctestplan for sample UI tests.
AXComponentKitSample/AXComponentKitSample/Views/Third Tab/SettingsView.swiftAdded Settings SwiftUI view with automation identifiers.
AXComponentKitSample/AXComponentKitSample/Views/Third Tab/ProfileView.swiftAdded Profile SwiftUI view with dynamic/static identifiers.
AXComponentKitSample/AXComponentKitSample/Views/Shared/ShareSheetView.swiftAdded Share sheet view with automation identifiers.
AXComponentKitSample/AXComponentKitSample/Views/Fourth Tab/ItemDetailView.swiftAdded Item detail view and identifiers.
AXComponentKitSample/AXComponentKitSample/Views/Fourth Tab/CategoryDetailView.swiftAdded Category detail view with dynamic identifiers.
AXComponentKitSample/AXComponentKitSample/Views/Fourth Tab/CatalogView.swiftAdded Catalog view with dynamic + scroll view identifiers.
AXComponentKitSample/AXComponentKitSample/Views/ContentView.swiftExpanded sample app to 4 tabs.
AXComponentKitSample/AXComponentKitSample/AXScreens/ShareScreen.swiftAdded screen model using @AXScreen.
AXComponentKitSample/AXComponentKitSample/AXScreens/SettingsScreen.swiftAdded screen model using @AXScreen.
AXComponentKitSample/AXComponentKitSample/AXScreens/SecondTabScreen.swiftMigrated screen model to @AXScreen.
AXComponentKitSample/AXComponentKitSample/AXScreens/ProfileScreen.swiftAdded screen model using @AXScreen.
AXComponentKitSample/AXComponentKitSample/AXScreens/ItemDetailScreen.swiftAdded screen model using @AXScreen.
AXComponentKitSample/AXComponentKitSample/AXScreens/FirstTabScreen.swiftMigrated screen model to @AXScreen.
AXComponentKitSample/AXComponentKitSample/AXScreens/DetailScreen.swiftMigrated screen model to @AXScreen.
AXComponentKitSample/AXComponentKitSample/AXScreens/CategoryDetailScreen.swiftAdded screen model using @AXScreen.
AXComponentKitSample/AXComponentKitSample/AXScreens/Category.swiftAdded sample dynamic value type (AXDynamicValue).
AXComponentKitSample/AXComponentKitSample/AXScreens/CatalogScreen.swiftAdded screen model using @AXScreen.
AXComponentKitSample/AXComponentKitSample/AXComponentKitSampleApp.swiftEnabled .automationOptimized() at app root.
AXComponentKitSample/AXComponentKitSample.xcodeproj/xcshareddata/xcschemes/AXComponentKitSample.xcschemeUpdated scheme to use test plan.
AXComponentKitSample/AXComponentKitSample.xcodeproj/project.pbxprojUpdated project format + package/framework linkage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadSources/AXComponentKitTestSupport/AXFailure.swift
Comment threadSources/AXComponentKitMacros/AXScreenMacro.swift
Comment threadSources/AXComponentKitMacros/AXScreenMacro.swift
Comment threadSources/AXComponentKitMacros/AXScreenMacro.swift
…component enhancements
- Bump swift-tools-version to 6.0, minimum deployment to iOS 16 / macOS 13
- Full Swift 6 strict concurrency compliance (Sendable, @mainactor)
- Add @AXScreen macro for automatic screenIdentifier synthesis
- Introduce AXIdentifierConvertible protocol, collapsing 4× overload explosion
- Refactor navigator: static .navigator property, rename performNavigation→navigate, add tap convenience
- Add optional-value and prefixed automationComponent view modifiers for dynamic components
- Add firstElement(anyOf:) and tapFirst(anyOf:) for prefix-based dynamic element queries
- Make AXDynamicComponent.prefix public for downstream query use
- Add navigator screen-appear logging via NSLog
- Add animation suppression system for UIKit, Core Animation, and SwiftUI
- Refactor AXFailure to avoid double failure output
- Fix accessibility modifiers interfering with VoiceOver
- Fix NSPredicate injection in tab query
- Improve scroll gesture reliability
- Remove deprecated XCTestCase async setUp bridge
- Add four-tab layout with catalog, profile, and settings screens
- Add deep navigation test coverage (catalog → category → item detail)
- Add capability protocols (DismissibleScreen, NavigationScreen)
- Convert UI tests to xctestplan format
- Demonstrate @AXScreen macro, animation suppression, and tab navigation
- Rewrite README with installation, quick start, animation suppression, and dynamic component sections
- Document optional-value and prefixed automationComponent overloads in IntegratingWithViews
- Document firstElement(anyOf:) and tapFirst(anyOf:) in WritingYourFirstTest
- Update navigator documentation for static .navigator property and navigate() rename
- Refresh Overview, ScreenModels, and CustomNavigatorOperations docc articles
…t interpolated macro identifiers
- Add explicit `import Foundation` to AXScreenNavigator.swift instead of
relying on transitive import from XCTest for NSLog availability
- Add `segments.count == 1` guard in @AXScreen macro's extractIdentifier
to fall back to auto-derived name instead of silently truncating
interpolated string literals
@Clstroud
Chris Stroud (Clstroud)force-pushed the enhancement/wip-modernization branch from 8d2c9fd to 08a9be2CompareMay 20, 2026 18:52
@Clstroud

Copy link
Copy Markdown
CollaboratorAuthor

Review feedback response

Thanks for the thorough review! Here's a breakdown of how we addressed each comment:

Accepted (fixed in 08a9be2)

  • Comment 2 (NSLog without Foundation import): Added explicit import Foundation to AXScreenNavigator.swift. The transitive import from XCTest works today, but explicit is better.
  • Comment 5 (interpolated string literal truncation): Added a segments.count == 1 guard in extractIdentifier. Interpolated strings now fall back to the auto-derived kebab-case name instead of silently truncating.

Not applicable — explained below

  • Comment 1 (#filePath vs StaticString): #filePath returns StaticString, not String. Both #file and #filePath produce StaticString when used as default parameter values — the difference is what path they expand to, not their type. No fix needed.

  • Comment 3 (char.lowercased() append won't compile): String has mutating func append(_ other: String) in addition to append(_ c: Character). Since Character.lowercased() returns String, this resolves to the String overload and compiles fine.

  • Comment 4 (PascalCase→kebab-case wrong for acronyms like UIKit):
    Tracing "UIKit" through the algorithm:

    • U (idx 0): no hyphen → "u"
    • I (idx 1): prev is uppercase, next is uppercase → no hyphen → "ui"
    • K (idx 2): prev is uppercase, next is lowercase + idx>0 → hyphen → "ui-k"
    • i,t"ui-kit"

    Also verified: URLSession"url-session", AXScreen"ax-screen", FirstTabScreen"first-tab-screen".

  • Comment 6 (missing where Value: AXIdentifierConvertible): The constraint is structurally enforced by AXDynamicComponent<Value> itself, which declares where Value: AXIdentifierConvertible on the type. Swift infers this from the KeyPath usage — you cannot form KeyPath<Self, AXDynamicComponent<Value>> without Value satisfying the constraint.

  • Comments 7–22 (UI tests need @testable import): The screen model source files have dual target membership — they're compiled directly into both the app target and the UITests target via PBXFileSystemSynchronizedBuildFileExceptionSet in the Xcode project (the membershipExceptions list). No cross-module import is needed because the types are native to the test module.

Also in this push

@Nitewriter

Joel Garrett (Nitewriter) commented May 20, 2026

Copy link
Copy Markdown
Member

Reviewed top-to-bottom. The modernization is genuinely strong — net public surface is smaller and more coherent, the AXIdentifierConvertible consolidation in particular is the right "deep module, narrow interface" move and replaces four parametric overloads cleanly. Two HIGH findings below with mechanical reproducers, plus a procedural nudge. Happy to open a follow-up PR for the fixes if useful.

H1 — firstElement(anyOf:) silently misses prefixed identifiers

The prefixed automationComponent(_:value:prefix:) variant (View+AXDynamicComponent.swift:64-72) produces identifiers of the form "{userPrefix}-{component.prefix}_{value}". The README's worked example resolves to "featured-catalog-category_electronics".

But firstElement(anyOf:) queries via:

letprefix=Self()[keyPath: path].prefix
letpredicate=NSPredicate(format:"identifier BEGINSWITH %@", prefix)

…using only component.prefix, which in this case is "catalog-category". The prefixed identifier doesn't begin with that, so the predicate misses it. Result: a writer who adopts the prefix: overload silently loses firstElement(anyOf:) / tapFirst(anyOf:) coverage — no compile error, no runtime warning, just a hang until the timeout fires.

Self-contained reproducer (uses the actual codepaths verbatim against Foundation's NSPredicate): https://gist.github.com/Nitewriter/fc323b1c400d0d3e8b81e032bffb9302

Run output:

Writer-produced identifier: featured-catalog-category_electronics
Reader predicate: identifier BEGINSWITH "catalog-category"
Predicate matches the prefixed identifier: false
Control — non-prefixed identifier: catalog-category_electronics
Control — predicate matches: true

Fix I'd suggest: an overload firstElement(anyOf:withPrefix:) mirroring the writer-side API — preserves exact-prefix-match semantics. (Switching to CONTAINS works but invites accidental collisions; pure docs deferral leaves the silent-miss UX in place.)

H2 — @AXScreen macro emits redundant member and conformance

The ExtensionMacro.expansion(...) in AXScreenMacro.swift:28-44 ignores the compiler-supplied protocols parameter and always emits extension Type: AXScreen {}. The MemberMacro.expansion(...) at :8-24 similarly emits static let screenIdentifier without inspecting existing members. Both make @AXScreen mutually exclusive with any pre-existing explicit conformance or manual identifier.

Reproduced against AXComponentKitSample on this branch (Xcode 26.5, iOS 26.5 simulator destination). Repo unmodified afterward.

Half 1 — added : AXScreen to CatalogScreen's declaration, xcodebuild build emits:

@__swiftmacro_20AXComponentKitSample13CatalogScreen8AXScreenfMe_.swift:1:26:
error: redundant conformance of 'CatalogScreen' to protocol 'AXScreen'
CatalogScreen.swift:4:1: note: in expansion of macro 'AXScreen' on struct 'CatalogScreen' here
CatalogScreen.swift:5:8: note: 'CatalogScreen' declares conformance to protocol 'AXScreen' here

Half 2 — kept the bare struct but added static let screenIdentifier = "manual-catalog-identifier":

@__swiftmacro_20AXComponentKitSample13CatalogScreen8AXScreenfMm_.swift:1:12:
error: invalid redeclaration of 'screenIdentifier'
CatalogScreen.swift:4:1: note: in expansion of macro 'AXScreen' on struct 'CatalogScreen' here
CatalogScreen.swift:6:16: note: 'screenIdentifier' previously declared here

The macro-generated files (fMe_.swift for the extension, fMm_.swift for the member) are explicit in both traces.

Fixes are small:

  • ExtensionMacro: guard !protocols.isEmpty else { return [] } at the top of the function.
  • MemberMacro: walk declaration.memberBlock.members and skip if a screenIdentifier declaration already exists.

The README's "Without the macro:" alternative already documents the explicit-conformance path, so today's contract is "@AXScreen is exclusive with manual conformance" — fine as a constraint, just worth either enforcing it cleanly or surfacing it as a custom diagnostic.

Procedural — sample-app validation

PR description's test plan still has the two sample-app boxes unchecked (Sample app builds and runs on simulator, Sample app UI tests pass with xctestplan). The sample-app expansion is roughly half the diff, so getting those green before tagging 2.0.0 would close a real evidence gap. (For what it's worth, the baseline xcodebuild build -scheme AXComponentKitSample -destination 'generic/platform=iOS Simulator' does succeed on Xcode 26.5 — exit 0, warnings only.)

Nice work overall.

…ards
- Add firstElement(anyOf:prefix:) and tapFirst(anyOf:prefix:) overloads
that mirror the writer-side automationComponent(_:value:prefix:) API,
so prefixed identifiers are not silently missed by BEGINSWITH queries
- Guard ExtensionMacro against emitting redundant AXScreen conformance
when the type already conforms (check protocols.isEmpty)
- Guard MemberMacro against emitting duplicate screenIdentifier when
the struct already declares one manually
Comment threadSources/AXComponentKitMacros/AXScreenMacro.swift
@Clstroud

Chris Stroud (Clstroud) commented May 20, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Joel Garrett (@Nitewriter) Thanks for the thorough review — both HIGH findings were valid and are fixed in 7328ff7. Inline replies on the specific files above.

Procedural — sample-app validation: Agreed, will run the sample app build + UI tests and check those boxes before tagging.

…case conversion
- 7 tests for pascalCaseToKebabCase: simple, acronyms (UIKit, URLSession,
AXScreen), single word, all-uppercase, already-lowercase
- 6 tests for macro expansion: basic generation, custom identifier,
interpolated string fallback, existing screenIdentifier skip,
existing conformance skip, error on class
- Dedicated Xcode scheme for running macro tests on macOS
Comment threadAXComponentKitSample/UITests/FirstTabScreenTests.swift
…clear background
Accidentally dropped during the AXIdentifierConvertible refactor. Without
it, the screen identifier element relies on an undocumented SwiftUI
heuristic to stay out of the VoiceOver tree.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@Clstroud@moyerr@Nitewriter@joannaLingenfelter