@tanstack/angular-query-experimental 5.34.1 → 5.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -2
- package/build/README.md +19 -2
- package/build/esm2022/create-base-query.mjs +3 -3
- package/build/esm2022/index.mjs +2 -2
- package/build/esm2022/infinite-query-options.mjs +9 -1
- package/build/esm2022/inject-infinite-query.mjs +11 -3
- package/build/esm2022/inject-is-fetching.mjs +11 -1
- package/build/esm2022/inject-is-mutating.mjs +10 -1
- package/build/esm2022/inject-mutation-state.mjs +8 -1
- package/build/esm2022/inject-mutation.mjs +13 -4
- package/build/esm2022/inject-queries.mjs +4 -1
- package/build/esm2022/inject-query-client.mjs +21 -3
- package/build/esm2022/inject-query.mjs +36 -3
- package/build/esm2022/providers.mjs +40 -1
- package/build/esm2022/query-options.mjs +23 -1
- package/build/esm2022/signal-proxy.mjs +2 -4
- package/build/esm2022/types.mjs +1 -1
- package/build/fesm2022/tanstack-angular-query-experimental.mjs +179 -14
- package/build/fesm2022/tanstack-angular-query-experimental.mjs.map +1 -1
- package/build/rollup.d.ts +591 -0
- package/package.json +10 -6
- package/build/create-base-query.d.ts +0 -6
- package/build/index.d.ts +0 -14
- package/build/infinite-query-options.d.ts +0 -18
- package/build/inject-infinite-query.d.ts +0 -7
- package/build/inject-is-fetching.d.ts +0 -3
- package/build/inject-is-mutating.d.ts +0 -3
- package/build/inject-mutation-state.d.ts +0 -11
- package/build/inject-mutation.d.ts +0 -4
- package/build/inject-queries.d.ts +0 -71
- package/build/inject-query-client.d.ts +0 -13
- package/build/inject-query.d.ts +0 -7
- package/build/providers.d.ts +0 -3
- package/build/query-options.d.ts +0 -16
- package/build/signal-proxy.d.ts +0 -13
- package/build/types.d.ts +0 -44
- package/build/util/assert-injector/assert-injector.d.ts +0 -54
- package/build/util/create-injection-token/create-injection-token.d.ts +0 -52
- package/build/util/index.d.ts +0 -2
- package/build/util/lazy-init/lazy-init.d.ts +0 -1
- package/build/util/lazy-signal-initializer/lazy-signal-initializer.d.ts +0 -4
- package/src/__tests__/inject-infinite-query.test.ts +0 -64
- package/src/__tests__/inject-is-fetching.test.ts +0 -35
- package/src/__tests__/inject-is-mutating.test.ts +0 -39
- package/src/__tests__/inject-mutation-state.test-d.ts +0 -22
- package/src/__tests__/inject-mutation-state.test.ts +0 -177
- package/src/__tests__/inject-mutation.test-d.ts +0 -71
- package/src/__tests__/inject-mutation.test.ts +0 -458
- package/src/__tests__/inject-query.test-d.ts +0 -59
- package/src/__tests__/inject-query.test.ts +0 -349
- package/src/__tests__/query-options.test-d.ts +0 -127
- package/src/__tests__/signal-proxy.test.ts +0 -27
- package/src/__tests__/test-utils.ts +0 -131
- package/src/__tests__/util/lazy-init/lazy-init.test.ts +0 -126
- package/src/__tests__/util/lazy-signal-initializer/lazy-signal-initializer.test.ts +0 -130
- package/src/create-base-query.ts +0 -116
- package/src/index.ts +0 -28
- package/src/infinite-query-options.ts +0 -94
- package/src/inject-infinite-query.ts +0 -93
- package/src/inject-is-fetching.ts +0 -39
- package/src/inject-is-mutating.ts +0 -39
- package/src/inject-mutation-state.ts +0 -97
- package/src/inject-mutation.ts +0 -109
- package/src/inject-queries.ts +0 -260
- package/src/inject-query-client.ts +0 -7
- package/src/inject-query.ts +0 -68
- package/src/providers.ts +0 -26
- package/src/query-options.ts +0 -50
- package/src/signal-proxy.ts +0 -48
- package/src/test-setup.ts +0 -12
- package/src/types.ts +0 -260
- package/src/util/assert-injector/assert-injector.test.ts +0 -74
- package/src/util/assert-injector/assert-injector.ts +0 -81
- package/src/util/create-injection-token/create-injection-token.test.ts +0 -32
- package/src/util/create-injection-token/create-injection-token.ts +0 -185
- package/src/util/index.ts +0 -13
- package/src/util/lazy-init/lazy-init.ts +0 -34
- package/src/util/lazy-signal-initializer/lazy-signal-initializer.ts +0 -28
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import { Component, input, signal } from '@angular/core'
|
|
2
|
-
import { QueryClient } from '@tanstack/query-core'
|
|
3
|
-
import { TestBed } from '@angular/core/testing'
|
|
4
|
-
import { describe, expect, test, vi } from 'vitest'
|
|
5
|
-
import { By } from '@angular/platform-browser'
|
|
6
|
-
import { JsonPipe } from '@angular/common'
|
|
7
|
-
import { injectMutation } from '../inject-mutation'
|
|
8
|
-
import { injectMutationState } from '../inject-mutation-state'
|
|
9
|
-
import { provideAngularQuery } from '../providers'
|
|
10
|
-
import { setFixtureSignalInputs, successMutator } from './test-utils'
|
|
11
|
-
|
|
12
|
-
const MUTATION_DURATION = 1000
|
|
13
|
-
|
|
14
|
-
const resolveMutations = () => vi.advanceTimersByTimeAsync(MUTATION_DURATION)
|
|
15
|
-
|
|
16
|
-
describe('injectMutationState', () => {
|
|
17
|
-
let queryClient: QueryClient
|
|
18
|
-
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
queryClient = new QueryClient()
|
|
21
|
-
vi.useFakeTimers()
|
|
22
|
-
TestBed.configureTestingModule({
|
|
23
|
-
providers: [provideAngularQuery(queryClient)],
|
|
24
|
-
})
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
vi.useRealTimers()
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
describe('injectMutationState', () => {
|
|
32
|
-
test('should return variables after calling mutate', async () => {
|
|
33
|
-
const mutationKey = ['mutation']
|
|
34
|
-
const variables = 'foo123'
|
|
35
|
-
|
|
36
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
37
|
-
return injectMutation(() => ({
|
|
38
|
-
mutationKey: mutationKey,
|
|
39
|
-
mutationFn: (params: string) => successMutator(params),
|
|
40
|
-
}))
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
mutation.mutate(variables)
|
|
44
|
-
|
|
45
|
-
const mutationState = TestBed.runInInjectionContext(() => {
|
|
46
|
-
return injectMutationState(() => ({
|
|
47
|
-
filters: { mutationKey, status: 'pending' },
|
|
48
|
-
select: (m) => m.state.variables,
|
|
49
|
-
}))
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
expect(mutationState()).toEqual([variables])
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
test('reactive options should update injectMutationState', async () => {
|
|
56
|
-
const mutationKey1 = ['mutation1']
|
|
57
|
-
const mutationKey2 = ['mutation2']
|
|
58
|
-
const variables1 = 'foo123'
|
|
59
|
-
const variables2 = 'bar234'
|
|
60
|
-
|
|
61
|
-
const [mutation1, mutation2] = TestBed.runInInjectionContext(() => {
|
|
62
|
-
return [
|
|
63
|
-
injectMutation(() => ({
|
|
64
|
-
mutationKey: mutationKey1,
|
|
65
|
-
mutationFn: (params: string) => successMutator(params),
|
|
66
|
-
})),
|
|
67
|
-
injectMutation(() => ({
|
|
68
|
-
mutationKey: mutationKey2,
|
|
69
|
-
mutationFn: (params: string) => successMutator(params),
|
|
70
|
-
})),
|
|
71
|
-
]
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
mutation1.mutate(variables1)
|
|
75
|
-
mutation2.mutate(variables2)
|
|
76
|
-
|
|
77
|
-
const filterKey = signal(mutationKey1)
|
|
78
|
-
|
|
79
|
-
const mutationState = TestBed.runInInjectionContext(() => {
|
|
80
|
-
return injectMutationState(() => ({
|
|
81
|
-
filters: { mutationKey: filterKey(), status: 'pending' },
|
|
82
|
-
select: (m) => m.state.variables,
|
|
83
|
-
}))
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
expect(mutationState()).toEqual([variables1])
|
|
87
|
-
|
|
88
|
-
filterKey.set(mutationKey2)
|
|
89
|
-
TestBed.flushEffects()
|
|
90
|
-
expect(mutationState()).toEqual([variables2])
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
test('should return variables after calling mutate', async () => {
|
|
94
|
-
queryClient.clear()
|
|
95
|
-
const mutationKey = ['mutation']
|
|
96
|
-
const variables = 'bar234'
|
|
97
|
-
|
|
98
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
99
|
-
return injectMutation(() => ({
|
|
100
|
-
mutationKey: mutationKey,
|
|
101
|
-
mutationFn: (params: string) => successMutator(params),
|
|
102
|
-
}))
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
mutation.mutate(variables)
|
|
106
|
-
|
|
107
|
-
const mutationState = TestBed.runInInjectionContext(() => {
|
|
108
|
-
return injectMutationState()
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
expect(mutationState()[0]?.variables).toEqual(variables)
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
test('should support required signal inputs', async () => {
|
|
115
|
-
queryClient.clear()
|
|
116
|
-
const fakeName = 'name1'
|
|
117
|
-
const mutationKey1 = ['fake', fakeName]
|
|
118
|
-
|
|
119
|
-
const mutations = TestBed.runInInjectionContext(() => {
|
|
120
|
-
return [
|
|
121
|
-
injectMutation(() => ({
|
|
122
|
-
mutationKey: mutationKey1,
|
|
123
|
-
mutationFn: () => Promise.resolve('myValue'),
|
|
124
|
-
})),
|
|
125
|
-
injectMutation(() => ({
|
|
126
|
-
mutationKey: mutationKey1,
|
|
127
|
-
mutationFn: () => Promise.reject('myValue2'),
|
|
128
|
-
})),
|
|
129
|
-
]
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
mutations.forEach((mutation) => mutation.mutate())
|
|
133
|
-
|
|
134
|
-
@Component({
|
|
135
|
-
selector: 'app-fake',
|
|
136
|
-
template: `
|
|
137
|
-
@for (mutation of mutationState(); track mutation) {
|
|
138
|
-
<span>{{ mutation.status }}</span>
|
|
139
|
-
}
|
|
140
|
-
`,
|
|
141
|
-
standalone: true,
|
|
142
|
-
imports: [JsonPipe],
|
|
143
|
-
})
|
|
144
|
-
class FakeComponent {
|
|
145
|
-
name = input.required<string>()
|
|
146
|
-
|
|
147
|
-
mutationState = injectMutationState(() => ({
|
|
148
|
-
filters: {
|
|
149
|
-
mutationKey: ['fake', this.name()],
|
|
150
|
-
exact: true,
|
|
151
|
-
},
|
|
152
|
-
}))
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const fixture = TestBed.createComponent(FakeComponent)
|
|
156
|
-
const { debugElement } = fixture
|
|
157
|
-
setFixtureSignalInputs(fixture, { name: fakeName })
|
|
158
|
-
|
|
159
|
-
fixture.detectChanges()
|
|
160
|
-
|
|
161
|
-
let spans = debugElement
|
|
162
|
-
.queryAll(By.css('span'))
|
|
163
|
-
.map((span) => span.nativeNode.textContent)
|
|
164
|
-
|
|
165
|
-
expect(spans).toEqual(['pending', 'pending'])
|
|
166
|
-
|
|
167
|
-
await resolveMutations()
|
|
168
|
-
fixture.detectChanges()
|
|
169
|
-
|
|
170
|
-
spans = debugElement
|
|
171
|
-
.queryAll(By.css('span'))
|
|
172
|
-
.map((span) => span.nativeNode.textContent)
|
|
173
|
-
|
|
174
|
-
expect(spans).toEqual(['success', 'error'])
|
|
175
|
-
})
|
|
176
|
-
})
|
|
177
|
-
})
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { describe, expectTypeOf } from 'vitest'
|
|
2
|
-
import { injectMutation } from '../inject-mutation'
|
|
3
|
-
import { successMutator } from './test-utils'
|
|
4
|
-
import type { Signal } from '@angular/core'
|
|
5
|
-
|
|
6
|
-
describe('Discriminated union return type', () => {
|
|
7
|
-
test('data should be possibly undefined by default', () => {
|
|
8
|
-
const mutation = injectMutation(() => ({
|
|
9
|
-
mutationFn: successMutator<string>,
|
|
10
|
-
}))
|
|
11
|
-
|
|
12
|
-
expectTypeOf(mutation.data).toEqualTypeOf<Signal<string | undefined>>()
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
test('data should be defined when mutation is success', () => {
|
|
16
|
-
const mutation = injectMutation(() => ({
|
|
17
|
-
mutationFn: successMutator<string>,
|
|
18
|
-
}))
|
|
19
|
-
|
|
20
|
-
if (mutation.isSuccess()) {
|
|
21
|
-
expectTypeOf(mutation.data).toEqualTypeOf<Signal<string>>()
|
|
22
|
-
}
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
test('error should be null when mutation is success', () => {
|
|
26
|
-
const mutation = injectMutation(() => ({
|
|
27
|
-
mutationFn: successMutator<string>,
|
|
28
|
-
}))
|
|
29
|
-
|
|
30
|
-
if (mutation.isSuccess()) {
|
|
31
|
-
expectTypeOf(mutation.error).toEqualTypeOf<Signal<null>>()
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
test('data should be undefined when mutation is pending', () => {
|
|
36
|
-
const mutation = injectMutation(() => ({
|
|
37
|
-
mutationFn: successMutator<string>,
|
|
38
|
-
}))
|
|
39
|
-
|
|
40
|
-
if (mutation.isPending()) {
|
|
41
|
-
expectTypeOf(mutation.data).toEqualTypeOf<Signal<undefined>>()
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
test('error should be defined when mutation is error', () => {
|
|
46
|
-
const mutation = injectMutation(() => ({
|
|
47
|
-
mutationFn: successMutator<string>,
|
|
48
|
-
}))
|
|
49
|
-
|
|
50
|
-
if (mutation.isError()) {
|
|
51
|
-
expectTypeOf(mutation.error).toEqualTypeOf<Signal<Error>>()
|
|
52
|
-
}
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
test('should narrow variables', () => {
|
|
56
|
-
const mutation = injectMutation(() => ({
|
|
57
|
-
mutationFn: successMutator<string>,
|
|
58
|
-
}))
|
|
59
|
-
|
|
60
|
-
if (mutation.isIdle()) {
|
|
61
|
-
expectTypeOf(mutation.variables).toEqualTypeOf<Signal<undefined>>()
|
|
62
|
-
}
|
|
63
|
-
if (mutation.isPending()) {
|
|
64
|
-
expectTypeOf(mutation.variables).toEqualTypeOf<Signal<string>>()
|
|
65
|
-
}
|
|
66
|
-
if (mutation.isSuccess()) {
|
|
67
|
-
expectTypeOf(mutation.variables).toEqualTypeOf<Signal<string>>()
|
|
68
|
-
}
|
|
69
|
-
expectTypeOf(mutation.variables).toEqualTypeOf<Signal<string | undefined>>()
|
|
70
|
-
})
|
|
71
|
-
})
|
|
@@ -1,458 +0,0 @@
|
|
|
1
|
-
import { Component, input, signal } from '@angular/core'
|
|
2
|
-
import { QueryClient } from '@tanstack/query-core'
|
|
3
|
-
import { TestBed } from '@angular/core/testing'
|
|
4
|
-
import { describe, expect, vi } from 'vitest'
|
|
5
|
-
import { By } from '@angular/platform-browser'
|
|
6
|
-
import { injectMutation } from '../inject-mutation'
|
|
7
|
-
import { provideAngularQuery } from '../providers'
|
|
8
|
-
import {
|
|
9
|
-
errorMutator,
|
|
10
|
-
expectSignals,
|
|
11
|
-
setFixtureSignalInputs,
|
|
12
|
-
successMutator,
|
|
13
|
-
} from './test-utils'
|
|
14
|
-
|
|
15
|
-
const MUTATION_DURATION = 1000
|
|
16
|
-
|
|
17
|
-
const resolveMutations = () => vi.advanceTimersByTimeAsync(MUTATION_DURATION)
|
|
18
|
-
|
|
19
|
-
describe('injectMutation', () => {
|
|
20
|
-
let queryClient: QueryClient
|
|
21
|
-
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
queryClient = new QueryClient()
|
|
24
|
-
vi.useFakeTimers()
|
|
25
|
-
TestBed.configureTestingModule({
|
|
26
|
-
providers: [provideAngularQuery(queryClient)],
|
|
27
|
-
})
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
afterEach(() => {
|
|
31
|
-
vi.useRealTimers()
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
describe('callback helpers', () => {
|
|
35
|
-
test('can access client from options callback', async () => {
|
|
36
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
37
|
-
return injectMutation((client) => ({
|
|
38
|
-
mutationFn: () => {
|
|
39
|
-
expect(client).toBe(queryClient)
|
|
40
|
-
return Promise.resolve()
|
|
41
|
-
},
|
|
42
|
-
}))
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
mutation.mutate()
|
|
46
|
-
vi.advanceTimersByTime(1)
|
|
47
|
-
expect(mutation.status()).toBe('pending')
|
|
48
|
-
})
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
test('should be in idle state initially', () => {
|
|
52
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
53
|
-
return injectMutation(() => ({
|
|
54
|
-
mutationFn: (params) => successMutator(params),
|
|
55
|
-
}))
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
expectSignals(mutation, {
|
|
59
|
-
isIdle: true,
|
|
60
|
-
isPending: false,
|
|
61
|
-
isError: false,
|
|
62
|
-
isSuccess: false,
|
|
63
|
-
})
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
test('should change state after invoking mutate', async () => {
|
|
67
|
-
const result = 'Mock data'
|
|
68
|
-
|
|
69
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
70
|
-
return injectMutation(() => ({
|
|
71
|
-
mutationFn: (params: string) => successMutator(params),
|
|
72
|
-
}))
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
mutation.mutate(result)
|
|
76
|
-
vi.advanceTimersByTime(1)
|
|
77
|
-
|
|
78
|
-
expectSignals(mutation, {
|
|
79
|
-
isIdle: false,
|
|
80
|
-
isPending: true,
|
|
81
|
-
isError: false,
|
|
82
|
-
isSuccess: false,
|
|
83
|
-
data: undefined,
|
|
84
|
-
error: null,
|
|
85
|
-
})
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
test('should return error when request fails', async () => {
|
|
89
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
90
|
-
return injectMutation(() => ({
|
|
91
|
-
mutationFn: errorMutator,
|
|
92
|
-
}))
|
|
93
|
-
})
|
|
94
|
-
mutation.mutate({})
|
|
95
|
-
|
|
96
|
-
await resolveMutations()
|
|
97
|
-
|
|
98
|
-
expectSignals(mutation, {
|
|
99
|
-
isIdle: false,
|
|
100
|
-
isPending: false,
|
|
101
|
-
isError: true,
|
|
102
|
-
isSuccess: false,
|
|
103
|
-
data: undefined,
|
|
104
|
-
error: Error('Some error'),
|
|
105
|
-
})
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
test('should return data when request succeeds', async () => {
|
|
109
|
-
const result = 'Mock data'
|
|
110
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
111
|
-
return injectMutation(() => ({
|
|
112
|
-
mutationFn: (params: string) => successMutator(params),
|
|
113
|
-
}))
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
mutation.mutate(result)
|
|
117
|
-
|
|
118
|
-
await resolveMutations()
|
|
119
|
-
|
|
120
|
-
expectSignals(mutation, {
|
|
121
|
-
isIdle: false,
|
|
122
|
-
isPending: false,
|
|
123
|
-
isError: false,
|
|
124
|
-
isSuccess: true,
|
|
125
|
-
data: result,
|
|
126
|
-
error: null,
|
|
127
|
-
})
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
test('reactive options should update mutation', async () => {
|
|
131
|
-
const mutationCache = queryClient.getMutationCache()
|
|
132
|
-
// Signal will be updated before the mutation is called
|
|
133
|
-
// this test confirms that the mutation uses the updated value
|
|
134
|
-
const mutationKey = signal(['1'])
|
|
135
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
136
|
-
return injectMutation(() => ({
|
|
137
|
-
mutationKey: mutationKey(),
|
|
138
|
-
mutationFn: (params: string) => successMutator(params),
|
|
139
|
-
}))
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
mutationKey.set(['2'])
|
|
143
|
-
|
|
144
|
-
TestBed.flushEffects()
|
|
145
|
-
|
|
146
|
-
mutation.mutate('xyz')
|
|
147
|
-
|
|
148
|
-
const mutations = mutationCache.find({ mutationKey: ['2'] })
|
|
149
|
-
|
|
150
|
-
expect(mutations?.options.mutationKey).toEqual(['2'])
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
test('should reset state after invoking mutation.reset', async () => {
|
|
154
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
155
|
-
return injectMutation(() => ({
|
|
156
|
-
mutationFn: (params: string) => errorMutator(params),
|
|
157
|
-
}))
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
mutation.mutate('')
|
|
161
|
-
|
|
162
|
-
await resolveMutations()
|
|
163
|
-
|
|
164
|
-
expect(mutation.isError()).toBe(true)
|
|
165
|
-
|
|
166
|
-
mutation.reset()
|
|
167
|
-
|
|
168
|
-
await resolveMutations()
|
|
169
|
-
|
|
170
|
-
expectSignals(mutation, {
|
|
171
|
-
isIdle: true,
|
|
172
|
-
isPending: false,
|
|
173
|
-
isError: false,
|
|
174
|
-
isSuccess: false,
|
|
175
|
-
data: undefined,
|
|
176
|
-
error: null,
|
|
177
|
-
})
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
describe('side effects', () => {
|
|
181
|
-
beforeEach(() => {
|
|
182
|
-
vi.clearAllMocks()
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
test('should call onMutate when passed as an option', async () => {
|
|
186
|
-
const onMutate = vi.fn()
|
|
187
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
188
|
-
return injectMutation(() => ({
|
|
189
|
-
mutationFn: (params: string) => successMutator(params),
|
|
190
|
-
onMutate,
|
|
191
|
-
}))
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
mutation.mutate('')
|
|
195
|
-
|
|
196
|
-
await resolveMutations()
|
|
197
|
-
|
|
198
|
-
expect(onMutate).toHaveBeenCalledTimes(1)
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
test('should call onError when passed as an option', async () => {
|
|
202
|
-
const onError = vi.fn()
|
|
203
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
204
|
-
return injectMutation(() => ({
|
|
205
|
-
mutationFn: (params: string) => errorMutator(params),
|
|
206
|
-
onError,
|
|
207
|
-
}))
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
mutation.mutate('')
|
|
211
|
-
|
|
212
|
-
await resolveMutations()
|
|
213
|
-
|
|
214
|
-
expect(onError).toHaveBeenCalledTimes(1)
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
test('should call onSuccess when passed as an option', async () => {
|
|
218
|
-
const onSuccess = vi.fn()
|
|
219
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
220
|
-
return injectMutation(() => ({
|
|
221
|
-
mutationFn: (params: string) => successMutator(params),
|
|
222
|
-
onSuccess,
|
|
223
|
-
}))
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
mutation.mutate('')
|
|
227
|
-
|
|
228
|
-
await resolveMutations()
|
|
229
|
-
|
|
230
|
-
expect(onSuccess).toHaveBeenCalledTimes(1)
|
|
231
|
-
})
|
|
232
|
-
|
|
233
|
-
test('should call onSettled when passed as an option', async () => {
|
|
234
|
-
const onSettled = vi.fn()
|
|
235
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
236
|
-
return injectMutation(() => ({
|
|
237
|
-
mutationFn: (params: string) => successMutator(params),
|
|
238
|
-
onSettled,
|
|
239
|
-
}))
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
mutation.mutate('')
|
|
243
|
-
|
|
244
|
-
await resolveMutations()
|
|
245
|
-
|
|
246
|
-
expect(onSettled).toHaveBeenCalledTimes(1)
|
|
247
|
-
})
|
|
248
|
-
|
|
249
|
-
test('should call onError when passed as an argument of mutate function', async () => {
|
|
250
|
-
const onError = vi.fn()
|
|
251
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
252
|
-
return injectMutation(() => ({
|
|
253
|
-
mutationFn: (params: string) => errorMutator(params),
|
|
254
|
-
}))
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
mutation.mutate('', { onError })
|
|
258
|
-
|
|
259
|
-
await resolveMutations()
|
|
260
|
-
|
|
261
|
-
expect(onError).toHaveBeenCalledTimes(1)
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
test('should call onSuccess when passed as an argument of mutate function', async () => {
|
|
265
|
-
const onSuccess = vi.fn()
|
|
266
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
267
|
-
return injectMutation(() => ({
|
|
268
|
-
mutationFn: (params: string) => successMutator(params),
|
|
269
|
-
}))
|
|
270
|
-
})
|
|
271
|
-
|
|
272
|
-
mutation.mutate('', { onSuccess })
|
|
273
|
-
|
|
274
|
-
await resolveMutations()
|
|
275
|
-
|
|
276
|
-
expect(onSuccess).toHaveBeenCalledTimes(1)
|
|
277
|
-
})
|
|
278
|
-
|
|
279
|
-
test('should call onSettled when passed as an argument of mutate function', async () => {
|
|
280
|
-
const onSettled = vi.fn()
|
|
281
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
282
|
-
return injectMutation(() => ({
|
|
283
|
-
mutationFn: (params: string) => successMutator(params),
|
|
284
|
-
}))
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
mutation.mutate('', { onSettled })
|
|
288
|
-
|
|
289
|
-
await resolveMutations()
|
|
290
|
-
|
|
291
|
-
expect(onSettled).toHaveBeenCalledTimes(1)
|
|
292
|
-
})
|
|
293
|
-
|
|
294
|
-
test('should fire both onSettled functions', async () => {
|
|
295
|
-
const onSettled = vi.fn()
|
|
296
|
-
const onSettledOnFunction = vi.fn()
|
|
297
|
-
const mutation = TestBed.runInInjectionContext(() => {
|
|
298
|
-
return injectMutation(() => ({
|
|
299
|
-
mutationFn: (params: string) => successMutator(params),
|
|
300
|
-
onSettled,
|
|
301
|
-
}))
|
|
302
|
-
})
|
|
303
|
-
|
|
304
|
-
mutation.mutate('', { onSettled: onSettledOnFunction })
|
|
305
|
-
|
|
306
|
-
await resolveMutations()
|
|
307
|
-
|
|
308
|
-
expect(onSettled).toHaveBeenCalledTimes(1)
|
|
309
|
-
expect(onSettledOnFunction).toHaveBeenCalledTimes(1)
|
|
310
|
-
})
|
|
311
|
-
})
|
|
312
|
-
|
|
313
|
-
test('should support required signal inputs', async () => {
|
|
314
|
-
const mutationCache = queryClient.getMutationCache()
|
|
315
|
-
|
|
316
|
-
@Component({
|
|
317
|
-
selector: 'app-fake',
|
|
318
|
-
template: `
|
|
319
|
-
<button (click)="mutate()"></button>
|
|
320
|
-
<span>{{ mutation.data() }}</span>
|
|
321
|
-
`,
|
|
322
|
-
standalone: true,
|
|
323
|
-
})
|
|
324
|
-
class FakeComponent {
|
|
325
|
-
name = input.required<string>()
|
|
326
|
-
|
|
327
|
-
mutation = injectMutation(() => ({
|
|
328
|
-
mutationKey: ['fake', this.name()],
|
|
329
|
-
mutationFn: () => successMutator(this.name()),
|
|
330
|
-
}))
|
|
331
|
-
|
|
332
|
-
mutate(): void {
|
|
333
|
-
this.mutation.mutate()
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
const fixture = TestBed.createComponent(FakeComponent)
|
|
338
|
-
const { debugElement } = fixture
|
|
339
|
-
setFixtureSignalInputs(fixture, { name: 'value' })
|
|
340
|
-
|
|
341
|
-
const button = debugElement.query(By.css('button'))
|
|
342
|
-
button.triggerEventHandler('click')
|
|
343
|
-
|
|
344
|
-
await resolveMutations()
|
|
345
|
-
fixture.detectChanges()
|
|
346
|
-
|
|
347
|
-
const text = debugElement.query(By.css('span')).nativeElement.textContent
|
|
348
|
-
expect(text).toEqual('value')
|
|
349
|
-
const mutation = mutationCache.find({ mutationKey: ['fake', 'value'] })
|
|
350
|
-
expect(mutation).toBeDefined()
|
|
351
|
-
expect(mutation!.options.mutationKey).toStrictEqual(['fake', 'value'])
|
|
352
|
-
})
|
|
353
|
-
|
|
354
|
-
test('should update options on required signal input change', async () => {
|
|
355
|
-
const mutationCache = queryClient.getMutationCache()
|
|
356
|
-
|
|
357
|
-
@Component({
|
|
358
|
-
selector: 'app-fake',
|
|
359
|
-
template: `
|
|
360
|
-
<button (click)="mutate()"></button>
|
|
361
|
-
<span>{{ mutation.data() }}</span>
|
|
362
|
-
`,
|
|
363
|
-
standalone: true,
|
|
364
|
-
})
|
|
365
|
-
class FakeComponent {
|
|
366
|
-
name = input.required<string>()
|
|
367
|
-
|
|
368
|
-
mutation = injectMutation(() => ({
|
|
369
|
-
mutationKey: ['fake', this.name()],
|
|
370
|
-
mutationFn: () => successMutator(this.name()),
|
|
371
|
-
}))
|
|
372
|
-
|
|
373
|
-
mutate(): void {
|
|
374
|
-
this.mutation.mutate()
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
const fixture = TestBed.createComponent(FakeComponent)
|
|
379
|
-
const { debugElement } = fixture
|
|
380
|
-
setFixtureSignalInputs(fixture, { name: 'value' })
|
|
381
|
-
|
|
382
|
-
const button = debugElement.query(By.css('button'))
|
|
383
|
-
const span = debugElement.query(By.css('span'))
|
|
384
|
-
|
|
385
|
-
button.triggerEventHandler('click')
|
|
386
|
-
await resolveMutations()
|
|
387
|
-
fixture.detectChanges()
|
|
388
|
-
|
|
389
|
-
expect(span.nativeElement.textContent).toEqual('value')
|
|
390
|
-
|
|
391
|
-
setFixtureSignalInputs(fixture, { name: 'updatedValue' })
|
|
392
|
-
|
|
393
|
-
button.triggerEventHandler('click')
|
|
394
|
-
await resolveMutations()
|
|
395
|
-
fixture.detectChanges()
|
|
396
|
-
|
|
397
|
-
expect(span.nativeElement.textContent).toEqual('updatedValue')
|
|
398
|
-
|
|
399
|
-
const mutations = mutationCache.findAll()
|
|
400
|
-
expect(mutations.length).toBe(2)
|
|
401
|
-
const [mutation1, mutation2] = mutations
|
|
402
|
-
expect(mutation1!.options.mutationKey).toEqual(['fake', 'value'])
|
|
403
|
-
expect(mutation2!.options.mutationKey).toEqual(['fake', 'updatedValue'])
|
|
404
|
-
})
|
|
405
|
-
|
|
406
|
-
describe('throwOnError', () => {
|
|
407
|
-
test('should evaluate throwOnError when mutation is expected to throw', async () => {
|
|
408
|
-
const err = new Error('Expected mock error. All is well!')
|
|
409
|
-
const boundaryFn = vi.fn()
|
|
410
|
-
const { mutate } = TestBed.runInInjectionContext(() => {
|
|
411
|
-
return injectMutation(() => ({
|
|
412
|
-
mutationKey: ['fake'],
|
|
413
|
-
mutationFn: () => {
|
|
414
|
-
return Promise.reject(err)
|
|
415
|
-
},
|
|
416
|
-
throwOnError: boundaryFn,
|
|
417
|
-
}))
|
|
418
|
-
})
|
|
419
|
-
|
|
420
|
-
mutate()
|
|
421
|
-
|
|
422
|
-
await resolveMutations()
|
|
423
|
-
|
|
424
|
-
expect(boundaryFn).toHaveBeenCalledTimes(1)
|
|
425
|
-
expect(boundaryFn).toHaveBeenCalledWith(err)
|
|
426
|
-
})
|
|
427
|
-
})
|
|
428
|
-
|
|
429
|
-
test('should throw when throwOnError is true', async () => {
|
|
430
|
-
const err = new Error('Expected mock error. All is well!')
|
|
431
|
-
const { mutateAsync } = TestBed.runInInjectionContext(() => {
|
|
432
|
-
return injectMutation(() => ({
|
|
433
|
-
mutationKey: ['fake'],
|
|
434
|
-
mutationFn: () => {
|
|
435
|
-
return Promise.reject(err)
|
|
436
|
-
},
|
|
437
|
-
throwOnError: true,
|
|
438
|
-
}))
|
|
439
|
-
})
|
|
440
|
-
|
|
441
|
-
await expect(() => mutateAsync()).rejects.toThrowError(err)
|
|
442
|
-
})
|
|
443
|
-
|
|
444
|
-
test('should throw when throwOnError function returns true', async () => {
|
|
445
|
-
const err = new Error('Expected mock error. All is well!')
|
|
446
|
-
const { mutateAsync } = TestBed.runInInjectionContext(() => {
|
|
447
|
-
return injectMutation(() => ({
|
|
448
|
-
mutationKey: ['fake'],
|
|
449
|
-
mutationFn: () => {
|
|
450
|
-
return Promise.reject(err)
|
|
451
|
-
},
|
|
452
|
-
throwOnError: () => true,
|
|
453
|
-
}))
|
|
454
|
-
})
|
|
455
|
-
|
|
456
|
-
await expect(() => mutateAsync()).rejects.toThrowError(err)
|
|
457
|
-
})
|
|
458
|
-
})
|