summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/dom/observable/tentative
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
commit8dd16259287f58f9273002717ec4d27e97127719 (patch)
tree3863e62a53829a84037444beab3abd4ed9dfc7d0 /testing/web-platform/tests/dom/observable/tentative
parentReleasing progress-linux version 126.0.1-1~progress7.99u1. (diff)
downloadfirefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz
firefox-8dd16259287f58f9273002717ec4d27e97127719.zip
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/dom/observable/tentative')
-rw-r--r--testing/web-platform/tests/dom/observable/tentative/observable-every.any.js250
-rw-r--r--testing/web-platform/tests/dom/observable/tentative/observable-filter.any.js12
-rw-r--r--testing/web-platform/tests/dom/observable/tentative/observable-find.any.js85
-rw-r--r--testing/web-platform/tests/dom/observable/tentative/observable-inspect.any.js412
-rw-r--r--testing/web-platform/tests/dom/observable/tentative/observable-some.any.js96
5 files changed, 855 insertions, 0 deletions
diff --git a/testing/web-platform/tests/dom/observable/tentative/observable-every.any.js b/testing/web-platform/tests/dom/observable/tentative/observable-every.any.js
new file mode 100644
index 0000000000..74a344b8f7
--- /dev/null
+++ b/testing/web-platform/tests/dom/observable/tentative/observable-every.any.js
@@ -0,0 +1,250 @@
+promise_test(async () => {
+ const source = new Observable(subscriber => {
+ subscriber.next("good");
+ subscriber.next("good");
+ subscriber.next("good");
+ subscriber.complete();
+ });
+
+ const result = await source.every((value) => value === "good");
+
+ assert_true(result, "Promise resolves with true if all values pass the predicate");
+}, "every(): Promise resolves to true if all values pass the predicate");
+
+promise_test(async () => {
+ const source = new Observable(subscriber => {
+ subscriber.next("good");
+ subscriber.next("good");
+ subscriber.next("bad");
+ subscriber.complete();
+ });
+
+ const result = await source.every((value) => value === "good");
+
+ assert_false(result, "Promise resolves with false if any value fails the predicate");
+}, "every(): Promise resolves to false if any value fails the predicate");
+
+promise_test(async () => {
+ let tornDown = false;
+ let subscriberActiveAfterFailingPredicate = true;
+ const source = new Observable(subscriber => {
+ subscriber.addTeardown(() => tornDown = true);
+ subscriber.next("good");
+ subscriber.next("good");
+ subscriber.next("bad");
+ subscriberActiveAfterFailingPredicate = subscriber.active;
+ subscriber.next("good");
+ subscriber.complete();
+ });
+
+ const result = await source.every((value) => value === "good");
+
+ assert_false(result, "Promise resolves with false if any value fails the predicate");
+ assert_false(subscriberActiveAfterFailingPredicate,
+ "Subscriber becomes inactive because every() unsubscribed");
+}, "every(): Abort the subscription to the source if the predicate does not pass");
+
+promise_test(async () => {
+ const logs = [];
+
+ const source = createTestSubject({
+ onSubscribe: () => logs.push("subscribed to source"),
+ onTeardown: () => logs.push("teardown"),
+ });
+
+ const resultPromise = source.every((value, index) => {
+ logs.push(`Predicate called with ${value}, ${index}`);
+ return true;
+ });
+
+ let promiseResolved = false;
+
+ resultPromise.then(() => promiseResolved = true);
+
+ assert_array_equals(logs, ["subscribed to source"],
+ "calling every() subscribes to the source immediately");
+
+ source.next("a");
+ assert_array_equals(logs, [
+ "subscribed to source",
+ "Predicate called with a, 0"
+ ], "Predicate called with the value and the index");
+
+ source.next("b");
+ assert_array_equals(logs, [
+ "subscribed to source",
+ "Predicate called with a, 0",
+ "Predicate called with b, 1",
+ ], "Predicate called with the value and the index");
+
+ // wait a tick, just to prove that you have to wait for complete to be called.
+ await Promise.resolve();
+
+ assert_false(promiseResolved,
+ "Promise should not resolve until after the source completes");
+
+ source.complete();
+ assert_array_equals(logs, [
+ "subscribed to source",
+ "Predicate called with a, 0",
+ "Predicate called with b, 1",
+ "teardown",
+ ], "Teardown function called immediately after the source completes");
+
+ const result = await resultPromise;
+
+ assert_true(result,
+ "Promise resolves with true if all values pass the predicate");
+}, "every(): Lifecycle checks when all values pass the predicate");
+
+promise_test(async () => {
+ const logs = [];
+
+ const source = createTestSubject({
+ onSubscribe: () => logs.push("subscribed to source"),
+ onTeardown: () => logs.push("teardown"),
+ });
+
+ const resultPromise = source.every((value, index) => {
+ logs.push(`Predicate called with ${value}, ${index}`);
+ return value === "good";
+ });
+
+ let promiseResolved = false;
+
+ resultPromise.then(() => promiseResolved = true);
+
+ assert_array_equals(logs, ["subscribed to source"],
+ "calling every() subscribes to the source immediately");
+
+ source.next("good");
+ source.next("good");
+ assert_array_equals(logs, [
+ "subscribed to source",
+ "Predicate called with good, 0",
+ "Predicate called with good, 1",
+ ], "Predicate called with the value and the index");
+
+ assert_false(promiseResolved, "Promise should not resolve until after the predicate fails");
+
+ source.next("bad");
+ assert_array_equals(logs, [
+ "subscribed to source",
+ "Predicate called with good, 0",
+ "Predicate called with good, 1",
+ "Predicate called with bad, 2",
+ "teardown",
+ ], "Predicate called with the value and the index, failing predicate immediately aborts subscription to source");
+
+ const result = await resultPromise;
+
+ assert_false(result, "Promise resolves with false if any value fails the predicate");
+}, "every(): Lifecycle checks when any value fails the predicate");
+
+promise_test(async () => {
+ const source = new Observable(subscriber => {
+ subscriber.complete();
+ });
+
+ const result = await source.every(() => true);
+
+ assert_true(result,
+ "Promise resolves with true if the observable completes without " +
+ "emitting a value");
+}, "every(): Resolves with true if the observable completes without " +
+ "emitting a value");
+
+promise_test(async t => {
+ const error = new Error("error from source");
+ const source = new Observable(subscriber => {
+ subscriber.error(error);
+ });
+
+ promise_rejects_exactly(t, error, source.every(() => true),
+ "Promise rejects with the error emitted from the source observable");
+}, "every(): Rejects with any error emitted from the source observable");
+
+promise_test(async t => {
+ const source = new Observable(subscriber => {
+ subscriber.next(1);
+ subscriber.next(2);
+ subscriber.next(3);
+ subscriber.complete();
+ });
+
+ const error = new Error("bad value");
+ const promise = source.every(value => {
+ if (value <= 2) return true;
+ throw error;
+ });
+
+ promise_rejects_exactly(t, error, promise, "Promise rejects with the " +
+ "error thrown from the predicate");
+}, "every(): Rejects with any error thrown from the predicate");
+
+promise_test(async () => {
+ const indices = [];
+
+ const source = new Observable(subscriber => {
+ subscriber.next("a");
+ subscriber.next("b");
+ subscriber.next("c");
+ subscriber.complete();
+ });
+
+ const value = await source.every((value, index) => {
+ indices.push(index);
+ return true;
+ });
+
+ assert_array_equals(indices, [0, 1, 2]);
+
+ assert_true(value,
+ "Promise resolves with true if all values pass the predicate");
+}, "every(): Index is passed into the predicate");
+
+promise_test(async t => {
+ const source = new Observable(subscriber => {});
+
+ const controller = new AbortController();
+ const promise = source.every(() => true, { signal: controller.signal });
+ controller.abort();
+
+ promise_rejects_dom(t, 'AbortError', promise, "Promise rejects with a " +
+ "DOMException if the source Observable is aborted");
+}, "every(): Rejects with a DOMException if the source Observable is aborted");
+
+function createTestSubject(options) {
+ const onTeardown = options?.onTeardown;
+
+ const subscribers = new Set();
+ const subject = new Observable(subscriber => {
+ options?.onSubscribe?.();
+ subscribers.add(subscriber);
+ subscriber.addTeardown(() => subscribers.delete(subscriber));
+ if (onTeardown) {
+ subscriber.addTeardown(onTeardown);
+ }
+ });
+
+ subject.next = (value) => {
+ for (const subscriber of Array.from(subscribers)) {
+ subscriber.next(value);
+ }
+ };
+ subject.error = (error) => {
+ for (const subscriber of Array.from(subscribers)) {
+ subscriber.error(error);
+ }
+ };
+ subject.complete = () => {
+ for (const subscriber of Array.from(subscribers)) {
+ subscriber.complete();
+ }
+ };
+ subject.subscriberCount = () => {
+ return subscribers.size;
+ };
+
+ return subject;
+}
diff --git a/testing/web-platform/tests/dom/observable/tentative/observable-filter.any.js b/testing/web-platform/tests/dom/observable/tentative/observable-filter.any.js
index 8a49bcf467..3c1a7d7824 100644
--- a/testing/web-platform/tests/dom/observable/tentative/observable-filter.any.js
+++ b/testing/web-platform/tests/dom/observable/tentative/observable-filter.any.js
@@ -103,3 +103,15 @@ test(() => {
['source teardown', 'source abort event', 'filter observable complete']);
}, "filter(): Upon source completion, source Observable teardown sequence " +
"happens after downstream filter complete() is called");
+
+test(() => {
+ const source = new Observable(subscriber => {
+ subscriber.next('value1');
+ subscriber.next('value2');
+ subscriber.next('value3');
+ });
+
+ const indices = [];
+ source.filter((value, index) => indices.push(index)).subscribe();
+ assert_array_equals(indices, [0, 1, 2]);
+}, "filter(): Index is passed correctly to predicate");
diff --git a/testing/web-platform/tests/dom/observable/tentative/observable-find.any.js b/testing/web-platform/tests/dom/observable/tentative/observable-find.any.js
new file mode 100644
index 0000000000..0e09060fc5
--- /dev/null
+++ b/testing/web-platform/tests/dom/observable/tentative/observable-find.any.js
@@ -0,0 +1,85 @@
+promise_test(async () => {
+ let inactiveAfterB = false;
+ const source = new Observable(subscriber => {
+ subscriber.next("a");
+ subscriber.next("b");
+ inactiveAfterB = !subscriber.active;
+ subscriber.next("c");
+ subscriber.complete();
+ });
+
+ const value = await source.find((value) => value === "b");
+
+ assert_equals(value, "b", "Promise resolves with the first value that passes the predicate");
+
+ assert_true(inactiveAfterB, "subscriber is inactive after the first value that passes the predicate");
+}, "find(): Promise resolves with the first value that passes the predicate");
+
+promise_test(async () => {
+ const source = new Observable(subscriber => {
+ subscriber.next("a");
+ subscriber.next("b");
+ subscriber.next("c");
+ subscriber.complete();
+ });
+
+ const value = await source.find(() => false);
+
+ assert_equals(value, undefined, "Promise resolves with undefined if no value passes the predicate");
+}, "find(): Promise resolves with undefined if no value passes the predicate");
+
+promise_test(async t => {
+ const error = new Error("error from source");
+ const source = new Observable(subscriber => {
+ subscriber.error(error);
+ });
+
+ promise_rejects_exactly(t, error, source.find(() => true), "Promise " +
+ "rejects with the error emitted from the source Observable");
+}, "find(): Promise rejects with the error emitted from the source Observable");
+
+promise_test(async t => {
+ const source = new Observable(subscriber => {
+ subscriber.next("ignored");
+ });
+
+ const error = new Error("thrown from predicate");
+ promise_rejects_exactly(t, error, source.find(() => {throw error}),
+ "Promise rejects with any error thrown from the predicate");
+}, "find(): Promise rejects with any error thrown from the predicate");
+
+promise_test(async () => {
+ let indices = [];
+
+ const source = new Observable(subscriber => {
+ subscriber.next("a");
+ subscriber.next("b");
+ subscriber.next("c");
+ subscriber.complete();
+ });
+
+ const value = await source.find((value, index) => {
+ indices.push(index);
+ return false;
+ });
+
+ assert_equals(value, undefined, "Promise resolves with undefined if no value passes the predicate");
+
+ assert_array_equals(indices, [0, 1, 2], "find(): Passes the index of the value to the predicate");
+}, "find(): Passes the index of the value to the predicate");
+
+promise_test(async t => {
+ const controller = new AbortController();
+ const source = new Observable(subscriber => {
+ subscriber.next("a");
+ subscriber.next("b");
+ subscriber.next("c");
+ subscriber.complete();
+ });
+
+ controller.abort();
+ const promise = source.find(() => true, { signal: controller.signal });
+
+ promise_rejects_dom(t, 'AbortError', promise, "Promise rejects with " +
+ "DOMException when the signal is aborted");
+}, "find(): Rejects with AbortError when the signal is aborted");
diff --git a/testing/web-platform/tests/dom/observable/tentative/observable-inspect.any.js b/testing/web-platform/tests/dom/observable/tentative/observable-inspect.any.js
new file mode 100644
index 0000000000..8aff741d26
--- /dev/null
+++ b/testing/web-platform/tests/dom/observable/tentative/observable-inspect.any.js
@@ -0,0 +1,412 @@
+// 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: (e) => results.push(`inspect() error ${e.message}`),
+ complete: () => results.push(`inspect() complete`),
+ });
+
+ result.subscribe({
+ next: (value) => results.push(`result next ${value}`),
+ error: (e) => results.push(`result error ${e.message}`),
+ complete: () => results.push(`result complete`),
+ });
+
+ result.subscribe({
+ next: (value) => results.push(`result next ${value}`),
+ error: (e) => results.push(`result error ${e.message}`),
+ 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 result = source.inspect({
+ subscribe: () => {
+ throw new Error("error from do subscribe handler");
+ },
+ });
+
+ const results = [];
+ result.subscribe({
+ next: () => results.push("next"),
+ error: (e) => results.push(e.message),
+ complete: () => results.push("complete"),
+ });
+
+ assert_array_equals(results, ["error from do subscribe handler"]);
+}, "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: (e) => results.push(`inspect() error ${e.message}`),
+ 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: (e) => results.push(`result error ${e.message}`),
+ 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 result = source.inspect({
+ abort: () => {
+ results.push('abort() handler run');
+ throw new Error("error from inspect() subscribe handler");
+ },
+ });
+
+ const controller = new AbortController();
+
+ self.on('error').take(1).subscribe(e =>
+ results.push(e.message + ', from report exception'));
+
+ result.subscribe({
+ next: (value) => {
+ results.push(value);
+ controller.abort();
+ },
+ // This should not be invoked at all!!
+ error: (e) => results.push(e.message + ', from Observer#error()'),
+ complete: () => results.push("complete"),
+ }, {signal: controller.signal});
+
+ assert_array_equals(results, [1, "abort() handler run",
+ "Uncaught Error: error from inspect() subscribe handler, from report " +
+ "exception"]);
+}, "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");
diff --git a/testing/web-platform/tests/dom/observable/tentative/observable-some.any.js b/testing/web-platform/tests/dom/observable/tentative/observable-some.any.js
new file mode 100644
index 0000000000..b692610df3
--- /dev/null
+++ b/testing/web-platform/tests/dom/observable/tentative/observable-some.any.js
@@ -0,0 +1,96 @@
+promise_test(async () => {
+ let inactiveAfterFirstGood = true;
+
+ const source = new Observable(subscriber => {
+ subscriber.next("good");
+ inactiveAfterFirstGood = !subscriber.active;
+ subscriber.next("good");
+ subscriber.next("good");
+ subscriber.complete();
+ });
+
+ const result = await source.some((value) => value === "good");
+
+ assert_true(result, "Promise resolves with true if any value passes the predicate");
+
+ assert_true(inactiveAfterFirstGood,
+ "subscriber is inactive after the first value that passes the " +
+ "predicate, because the source was unsubscribed from");
+}, "some(): subscriber is inactive after the first value that passes the predicate, because the source was unsubscribed from");
+
+promise_test(async () => {
+ const source = new Observable(subscriber => {
+ subscriber.next("bad");
+ subscriber.next("bad");
+ subscriber.next("bad");
+ subscriber.complete();
+ });
+
+ const result = await source.some((value) => value === "good");
+
+ assert_false(result, "some(): Promise resolves with false if no value passes the predicate");
+});
+
+promise_test(async () => {
+ const source = new Observable(subscriber => {
+ subscriber.next("bad");
+ subscriber.next("bad");
+ subscriber.next("good");
+ subscriber.complete();
+ });
+
+ const result = await source.some((value) => value === "good");
+
+ assert_true(result, "some(): Promise resolves with true if any value passes the predicate");
+});
+
+promise_test(async t => {
+ const source = new Observable(subscriber => {
+ subscriber.next("not used");
+ });
+
+ const error = new Error("thrown from predicate");
+ promise_rejects_exactly(t, error, source.some(() => {throw error}),
+ "The returned promise rejects with an error if the predicate errors");
+}, "some(): The returned promise rejects with an error if the predicate errors");
+
+promise_test(async t => {
+ const error = new Error("error from source");
+ const source = new Observable(subscriber => {
+ subscriber.error(error);
+ });
+
+ promise_rejects_exactly(t, error, source.some(() => true),
+ "The returned promise rejects with an error if the source observable errors");
+}, "some(): The returned promise rejects with an error if the source observable errors");
+
+promise_test(async () => {
+ const source = new Observable(subscriber => {
+ subscriber.complete();
+ });
+
+ const result = await source.some(() => true);
+
+ assert_false(result,
+ "The returned promise resolves as false if the source observable " +
+ "completes without emitting a value");
+}, "some(): The returned promise resolves as false if the source observable " +
+ "completes without emitting a value");
+
+promise_test(async t => {
+ let teardownCalled = false;
+ const source = new Observable(subscriber => {
+ subscriber.addTeardown(() => {
+ teardownCalled = true;
+ });
+ });
+
+ const controller = new AbortController();
+ const promise = source.some(() => true, { signal: controller.signal });
+
+ controller.abort();
+
+ promise_rejects_dom(t, 'AbortError', promise);
+ assert_true(teardownCalled,
+ "The teardown function is called when the signal is aborted");
+}, "some(): The return promise rejects with a DOMException if the signal is aborted");