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
|
promise_test(async (t) => {
const source = new Observable(subscriber => {
subscriber.next(1);
subscriber.next(2);
subscriber.next(3);
t.step_timeout(() => subscriber.complete(), 0);
});
const reducerArguments = [];
const promiseToResult = source.reduce((acc, value, index) => {
reducerArguments.push([acc, value, index]);
return acc + value;
}, 0);
// The reducer should be called immediately when the source emits a value.
assert_equals(reducerArguments.length, 3);
assert_array_equals(reducerArguments[0], [0, 1, 0]);
assert_array_equals(reducerArguments[1], [1, 2, 1]);
assert_array_equals(reducerArguments[2], [3, 3, 2]);
const result = await promiseToResult;
assert_equals(result, 6);
}, "reduce(): Reduces the values of the Observable, starting with the " +
"initial seed value");
promise_test(async (t) => {
let error = new Error('from the source');
const source = new Observable(subscriber => {
subscriber.next(1);
subscriber.error(error);
});
return promise_rejects_exactly(t, error, source.reduce((acc, value) => acc + value, 0));
}, "reduce(): Rejects if the source observable emits an error");
promise_test(async (t) => {
const source = new Observable(subscriber => {
subscriber.next(1);
subscriber.next(2);
subscriber.next(3);
t.step_timeout(() => subscriber.complete(), 0);
});
const reducerArguments = [];
const promiseToResult = source.reduce((acc, value, index) => {
reducerArguments.push([acc, value, index]);
return acc + value;
});
// The reducer should be called immediately when the source emits a value.
assert_equals(reducerArguments.length, 2);
assert_array_equals(reducerArguments[0], [1, 2, 1]);
assert_array_equals(reducerArguments[1], [3, 3, 2]);
const result = await promiseToResult;
assert_equals(result, 6);
}, "reduce(): Seeds with the first value of the source, if no initial value " +
"is provided");
promise_test(async (t) => {
const logs = [];
const source = new Observable(subscriber => {
subscriber.addTeardown(() => logs.push('teardown'));
logs.push('next 1');
subscriber.next(1);
logs.push('next 2');
subscriber.next(2);
logs.push('try to next 3');
subscriber.next(3);
logs.push('try to complete');
subscriber.complete();
});
const error = new Error('from the reducer');
const promiseToResult = source.reduce((acc, value) => {
if (value === 2) {
logs.push('throw error');
throw error;
}
return acc + value;
}, 0);
await promise_rejects_exactly(t, error, promiseToResult);
assert_array_equals(logs, [
'next 1',
'next 2',
'throw error',
'teardown',
'try to next 3',
'try to complete',
]);
}, "reduce(): Errors thrown in reducer reject the promise and abort the source");
promise_test(async () => {
const source = new Observable(subscriber => {
subscriber.complete();
});
const result = await source.reduce(() => 'reduced', 'seed');
assert_equals(result, 'seed');
}, "reduce(): When source is empty, promise resolves with initial value");
promise_test(async (t) => {
// This tests behavior that is analogous to `[].reduce(() => 'reduced')`,
// which throws a TypeError.
const source = new Observable(subscriber => {
subscriber.complete();
});
return promise_rejects_js(t, TypeError, source.reduce(() => 'reduced'));
}, "reduce(): When source is empty, AND no seed value is provided, the " +
"promise rejects with a TypeError");
promise_test(async (t) => {
let tornDown = false;
const source = new Observable((subscriber) => {
subscriber.addTeardown(() => {
tornDown = true;
});
// Waits forever.
});
const abortController = new AbortController();
t.step_timeout(() => {
abortController.abort();
assert_true(tornDown);
}, 0);
return promise_rejects_dom(t, 'AbortError', source.reduce(() => 'reduced', 'seed', { signal: abortController.signal }));
}, "reduce(): Reject with an AbortError if the subscription is aborted " +
"before the source completes");
promise_test(async () => {
const source = new Observable(subscriber => {
subscriber.complete();
});
const values = [{}, [], new Error("some error")];
for (let value of values) {
const result = await source.reduce(() => {}, value);
assert_equals(result, value);
}
}, "reduce(): Reduces the values for different objects");
|