-
Notifications
You must be signed in to change notification settings - Fork 3
/
actions.test.ts
190 lines (160 loc) · 5.79 KB
/
actions.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import * as assert from 'assert';
import {
createAction,
createAsyncAction,
onFulfilled,
onPending,
onRejected,
} from '../src/actions';
describe('actions', () => {
const TYPE = 'TEST_ACTION';
describe('createAction', () => {
it('should create an action object with type and no payload', () => {
const action = createAction(TYPE);
assert.deepEqual(action(), { type: TYPE });
});
it('should output action name on toString()', () => {
const action = createAction(TYPE);
assert.equal(action.toString(), TYPE);
});
it('should add the input to the payload', () => {
const action = createAction(TYPE, (input: number) => input);
assert.equal(action(1234).payload, 1234);
});
it('should execute the action creator and add it to the payload', () => {
const action = createAction(TYPE, (a: number, b: number) => a + b);
assert.equal(action(40, 2).payload, 42);
});
describe('metadataCreator', () => {
it('should not have metadata', () => {
const action = createAction(TYPE, (n: number) => ({ n }));
assert.equal('meta' in action(42), false);
});
it('should forward same payload and metadata', () => {
const action = createAction(TYPE, (n: number) => ({ n }), (n: number) => ({ n }));
assert.deepEqual(action(42), {
type: TYPE,
payload: { n: 42 },
meta: { n: 42 },
});
});
it('should have different payload and metadata', () => {
const action = createAction(TYPE, (n: number) => ({ n }), () => ({ asdf: 1234 }));
assert.deepEqual(action(42), {
type: TYPE,
payload: { n: 42 },
meta: { asdf: 1234 },
});
});
it('should have only metadata', () => {
const action = createAction(TYPE, () => undefined, () => ({ asdf: 1234 }));
assert.deepEqual(action(), {
type: TYPE,
meta: { asdf: 1234 },
});
});
});
});
describe('createAsyncAction', () => {
const action = createAsyncAction(TYPE, (s: string) => Promise.resolve(s));
it('should create an action with correct type', () => {
assert.equal(action('x').type, TYPE);
});
it('should create an action with Promise payload', async () => {
assert(action('x').payload instanceof Promise);
});
it('should create an action with correct payload', async () => {
assert.equal(await action('x').payload, 'x');
});
it('should throw on toString()', () => {
assert.throws(
() => action.toString(),
new RegExp(`Async action ${TYPE} must be handled with pending, fulfilled or rejected`)
);
});
it('should create action with 0 arguments', async () => {
const action0 = createAsyncAction(TYPE, () => Promise.resolve(42));
assert.equal(await action0().payload, 42);
});
it('should create action with 1 arguments', async () => {
const action1 = createAsyncAction(TYPE, (n: number) => Promise.resolve(n));
assert.equal(await action1(42).payload, 42);
});
it('should create action with 2 arguments', async () => {
const action1 = createAsyncAction(TYPE, (n: number, s: string) => Promise.resolve({ n, s }));
assert.deepEqual(await action1(42, 'hello').payload, { n: 42, s: 'hello' });
});
it('should create action with 3 arguments', async () => {
const action1 = createAsyncAction(TYPE, (n: number, s: string, b: boolean) => Promise.resolve({ n, s, b }));
assert.deepEqual(await action1(42, 'hello', true).payload, { n: 42, s: 'hello', b: true });
});
describe('pending', () => {
it('should have a pending action prop', () => {
assert('pending' in action);
});
it('should output pending action name on toString()', () => {
assert.equal(action.pending.toString(), onPending(TYPE));
});
});
describe('fulfilled', () => {
it('should have a fulfilled action prop', () => {
assert('fulfilled' in action);
});
it('should output fulfilled action name on toString()', () => {
assert.equal(action.fulfilled.toString(), onFulfilled(TYPE));
});
it('should create a fulfilled action with payload', () => {
assert.deepEqual(action.fulfilled('payload'), {
type: onFulfilled(TYPE),
payload: 'payload',
});
});
});
describe('rejected', () => {
it('should have a rejected action prop', () => {
assert('rejected' in action);
});
it('should output rejected action name on toString()', () => {
assert.equal(action.rejected.toString(), onRejected(TYPE));
});
it('should create a rejected action with payload', () => {
assert.deepEqual(action.rejected('error'), {
type: onRejected(TYPE),
payload: 'error',
});
});
});
});
describe('thunk', () => {
const getStateMock = () => 42;
const dispatchMock = (action: any) => {
if (typeof action === 'function') {
return action(dispatchMock, getStateMock);
}
return action;
};
it('should return a thunk function', () => {
const thunk = createAction(
'THUNK',
(n: number) => (_, getState) => getState() + n
);
assert(typeof thunk(1) === 'function');
});
it('should dispatch thunk payload', () => {
const thunk = createAction(
'THUNK',
(n: number) => (_, getState) => getState() + n
);
const result = dispatchMock(thunk(1));
assert.equal(result, 43);
});
it('should return a thunk with metadata', () => {
const thunk = createAction(
'THUNK',
(n: number) => (_, getState) => getState() + n,
(n: number) => ({ n })
);
assert(typeof thunk(1) === 'function');
});
});
});