observable-every.any.js (7608B)
1 promise_test(async () => { 2 const source = new Observable(subscriber => { 3 subscriber.next("good"); 4 subscriber.next("good"); 5 subscriber.next("good"); 6 subscriber.complete(); 7 }); 8 9 const result = await source.every((value) => value === "good"); 10 11 assert_true(result, "Promise resolves with true if all values pass the predicate"); 12 }, "every(): Promise resolves to true if all values pass the predicate"); 13 14 promise_test(async () => { 15 const source = new Observable(subscriber => { 16 subscriber.next("good"); 17 subscriber.next("good"); 18 subscriber.next("bad"); 19 subscriber.complete(); 20 }); 21 22 const result = await source.every((value) => value === "good"); 23 24 assert_false(result, "Promise resolves with false if any value fails the predicate"); 25 }, "every(): Promise resolves to false if any value fails the predicate"); 26 27 promise_test(async () => { 28 let tornDown = false; 29 let subscriberActiveAfterFailingPredicate = true; 30 const source = new Observable(subscriber => { 31 subscriber.addTeardown(() => tornDown = true); 32 subscriber.next("good"); 33 subscriber.next("good"); 34 subscriber.next("bad"); 35 subscriberActiveAfterFailingPredicate = subscriber.active; 36 subscriber.next("good"); 37 subscriber.complete(); 38 }); 39 40 const result = await source.every((value) => value === "good"); 41 42 assert_false(result, "Promise resolves with false if any value fails the predicate"); 43 assert_false(subscriberActiveAfterFailingPredicate, 44 "Subscriber becomes inactive because every() unsubscribed"); 45 }, "every(): Abort the subscription to the source if the predicate does not pass"); 46 47 promise_test(async () => { 48 const logs = []; 49 50 const source = createTestSubject({ 51 onSubscribe: () => logs.push("subscribed to source"), 52 onTeardown: () => logs.push("teardown"), 53 }); 54 55 const resultPromise = source.every((value, index) => { 56 logs.push(`Predicate called with ${value}, ${index}`); 57 return true; 58 }); 59 60 let promiseResolved = false; 61 62 resultPromise.then(() => promiseResolved = true); 63 64 assert_array_equals(logs, ["subscribed to source"], 65 "calling every() subscribes to the source immediately"); 66 67 source.next("a"); 68 assert_array_equals(logs, [ 69 "subscribed to source", 70 "Predicate called with a, 0" 71 ], "Predicate called with the value and the index"); 72 73 source.next("b"); 74 assert_array_equals(logs, [ 75 "subscribed to source", 76 "Predicate called with a, 0", 77 "Predicate called with b, 1", 78 ], "Predicate called with the value and the index"); 79 80 // wait a tick, just to prove that you have to wait for complete to be called. 81 await Promise.resolve(); 82 83 assert_false(promiseResolved, 84 "Promise should not resolve until after the source completes"); 85 86 source.complete(); 87 assert_array_equals(logs, [ 88 "subscribed to source", 89 "Predicate called with a, 0", 90 "Predicate called with b, 1", 91 "teardown", 92 ], "Teardown function called immediately after the source completes"); 93 94 const result = await resultPromise; 95 96 assert_true(result, 97 "Promise resolves with true if all values pass the predicate"); 98 }, "every(): Lifecycle checks when all values pass the predicate"); 99 100 promise_test(async () => { 101 const logs = []; 102 103 const source = createTestSubject({ 104 onSubscribe: () => logs.push("subscribed to source"), 105 onTeardown: () => logs.push("teardown"), 106 }); 107 108 const resultPromise = source.every((value, index) => { 109 logs.push(`Predicate called with ${value}, ${index}`); 110 return value === "good"; 111 }); 112 113 let promiseResolved = false; 114 115 resultPromise.then(() => promiseResolved = true); 116 117 assert_array_equals(logs, ["subscribed to source"], 118 "calling every() subscribes to the source immediately"); 119 120 source.next("good"); 121 source.next("good"); 122 assert_array_equals(logs, [ 123 "subscribed to source", 124 "Predicate called with good, 0", 125 "Predicate called with good, 1", 126 ], "Predicate called with the value and the index"); 127 128 assert_false(promiseResolved, "Promise should not resolve until after the predicate fails"); 129 130 source.next("bad"); 131 assert_array_equals(logs, [ 132 "subscribed to source", 133 "Predicate called with good, 0", 134 "Predicate called with good, 1", 135 "Predicate called with bad, 2", 136 "teardown", 137 ], "Predicate called with the value and the index, failing predicate immediately aborts subscription to source"); 138 139 const result = await resultPromise; 140 141 assert_false(result, "Promise resolves with false if any value fails the predicate"); 142 }, "every(): Lifecycle checks when any value fails the predicate"); 143 144 promise_test(async () => { 145 const source = new Observable(subscriber => { 146 subscriber.complete(); 147 }); 148 149 const result = await source.every(() => true); 150 151 assert_true(result, 152 "Promise resolves with true if the observable completes without " + 153 "emitting a value"); 154 }, "every(): Resolves with true if the observable completes without " + 155 "emitting a value"); 156 157 promise_test(async t => { 158 const error = new Error("error from source"); 159 const source = new Observable(subscriber => { 160 subscriber.error(error); 161 }); 162 163 promise_rejects_exactly(t, error, source.every(() => true), 164 "Promise rejects with the error emitted from the source observable"); 165 }, "every(): Rejects with any error emitted from the source observable"); 166 167 promise_test(async t => { 168 const source = new Observable(subscriber => { 169 subscriber.next(1); 170 subscriber.next(2); 171 subscriber.next(3); 172 subscriber.complete(); 173 }); 174 175 const error = new Error("bad value"); 176 const promise = source.every(value => { 177 if (value <= 2) return true; 178 throw error; 179 }); 180 181 promise_rejects_exactly(t, error, promise, "Promise rejects with the " + 182 "error thrown from the predicate"); 183 }, "every(): Rejects with any error thrown from the predicate"); 184 185 promise_test(async () => { 186 const indices = []; 187 188 const source = new Observable(subscriber => { 189 subscriber.next("a"); 190 subscriber.next("b"); 191 subscriber.next("c"); 192 subscriber.complete(); 193 }); 194 195 const value = await source.every((value, index) => { 196 indices.push(index); 197 return true; 198 }); 199 200 assert_array_equals(indices, [0, 1, 2]); 201 202 assert_true(value, 203 "Promise resolves with true if all values pass the predicate"); 204 }, "every(): Index is passed into the predicate"); 205 206 promise_test(async t => { 207 const source = new Observable(subscriber => {}); 208 209 const controller = new AbortController(); 210 const promise = source.every(() => true, { signal: controller.signal }); 211 controller.abort(); 212 213 promise_rejects_dom(t, 'AbortError', promise, "Promise rejects with a " + 214 "DOMException if the source Observable is aborted"); 215 }, "every(): Rejects with a DOMException if the source Observable is aborted"); 216 217 function createTestSubject(options) { 218 const onTeardown = options?.onTeardown; 219 220 const subscribers = new Set(); 221 const subject = new Observable(subscriber => { 222 options?.onSubscribe?.(); 223 subscribers.add(subscriber); 224 subscriber.addTeardown(() => subscribers.delete(subscriber)); 225 if (onTeardown) { 226 subscriber.addTeardown(onTeardown); 227 } 228 }); 229 230 subject.next = (value) => { 231 for (const subscriber of Array.from(subscribers)) { 232 subscriber.next(value); 233 } 234 }; 235 subject.error = (error) => { 236 for (const subscriber of Array.from(subscribers)) { 237 subscriber.error(error); 238 } 239 }; 240 subject.complete = () => { 241 for (const subscriber of Array.from(subscribers)) { 242 subscriber.complete(); 243 } 244 }; 245 subject.subscriberCount = () => { 246 return subscribers.size; 247 }; 248 249 return subject; 250 }