@webqit/fetch-plus 0.1.2 → 0.1.3

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.
@@ -0,0 +1,261 @@
1
+ import chai, { expect } from 'chai';
2
+ import chaiAsPromised from 'chai-as-promised';
3
+ chai.use(chaiAsPromised);
4
+ import { LiveResponse } from '../src/LiveResponse.js';
5
+ import Observer from '@webqit/observer';
6
+
7
+ describe('LiveResponse Basic Instance Tests', function () {
8
+
9
+ it('should quak like a Response and EventTarget', async function () {
10
+ const body = 'Hello World';
11
+ const liveResponse = new LiveResponse(body);
12
+
13
+ expect(liveResponse).to.be.instanceOf(EventTarget);
14
+ expect(liveResponse.headers).to.exist;
15
+ });
16
+
17
+ it('should initialize synchronously for a "sync" body input', async function () {
18
+ const body = 'Hello World';
19
+ const liveResponse = new LiveResponse(body);
20
+
21
+ expect(liveResponse.body).to.equal(body);
22
+ expect(liveResponse.status).to.equal(200);
23
+ expect(liveResponse.ok).to.be.true;
24
+
25
+ expect((await liveResponse.now()).body).to.equal(body);
26
+ });
27
+
28
+ it('should switch readyState to "live" synchronously for a "sync" body input', async function () {
29
+ const body = 'Hello World';
30
+ const liveResponse = new LiveResponse(body);
31
+
32
+ expect(liveResponse.readyState).to.equal('live');
33
+ expect(liveResponse.body).to.equal(body);
34
+ });
35
+
36
+ it('should switch readyState to "done" asynchronously', async function () {
37
+ const body = 'Hello World';
38
+ const liveResponse = new LiveResponse(body);
39
+
40
+ expect(liveResponse.readyState).to.equal('live');
41
+ expect(liveResponse.body).to.equal(body);
42
+
43
+ await new Promise((resolve) => setTimeout(() => resolve(), 0));
44
+
45
+ expect(liveResponse.readyState).to.equal('done');
46
+ });
47
+
48
+ it('should have a .now() method that snapshots state synchronously and returns a promise that resolves to it', async function () {
49
+ const body = 'Hello World';
50
+ const liveResponse = new LiveResponse(body);
51
+
52
+ expect(liveResponse.readyState).to.equal('live');
53
+ expect(liveResponse.body).to.equal(body);
54
+
55
+ expect((await liveResponse.now()).body).to.equal(body);
56
+
57
+ expect(liveResponse.readyState).to.equal('done');
58
+ });
59
+
60
+ it('should reject .replaceWith() if the response is aliveResponseeady done', async function () {
61
+ const body = 'Hello World';
62
+ const liveResponse = new LiveResponse(body);
63
+
64
+ expect(liveResponse.readyState).to.equal('live');
65
+ expect((await liveResponse.now()).body).to.equal(body);
66
+
67
+ expect(liveResponse.readyState).to.equal('done');
68
+
69
+ expect(liveResponse.replaceWith('final', { done: true })).to.be.rejectedWith(/Response aliveResponseeady done/);
70
+ });
71
+
72
+ it('should emit a "replace" event when the body is replaced. Fires synchronously for sync body inputs', function () {
73
+ const liveResponse = new LiveResponse('initial');
74
+ const sequence = [];
75
+
76
+ liveResponse.addEventListener('replace', () => sequence.push('replace'));
77
+ liveResponse.replaceWith('updated');
78
+ sequence.push('done');
79
+
80
+ expect(sequence[0]).to.equal('replace');
81
+ expect(sequence[1]).to.equal('done');
82
+
83
+ expect(liveResponse.body).to.equal('updated');
84
+ expect(liveResponse.readyState).to.equal('live');
85
+ });
86
+ });
87
+
88
+ describe('LiveResponse Async Body Tests', function () {
89
+
90
+ it('should initialize asynchronously for an "async" body input', async function () {
91
+ const body = 'Hello World';
92
+ const p = new Promise((resolve) => setTimeout(() => resolve(body), 10));
93
+ const liveResponse = new LiveResponse(p);
94
+
95
+ expect(liveResponse.body).to.equal(null);
96
+ expect(liveResponse.readyState).to.equal('waiting');
97
+
98
+ await new Promise((resolve) => setTimeout(() => resolve(), 10));
99
+ expect(liveResponse.readyState).to.equal('done');
100
+ expect(liveResponse.body).to.equal(body);
101
+ });
102
+
103
+ it('should treat Response body inputs as async', async function () {
104
+ const body = 'Hello World';
105
+
106
+ const liveResponse = new LiveResponse(new Response(body));
107
+
108
+ expect(liveResponse.body).to.equal(null);
109
+ expect(liveResponse.readyState).to.equal('waiting');
110
+
111
+ await new Promise((resolve) => setTimeout(() => resolve(), 20));
112
+ expect(liveResponse.readyState).to.equal('done');
113
+ expect(liveResponse.body).to.equal(body);
114
+ });
115
+
116
+ it('.now() should snapshot async body input synchronously and return a promise that resolves to it', async function () {
117
+ const body = 'async body';
118
+ const p = new Promise((resolve) => setTimeout(() => resolve(body), 10));
119
+ const liveResponse = new LiveResponse(p);
120
+
121
+ expect(liveResponse.body).to.equal(null);
122
+ expect(liveResponse.readyState).to.equal('waiting');
123
+
124
+ expect((await liveResponse.now()).body).to.equal(body);
125
+ expect(liveResponse.readyState).to.equal('done');
126
+ });
127
+
128
+ it('.now() should successively snapshot synchronously and return a promise each that resolves to it', async function () {
129
+ const frame1 = new Promise((resolve) => setTimeout(() => resolve('frame 1'), 10));
130
+ const liveResponse = new LiveResponse(frame1, { done: false });
131
+ const snapshot1 = liveResponse.now(); // Snapshot 'frame 1' while still resolving
132
+
133
+ liveResponse.replaceWith('frame 2', { done: false }); // 'frame 1' is abanddoned now while still resolving
134
+ const snapshot2 = liveResponse.now(); // Snapshot 'frame 2'
135
+
136
+ const frame3 = new Promise((resolve) => setTimeout(() => resolve('frame 3'), 10));
137
+ liveResponse.replaceWith(frame3, { done: false }); // 'frame 2' – which resolved synchronously – is replaced now
138
+ const snapshot3 = liveResponse.now(); // Snapshot 'frame 3' while still resolving
139
+
140
+ const frame4 = new Promise((resolve) => setTimeout(() => resolve('frame 4'), 10));
141
+ liveResponse.replaceWith(frame4, { done: true }); // 'frame 3' is abanddoned now while still resolving
142
+ const snapshot4 = liveResponse.now(); // Snapshot 'frame 4' while still resolving
143
+
144
+ expect((await snapshot1).body).to.equal('frame 1');
145
+ expect((await snapshot2).body).to.equal('frame 2');
146
+ expect((await snapshot3).body).to.equal('frame 3');
147
+ expect((await snapshot4).body).to.equal('frame 4');
148
+ });
149
+ });
150
+
151
+ describe('LiveResponse Replacement Tests', function () {
152
+
153
+ it('should keep readyState live when options.done is false (sync)', async function () {
154
+ const body = 'Hello World';
155
+ const liveResponse = new LiveResponse(body, { done: false });
156
+
157
+ expect(liveResponse.body).to.equal(body);
158
+ expect(liveResponse.readyState).to.equal('live');
159
+ expect((await liveResponse.now()).body).to.equal(body);
160
+ expect(liveResponse.readyState).to.equal('live');
161
+
162
+ liveResponse.replaceWith('final', { done: true });
163
+
164
+ expect(liveResponse.body).to.equal('final');
165
+ expect(liveResponse.readyState).to.equal('live');
166
+ expect((await liveResponse.now()).body).to.equal('final');
167
+ expect(liveResponse.readyState).to.equal('done');
168
+ });
169
+
170
+ it('should keep readyState live when options.done is false (async)', async function () {
171
+ const body = 'async body';
172
+ const p = new Promise((resolve) => setTimeout(() => resolve(body), 10));
173
+ const liveResponse = new LiveResponse(p, { done: false });
174
+
175
+ expect(liveResponse.body).to.equal(null);
176
+ expect(liveResponse.readyState).to.equal('waiting');
177
+ expect((await liveResponse.now()).body).to.equal(body);
178
+ expect(liveResponse.readyState).to.equal('live');
179
+
180
+ const p2 = new Promise((resolve) => setTimeout(() => resolve('final'), 10));
181
+ liveResponse.replaceWith(p2, { done: true });
182
+
183
+ expect(liveResponse.body).to.equal(body);
184
+ expect(liveResponse.readyState).to.equal('live');
185
+ expect((await liveResponse.now()).body).to.equal('final');
186
+ expect(liveResponse.readyState).to.equal('done');
187
+ });
188
+
189
+ it('should feed from a Generator object', async function () {
190
+ const result = [];
191
+ const liveResponse = new LiveResponse((async function* () {
192
+ yield 'async body 1';
193
+ return 'async body 2';
194
+ })(), { done: false });
195
+
196
+ liveResponse.addEventListener('replace', (event) => {
197
+ result.push(liveResponse.body);
198
+ });
199
+
200
+ expect(liveResponse.body).to.equal(null);
201
+ expect(liveResponse.readyState).to.equal('waiting');
202
+
203
+ await liveResponse.readyStateChange('live'); // Allow for async body to be processed
204
+ await new Promise((r) => setTimeout(r, 0)); // Allow for async body to be processed
205
+
206
+ expect(result).to.eql(['async body 1', 'async body 2']);
207
+ expect(liveResponse.readyState).to.equal('live'); // We expect the readyState to be live even when the gen is done – going by our options.done === false
208
+
209
+ liveResponse.replaceWith((async function* () {
210
+ const v = { value: 'final 1' };
211
+ yield v;
212
+
213
+ await new Promise((r) => setTimeout(r, 0));
214
+ v.value = 'final 1 - tada';
215
+
216
+ return 'final 2';
217
+ })());
218
+
219
+ await new Promise((r) => setTimeout(r, 10)); // Allow for async entries to be processed
220
+
221
+ expect(result).to.eql(['async body 1', 'async body 2', { value: 'final 1 - tada' }, 'final 2']);
222
+ expect(liveResponse.readyState).to.equal('done'); // We expect to be done now
223
+ });
224
+
225
+ it('should live state from a closure, then replace with a generator', async function () {
226
+ const result = [];
227
+ const initialState = { a: 'a' };
228
+ const liveResponse = new LiveResponse(initialState, async function ($state, sig) {
229
+ $state.b = 'b';
230
+ await new Promise((r) => setTimeout(r, 10));
231
+ if (sig.aborted) return;
232
+ $state.c = 'c';
233
+ }, { done: false });
234
+
235
+ liveResponse.addEventListener('replace', (event) => {
236
+ result.push(liveResponse.body);
237
+ });
238
+
239
+ expect(liveResponse.body).to.eql(initialState);
240
+ expect(liveResponse.readyState).to.equal('live');
241
+
242
+ await new Promise((r) => setTimeout(r, 5));
243
+
244
+ liveResponse.replaceWith((async function* () {
245
+ const v = { value: 'final 1' };
246
+ yield v;
247
+
248
+ await new Promise((r) => setTimeout(r, 0));
249
+ v.value = 'final 1 - tada';
250
+
251
+ return 'final 2';
252
+ })());
253
+
254
+ await new Promise((r) => setTimeout(r, 10)); // Allow for async entries to be processed
255
+
256
+ expect(initialState).to.eql({ a: 'a', b: 'b' }); // When we replaced the generator, sig.aborted fired, so $state.c was never set
257
+
258
+ expect(result).to.eql([{ value: 'final 1 - tada' }, 'final 2']);
259
+ expect(liveResponse.readyState).to.equal('done'); // We expect to be done now
260
+ });
261
+ });