|
| 1 | +import { expect } from 'chai'; |
1 | 2 | import { describe, it } from 'mocha';
|
2 | 3 |
|
3 | 4 | import { expectPromise } from '../../__testUtils__/expectPromise.js';
|
4 | 5 |
|
5 | 6 | import { PromiseCanceller } from '../PromiseCanceller.js';
|
6 | 7 |
|
7 | 8 | describe('PromiseCanceller', () => {
|
8 |
| - it('works to cancel an already resolved promise', async () => { |
9 |
| - const abortController = new AbortController(); |
10 |
| - const abortSignal = abortController.signal; |
| 9 | + describe('cancellablePromise', () => { |
| 10 | + it('works to cancel an already resolved promise', async () => { |
| 11 | + const abortController = new AbortController(); |
| 12 | + const abortSignal = abortController.signal; |
11 | 13 |
|
12 |
| - const promiseCanceller = new PromiseCanceller(abortSignal); |
| 14 | + const promiseCanceller = new PromiseCanceller(abortSignal); |
13 | 15 |
|
14 |
| - const promise = Promise.resolve(1); |
| 16 | + const promise = Promise.resolve(1); |
15 | 17 |
|
16 |
| - const withCancellation = promiseCanceller.withCancellation(promise); |
| 18 | + const withCancellation = promiseCanceller.cancellablePromise(promise); |
17 | 19 |
|
18 |
| - abortController.abort(new Error('Cancelled!')); |
| 20 | + abortController.abort(new Error('Cancelled!')); |
19 | 21 |
|
20 |
| - await expectPromise(withCancellation).toRejectWith('Cancelled!'); |
21 |
| - }); |
| 22 | + await expectPromise(withCancellation).toRejectWith('Cancelled!'); |
| 23 | + }); |
| 24 | + |
| 25 | + it('works to cancel an already resolved promise after abort signal triggered', async () => { |
| 26 | + const abortController = new AbortController(); |
| 27 | + const abortSignal = abortController.signal; |
| 28 | + |
| 29 | + abortController.abort(new Error('Cancelled!')); |
| 30 | + |
| 31 | + const promiseCanceller = new PromiseCanceller(abortSignal); |
| 32 | + |
| 33 | + const promise = Promise.resolve(1); |
| 34 | + |
| 35 | + const withCancellation = promiseCanceller.cancellablePromise(promise); |
| 36 | + |
| 37 | + await expectPromise(withCancellation).toRejectWith('Cancelled!'); |
| 38 | + }); |
| 39 | + |
| 40 | + it('works to cancel a hanging promise', async () => { |
| 41 | + const abortController = new AbortController(); |
| 42 | + const abortSignal = abortController.signal; |
| 43 | + |
| 44 | + const promiseCanceller = new PromiseCanceller(abortSignal); |
| 45 | + |
| 46 | + const promise = new Promise(() => { |
| 47 | + /* never resolves */ |
| 48 | + }); |
| 49 | + |
| 50 | + const withCancellation = promiseCanceller.cancellablePromise(promise); |
| 51 | + |
| 52 | + abortController.abort(new Error('Cancelled!')); |
| 53 | + |
| 54 | + await expectPromise(withCancellation).toRejectWith('Cancelled!'); |
| 55 | + }); |
22 | 56 |
|
23 |
| - it('works to cancel a hanging promise', async () => { |
24 |
| - const abortController = new AbortController(); |
25 |
| - const abortSignal = abortController.signal; |
| 57 | + it('works to cancel a hanging promise created after abort signal triggered', async () => { |
| 58 | + const abortController = new AbortController(); |
| 59 | + const abortSignal = abortController.signal; |
26 | 60 |
|
27 |
| - const promiseCanceller = new PromiseCanceller(abortSignal); |
| 61 | + abortController.abort(new Error('Cancelled!')); |
28 | 62 |
|
29 |
| - const promise = new Promise(() => { |
30 |
| - /* never resolves */ |
| 63 | + const promiseCanceller = new PromiseCanceller(abortSignal); |
| 64 | + |
| 65 | + const promise = new Promise(() => { |
| 66 | + /* never resolves */ |
| 67 | + }); |
| 68 | + |
| 69 | + const withCancellation = promiseCanceller.cancellablePromise(promise); |
| 70 | + |
| 71 | + await expectPromise(withCancellation).toRejectWith('Cancelled!'); |
| 72 | + }); |
| 73 | + |
| 74 | + it('works to trigger onCancel when cancelling a hanging promise', async () => { |
| 75 | + const abortController = new AbortController(); |
| 76 | + const abortSignal = abortController.signal; |
| 77 | + |
| 78 | + const promiseCanceller = new PromiseCanceller(abortSignal); |
| 79 | + |
| 80 | + const promise = new Promise(() => { |
| 81 | + /* never resolves */ |
| 82 | + }); |
| 83 | + |
| 84 | + let onCancelCalled = false; |
| 85 | + const onCancel = () => { |
| 86 | + onCancelCalled = true; |
| 87 | + }; |
| 88 | + |
| 89 | + const withCancellation = promiseCanceller.cancellablePromise( |
| 90 | + promise, |
| 91 | + onCancel, |
| 92 | + ); |
| 93 | + |
| 94 | + expect(onCancelCalled).to.equal(false); |
| 95 | + |
| 96 | + abortController.abort(new Error('Cancelled!')); |
| 97 | + |
| 98 | + expect(onCancelCalled).to.equal(true); |
| 99 | + |
| 100 | + await expectPromise(withCancellation).toRejectWith('Cancelled!'); |
31 | 101 | });
|
32 | 102 |
|
33 |
| - const withCancellation = promiseCanceller.withCancellation(promise); |
| 103 | + it('works to trigger onCancel when cancelling a hanging promise created after abort signal triggered', async () => { |
| 104 | + const abortController = new AbortController(); |
| 105 | + const abortSignal = abortController.signal; |
| 106 | + |
| 107 | + abortController.abort(new Error('Cancelled!')); |
| 108 | + |
| 109 | + const promiseCanceller = new PromiseCanceller(abortSignal); |
| 110 | + |
| 111 | + const promise = new Promise(() => { |
| 112 | + /* never resolves */ |
| 113 | + }); |
34 | 114 |
|
35 |
| - abortController.abort(new Error('Cancelled!')); |
| 115 | + let onCancelCalled = false; |
| 116 | + const onCancel = () => { |
| 117 | + onCancelCalled = true; |
| 118 | + }; |
36 | 119 |
|
37 |
| - await expectPromise(withCancellation).toRejectWith('Cancelled!'); |
| 120 | + const withCancellation = promiseCanceller.cancellablePromise( |
| 121 | + promise, |
| 122 | + onCancel, |
| 123 | + ); |
| 124 | + |
| 125 | + expect(onCancelCalled).to.equal(true); |
| 126 | + |
| 127 | + await expectPromise(withCancellation).toRejectWith('Cancelled!'); |
| 128 | + }); |
38 | 129 | });
|
39 | 130 |
|
40 |
| - it('works to cancel a hanging promise created after abort signal triggered', async () => { |
41 |
| - const abortController = new AbortController(); |
42 |
| - const abortSignal = abortController.signal; |
| 131 | + describe('cancellableAsyncIterable', () => { |
| 132 | + it('works to abort a next call', async () => { |
| 133 | + const abortController = new AbortController(); |
| 134 | + const abortSignal = abortController.signal; |
| 135 | + |
| 136 | + const promiseCanceller = new PromiseCanceller(abortSignal); |
| 137 | + |
| 138 | + const asyncIterable = { |
| 139 | + [Symbol.asyncIterator]: () => ({ |
| 140 | + next: () => Promise.resolve({ value: 1, done: false }), |
| 141 | + }), |
| 142 | + }; |
| 143 | + |
| 144 | + const cancellableAsyncIterable = |
| 145 | + promiseCanceller.cancellableIterable(asyncIterable); |
| 146 | + |
| 147 | + const nextPromise = |
| 148 | + cancellableAsyncIterable[Symbol.asyncIterator]().next(); |
| 149 | + |
| 150 | + abortController.abort(new Error('Cancelled!')); |
| 151 | + |
| 152 | + await expectPromise(nextPromise).toRejectWith('Cancelled!'); |
| 153 | + }); |
| 154 | + |
| 155 | + it('works to abort a next call when already aborted', async () => { |
| 156 | + const abortController = new AbortController(); |
| 157 | + const abortSignal = abortController.signal; |
| 158 | + |
| 159 | + abortController.abort(new Error('Cancelled!')); |
| 160 | + |
| 161 | + const promiseCanceller = new PromiseCanceller(abortSignal); |
| 162 | + |
| 163 | + const asyncIterable = { |
| 164 | + [Symbol.asyncIterator]: () => ({ |
| 165 | + next: () => Promise.resolve({ value: 1, done: false }), |
| 166 | + }), |
| 167 | + }; |
| 168 | + |
| 169 | + const cancellableAsyncIterable = |
| 170 | + promiseCanceller.cancellableIterable(asyncIterable); |
| 171 | + |
| 172 | + const nextPromise = |
| 173 | + cancellableAsyncIterable[Symbol.asyncIterator]().next(); |
43 | 174 |
|
44 |
| - abortController.abort(new Error('Cancelled!')); |
| 175 | + await expectPromise(nextPromise).toRejectWith('Cancelled!'); |
| 176 | + }); |
| 177 | + |
| 178 | + it('works to call return', async () => { |
| 179 | + const abortController = new AbortController(); |
| 180 | + const abortSignal = abortController.signal; |
| 181 | + |
| 182 | + const promiseCanceller = new PromiseCanceller(abortSignal); |
| 183 | + |
| 184 | + let returned = false; |
| 185 | + const asyncIterable = { |
| 186 | + [Symbol.asyncIterator]: () => ({ |
| 187 | + next: () => Promise.resolve({ value: 1, done: false }), |
| 188 | + return: () => { |
| 189 | + returned = true; |
| 190 | + return Promise.resolve({ value: undefined, done: true }); |
| 191 | + }, |
| 192 | + }), |
| 193 | + }; |
| 194 | + |
| 195 | + const cancellableAsyncIterable = |
| 196 | + promiseCanceller.cancellableIterable(asyncIterable); |
| 197 | + |
| 198 | + abortController.abort(new Error('Cancelled!')); |
| 199 | + |
| 200 | + expect(returned).to.equal(false); |
| 201 | + |
| 202 | + const nextPromise = |
| 203 | + cancellableAsyncIterable[Symbol.asyncIterator]().next(); |
45 | 204 |
|
46 |
| - const promiseCanceller = new PromiseCanceller(abortSignal); |
| 205 | + expect(returned).to.equal(true); |
47 | 206 |
|
48 |
| - const promise = new Promise(() => { |
49 |
| - /* never resolves */ |
| 207 | + await expectPromise(nextPromise).toRejectWith('Cancelled!'); |
50 | 208 | });
|
51 | 209 |
|
52 |
| - const withCancellation = promiseCanceller.withCancellation(promise); |
| 210 | + it('works to call return when already aborted', async () => { |
| 211 | + const abortController = new AbortController(); |
| 212 | + const abortSignal = abortController.signal; |
53 | 213 |
|
54 |
| - await expectPromise(withCancellation).toRejectWith('Cancelled!'); |
| 214 | + abortController.abort(new Error('Cancelled!')); |
| 215 | + |
| 216 | + const promiseCanceller = new PromiseCanceller(abortSignal); |
| 217 | + |
| 218 | + let returned = false; |
| 219 | + const asyncIterable = { |
| 220 | + [Symbol.asyncIterator]: () => ({ |
| 221 | + next: () => Promise.resolve({ value: 1, done: false }), |
| 222 | + return: () => { |
| 223 | + returned = true; |
| 224 | + return Promise.resolve({ value: undefined, done: true }); |
| 225 | + }, |
| 226 | + }), |
| 227 | + }; |
| 228 | + |
| 229 | + const cancellableAsyncIterable = |
| 230 | + promiseCanceller.cancellableIterable(asyncIterable); |
| 231 | + |
| 232 | + expect(returned).to.equal(false); |
| 233 | + |
| 234 | + const nextPromise = |
| 235 | + cancellableAsyncIterable[Symbol.asyncIterator]().next(); |
| 236 | + |
| 237 | + expect(returned).to.equal(true); |
| 238 | + |
| 239 | + await expectPromise(nextPromise).toRejectWith('Cancelled!'); |
| 240 | + }); |
55 | 241 | });
|
56 | 242 | });
|
0 commit comments