mirror of
https://github.com/RevenueCat/purchases-ios
synced 2026-11-11 22:55:55 +05:45
* Refactor: Extract flushEvents logic into flushFeatureEvents Separates feature event flushing into its own method: - Add flushFeatureEvents to EventsManagerType protocol - Implement flushFeatureEvents with existing flush logic - Update flushEvents to delegate to flushFeatureEvents - Update Purchases.flushPaywallEvents to call flushFeatureEvents - Add flushFeatureEvents to MockEventsManager This prepares EventsManager for supporting multiple event types. * Add ad event storage and serialization Adds core infrastructure for storing and serializing ad events: - StoredAdEvent: Model for ad events with user context - StoredAdEventSerializer: JSON serialization/deserialization - AdEventStore: File-based persistent storage with fetch/clear operations - AdEventStoreTests: Comprehensive test coverage Clean implementation without legacy migration code since feature is behind compiler flag. * Add ad events integration to EventsManager Implements complete ad events lifecycle in EventsManager: - Add flushAdEvents to EventsManagerType protocol - AdEventStore integration with new initialization parameter - Implement track(adEvent:) with proper serialization and storage - Update flushEvents to flush both feature and ad events - Network request handling via InternalAPI.postAdEvents - Comprehensive error handling and logging (EventsManagerStrings) - Full test coverage (EventsManagerAdEventsTests) - Mock support for ad events in test infrastructure Network layer additions: - AdEventsRequest: HTTP request body for ad events endpoint - PostAdEventsOperation: Network operation for posting ad events - InternalAPI.postAdEvents: Async method for posting ad events * Rename adInstanceId to impressionId to match backend schema The backend expects `impression_id` but we were sending `ad_instance_id`. This renames the field throughout the codebase: - AdEvent.swift: Update AdEventData protocol and all event classes - AdEventsRequest.swift: Update serialization field name - All test files: Update to use impressionId parameter - Objective-C API: Update parameter names The field will be serialized as `impression_id` via snake_case conversion. * Add AdEventsIntegrationTests and internal flush method - Add AdEventsIntegrationTests.swift following BaseBackendIntegrationTests pattern - Add internal flushAdEvents() method in Purchases for test access - Add 4 test cases: tracking/flushing, empty flush, clearing after flush, persistence 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Clarify side-effects of removing the file Co-authored-by: JayShortway <29483617+JayShortway@users.noreply.github.com> * Remove test-only flushAdEvents method from Purchases Refactor to expose eventsManager as internal instead of having a test-only wrapper method. Changes: - Make eventsManager internal instead of private in Purchases - Remove flushAdEvents wrapper method from Purchases - Update integration tests to access eventsManager.flushAdEvents() directly This keeps test-only code out of the Purchases API while maintaining test access via @testable import. * Simplify StoredAdEvent equality with sorted keys Use JSONEncoder with sortedKeys to ensure consistent JSON encoding, allowing StoredAdEvent to rely on automatic Equatable synthesis instead of complex JSON decoding and NSDictionary comparison. Benefits: - Cleaner code: removed 18 lines of custom equality logic - Better performance: direct string comparison vs JSON decoding - More maintainable: automatic Equatable synthesis 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Refactor ad events integration tests to use app lifecycle events instead of internal API - Remove dependency on internal eventsManager property - Revert eventsManager back to private access level - Tests now simulate app backgrounding to trigger automatic event flushing - Aligns with production behavior where events flush on app lifecycle events - No public API needed for testing * Improve testSizeLimitTriggersCleanup with stronger assertions - Add event identity verification to ensure the new event is retained after cleanup - Replace count-only assertions with exact event equality checks - Add logging verification to confirm cleanup was triggered - Remove unused mock reset code - Improve variable naming for clarity (overflowedEvents -> remainingEvents) * Replace Task.sleep with deterministic message waiting in ad events tests Test improvements: - Replace arbitrary Task.sleep() delays with await logger.waitForMessage() - Wait for specific log messages instead of fixed time delays - Add allowNoMessages parameter where needed for empty flush scenarios TestLogHandler enhancements: - Add waitForMessage() async method for deterministic waiting - Support task cancellation with proper cleanup - Resume waiting continuations when matching messages arrive - Change EntryCondition from private to fileprivate for internal usage This eliminates race conditions and makes tests more reliable by waiting for actual events rather than guessing at timing delays. * Replace waitForMessage with verifyMessageIsEventuallyLogged in ad events tests Test changes: - Replace custom event-driven waitForMessage() with Nimble's verifyMessageIsEventuallyLogged() - Use established polling-based assertion pattern consistent with rest of test suite - All 5 call sites in AdEventsIntegrationTests updated to use try await TestLogHandler cleanup: - Remove waitForMessage() method and continuation-based waiting infrastructure - Remove PendingWait struct, pendingWaits property, and related helper methods - Remove continuation resumption logic from didReceive() - Change EntryCondition back to private This simplifies the test helper while using the existing, proven polling approach. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: JayShortway <29483617+JayShortway@users.noreply.github.com>