mirror of
https://github.com/vector-im/element-call.git
synced 2026-08-08 20:09:19 +00:00
Error behavior example
This commit is contained in:
111
src/useBehavior.test.tsx
Normal file
111
src/useBehavior.test.tsx
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2025 New Vector Ltd.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
Please see LICENSE in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { render } from "@testing-library/react";
|
||||||
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
import { catchError, of, tap, Subject, map } from "rxjs";
|
||||||
|
|
||||||
|
import { type Behavior } from "./state/Behavior";
|
||||||
|
import { useBehavior } from "./useBehavior";
|
||||||
|
import { ObservableScope } from "./state/ObservableScope";
|
||||||
|
|
||||||
|
function TestComponent({
|
||||||
|
behavior$,
|
||||||
|
shouldThrow = false,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
behavior$: Behavior<string>;
|
||||||
|
shouldThrow?: boolean;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}): React.ReactNode {
|
||||||
|
if (shouldThrow) throw Error("Test error");
|
||||||
|
|
||||||
|
const value = useBehavior(behavior$);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
value: {value}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("useBehavior", () => {
|
||||||
|
let scope: ObservableScope;
|
||||||
|
beforeEach(() => (scope = new ObservableScope()));
|
||||||
|
afterEach(() => scope.end());
|
||||||
|
|
||||||
|
it("reference test", () => {
|
||||||
|
expect(() =>
|
||||||
|
render(
|
||||||
|
<TestComponent behavior$={scope.behavior(of("test"))}>
|
||||||
|
Test
|
||||||
|
</TestComponent>,
|
||||||
|
),
|
||||||
|
).not.toThrow();
|
||||||
|
});
|
||||||
|
it("should return the correct behavior", () => {
|
||||||
|
expect(() =>
|
||||||
|
render(
|
||||||
|
<TestComponent
|
||||||
|
shouldThrow={true}
|
||||||
|
behavior$={scope.behavior(of("test"))}
|
||||||
|
>
|
||||||
|
Test
|
||||||
|
</TestComponent>,
|
||||||
|
),
|
||||||
|
).toThrow("Test error");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("useBehavior forwards the throw in obs computation", () => {
|
||||||
|
const throwingOperation = (): string => {
|
||||||
|
throw new Error("Test error");
|
||||||
|
return "a";
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
const s$ = new Subject<string>();
|
||||||
|
const b$ = scope.behavior(s$, "");
|
||||||
|
s$.next("test");
|
||||||
|
s$.next(throwingOperation());
|
||||||
|
render(<TestComponent behavior$={b$}>Test</TestComponent>);
|
||||||
|
}).toThrow("Test error");
|
||||||
|
});
|
||||||
|
it("useBehavior does not throw in caught obs computation", () => {
|
||||||
|
function errorOnE(s: string): string {
|
||||||
|
if (s === "E") throw new Error("Test error");
|
||||||
|
return s + "CheckedForE";
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("hello");
|
||||||
|
const s$ = new Subject<string>();
|
||||||
|
const b$ = scope.behavior(s$.pipe(map(errorOnE)), "START");
|
||||||
|
|
||||||
|
const inheritForThrowCatch$ = scope.behavior(
|
||||||
|
b$.pipe(
|
||||||
|
tap((v) => console.log("tap-" + v)),
|
||||||
|
catchError((err) => {
|
||||||
|
console.log("caught error" + err);
|
||||||
|
return of("I caught an error and converted it to sth nicer");
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
s$.next("test");
|
||||||
|
s$.next("E");
|
||||||
|
s$.next("after error");
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
render(
|
||||||
|
<TestComponent behavior$={inheritForThrowCatch$}>Test</TestComponent>,
|
||||||
|
);
|
||||||
|
}).not.toThrow();
|
||||||
|
expect(() => {
|
||||||
|
render(<TestComponent behavior$={b$}>Test</TestComponent>);
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -15,7 +15,12 @@ import { type Behavior } from "./state/Behavior";
|
|||||||
export function useBehavior<T>(behavior: Behavior<T>): T {
|
export function useBehavior<T>(behavior: Behavior<T>): T {
|
||||||
const subscribe = useCallback(
|
const subscribe = useCallback(
|
||||||
(onChange: () => void) => {
|
(onChange: () => void) => {
|
||||||
const s = behavior.subscribe(onChange);
|
const s = behavior.subscribe({
|
||||||
|
next: onChange,
|
||||||
|
error: (e) => {
|
||||||
|
throw e;
|
||||||
|
},
|
||||||
|
});
|
||||||
return (): void => s.unsubscribe();
|
return (): void => s.unsubscribe();
|
||||||
},
|
},
|
||||||
[behavior],
|
[behavior],
|
||||||
|
|||||||
Reference in New Issue
Block a user