diff --git a/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test.ts b/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test.ts
index e3c3744d56..f1f38acc7a 100644
--- a/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test.ts
+++ b/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test.ts
@@ -66,6 +66,44 @@ describe('injectInfiniteQuery', () => {
).toBeInTheDocument()
})
+ it('should reject and update signal', async () => {
+ const key = queryKey()
+
+ @Component({
+ template: `
+
status: {{ query.status() }}
+ pages: {{ query.data()?.pages?.join(', ') ?? 'none' }}
+ error: {{ query.error()?.message ?? 'none' }}
+ isError: {{ query.isError() }}
+ failureCount: {{ query.failureCount() }}
+ `,
+ })
+ class Page {
+ readonly query = injectInfiniteQuery(() => ({
+ retry: false,
+ queryKey: key,
+ queryFn: () =>
+ sleep(10).then(() => Promise.reject(new Error('Some error'))),
+ initialPageParam: 0,
+ getNextPageParam: () => 12,
+ }))
+ }
+
+ const rendered = await render(Page)
+
+ expect(rendered.getByText('status: pending')).toBeInTheDocument()
+ expect(rendered.getByText('pages: none')).toBeInTheDocument()
+
+ await vi.advanceTimersByTimeAsync(11)
+ rendered.fixture.detectChanges()
+
+ expect(rendered.getByText('status: error')).toBeInTheDocument()
+ expect(rendered.getByText('pages: none')).toBeInTheDocument()
+ expect(rendered.getByText('error: Some error')).toBeInTheDocument()
+ expect(rendered.getByText('isError: true')).toBeInTheDocument()
+ expect(rendered.getByText('failureCount: 1')).toBeInTheDocument()
+ })
+
describe('injection context', () => {
it('should throw NG0203 with descriptive error outside injection context', () => {
const key = queryKey()
diff --git a/packages/angular-query-experimental/src/__tests__/inject-mutation.test.ts b/packages/angular-query-experimental/src/__tests__/inject-mutation.test.ts
index b9d3eea6e1..fd32ee09b8 100644
--- a/packages/angular-query-experimental/src/__tests__/inject-mutation.test.ts
+++ b/packages/angular-query-experimental/src/__tests__/inject-mutation.test.ts
@@ -50,47 +50,67 @@ describe('injectMutation', () => {
it('should change state after invoking mutate', async () => {
const result = 'Mock data'
- const mutation = TestBed.runInInjectionContext(() => {
- return injectMutation(() => ({
+ @Component({
+ template: `
+ isIdle: {{ mutation.isIdle() }}
+ isPending: {{ mutation.isPending() }}
+ isError: {{ mutation.isError() }}
+ isSuccess: {{ mutation.isSuccess() }}
+ data: {{ mutation.data() ?? 'none' }}
+ error: {{ mutation.error()?.message ?? 'none' }}
+ `,
+ })
+ class Page {
+ readonly mutation = injectMutation(() => ({
mutationFn: (params: string) => sleep(10).then(() => params),
}))
- })
+ }
- TestBed.tick()
+ const rendered = await render(Page)
- mutation.mutate(result)
+ rendered.fixture.componentInstance.mutation.mutate(result)
await vi.advanceTimersByTimeAsync(0)
+ rendered.fixture.detectChanges()
- expectSignals(mutation, {
- isIdle: false,
- isPending: true,
- isError: false,
- isSuccess: false,
- data: undefined,
- error: null,
- })
+ expect(rendered.getByText('isIdle: false')).toBeInTheDocument()
+ expect(rendered.getByText('isPending: true')).toBeInTheDocument()
+ expect(rendered.getByText('isError: false')).toBeInTheDocument()
+ expect(rendered.getByText('isSuccess: false')).toBeInTheDocument()
+ expect(rendered.getByText('data: none')).toBeInTheDocument()
+ expect(rendered.getByText('error: none')).toBeInTheDocument()
})
it('should return error when request fails', async () => {
- const mutation = TestBed.runInInjectionContext(() => {
- return injectMutation(() => ({
+ @Component({
+ template: `
+ isIdle: {{ mutation.isIdle() }}
+ isPending: {{ mutation.isPending() }}
+ isError: {{ mutation.isError() }}
+ isSuccess: {{ mutation.isSuccess() }}
+ data: {{ mutation.data() ?? 'none' }}
+ error: {{ mutation.error()?.message ?? 'none' }}
+ `,
+ })
+ class Page {
+ readonly mutation = injectMutation(() => ({
mutationFn: () =>
sleep(10).then(() => Promise.reject(new Error('Some error'))),
}))
- })
+ }
- mutation.mutate()
+ const rendered = await render(Page)
+
+ rendered.fixture.componentInstance.mutation.mutate()
await vi.advanceTimersByTimeAsync(11)
+ rendered.fixture.detectChanges()
- expectSignals(mutation, {
- isIdle: false,
- isPending: false,
- isError: true,
- isSuccess: false,
- data: undefined,
- error: Error('Some error'),
- })
+ expect(rendered.getByText('isIdle: false')).toBeInTheDocument()
+ expect(rendered.getByText('isPending: false')).toBeInTheDocument()
+ expect(rendered.getByText('isError: true')).toBeInTheDocument()
+ expect(rendered.getByText('isSuccess: false')).toBeInTheDocument()
+ expect(rendered.getByText('data: none')).toBeInTheDocument()
+ expect(rendered.getByText('error: Some error')).toBeInTheDocument()
})
it('should return data when request succeeds', async () => {
diff --git a/packages/angular-query-experimental/src/__tests__/inject-query.test.ts b/packages/angular-query-experimental/src/__tests__/inject-query.test.ts
index 82eb8f0f34..a8bff8527b 100644
--- a/packages/angular-query-experimental/src/__tests__/inject-query.test.ts
+++ b/packages/angular-query-experimental/src/__tests__/inject-query.test.ts
@@ -356,6 +356,62 @@ describe('injectQuery', () => {
expect(rendered.getByText('failureReason: Some error')).toBeInTheDocument()
})
+ it('should be able to select a part of the data with select', async () => {
+ const key = queryKey()
+
+ @Component({
+ template: `data: {{ query.data() ?? 'none' }}
`,
+ })
+ class Page {
+ readonly query = injectQuery<{ name: string }, Error, string>(() => ({
+ queryKey: key,
+ queryFn: () => sleep(10).then(() => ({ name: 'test' })),
+ select: (data) => data.name,
+ }))
+ }
+
+ const rendered = await render(Page)
+
+ expect(rendered.getByText('data: none')).toBeInTheDocument()
+
+ await vi.advanceTimersByTimeAsync(11)
+ rendered.fixture.detectChanges()
+
+ expect(rendered.getByText('data: test')).toBeInTheDocument()
+ })
+
+ it('should show placeholderData until queryFn resolves and then expose real data', async () => {
+ const key = queryKey()
+
+ @Component({
+ template: `
+ data: {{ query.data() }}
+ isPlaceholderData: {{ query.isPlaceholderData() }}
+ isSuccess: {{ query.isSuccess() }}
+ `,
+ })
+ class Page {
+ readonly query = injectQuery(() => ({
+ queryKey: key,
+ queryFn: () => sleep(10).then(() => 'real-data'),
+ placeholderData: 'placeholder',
+ }))
+ }
+
+ const rendered = await render(Page)
+
+ expect(rendered.getByText('data: placeholder')).toBeInTheDocument()
+ expect(rendered.getByText('isPlaceholderData: true')).toBeInTheDocument()
+ expect(rendered.getByText('isSuccess: true')).toBeInTheDocument()
+
+ await vi.advanceTimersByTimeAsync(11)
+ rendered.fixture.detectChanges()
+
+ expect(rendered.getByText('data: real-data')).toBeInTheDocument()
+ expect(rendered.getByText('isPlaceholderData: false')).toBeInTheDocument()
+ expect(rendered.getByText('isSuccess: true')).toBeInTheDocument()
+ })
+
it('should update query on options contained signal change', async () => {
const key1 = queryKey()
const key2 = queryKey()
@@ -548,24 +604,6 @@ describe('injectQuery', () => {
})
})
- it('should set state to error when queryFn returns reject promise', async () => {
- const key = queryKey()
- const query = TestBed.runInInjectionContext(() => {
- return injectQuery(() => ({
- retry: false,
- queryKey: key,
- queryFn: () =>
- sleep(10).then(() => Promise.reject(new Error('Some error'))),
- }))
- })
-
- expect(query.status()).toBe('pending')
-
- await vi.advanceTimersByTimeAsync(11)
-
- expect(query.status()).toBe('error')
- })
-
it('should render with required signal inputs', async () => {
@Component({
selector: 'app-fake',