420 lines
11 KiB
JavaScript
420 lines
11 KiB
JavaScript
// Because we test that the global error handler is called at various times.
|
|
setup({ allow_uncaught_exception: true });
|
|
|
|
test(() => {
|
|
const results = [];
|
|
let sourceSubscriptionCall = 0;
|
|
const source = new Observable(subscriber => {
|
|
sourceSubscriptionCall++;
|
|
results.push(`source subscribe ${sourceSubscriptionCall}`);
|
|
subscriber.next(1);
|
|
subscriber.next(2);
|
|
subscriber.next(3);
|
|
subscriber.complete();
|
|
});
|
|
|
|
let inspectSubscribeCall = 0;
|
|
const result = source.inspect({
|
|
subscribe: () => {
|
|
inspectSubscribeCall++;
|
|
results.push(`inspect() subscribe ${inspectSubscribeCall}`);
|
|
},
|
|
next: (value) => results.push(`inspect() next ${value}`),
|
|
error: () => results.push('inspect() error'),
|
|
complete: () => results.push('inspect() complete'),
|
|
});
|
|
|
|
result.subscribe({
|
|
next: (value) => results.push(`result next ${value}`),
|
|
error: () => results.push('result error'),
|
|
complete: () => results.push('result complete'),
|
|
});
|
|
|
|
result.subscribe({
|
|
next: (value) => results.push(`result next ${value}`),
|
|
error: () => results.push('result error'),
|
|
complete: () => results.push('result complete'),
|
|
});
|
|
|
|
assert_array_equals(results,
|
|
[
|
|
"inspect() subscribe 1",
|
|
"source subscribe 1",
|
|
"inspect() next 1",
|
|
"result next 1",
|
|
"inspect() next 2",
|
|
"result next 2",
|
|
"inspect() next 3",
|
|
"result next 3",
|
|
"inspect() complete",
|
|
"result complete",
|
|
"inspect() subscribe 2",
|
|
"source subscribe 2",
|
|
"inspect() next 1",
|
|
"result next 1",
|
|
"inspect() next 2",
|
|
"result next 2",
|
|
"inspect() next 3",
|
|
"result next 3",
|
|
"inspect() complete",
|
|
"result complete",
|
|
]);
|
|
}, "inspect(): Provides a pre-subscription subscribe callback");
|
|
|
|
test(() => {
|
|
const source = new Observable(subscriber => {
|
|
subscriber.next(1);
|
|
subscriber.next(2);
|
|
subscriber.next(3);
|
|
subscriber.complete();
|
|
});
|
|
|
|
const results = [];
|
|
|
|
const result = source.inspect({
|
|
next: value => results.push(value),
|
|
error: e => results.push(e),
|
|
complete: () => results.push("complete"),
|
|
});
|
|
|
|
result.subscribe();
|
|
result.subscribe();
|
|
|
|
assert_array_equals(results, [1, 2, 3, "complete", 1, 2, 3, "complete"]);
|
|
}, "inspect(): Provides a way to tap into the values and completions of the " +
|
|
"source observable using an observer");
|
|
|
|
test(() => {
|
|
const error = new Error("error from source");
|
|
const source = new Observable(subscriber => subscriber.error(error));
|
|
|
|
const results = [];
|
|
|
|
const result = source.inspect({
|
|
next: value => results.push(value),
|
|
error: e => results.push(e),
|
|
complete: () => results.push("complete"),
|
|
});
|
|
|
|
let errorReported = null;
|
|
self.addEventListener('error', e => errorReported = e.error, {once: true});
|
|
result.subscribe();
|
|
|
|
assert_array_equals(results, [error]);
|
|
assert_equals(errorReported, error,
|
|
"errorReported to global matches error from source Observable");
|
|
}, "inspect(): Error handler does not stop error from being reported to the " +
|
|
"global, when subscriber does not pass error handler");
|
|
|
|
test(() => {
|
|
const error = new Error("error from source");
|
|
const source = new Observable(subscriber => {
|
|
subscriber.next(1);
|
|
subscriber.next(2);
|
|
subscriber.next(3);
|
|
subscriber.error(error);
|
|
});
|
|
|
|
const results = [];
|
|
|
|
const result = source.inspect({
|
|
next: value => results.push(value),
|
|
error: e => results.push(e),
|
|
complete: () => results.push("complete"),
|
|
});
|
|
|
|
const observer = {
|
|
error: e => results.push(e),
|
|
};
|
|
result.subscribe(observer);
|
|
result.subscribe(observer);
|
|
|
|
assert_array_equals(results, [1, 2, 3, error, error, 1, 2, 3, error, error]);
|
|
}, "inspect(): Provides a way to tap into the values and errors of the " +
|
|
"source observable using an observer. Errors are passed through");
|
|
|
|
test(() => {
|
|
const source = new Observable(subscriber => {
|
|
subscriber.next(1);
|
|
subscriber.next(2);
|
|
subscriber.next(3);
|
|
subscriber.complete();
|
|
});
|
|
|
|
const results = [];
|
|
|
|
const result = source.inspect(value => results.push(value));
|
|
|
|
result.subscribe();
|
|
result.subscribe();
|
|
|
|
assert_array_equals(results, [1, 2, 3, 1, 2, 3]);
|
|
}, "inspect(): ObserverCallback passed in");
|
|
|
|
test(() => {
|
|
const source = new Observable(subscriber => {
|
|
subscriber.next(1);
|
|
subscriber.next(2);
|
|
subscriber.next(3);
|
|
});
|
|
|
|
const error = new Error("error from inspect() next handler");
|
|
const result = source.inspect({
|
|
next: (value) => {
|
|
if (value === 2) {
|
|
throw error;
|
|
}
|
|
},
|
|
});
|
|
|
|
const results1 = [];
|
|
result.subscribe({
|
|
next: (value) => results1.push(value),
|
|
error: (e) => results1.push(e),
|
|
complete: () => results1.push("complete"),
|
|
});
|
|
|
|
const results2 = [];
|
|
result.subscribe({
|
|
next: (value) => results2.push(value),
|
|
error: (e) => results2.push(e),
|
|
complete: () => results2.push("complete"),
|
|
});
|
|
|
|
assert_array_equals(results1, [1, error]);
|
|
assert_array_equals(results2, [1, error]);
|
|
}, "inspect(): Throwing an error in the observer next handler is caught and " +
|
|
"sent to the error callback of the result observable");
|
|
|
|
test(() => {
|
|
const sourceError = new Error("error from source");
|
|
const inspectError = new Error("error from inspect() error handler");
|
|
|
|
const source = new Observable(subscriber => {
|
|
subscriber.error(sourceError);
|
|
});
|
|
|
|
const result = source.inspect({
|
|
error: () => {
|
|
throw inspectError;
|
|
},
|
|
});
|
|
|
|
const results = [];
|
|
result.subscribe({
|
|
next: () => results.push("next"),
|
|
error: (e) => results.push(e),
|
|
complete: () => results.push("complete"),
|
|
});
|
|
|
|
assert_array_equals(results, [inspectError]);
|
|
}, "inspect(): Throwing an error in the observer error handler in " +
|
|
"inspect() is caught and sent to the error callback of the result " +
|
|
"observable");
|
|
|
|
test(() => {
|
|
const source = new Observable(subscriber => {
|
|
subscriber.next(1);
|
|
subscriber.next(2);
|
|
subscriber.next(3);
|
|
subscriber.complete();
|
|
});
|
|
|
|
const error = new Error("error from inspect() complete handler");
|
|
const result = source.inspect({
|
|
complete: () => {
|
|
throw error;
|
|
},
|
|
});
|
|
|
|
const results = [];
|
|
result.subscribe({
|
|
next: (value) => results.push(value),
|
|
error: (e) => results.push(e),
|
|
complete: () => results.push("complete"),
|
|
});
|
|
|
|
assert_array_equals(results, [1, 2, 3, error]);
|
|
}, "inspect(): Throwing an error in the observer complete handler is caught " +
|
|
"and sent to the error callback of the result observable");
|
|
|
|
test(() => {
|
|
const source = new Observable(subscriber => {
|
|
subscriber.next(1);
|
|
subscriber.next(2);
|
|
subscriber.next(3);
|
|
});
|
|
|
|
const error = new Error("error from inspect() next handler");
|
|
const result = source.inspect({
|
|
next: (value) => {
|
|
if (value === 2) {
|
|
throw error;
|
|
}
|
|
},
|
|
});
|
|
|
|
const results = [];
|
|
result.subscribe({
|
|
next: (value) => results.push(value),
|
|
error: (e) => results.push(e),
|
|
complete: () => results.push("complete"),
|
|
});
|
|
|
|
assert_array_equals(results, [1, error]);
|
|
}, "inspect(): Throwing an error in the next handler function in do should " +
|
|
"be caught and sent to the error callback of the result observable");
|
|
|
|
test(() => {
|
|
const source = new Observable(subscriber => {});
|
|
const error = new Error("error from do subscribe handler");
|
|
|
|
const result = source.inspect({
|
|
subscribe: () => {
|
|
throw error;
|
|
},
|
|
});
|
|
|
|
const results = [];
|
|
result.subscribe({
|
|
next: () => results.push("next"),
|
|
error: (e) => results.push(e),
|
|
complete: () => results.push("complete"),
|
|
});
|
|
|
|
assert_array_equals(results, [error]);
|
|
}, "inspect(): Errors thrown in subscribe() Inspector handler subscribe " +
|
|
"handler are caught and sent to error callback");
|
|
|
|
test(() => {
|
|
const results = [];
|
|
let sourceTeardownCall = 0;
|
|
const source = new Observable(subscriber => {
|
|
subscriber.addTeardown(() => {
|
|
sourceTeardownCall++;
|
|
results.push(`source teardown ${sourceTeardownCall}`);
|
|
});
|
|
subscriber.next(1);
|
|
subscriber.next(2);
|
|
subscriber.next(3);
|
|
subscriber.complete();
|
|
});
|
|
|
|
let doUnsubscribeCall = 0;
|
|
const result = source.inspect({
|
|
abort: (reason) => {
|
|
doUnsubscribeCall++;
|
|
results.push(`inspect() abort ${doUnsubscribeCall} ${reason}`);
|
|
},
|
|
next: (value) => results.push(`inspect() next ${value}`),
|
|
error: () => results.push('inspect() error'),
|
|
complete: () => results.push(`inspect() complete`),
|
|
});
|
|
|
|
const controller = new AbortController();
|
|
result.subscribe({
|
|
next: (value) => {
|
|
results.push(`result next ${value}`);
|
|
if (value === 2) {
|
|
controller.abort("abort reason");
|
|
}
|
|
},
|
|
error: () => results.push('result error'),
|
|
complete: () => results.push(`result complete`),
|
|
}, { signal: controller.signal });
|
|
|
|
assert_array_equals(results, [
|
|
"inspect() next 1",
|
|
"result next 1",
|
|
"inspect() next 2",
|
|
"result next 2",
|
|
"inspect() abort 1 abort reason",
|
|
"source teardown 1",
|
|
]);
|
|
}, "inspect(): Provides a way to tap into the moment a source observable is unsubscribed from");
|
|
|
|
test(() => {
|
|
const results = [];
|
|
let sourceTeardownCall = 0;
|
|
const source = new Observable(subscriber => {
|
|
subscriber.addTeardown(() => {
|
|
sourceTeardownCall++;
|
|
results.push(`source teardown ${sourceTeardownCall}`);
|
|
});
|
|
subscriber.next(1);
|
|
subscriber.next(2);
|
|
subscriber.next(3);
|
|
subscriber.complete();
|
|
});
|
|
|
|
let inspectUnsubscribeCall = 0;
|
|
const result = source.inspect({
|
|
next: (value) => results.push(`inspect() next ${value}`),
|
|
complete: () => results.push(`inspect() complete`),
|
|
abort: (reason) => {
|
|
inspectUnsubscribeCall++;
|
|
results.push(`inspect() abort ${inspectUnsubscribeCall} ${reason}`);
|
|
},
|
|
});
|
|
|
|
result.subscribe({
|
|
next: (value) => results.push(`result next ${value}`),
|
|
complete: () => results.push(`result complete`),
|
|
});
|
|
|
|
assert_array_equals(results, [
|
|
"inspect() next 1",
|
|
"result next 1",
|
|
"inspect() next 2",
|
|
"result next 2",
|
|
"inspect() next 3",
|
|
"result next 3",
|
|
"source teardown 1",
|
|
"inspect() complete",
|
|
"result complete",
|
|
]);
|
|
}, "inspect(): Inspector abort() handler is not called if the source " +
|
|
"completes before the result is unsubscribed from");
|
|
|
|
test(() => {
|
|
const source = new Observable(subscriber => {
|
|
subscriber.next(1);
|
|
});
|
|
|
|
const results = [];
|
|
const error = new Error("error from inspect() subscribe handler");
|
|
|
|
const result = source.inspect({
|
|
abort: () => {
|
|
results.push("abort() handler run");
|
|
throw error;
|
|
},
|
|
});
|
|
|
|
const controller = new AbortController();
|
|
|
|
self.when("error").take(1).subscribe((e) => {
|
|
results.push("from report exception");
|
|
results.push(e.error);
|
|
});
|
|
|
|
result.subscribe({
|
|
next: (value) => {
|
|
results.push(value);
|
|
controller.abort();
|
|
},
|
|
error: () => {
|
|
assert_unreached("This should not be invoked at all!!");
|
|
},
|
|
complete: () => results.push("complete"),
|
|
}, { signal: controller.signal });
|
|
|
|
assert_array_equals(results, [
|
|
1,
|
|
"abort() handler run",
|
|
"from report exception",
|
|
error,
|
|
]);
|
|
}, "inspect(): Errors thrown from inspect()'s abort() handler are caught " +
|
|
"and reported to the global, because the subscription is already closed " +
|
|
"by the time the handler runs");
|