-
Notifications
You must be signed in to change notification settings - Fork 0
Refactor RemoteWordLoader as composite loader with mappers #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Convert SUT from struct to final class to properly track deallocation of all components (loader, remote, local, cache) via weak reference
Update naming convention to use ViewStore instead of ViewModel for ScreenActionStore actors across all features (Home, Library, Quiz)
- Create HomeViewStore actor implementing ScreenActionStore - Add HomeViewStoreTests with memory leak tracking - Update WordLoaderSpy with loadCallCount tracking
- loadWords_deliversEmptyWordsOnLoaderEmpty - loadWords_deliversErrorOnLoaderError - Add AppError for abnormal state handling
- HomeViewState now uses tryUpdate for private(set) properties - makeSUT binds state automatically - Add uniqueWord() and anyNSError() test helpers
- Add loadWords_doesNotRequestLoadTwiceWhilePending test - Use actionLocker.canExecute() and unlock() in isolatedReceive
- Integration test verifying receive() propagates errors to viewState - Uses ConcurrencyExtras withMainSerialExecutor for deterministic async
Filter out duplicate words when appending via loadMore action.
Also fix loadWords action locking test name.
Add selectedLanguage state and selectLanguage action to HomeViewStore. Uses Locale.LanguageCode from Foundation for domain purity.
selectLanguage now clears existing words and reloads from loader.
Crash immediately when stub is not set for clearer test failures.
Refactor HomeViewStore to use LoaderFactory pattern. The factory is called with selectedLanguage to create language-specific loaders. Uses LockIsolated from ConcurrencyExtras for thread-safe language capture in tests.
- WordCardView: displays word, phonetic, and meanings - LanguagePickerView: dropdown menu for language selection - HomeView: main view with pull-to-refresh and load more - Preview helpers for mock data and preview stores
- Add LoadState enum (.idle, .loaded, .error) to HomeViewState for explicit state management - Add inline error view with retry button using ContentUnavailableView - Move mocks to WordFeature module (Word+Mocks, Meaning+Mocks, MockWordLoader) for reuse in tests and previews - Refactor HomeViewStore with separate action functions and centralized error handling - Add tests for error state transitions and loading flag behavior 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Switch from ScrollView+LazyVStack to List for word display - Add ProgressView at end of list for load more indication - Extract toolbar into @ToolbarContentBuilder - Organize view into extensions with MARK comments - Add Home.xcstrings String Catalog for localization - Remove unnecessary Task.sleep from refresh
- Add swift-snapshot-testing package dependency - Create HomeViewSnapshotTests with device-based snapshot testing - Refactor HomeView to accept viewState via initializer for testability - Extract makeState and makeLoader helpers for test clarity
- Add homeView_withEmptyWords_showsEmptyState test - Add homeView_withError_showsErrorState test - Add anyNSError helper for test error generation
- Add HomeUIComposer to compose HomeView with dependencies - Remove placeholder ContentView - Wire DefineryApp with WordLoaderFactory for shared dependencies - Extract WordLoaderFactory typealias to module level - Add WordLoaderProtocol conformance to LocalWordLoader
TDD red phase: test expects invalidData error on non-200 status codes
- Maps Random Word API response (array of strings) - Validates 200 status code and valid JSON - Add makeWordsJSON helper to SharedTestHelpers
- Maps Dictionary API response to Word domain model - Handles multiple meanings per word (noun, verb, etc.) - Takes first definition per meaning - Update README introduction section
- Update RemoteWordLoader to fetch random words then definitions - Add withTaskGroup for concurrent definition fetching - Implement HTTPClientSpy with dictionary-based stubbing - Add tests for request flow, error handling, and partial failures 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace manual JSON validation with RandomWordMapper - Replace manual JSON validation with DefinitionMapper - Tests now verify APIs return mapper-compatible responses 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Centralize URL construction in WordsEndpoint instead of manually appending paths. Updates composition root to pass simple base URLs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Mark Phase 5 (Composition) as complete - Update WordAPI structure with DefinitionMapper, RandomWordMapper - Update project structure to match current implementation - Add DefineryTests section with actual test files - Update current progress to Phase 1-6 complete
Move snapshot directory computation to file-level constant using #filePath at declaration time, ensuring consistent path resolution across local and CI environments.
- Rewrite DefinitionMapper to parse Wiktionary wikitext format - Update WordsEndpoint with Wiktionary URL structure - Add support for 7 languages: en, es, it, de, fr, zh, pt-br - Update all related tests for new API format - Fix HTTPClientSpy thread-safety for concurrent requests - Update documentation with new API endpoints
- Extract IPA phonetic from {{IPA|lang|/phonetic/}} templates
- Handle real Wiktionary format with {{ng|...}} wrapped definitions
- Add tests for phonetic extraction and real wikitext format
- Add isLoadingMore state to HomeViewState for inline progress indicator - Configure canTrackLoading to return false for loadMore action - Use loadingStarted(action:) to respect canTrackLoading property - Show ProgressView only when isLoadingMore is true in HomeView
DefinitionMapper: - Improve phonetic extraction to handle parentheses and special chars - Add isValidDefinition to filter out empty/punctuation-only definitions - Skip invalid definitions and use next valid one - Support usex template in addition to ux for examples HomeViewStore: - Add refresh action for pull-to-refresh without global loading overlay - Fix Portuguese language code mapping (pt -> pt-br for Random Word API) Tests: - Add phonetic extraction tests for edge cases - Add example extraction tests - Add invalid definition handling tests
Replace direct WordsEndpoint dependency with DefinitionURLBuilder closure, moving endpoint construction responsibility to the composition root.
WordFeature is a pure domain layer with no tests needed. Updated project structure documentation to reflect this.
1cba4c5 to
da44b08
Compare
Disable DEFINES_MODULE for Swift-only framework that doesn't need an umbrella header for module map generation.
- Add symlink in ci_scripts to Snapshots folder (Xcode Cloud copies this) - Update resolveSnapshotDirectory to check multiple locations: 1. ci_scripts folder (Xcode Cloud test environment) 2. Test bundle resources (if bundled) 3. File-based path (local development) This allows snapshot tests to find reference images in both local development and Xcode Cloud CI environments.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
["word1", "word2"])Test plan