-
Notifications
You must be signed in to change notification settings - Fork 0
feat(docs): add the angular testing documentation #2
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
base: main
Are you sure you want to change the base?
Conversation
@coderabbitai full review |
✅ Actions performedFull review triggered. |
WalkthroughThis update introduces a comprehensive Angular unit testing example using TanStack Query, Jest, and Angular Testing Library. It adds new documentation and guides on testing Angular applications, including practical examples and setup instructions. The new example project includes all necessary configuration files, a mock API interceptor for simulating backend responses, a service for managing tasks with optimistic updates, and a complete test suite verifying query and mutation behaviors. Additional minor changes improve type safety, control flow, and error handling in related Angular examples. Documentation and configuration are updated to reflect these new testing resources. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UnitTestingComponent
participant TasksService
participant MockAPIInterceptor
participant QueryClient
User->>UnitTestingComponent: Enters a new task and clicks "Add"
UnitTestingComponent->>TasksService: Calls addTask mutation
TasksService->>QueryClient: Cancel ongoing 'tasks' queries
TasksService->>QueryClient: Snapshot current tasks cache
TasksService->>QueryClient: Optimistically update cache with new task
TasksService->>MockAPIInterceptor: POST /api/tasks (simulate network)
MockAPIInterceptor-->>TasksService: Responds with success or error after delay
alt Success
TasksService->>QueryClient: Invalidate 'tasks' query cache
QueryClient->>TasksService: Refetch tasks
TasksService->>MockAPIInterceptor: GET /api/tasks
MockAPIInterceptor-->>TasksService: Responds with updated tasks
TasksService->>UnitTestingComponent: Updates with latest tasks
else Error
TasksService->>QueryClient: Rollback cache to previous state
TasksService->>UnitTestingComponent: Updates with rolled-back tasks
end
Poem
Tip ⚡💬 Agentic Chat (Pro Plan, General Availability)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (8)
examples/angular/unit-testing/README.md (1)
1-7
: Clear instructions, but consider adding more contextThe README provides concise instructions for running the example and tests, which is good. However, it would be helpful to add more context about what this example demonstrates and what technologies it uses (TanStack Query, Jest, Angular Testing Library).
Consider expanding the README with:
# TanStack Query Angular unit-testing example +This example demonstrates how to test Angular applications that use TanStack Query for data fetching. It includes: + +- Jest configuration for Angular testing +- Angular Testing Library for component testing +- Mock HTTP interceptors for API simulation +- Testing queries and mutations with optimistic updates + To run this example: - `npm install` or `yarn` or `pnpm i` or `bun i` - `npm run start` or `yarn start` or `pnpm start` or `bun start` - `npm run test` to run the tests🧰 Tools
🪛 LanguageTool
[duplication] ~5-~5: Possible typo: you repeated a word.
Context: ... -npm install
oryarn
orpnpm i
orbun i
-npm run start
oryarn start
orpnpm start
or `bun st...(ENGLISH_WORD_REPEAT_RULE)
examples/angular/unit-testing/jest.config.ts (3)
1-1
: Fix the type import syntax.The import for Jest's Config type should use explicit type import syntax.
-const config: import('jest').Config = { +import type { Config } from 'jest'; + +const config: Config = {🧰 Tools
🪛 ESLint
[error] 1-1:
import()
type annotations are forbidden.(@typescript-eslint/consistent-type-imports)
1-5
: Fix inconsistent indentation.The file has unnecessary indentation that should be removed for consistency.
-const config: import('jest').Config = { - roots: ['<rootDir>/src/'], - setupFilesAfterEnv: [] - }; - export default config; +const config: import('jest').Config = { + roots: ['<rootDir>/src/'], + setupFilesAfterEnv: [] +}; +export default config;🧰 Tools
🪛 ESLint
[error] 1-1:
import()
type annotations are forbidden.(@typescript-eslint/consistent-type-imports)
3-3
: Consider adding common Jest setup files.The
setupFilesAfterEnv
array is empty. For Angular testing, you might want to include setup files for common testing utilities.For example, you could add:
- setupFilesAfterEnv: [] + setupFilesAfterEnv: ['<rootDir>/setup-jest.ts']And create a
setup-jest.ts
file with common test utilities and global setup.examples/angular/unit-testing/src/app/app.config.ts (2)
21-21
: Use a named constant for time values.Using magic numbers for time calculations can make code less maintainable. Consider using a named constant for clarity.
+// Constants for better readability +const DAY_IN_MS = 1000 * 60 * 60 * 24; + export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withFetch(), withInterceptors([mockInterceptor])), provideTanStackQuery( new QueryClient({ defaultOptions: { queries: { - gcTime: 1000 * 60 * 60 * 24, // 24 hours + gcTime: DAY_IN_MS, // 24 hours }, }, }),
25-25
: Consider conditionally enabling devtools based on environment.For production builds, you might want to disable devtools. Consider using environment variables or Angular's isDevMode() to conditionally include devtools.
import { provideHttpClient, withFetch, withInterceptors, } from '@angular/common/http' import { QueryClient, provideTanStackQuery, withDevtools, } from '@tanstack/angular-query-experimental' +import { isDevMode } from '@angular/core' import { mockInterceptor } from './interceptor/mock-api.interceptor' import type { ApplicationConfig } from '@angular/core' export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withFetch(), withInterceptors([mockInterceptor])), provideTanStackQuery( new QueryClient({ defaultOptions: { queries: { gcTime: 1000 * 60 * 60 * 24, // 24 hours }, }, }), - withDevtools(), + isDevMode() ? withDevtools() : undefined, ), ], }Note: This is needed only if the
withDevtools()
function doesn't already handle this internally. From the code snippets, it looks like it might already checkisDevMode()
internally.examples/angular/unit-testing/src/app/services/tasks.service.spec.ts (1)
10-15
: Improve type annotation for mutation result.The
addTask
variable usesany
type which could be more strictly typed for better type safety.-let addTask: any; +import { CreateMutationResult } from "@tanstack/angular-query-experimental"; +let addTask: CreateMutationResult<any, Error, {task: string, failMutation: boolean}, unknown>;examples/angular/unit-testing/src/app/services/tasks.service.ts (1)
30-33
: Minor typo in documentation comment.There's a small grammatical error in the JSDoc comment.
/** * Creates a mutation for adding a task. - * On success, invalidates and refetch the "tasks" query cache to update the task list. + * On success, invalidates and refetches the "tasks" query cache to update the task list. */
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
examples/angular/unit-testing/src/favicon.ico
is excluded by!**/*.ico
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (23)
docs/config.json
(2 hunks)docs/framework/angular/guides/testing.md
(1 hunks)examples/angular/auto-refetching/src/app/services/tasks.service.ts
(2 hunks)examples/angular/optimistic-updates/src/app/components/optimistic-updates.component.ts
(0 hunks)examples/angular/optimistic-updates/src/app/interceptor/mock-api.interceptor.ts
(2 hunks)examples/angular/optimistic-updates/src/app/services/tasks.service.ts
(2 hunks)examples/angular/unit-testing/.devcontainer/devcontainer.json
(1 hunks)examples/angular/unit-testing/.eslintrc.cjs
(1 hunks)examples/angular/unit-testing/README.md
(1 hunks)examples/angular/unit-testing/angular.json
(1 hunks)examples/angular/unit-testing/jest.config.ts
(1 hunks)examples/angular/unit-testing/package.json
(1 hunks)examples/angular/unit-testing/src/app/app.component.ts
(1 hunks)examples/angular/unit-testing/src/app/app.config.ts
(1 hunks)examples/angular/unit-testing/src/app/components/unit-testing.component.ts
(1 hunks)examples/angular/unit-testing/src/app/interceptor/mock-api.interceptor.ts
(1 hunks)examples/angular/unit-testing/src/app/services/tasks.service.spec.ts
(1 hunks)examples/angular/unit-testing/src/app/services/tasks.service.ts
(1 hunks)examples/angular/unit-testing/src/index.html
(1 hunks)examples/angular/unit-testing/src/main.ts
(1 hunks)examples/angular/unit-testing/tsconfig.app.json
(1 hunks)examples/angular/unit-testing/tsconfig.json
(1 hunks)examples/angular/unit-testing/tsconfig.spec.json
(1 hunks)
💤 Files with no reviewable changes (1)
- examples/angular/optimistic-updates/src/app/components/optimistic-updates.component.ts
🧰 Additional context used
🧬 Code Graph Analysis (4)
examples/angular/unit-testing/src/app/app.config.ts (2)
examples/angular/unit-testing/src/app/interceptor/mock-api.interceptor.ts (1)
mockInterceptor
(20-64)packages/angular-query-experimental/src/providers.ts (2)
provideTanStackQuery
(93-111)withDevtools
(242-335)
examples/angular/unit-testing/src/main.ts (1)
examples/angular/unit-testing/src/app/app.config.ts (1)
appConfig
(14-28)
examples/angular/unit-testing/src/app/interceptor/mock-api.interceptor.ts (1)
examples/angular/optimistic-updates/src/app/interceptor/mock-api.interceptor.ts (1)
mockInterceptor
(18-53)
examples/angular/unit-testing/src/app/services/tasks.service.ts (1)
examples/angular/optimistic-updates/src/app/services/tasks.service.ts (1)
Injectable
(11-82)
🪛 ESLint
examples/angular/unit-testing/jest.config.ts
[error] 1-1: import()
type annotations are forbidden.
(@typescript-eslint/consistent-type-imports)
🪛 LanguageTool
examples/angular/unit-testing/README.md
[duplication] ~5-~5: Possible typo: you repeated a word.
Context: ... - npm install
or yarn
or pnpm i
or bun i
- npm run start
or yarn start
or pnpm start
or `bun st...
(ENGLISH_WORD_REPEAT_RULE)
docs/framework/angular/guides/testing.md
[uncategorized] ~6-~6: A comma might be missing here.
Context: ...y to await a signal to reach a specific value we will use polling to wait in our test...
(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)
[uncategorized] ~6-~6: The preposition “into” seems more likely in this position than the preposition “in”.
Context: ...st (instead of transforming our signals in observable and use RxJS features to fil...
(AI_EN_LECTOR_REPLACEMENT_PREPOSITION_IN_INTO)
[uncategorized] ~6-~6: This verb may not be in the correct form. Consider using a different form for this context.
Context: ...nsforming our signals in observable and use RxJS features to filter the values). If...
(AI_EN_LECTOR_REPLACEMENT_VERB_FORM)
[uncategorized] ~6-~6: A comma might be missing here.
Context: ...ues). If you want to do like us for the polling you can use the angular testing library...
(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)
[uncategorized] ~13-~13: A comma may be missing after the conjunctive/linking adverb ‘Otherwise’.
Context: ...sh ng add @testing-library/angular ``` Otherwise we recommend to use the toObservable fe...
(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)
[grammar] ~14-~14: The verb ‘recommend’ is used with the gerund form.
Context: ...sting-library/angular ``` Otherwise we recommend to use the toObservable feature from Angular. ...
(ADMIT_ENJOY_VB)
[uncategorized] ~18-~18: A comma might be missing here.
Context: ... that provide the Query options through function this is what we are going to do. ## A ...
(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)
[uncategorized] ~166-~166: Possible missing comma found.
Context: ...provideTanStackQuery during the TestBed setup as shown in the above example. ## Test...
(AI_HYDRA_LEO_MISSING_COMMA)
[grammar] ~170-~170: Please check whether an article is missing.
Context: ...you should mock the requests. There are multiple way of handling the mocking, we recomme...
(THE_BEST_WAY)
[grammar] ~170-~170: The verb ‘recommend’ is used with the gerund form.
Context: ...ultiple way of handling the mocking, we recommend to use the Interceptor from Angular, see [here...
(ADMIT_ENJOY_VB)
[duplication] ~171-~171: Possible typo: you repeated a word.
Context: ...rceptors) for more details. You can see the the Interceptor setup in the "Unit testing ...
(ENGLISH_WORD_REPEAT_RULE)
🪛 Biome (1.9.4)
examples/angular/unit-testing/src/app/interceptor/mock-api.interceptor.ts
[error] 45-47: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
🔇 Additional comments (39)
examples/angular/unit-testing/.eslintrc.cjs (1)
1-6
: Simple ESLint configuration looks good!This is a minimal but correctly configured ESLint setup for the Angular unit testing example. The TypeScript checking is enabled and the config is properly typed.
examples/angular/optimistic-updates/src/app/interceptor/mock-api.interceptor.ts (2)
9-9
: LGTM - Import for throwError added correctly.The
throwError
import is correctly added to the imports from 'rxjs', which will be used for error handling.
49-49
: Better error handling implementation!Good improvement! You've changed from returning an HTTP response with error status to using RxJS's
throwError
operator, which better simulates actual network failures and allows proper error handling testing.examples/angular/unit-testing/tsconfig.json (1)
1-32
: Well-configured TypeScript settings for Angular testingThis is a comprehensive TypeScript configuration that enables strict type checking and modern ES2022 features. The Angular compiler options are also well configured with strict template checking which will help catch errors early in the development process.
examples/angular/auto-refetching/src/app/services/tasks.service.ts (2)
40-42
: Improved promise handling in onSuccess callbacksThe addition of
return
statements for invalidateQueries ensures the promise chain is maintained, allowing consumers to properly await the completion of cache invalidation after mutations succeed.
54-56
: Improved promise handling in onSuccess callbacksSame improvement as in the addTask method - returning the invalidation promise maintains the promise chain, ensuring proper control flow in async operations.
examples/angular/unit-testing/.devcontainer/devcontainer.json (1)
1-4
: Good development container configurationThis configuration provides a standardized Node.js 22 development environment for the Angular unit testing example, ensuring consistent development experience across different machines.
examples/angular/unit-testing/tsconfig.app.json (1)
1-9
: Proper TypeScript application configurationThe configuration correctly extends the base tsconfig.json while specifying app-specific settings. It properly sets the output directory and includes only the necessary files for the application build, excluding test files.
examples/angular/unit-testing/src/main.ts (1)
1-5
: Standard Angular application bootstrappingThis main entry file properly bootstraps the Angular application using the standalone approach with appropriate error handling. It correctly imports and uses the appConfig which provides HTTP client with mock interceptors and TanStack Query configuration.
examples/angular/unit-testing/tsconfig.spec.json (1)
1-8
: Code looks good.The TypeScript configuration for test files is properly set up with the correct extends, output directory, and type definitions for Jest.
docs/config.json (2)
710-713
: Great addition of Angular testing documentation.The addition of the Testing guide for Angular is well-placed in the documentation structure. This helps users find testing resources for Angular applications.
1291-1294
: Good example addition for Angular unit testing.Adding the "Unit Testing / Jest" example to the Angular examples section provides a valuable resource for users looking to implement testing in their Angular applications.
examples/angular/unit-testing/src/app/app.config.ts (2)
1-12
: Well-organized imports.The imports are properly organized by package, with type imports correctly using the
type
keyword.
14-28
: Good configuration setup for the demo application.The
appConfig
sets up the necessary providers for HTTP client and TanStack Query client with appropriate configuration. The mock interceptor integration allows for realistic testing scenarios without a real backend.examples/angular/unit-testing/src/index.html (1)
1-13
: Well-structured HTML documentThis is a clean, standard HTML5 document that follows best practices for Angular applications. It properly sets up the viewport, character encoding, and base href. The app-root selector matches the component defined in app.component.ts.
examples/angular/unit-testing/src/app/app.component.ts (1)
1-11
: Good implementation with modern Angular practicesThis component follows current Angular best practices:
- Uses OnPush change detection for better performance
- Implemented as a standalone component
- Clean minimal template
- Properly imports the UnitTestingComponent
The structure is appropriate for a root component in a testing example.
examples/angular/optimistic-updates/src/app/services/tasks.service.ts (4)
51-51
: Improved type safetyAdding explicit type annotation for the task parameter improves type safety and code readability.
71-71
: Better parameter naming conventionUsing underscore prefix for unused parameters follows best practices by explicitly indicating these parameters aren't used in the function body.
78-78
: Improved promise handlingReturning the invalidateQueries promise is better than the previous implementation as it allows proper promise chaining when calling code needs to wait for the invalidation to complete.
50-50
:❓ Verification inconclusive
Verify the empty onSuccess handler intention
The onSuccess handler has been changed to an empty function. Since this previously may have contained the query invalidation logic (now moved to onSettled), please confirm this change is intentional and doesn't affect the optimistic update flow.
🏁 Script executed:
#!/bin/bash # Check if this was intentional by looking at related component usage and tests rg -A 3 -B 3 "onSuccess" --glob "examples/angular/**/*.ts" | grep -v "node_modules"Length of output: 3608
Confirm Intentional Removal of Query Invalidation from onSuccess
It appears that in
examples/angular/optimistic-updates/src/app/services/tasks.service.ts
theonSuccess
handler has been changed to an empty function—consistent with the unit-testing variant, while the auto-refetching variant still performs query invalidation inonSuccess
. Since the invalidation logic seems to have been migrated to anonSettled
callback in this flow, please confirm that this design change is deliberate and does not adversely affect the optimistic update mechanism.examples/angular/unit-testing/package.json (2)
1-37
: Well-configured package.json for Angular testingThe package.json is properly configured with:
- All necessary Angular dependencies at consistent versions
- Appropriate testing libraries (Jest and Testing Library)
- Standard npm scripts for Angular development
The combination of Jest and Testing Library is a good choice for Angular unit testing and matches the purpose of this example.
18-18
:✅ Verification successful
Note about experimental package
The package uses
@tanstack/angular-query-experimental
which is marked as experimental. This is appropriate for a testing example, but you might want to add a note in the documentation about the experimental status of this package.
🌐 Web query:
What is the current status of @tanstack/angular-query-experimental?
💡 Result:
Current Status of
@tanstack/angular-query-experimental
@tanstack/angular-query-experimental is currently in an experimental phase and not considered stable for production use. This status is clearly communicated across official documentation and package information:
- Experimental Stage: The library is subject to breaking changes even in minor and patch releases. Users are strongly advised to upgrade carefully and, if used in production, to lock to a specific patch version to avoid unexpected breaking changes[1][5][9].
- Angular Compatibility: The adapter primarily targets Angular 16 and higher, utilizing recent Angular features like signals for reactivity[1][10].
- Active Development: The project is actively maintained, with new features and changes appearing regularly in recent release notes (for example, v5.74.0 released in April 2025 included Angular-specific updates)[6]. However, no official timeline for a stable release has been announced yet[2][3].
- Usage Guidance: For stable, long-term projects or production environments, developers are encouraged to consider other, stable alternatives—such as
@tanstack/query-angular
for Angular v18 and above[7].Key Points for Developers
- Usage Risks: Because breaking changes can occur at any time (including minor and patch releases), production use is discouraged unless the package version is locked tightly[1][5][9].
- Features: The library leverages Angular signals and provides a declarative API for data fetching, caching, and synchronization, similar to TanStack Query’s APIs for other frameworks[8][10].
- Active Tracking: There is an open discussion and issue on GitHub for tracking progress toward a stable release, but as of April 2025, it remains in experimental status[2][3].
Summary Table
Status Angular Version Support Stable? Recent Updates Key Recommendation Experimental 16+ No April 2025 Lock version if used; not for production Recommendation
Use
@tanstack/angular-query-experimental
for experimentation, learning, or prototyping in supported Angular versions. For production or mission-critical projects, wait for the stable release or consider using a stable alternative such as@tanstack/query-angular
[7].Citations:
- 1: https://www.npmjs.com/package/@tanstack/angular-query-experimental
- 2: When query in angular version is no long experimental? TanStack/query#7836
- 3: Stable release of
@tanstack/angular-query
and@tanstack/angular-query-devtools
packages TanStack/query#8703- 4: https://javascript.plainenglish.io/tanstack-query-a-new-era-for-angular-developers-part-two-5f57d82049be
- 5: https://tanstack.com/query/latest/docs/angular/overview
- 6: https://github.com/tanstack/query/releases
- 7: https://dev.to/this-is-angular/streamlining-api-calls-in-angular-v18-with-tanstack-angular-query-5ahc
- 8: https://tanstack.com/query/latest/docs/framework/angular/guides/queries
- 9: https://tanstack.com/query/latest/docs/framework/angular/overview
- 10: https://www.telerik.com/blogs/data-fetching-angular-using-tanstack-query
Documentation Update: Clarify Experimental Status of Angular Query Package
The use of
@tanstack/angular-query-experimental
is confirmed to be experimental, meaning it may introduce breaking changes even in minor updates. While its inclusion is acceptable for a testing example, please update the associated documentation (e.g., in the README or a dedicated docs section) to clearly state that this package is experimental and not recommended for production without version locking. This note will help future users understand the risks involved with using an experimental package.examples/angular/unit-testing/src/app/components/unit-testing.component.ts (5)
1-9
: Good use of experimental query hooks.The component properly imports necessary dependencies including the experimental TanStack Query hooks. This approach demonstrates cutting-edge usage of the Angular Query features.
10-14
: Strong component configuration with OnPush change detection.The component uses OnPush change detection strategy which is optimal for performance. The selector and imports are properly defined with good component hygiene.
15-47
: Well-structured template with modern Angular control flow syntax.The template uses Angular's modern control flow syntax (
@if
,@for
) and properly handles different states:
- Loading state
- Background fetching indicator
- Form controls with two-way binding
- Mutation failure toggle
This provides a complete example of how to build interfaces that respond to query states.
49-56
: Good service integration and state management.The component correctly injects the TasksService and uses TanStack Query hooks to manage data fetching and mutations. The private service field with the
#
prefix follows best practices.
58-66
: Proper input validation in addItem method.The method correctly validates that the input is not empty before triggering a mutation. It also resets the input field after submission, which is a good practice for user experience.
examples/angular/unit-testing/src/app/interceptor/mock-api.interceptor.ts (1)
1-7
: Good documentation with JSDoc comments.The JSDoc header clearly explains the purpose of the interceptor and the endpoints it mocks, making it easier for developers to understand its role in the testing environment.
examples/angular/unit-testing/src/app/services/tasks.service.spec.ts (4)
1-9
: Good testing setup with proper imports.The test file correctly imports all necessary dependencies for testing Angular services with TanStack Query.
17-44
: Well-structured test setup with disabled retries.The setup disables query retries which is a best practice for testing. The TestBed configuration is thorough and includes all necessary providers.
51-85
: Comprehensive query testing with waitFor pattern.The test correctly uses Angular Testing Library's
waitFor
to handle asynchronous state changes and validates both the initial data fetching and optimistic updates.
86-111
: Good error handling test coverage.The test properly verifies the error case scenario, including checking optimistic updates, error rejection, and cache rollback behavior.
examples/angular/unit-testing/src/app/services/tasks.service.ts (6)
1-10
: Good import organization.The imports are properly organized with Angular core imports first, followed by library imports, with a blank line separating import groups.
11-17
: Well-structured service setup.The service is properly configured with
providedIn: 'root'
and uses the recommended private field notation with the#
prefix.
18-28
: Clear query implementation with proper typing.The
allTasks
method uses correct typing with the TanStack Query options pattern. The use oflastValueFrom
to convert the Observable to a Promise is appropriate.
34-50
: Well-implemented mutation function.The
addTask
method properly implements a mutation with typed parameters and correctly handles the conditional URL for simulating errors.
51-70
: Robust optimistic update implementation.The
onMutate
handler correctly implements all the steps for optimistic updates:
- Cancels outgoing queries
- Takes a snapshot of the current state
- Updates the cache optimistically
- Returns the previous state for rollback
This follows the recommended pattern for optimistic updates with TanStack Query.
71-81
: Complete error handling with cache invalidation.The service properly handles errors by rolling back to the previous state and ensures that the cache is invalidated after settlement, which will trigger a refetch.
examples/angular/unit-testing/angular.json (1)
1-113
: Angular workspace configuration looks correct and follows best practices.The configuration is standard, well-structured, and integrates Jest for testing. No issues found.
} from '@angular/common/http' | ||
import type { Observable } from 'rxjs' | ||
|
||
let callNumber = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential test isolation issue with shared static variable.
The callNumber
variable is declared at module level and not reset between tests, which could cause test interdependency issues.
Consider moving this variable inside the interceptor function or adding a reset method to ensure test isolation:
-let callNumber = 0;
+export const mockInterceptor: HttpInterceptorFn = (
+ req: HttpRequest<unknown>,
+ next: HttpHandlerFn,
+): Observable<HttpEvent<any>> => {
+ // Move counter inside function scope for better test isolation
+ static let callNumber = 0;
Committable suggestion skipped: line range outside the PR's diff.
const tasks = JSON.parse( | ||
sessionStorage.getItem('unit-testing-tasks') || '[]', | ||
) | ||
tasks.push(req.body) | ||
sessionStorage.setItem( | ||
'unit-testing-tasks', | ||
JSON.stringify(tasks), | ||
) | ||
return respondWith(201, { | ||
status: 'success', | ||
task: req.body, | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Wrap variable declaration in block scope within switch case.
The tasks
variable declaration inside the switch case should be wrapped in a block to avoid potential scope issues.
case 'POST':
+ {
const tasks = JSON.parse(
sessionStorage.getItem('unit-testing-tasks') || '[]',
)
tasks.push(req.body)
sessionStorage.setItem(
'unit-testing-tasks',
JSON.stringify(tasks),
)
return respondWith(201, {
status: 'success',
task: req.body,
})
+ }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const tasks = JSON.parse( | |
sessionStorage.getItem('unit-testing-tasks') || '[]', | |
) | |
tasks.push(req.body) | |
sessionStorage.setItem( | |
'unit-testing-tasks', | |
JSON.stringify(tasks), | |
) | |
return respondWith(201, { | |
status: 'success', | |
task: req.body, | |
}) | |
} | |
case 'POST': { | |
const tasks = JSON.parse( | |
sessionStorage.getItem('unit-testing-tasks') || '[]', | |
) | |
tasks.push(req.body) | |
sessionStorage.setItem( | |
'unit-testing-tasks', | |
JSON.stringify(tasks), | |
) | |
return respondWith(201, { | |
status: 'success', | |
task: req.body, | |
}) | |
} |
🧰 Tools
🪛 Biome (1.9.4)
[error] 45-47: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
if (req.url === '/api/tasks') { | ||
switch (req.method) { | ||
case 'GET': | ||
callNumber++; | ||
if (callNumber === 1) { | ||
return respondWith( | ||
200, | ||
JSON.parse( | ||
sessionStorage.getItem('unit-testing-tasks') || '[]', | ||
), | ||
) } else { | ||
return respondWith( | ||
200, | ||
JSON.parse( | ||
sessionStorage.getItem('unit-testing-tasks') || '[]', | ||
).concat([`CallNumber ${callNumber}`]), | ||
) | ||
} | ||
case 'POST': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switch case with declaration issue.
There's a potential scoping issue with the variable declaration in the switch case. Additionally, the conditional response logic based on callNumber
adds complexity to the mock.
Wrap the declaration in a block to restrict its access to the switch clause:
case 'GET':
callNumber++;
if (callNumber === 1) {
+ {
return respondWith(
200,
JSON.parse(
sessionStorage.getItem('unit-testing-tasks') || '[]',
),
)
+ }
} else {
+ {
return respondWith(
200,
JSON.parse(
sessionStorage.getItem('unit-testing-tasks') || '[]',
).concat([`CallNumber ${callNumber}`]),
)
+ }
}
Committable suggestion skipped: line range outside the PR's diff.
title: Testing | ||
--- | ||
|
||
As there is currently no simple way to await a signal to reach a specific value we will use polling to wait in our test (instead of transforming our signals in observable and use RxJS features to filter the values). If you want to do like us for the polling you can use the angular testing library. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Polish grammar, punctuation, and style for clarity and professionalism.
The technical content is excellent, but the following refinements are recommended:
- Add missing commas for better readability.
- Use "into" instead of "in" for "transforming our signals into observables".
- Use gerund form ("recommend using") for correct verb usage.
- Fix repeated word ("the the Interceptor").
- Add missing articles ("multiple ways of handling the mocking").
Here is a suggested diff for the most important corrections:
-As there is currently no simple way to await a signal to reach a specific value we will use polling to wait in our test (instead of transforming our signals in observable and use RxJS features to filter the values). If you want to do like us for the polling you can use the angular testing library.
+As there is currently no simple way to await a signal to reach a specific value, we will use polling to wait in our test (instead of transforming our signals into observables and using RxJS features to filter the values). If you want to do as we do for polling, you can use the Angular Testing Library.
-Otherwise we recommend to use the toObservable feature from Angular.
+Otherwise, we recommend using the toObservable feature from Angular.
-Because the recommendation is to use services that provide the Query options through function this is what we are going to do.
+Because the recommendation is to use services that provide the Query options through a function, this is what we are going to do.
-The library defaults to three retries with exponential backoff, which means that your tests are likely to timeout if you want to test an erroneous query. The easiest way to turn retries off is via the provideTanStackQuery during the TestBed setup as shown in the above example.
+The library defaults to three retries with exponential backoff, which means that your tests are likely to time out if you want to test an erroneous query. The easiest way to turn retries off is via provideTanStackQuery during the TestBed setup, as shown in the above example.
-Instead of targetting a server for the data you should mock the requests. There are multiple way of handling the mocking, we recommend to use the Interceptor from Angular, see [here](https://angular.dev/guide/http/interceptors) for more details.
-You can see the the Interceptor setup in the "Unit testing / Jest" examples.
+Instead of targeting a server for the data, you should mock the requests. There are multiple ways of handling the mocking; we recommend using the Interceptor from Angular. See [here](https://angular.dev/guide/http/interceptors) for more details.
+You can see the Interceptor setup in the "Unit testing / Jest" examples.
Also applies to: 13-14, 18-18, 166-166, 170-171
🧰 Tools
🪛 LanguageTool
[uncategorized] ~6-~6: A comma might be missing here.
Context: ...y to await a signal to reach a specific value we will use polling to wait in our test...
(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)
[uncategorized] ~6-~6: The preposition “into” seems more likely in this position than the preposition “in”.
Context: ...st (instead of transforming our signals in observable and use RxJS features to fil...
(AI_EN_LECTOR_REPLACEMENT_PREPOSITION_IN_INTO)
[uncategorized] ~6-~6: This verb may not be in the correct form. Consider using a different form for this context.
Context: ...nsforming our signals in observable and use RxJS features to filter the values). If...
(AI_EN_LECTOR_REPLACEMENT_VERB_FORM)
[uncategorized] ~6-~6: A comma might be missing here.
Context: ...ues). If you want to do like us for the polling you can use the angular testing library...
(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)
This PR is to improve the testing doc of Angular package.
Let's discuss what is missing and you would like to be added.
BR
Summary by CodeRabbit
New Features
Documentation
Tests