diff --git a/docs/docs/testing/intersection-observer-mock.mdx b/docs/docs/testing/intersection-observer-mock.mdx
index a713991..ea65fc7 100644
--- a/docs/docs/testing/intersection-observer-mock.mdx
+++ b/docs/docs/testing/intersection-observer-mock.mdx
@@ -30,3 +30,65 @@ observer.simulateIntersection([
},
]);
```
+
+### Typical unit-test
+
+Here is an example of unit test with `IntersectionObserverMock`. For implementation `useIntersection` is used:
+
+```tsx
+import { IntersectionObserverContext, useIntersection } from '@krutoo/utils/react';
+import { IntersectionObserverMock } from '@krutoo/utils/testing';
+import { act, render } from '@testing-library/react';
+import { describe, expect, mock, test } from '#test-utils';
+
+function MyComponent({ onChange }) {
+ const ref = useRef(null);
+
+ useIntersection(ref, () => {
+ onChange?.();
+ });
+
+ return (
+
+ Hello from my component
+
+ );
+}
+
+describe('MyComponent', () => {
+ test('should call onChange on intersection change', () => {
+ const observer = new ResizeObserverMock(() => {});
+
+ const context = {
+ getObserver(callback: IntersectionObserverCallback) {
+ return observer.addCallback(callback);
+ },
+ };
+
+ const spy = mock.fn();
+
+ const { getByTestId } = render(
+
+
+ ,
+ );
+
+ // no calls after render
+ expect(spy.mock.callCount()).toBe(0);
+
+ // one call after intersection simulated
+ act(() => {
+ observer.simulateIntersection([
+ {
+ target: getByTestId('my-component'),
+ isIntersecting: true,
+ },
+ ]);
+ });
+ expect(spy.mock.callCount()).toBe(1);
+ });
+});
+```
+
+As you can see, mock includes chainable `addCallback` method.
+You can use it to provide one observer for multiple components during test.
diff --git a/docs/docs/testing/resize-observer-mock.mdx b/docs/docs/testing/resize-observer-mock.mdx
index 0e5e9ca..7d1d900 100644
--- a/docs/docs/testing/resize-observer-mock.mdx
+++ b/docs/docs/testing/resize-observer-mock.mdx
@@ -29,3 +29,64 @@ observer.simulateResize([
},
]);
```
+
+### Typical unit-test
+
+Here is an example of unit test with `ResizeObserverMock`. For implementation `useResize` is used:
+
+```tsx
+import { ResizeObserverContext, useResize } from '@krutoo/utils/react';
+import { ResizeObserverMock } from '@krutoo/utils/testing';
+import { act, render } from '@testing-library/react';
+import { describe, expect, mock, test } from '#test-utils';
+
+function MyComponent({ onResize }) {
+ const ref = useRef(null);
+
+ useResize(ref, () => {
+ onResize?.();
+ });
+
+ return (
+
+ Hello from my component
+
+ );
+}
+
+describe('MyComponent', () => {
+ test('should call onResize on resize', () => {
+ const observer = new ResizeObserverMock(() => {});
+
+ const context = {
+ getObserver(callback: ResizeObserverCallback) {
+ return observer.addCallback(callback);
+ },
+ };
+
+ const spy = mock.fn();
+
+ const { getByTestId } = render(
+
+
+ ,
+ );
+
+ // no calls after render
+ expect(spy.mock.callCount()).toBe(0);
+
+ // one call after resize simulated
+ act(() => {
+ observer.simulateResize([
+ {
+ target: getByTestId('my-component'),
+ },
+ ]);
+ });
+ expect(spy.mock.callCount()).toBe(1);
+ });
+});
+```
+
+As you can see, mock includes chainable `addCallback` method.
+You can use it to provide one observer for multiple components during test.
diff --git a/src/testing/intersection-observer-mock.ts b/src/testing/intersection-observer-mock.ts
index 25a075e..3061a6c 100644
--- a/src/testing/intersection-observer-mock.ts
+++ b/src/testing/intersection-observer-mock.ts
@@ -17,8 +17,8 @@ export class IntersectionObserverMock implements IntersectionObserver {
/** @inheritdoc */
readonly thresholds: ReadonlyArray;
- /** Callback. */
- protected readonly callback: IntersectionObserverCallback;
+ /** Callbacks. */
+ protected readonly callbacks: Set;
/** Observed elements. */
protected readonly elements: Set;
@@ -28,7 +28,7 @@ export class IntersectionObserverMock implements IntersectionObserver {
this.rootMargin = init?.rootMargin ?? '0px 0px 0px 0px';
this.thresholds = Array.isArray(init?.threshold) ? init.threshold : [init?.threshold ?? 0];
- this.callback = callback;
+ this.callbacks = new Set([callback]);
this.elements = new Set();
}
@@ -82,6 +82,18 @@ export class IntersectionObserverMock implements IntersectionObserver {
});
}
- this.callback(readyEntries, this);
+ this.callbacks.forEach(fn => fn(readyEntries, this));
+ }
+
+ /**
+ * Adds callback.
+ * Useful to define single observer during tests and add callbacks to it.
+ * @param callback Callback.
+ * @returns This instance.
+ */
+ addCallback(callback: IntersectionObserverCallback): this {
+ this.callbacks.add(callback);
+
+ return this;
}
}
diff --git a/src/testing/resize-observer-mock.ts b/src/testing/resize-observer-mock.ts
index e9c079b..1bba8fe 100644
--- a/src/testing/resize-observer-mock.ts
+++ b/src/testing/resize-observer-mock.ts
@@ -8,14 +8,14 @@ export type PartialResizeObserverEntry = Pick &
* Useful for unit testing.
*/
export class ResizeObserverMock implements ResizeObserver {
- /** Callback. */
- protected readonly callback: ResizeObserverCallback;
+ /** Callbacks. */
+ protected readonly callbacks: Set;
/** Observed elements. */
protected readonly elements: Set;
constructor(callback: ResizeObserverCallback) {
- this.callback = callback;
+ this.callbacks = new Set([callback]);
this.elements = new Set();
}
@@ -60,6 +60,18 @@ export class ResizeObserverMock implements ResizeObserver {
});
}
- this.callback(readyEntries, this);
+ this.callbacks.forEach(fn => fn(readyEntries, this));
+ }
+
+ /**
+ * Adds callback.
+ * Useful to define single observer during tests and add callbacks to it.
+ * @param callback Callback.
+ * @returns This instance.
+ */
+ addCallback(callback: ResizeObserverCallback): this {
+ this.callbacks.add(callback);
+
+ return this;
}
}