saga-toolkit 2.0.6 → 2.1.1
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 +1 -1
- package/example/package-lock.json +9 -34
- package/example/package.json +2 -2
- package/example/src/sagas.js +25 -28
- package/example/src/slice.js +1 -1
- package/index.d.ts +72 -0
- package/package.json +1 -1
- package/.babelrc +0 -12
- package/example/src/sagaToolkit.js +0 -154
- package/test/createStore.js +0 -24
- package/test/sagaToolkit.test.js +0 -95
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "example",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.0.1",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
|
-
"version": "0.1
|
|
8
|
+
"version": "0.0.1",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@reduxjs/toolkit": "^1.6.1",
|
|
11
11
|
"@testing-library/jest-dom": "^5.11.4",
|
|
@@ -17,26 +17,10 @@
|
|
|
17
17
|
"react-scripts": "4.0.3",
|
|
18
18
|
"redux": "^4.1.1",
|
|
19
19
|
"redux-saga": "^1.1.3",
|
|
20
|
-
"saga-toolkit": "
|
|
20
|
+
"saga-toolkit": "^2.0.6",
|
|
21
21
|
"web-vitals": "^1.0.1"
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
|
-
"..": {
|
|
25
|
-
"version": "2.0.4",
|
|
26
|
-
"license": "ISC",
|
|
27
|
-
"devDependencies": {
|
|
28
|
-
"@babel/cli": "^7.16.8",
|
|
29
|
-
"@babel/core": "^7.16.12",
|
|
30
|
-
"@babel/node": "^7.16.8",
|
|
31
|
-
"@babel/preset-env": "^7.16.11",
|
|
32
|
-
"@reduxjs/toolkit": "^1.7.2",
|
|
33
|
-
"babel-jest": "^27.4.6",
|
|
34
|
-
"jest": "^27.4.7",
|
|
35
|
-
"redux": "^4.1.2",
|
|
36
|
-
"redux-saga": "^1.1.3",
|
|
37
|
-
"redux-saga-test-plan": "^4.0.4"
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
24
|
"node_modules/@babel/code-frame": {
|
|
41
25
|
"version": "7.12.13",
|
|
42
26
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
|
|
@@ -15302,8 +15286,9 @@
|
|
|
15302
15286
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
|
15303
15287
|
},
|
|
15304
15288
|
"node_modules/saga-toolkit": {
|
|
15305
|
-
"
|
|
15306
|
-
"
|
|
15289
|
+
"version": "2.0.6",
|
|
15290
|
+
"resolved": "https://registry.npmjs.org/saga-toolkit/-/saga-toolkit-2.0.6.tgz",
|
|
15291
|
+
"integrity": "sha512-KBWuzC0PSmGFGm8/t7dhjvnyoudBqWK2VENKx0Ka+sroPZq6/inAXWSCpukHxaOYAH4afO2czZb1fgve3dyB8g=="
|
|
15307
15292
|
},
|
|
15308
15293
|
"node_modules/sane": {
|
|
15309
15294
|
"version": "4.1.0",
|
|
@@ -30691,19 +30676,9 @@
|
|
|
30691
30676
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
|
30692
30677
|
},
|
|
30693
30678
|
"saga-toolkit": {
|
|
30694
|
-
"version": "
|
|
30695
|
-
"
|
|
30696
|
-
|
|
30697
|
-
"@babel/core": "^7.16.12",
|
|
30698
|
-
"@babel/node": "^7.16.8",
|
|
30699
|
-
"@babel/preset-env": "^7.16.11",
|
|
30700
|
-
"@reduxjs/toolkit": "^1.7.2",
|
|
30701
|
-
"babel-jest": "^27.4.6",
|
|
30702
|
-
"jest": "^27.4.7",
|
|
30703
|
-
"redux": "^4.1.2",
|
|
30704
|
-
"redux-saga": "^1.1.3",
|
|
30705
|
-
"redux-saga-test-plan": "^4.0.4"
|
|
30706
|
-
}
|
|
30679
|
+
"version": "2.0.6",
|
|
30680
|
+
"resolved": "https://registry.npmjs.org/saga-toolkit/-/saga-toolkit-2.0.6.tgz",
|
|
30681
|
+
"integrity": "sha512-KBWuzC0PSmGFGm8/t7dhjvnyoudBqWK2VENKx0Ka+sroPZq6/inAXWSCpukHxaOYAH4afO2czZb1fgve3dyB8g=="
|
|
30707
30682
|
},
|
|
30708
30683
|
"sane": {
|
|
30709
30684
|
"version": "4.1.0",
|
package/example/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "example",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.0.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@reduxjs/toolkit": "^1.6.1",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"react-scripts": "4.0.3",
|
|
14
14
|
"redux": "^4.1.1",
|
|
15
15
|
"redux-saga": "^1.1.3",
|
|
16
|
-
"saga-toolkit": "
|
|
16
|
+
"saga-toolkit": "^2.0.6",
|
|
17
17
|
"web-vitals": "^1.0.1"
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
package/example/src/sagas.js
CHANGED
|
@@ -1,40 +1,44 @@
|
|
|
1
1
|
import { call, cancelled, delay, put, select, takeEvery } from 'redux-saga/effects'
|
|
2
|
-
import { LOCATION_CHANGE } from 'connected-react-router'
|
|
3
2
|
import {
|
|
4
3
|
takeEveryAsync,
|
|
5
4
|
takeLatestAsync,
|
|
6
5
|
takeAggregateAsync,
|
|
7
6
|
putAsync,
|
|
8
|
-
} from '
|
|
7
|
+
} from 'saga-toolkit'
|
|
9
8
|
import * as actions from './slice'
|
|
10
9
|
|
|
11
10
|
const hyperSuperApi = (success = true) => {
|
|
12
11
|
console.log('hyperSuperApi')
|
|
13
12
|
|
|
14
|
-
let timeoutId
|
|
15
|
-
const deferred = {}
|
|
13
|
+
// let timeoutId
|
|
14
|
+
// const deferred = {}
|
|
16
15
|
|
|
17
16
|
const promise = new Promise((resolve, reject) => {
|
|
18
|
-
deferred.resolve = resolve
|
|
19
|
-
deferred.reject = reject
|
|
20
|
-
timeoutId = setTimeout(() => (success ? resolve : reject)('result'), 1000)
|
|
17
|
+
// deferred.resolve = resolve
|
|
18
|
+
// deferred.reject = reject
|
|
19
|
+
// timeoutId = setTimeout(() => (success ? resolve : reject)('result'), 1000)
|
|
20
|
+
setTimeout(() => (success ? resolve : reject)('result'), 1000)
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
-
deferred.promise = promise
|
|
23
|
+
// deferred.promise = promise
|
|
24
24
|
|
|
25
|
-
promise.abort = () => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
25
|
+
// promise.abort = () => {
|
|
26
|
+
// clearTimeout(timeoutId)
|
|
27
|
+
// deferred.reject('Aborted')
|
|
28
|
+
// }
|
|
29
29
|
|
|
30
30
|
return promise
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function* appStart() {
|
|
34
34
|
try {
|
|
35
|
+
// fetch things at app start
|
|
36
|
+
|
|
37
|
+
// non blocking way
|
|
35
38
|
// yield put(actions.fetchThings())
|
|
36
|
-
|
|
37
|
-
//
|
|
39
|
+
|
|
40
|
+
// OR wait for it to finish - a blocking way
|
|
41
|
+
// yield putAsync(actions.fetchThings())
|
|
38
42
|
} catch (error) {
|
|
39
43
|
console.log('appStart 1', error)
|
|
40
44
|
}
|
|
@@ -50,9 +54,6 @@ function* appStart() {
|
|
|
50
54
|
console.log('Started')
|
|
51
55
|
}
|
|
52
56
|
|
|
53
|
-
function* locationChange() {
|
|
54
|
-
}
|
|
55
|
-
|
|
56
57
|
function* fetchThings({ meta }) {
|
|
57
58
|
const result = yield call(() => hyperSuperApi(meta.arg))
|
|
58
59
|
|
|
@@ -62,7 +63,7 @@ function* fetchThings({ meta }) {
|
|
|
62
63
|
function* fetchThingsDebounce({ meta }) {
|
|
63
64
|
try {
|
|
64
65
|
yield delay(1000)
|
|
65
|
-
|
|
66
|
+
|
|
66
67
|
console.log('STILL RUNNING', meta.requestId)
|
|
67
68
|
} finally {
|
|
68
69
|
if (yield cancelled()) {
|
|
@@ -70,25 +71,21 @@ function* fetchThingsDebounce({ meta }) {
|
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
// const result = yield call(() => hyperSuperApi(true))
|
|
74
|
-
|
|
75
|
-
// return result
|
|
76
74
|
return 'shite'
|
|
77
75
|
}
|
|
78
76
|
|
|
79
77
|
function* click() {
|
|
80
78
|
try {
|
|
81
|
-
yield putAsync(actions.fetchThings(false))
|
|
79
|
+
yield putAsync(actions.fetchThings(false)) // wait
|
|
82
80
|
} catch (error) {
|
|
83
81
|
console.log('click', { error })
|
|
84
82
|
}
|
|
85
83
|
}
|
|
86
84
|
|
|
87
85
|
export default [
|
|
88
|
-
takeEveryAsync(actions.start.pending
|
|
89
|
-
// takeAggregateAsync(actions.fetchThings.pending
|
|
90
|
-
takeEveryAsync(actions.fetchThings.pending
|
|
91
|
-
takeLatestAsync(actions.fetchThingsDebounce.pending
|
|
92
|
-
takeEvery(actions.click.type
|
|
93
|
-
takeEvery(LOCATION_CHANGE, locationChange),
|
|
86
|
+
takeEveryAsync(actions.start.pending, appStart),
|
|
87
|
+
// takeAggregateAsync(actions.fetchThings.pending, fetchThings),
|
|
88
|
+
takeEveryAsync(actions.fetchThings.pending, fetchThings),
|
|
89
|
+
takeLatestAsync(actions.fetchThingsDebounce.pending, fetchThingsDebounce),
|
|
90
|
+
takeEvery(actions.click.type, click),
|
|
94
91
|
]
|
package/example/src/slice.js
CHANGED
package/index.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// generated with chatGPT
|
|
2
|
+
|
|
3
|
+
import { ThunkAction } from '@reduxjs/toolkit'
|
|
4
|
+
|
|
5
|
+
declare module 'saga-toolkit' {
|
|
6
|
+
import { Dispatch } from 'redux'
|
|
7
|
+
import { SagaIterator } from 'redux-saga'
|
|
8
|
+
import { AsyncThunkFulfilledActionCreator, AsyncThunkConfig } from '@reduxjs/toolkit/src/createAsyncThunk'
|
|
9
|
+
|
|
10
|
+
type AsyncSagaPayloadCreator<Returned, ThunkArg = void> = (
|
|
11
|
+
arg: ThunkArg,
|
|
12
|
+
requestId: string
|
|
13
|
+
) => Promise<Returned>
|
|
14
|
+
|
|
15
|
+
type AsyncSagaActionCreator<
|
|
16
|
+
Returned,
|
|
17
|
+
ThunkArg,
|
|
18
|
+
ThunkApiConfig extends AsyncThunkConfig = {}
|
|
19
|
+
> = (
|
|
20
|
+
arg: ThunkArg
|
|
21
|
+
) => ThunkAction<
|
|
22
|
+
Promise<Returned>,
|
|
23
|
+
ReturnType<Dispatch>,
|
|
24
|
+
unknown,
|
|
25
|
+
ReturnType<
|
|
26
|
+
AsyncThunkFulfilledActionCreator<Returned, ThunkArg, ThunkApiConfig>
|
|
27
|
+
>
|
|
28
|
+
>
|
|
29
|
+
|
|
30
|
+
export interface AsyncSagaThunkConfig {
|
|
31
|
+
requestId: string
|
|
32
|
+
signal: AbortSignal
|
|
33
|
+
abort: (reason?: string) => void
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function createSagaAction<Returned, ThunkArg = void>(
|
|
37
|
+
type: string
|
|
38
|
+
): AsyncSagaActionCreator<Returned, ThunkArg> & {
|
|
39
|
+
pending: string;
|
|
40
|
+
fulfilled: string;
|
|
41
|
+
rejected: string;
|
|
42
|
+
typePrefix: string;
|
|
43
|
+
type: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type SagaFunction<Args extends any[]> = (...args: Args) => SagaIterator;
|
|
47
|
+
|
|
48
|
+
export function takeEveryAsync<ActionPattern>(
|
|
49
|
+
pattern: ActionPattern,
|
|
50
|
+
saga: SagaFunction<[...args: any[]]>,
|
|
51
|
+
...args: any[]
|
|
52
|
+
): void;
|
|
53
|
+
|
|
54
|
+
export function takeLatestAsync<ActionPattern>(
|
|
55
|
+
pattern: ActionPattern,
|
|
56
|
+
saga: SagaFunction<[...args: any[]]>,
|
|
57
|
+
...args: any[]
|
|
58
|
+
): void;
|
|
59
|
+
|
|
60
|
+
export function takeAggregateAsync<ActionPattern>(
|
|
61
|
+
pattern: ActionPattern,
|
|
62
|
+
saga: SagaFunction<[...args: any[]]>,
|
|
63
|
+
...args: any[]
|
|
64
|
+
): void;
|
|
65
|
+
|
|
66
|
+
export function putAsync<T>(action: T): T;
|
|
67
|
+
|
|
68
|
+
// export function takeEveryAsync(pattern: any, saga: any, ...args: any[]): any
|
|
69
|
+
// export function takeLatestAsync(pattern: any, saga: any, ...args: any[]): any
|
|
70
|
+
// export function takeAggregateAsync(pattern: any, saga: any, ...args: any[]): any
|
|
71
|
+
// export function putAsync(action: any): any
|
|
72
|
+
}
|
package/package.json
CHANGED
package/.babelrc
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import { createAsyncThunk, unwrapResult } from '@reduxjs/toolkit'
|
|
2
|
-
import { put, take, fork, takeEvery, cancel } from '@redux-saga/core/effects'
|
|
3
|
-
import createDeferred from '@redux-saga/deferred'
|
|
4
|
-
|
|
5
|
-
const requests = {}
|
|
6
|
-
|
|
7
|
-
const addRequest = requestId => {
|
|
8
|
-
const deferred = createDeferred()
|
|
9
|
-
const request = {
|
|
10
|
-
...requests[requestId],
|
|
11
|
-
requestId,
|
|
12
|
-
deferred,
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if (requests[requestId]) {
|
|
16
|
-
requests[requestId].deferred = deferred
|
|
17
|
-
requests[requestId].onAdd(request)
|
|
18
|
-
} else {
|
|
19
|
-
requests[requestId] = request
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return deferred.promise
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const createSagaAction = type => {
|
|
26
|
-
const thunk = createAsyncThunk(type, (_, { requestId }) => addRequest(requestId))
|
|
27
|
-
|
|
28
|
-
function actionCreator(...args) {
|
|
29
|
-
const originalActionCreator = thunk(...args)
|
|
30
|
-
|
|
31
|
-
return (...args) => {
|
|
32
|
-
const promise = originalActionCreator(...args)
|
|
33
|
-
requests[promise.requestId].abort = promise.abort
|
|
34
|
-
|
|
35
|
-
return promise
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
actionCreator.pending = thunk.pending
|
|
40
|
-
actionCreator.rejected = thunk.rejected
|
|
41
|
-
actionCreator.fulfilled = thunk.fulfilled
|
|
42
|
-
actionCreator.typePrefix = thunk.typePrefix
|
|
43
|
-
actionCreator.type = thunk.pending
|
|
44
|
-
|
|
45
|
-
return actionCreator
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const cleanup = requestId => {
|
|
49
|
-
delete requests[requestId]
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function* getRequest(requestId) {
|
|
53
|
-
// const { requestId } = action.meta
|
|
54
|
-
const request = requests[requestId]
|
|
55
|
-
|
|
56
|
-
if (!request) {
|
|
57
|
-
return yield (new Promise(onAdd => {
|
|
58
|
-
requests[requestId] = { onAdd }
|
|
59
|
-
}))
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return request
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const wrap = saga => function* (action, ...rest) {
|
|
66
|
-
const { requestId } = action.meta
|
|
67
|
-
const request = yield getRequest(requestId)
|
|
68
|
-
const deferred = request.deferred
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
deferred.resolve(yield saga(action, ...rest))
|
|
72
|
-
} catch (error) {
|
|
73
|
-
console.log(error)
|
|
74
|
-
deferred.reject(error)
|
|
75
|
-
} finally {
|
|
76
|
-
cleanup(requestId)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function takeEveryAsync(pattern, saga, ...args) {
|
|
81
|
-
return takeEvery(pattern, wrap(saga), ...args)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function takeLatestAsync(pattern, saga, ...args) {
|
|
85
|
-
let deferred
|
|
86
|
-
const tasks = {}
|
|
87
|
-
|
|
88
|
-
function* wrapper(action, ...rest) {
|
|
89
|
-
if (deferred) {
|
|
90
|
-
const lastRequestId = yield deferred.promise
|
|
91
|
-
const request = yield getRequest(lastRequestId)
|
|
92
|
-
|
|
93
|
-
request.abort()
|
|
94
|
-
|
|
95
|
-
const task = yield tasks[lastRequestId].promise
|
|
96
|
-
|
|
97
|
-
yield cancel(task)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
deferred = createDeferred()
|
|
101
|
-
const { requestId } = yield getRequest(action.meta.requestId)
|
|
102
|
-
|
|
103
|
-
deferred.resolve(requestId)
|
|
104
|
-
|
|
105
|
-
yield wrap(saga)(action, ...rest)
|
|
106
|
-
|
|
107
|
-
deferred = null
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const takeEvery = (patternOrChannel, saga, ...args) => fork(function* () {
|
|
111
|
-
while (true) {
|
|
112
|
-
const action = yield take(patternOrChannel)
|
|
113
|
-
const { requestId } = action.meta
|
|
114
|
-
tasks[requestId] = createDeferred()
|
|
115
|
-
tasks[requestId].resolve(yield fork(saga, ...args.concat(action)))
|
|
116
|
-
}
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
return takeEvery(pattern, wrapper, ...args)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export function takeAggregateAsync(pattern, saga, ...args) {
|
|
123
|
-
let deferred
|
|
124
|
-
|
|
125
|
-
function* wrapper(action, ...rest) {
|
|
126
|
-
const { requestId } = action.meta
|
|
127
|
-
|
|
128
|
-
if (deferred) {
|
|
129
|
-
const request = yield getRequest(requestId)
|
|
130
|
-
const { resolve, reject } = request.deferred
|
|
131
|
-
const { promise } = yield deferred.promise
|
|
132
|
-
|
|
133
|
-
promise
|
|
134
|
-
.then(resolve, reject)
|
|
135
|
-
.finally(() => cleanup(requestId))
|
|
136
|
-
.catch(() => { })
|
|
137
|
-
} else {
|
|
138
|
-
deferred = createDeferred()
|
|
139
|
-
const request = yield getRequest(requestId)
|
|
140
|
-
const { promise } = request.deferred
|
|
141
|
-
|
|
142
|
-
yield wrap(saga)(action, ...rest)
|
|
143
|
-
|
|
144
|
-
deferred.resolve({ promise })
|
|
145
|
-
deferred = null
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return takeEvery(pattern, wrapper, ...args)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export function* putAsync(action) {
|
|
153
|
-
return unwrapResult(yield (yield put(action)))
|
|
154
|
-
}
|
package/test/createStore.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { combineReducers } from 'redux'
|
|
2
|
-
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'
|
|
3
|
-
import createSagaMiddleware from 'redux-saga'
|
|
4
|
-
import { all } from 'redux-saga/effects'
|
|
5
|
-
|
|
6
|
-
export default ({ initialState, reducers, sagas }) => {
|
|
7
|
-
const sagaMiddleware = createSagaMiddleware()
|
|
8
|
-
const store = configureStore({
|
|
9
|
-
reducer: combineReducers(reducers),
|
|
10
|
-
middleware: [...getDefaultMiddleware(), sagaMiddleware],
|
|
11
|
-
devTools: false,
|
|
12
|
-
})
|
|
13
|
-
// const store = createStore(
|
|
14
|
-
// combineReducers(reducers),
|
|
15
|
-
// initialState,
|
|
16
|
-
// applyMiddleware(sagaMiddleware)
|
|
17
|
-
// )
|
|
18
|
-
|
|
19
|
-
sagaMiddleware.run(function* () {
|
|
20
|
-
yield all(sagas)
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
return store
|
|
24
|
-
}
|
package/test/sagaToolkit.test.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { put } from 'redux-saga/effects'
|
|
2
|
-
import { createSlice } from '@reduxjs/toolkit'
|
|
3
|
-
import { expectSaga, testSaga } from 'redux-saga-test-plan'
|
|
4
|
-
import createStore from './createStore'
|
|
5
|
-
import { createSagaAction, takeEveryAsync } from '../sagaToolkit'
|
|
6
|
-
|
|
7
|
-
const initialState = {
|
|
8
|
-
test: null,
|
|
9
|
-
testAsync: null,
|
|
10
|
-
error: null,
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const testAsyncAction = createSagaAction('testSlice/testAsyncAction')
|
|
14
|
-
|
|
15
|
-
const slice = createSlice({
|
|
16
|
-
name: 'testSlice',
|
|
17
|
-
initialState,
|
|
18
|
-
reducers: {
|
|
19
|
-
testAction: (state, action) => ({ test: action.payload }),
|
|
20
|
-
},
|
|
21
|
-
extraReducers: {
|
|
22
|
-
[testAsyncAction.pending]: (state, action) => ({
|
|
23
|
-
...state,
|
|
24
|
-
test: action.payload,
|
|
25
|
-
}),
|
|
26
|
-
[testAsyncAction.resolved]: (state, action) => ({
|
|
27
|
-
...state,
|
|
28
|
-
testAsync: 'action.meta.args',
|
|
29
|
-
}),
|
|
30
|
-
[testAsyncAction.rejected]: (state, action) => ({
|
|
31
|
-
...state,
|
|
32
|
-
test: action.payload,
|
|
33
|
-
}),
|
|
34
|
-
},
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const { testAction } = slice.actions
|
|
38
|
-
|
|
39
|
-
function* saga() {
|
|
40
|
-
yield put(testAction('testing'))
|
|
41
|
-
|
|
42
|
-
return 'resolved value'
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
test('testing sync', () => {
|
|
46
|
-
const reducers = { slice: slice.reducer }
|
|
47
|
-
const sagas = [takeEveryAsync(testAsyncAction.pending, saga)]
|
|
48
|
-
const store = createStore({ initialState, reducers, sagas })
|
|
49
|
-
|
|
50
|
-
store.dispatch(testAction('testing'))
|
|
51
|
-
|
|
52
|
-
const state = store.getState()
|
|
53
|
-
|
|
54
|
-
expect(state).toEqual({
|
|
55
|
-
slice: { test: 'testing' },
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
test('testing async', () => {
|
|
60
|
-
return expectSaga(saga)
|
|
61
|
-
.withReducer(slice.reducer)
|
|
62
|
-
.hasFinalState({
|
|
63
|
-
test: 'testing',
|
|
64
|
-
testAsync: 'testing async',
|
|
65
|
-
})
|
|
66
|
-
.run()
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
test('testing async 2', () => {
|
|
70
|
-
testSaga(function *() {
|
|
71
|
-
yield takeEveryAsync(testAsyncAction.pending, saga)
|
|
72
|
-
}, 40, 2)
|
|
73
|
-
// advance saga with `next()`
|
|
74
|
-
.next()
|
|
75
|
-
|
|
76
|
-
// assert that the saga yields `take` with `'HELLO'` as type
|
|
77
|
-
// .take('HELLO')
|
|
78
|
-
|
|
79
|
-
// pass back in a value to a saga after it yields
|
|
80
|
-
// .next(action)
|
|
81
|
-
|
|
82
|
-
// assert that the saga yields `put` with the expected action
|
|
83
|
-
.put(testAction('testing'))
|
|
84
|
-
|
|
85
|
-
.next()
|
|
86
|
-
|
|
87
|
-
// assert that the saga yields a `call` to `identity` with
|
|
88
|
-
// the `action` argument
|
|
89
|
-
// .call(identity, action)
|
|
90
|
-
|
|
91
|
-
.next()
|
|
92
|
-
|
|
93
|
-
// assert that the saga is finished
|
|
94
|
-
.isDone();
|
|
95
|
-
})
|