← Back to all jobsRenatus · signed audit report

migrateAudit e912325a

Repository: https://github.com/streamich/react-use · 18.0.019.0.0

Summary

State
done
Total events
29
Patches
3
Tests
3
Failures
0

Signature

Algorithm
ed25519
Public key
b7676a22b900644e4e8e87e058a02bec5477978243d525d49619474e3c7d10df
Message hash
7533975024517cc8592f5f899adaeb19f361b8415ac0a1f87efe19dcf2be3107
Signature
8d49cc3837d19f7e206a7b692d8e96cd6e3ed4c90c62a63747b9418134c9d8cbd8fe3ccaa12a51606a1f338dfebda75a9334b56dcffd12abe288cd5bbaaea103
Signed at
2026-05-17T15:32:26.137Z

Verify cryptographically

Hand this signed report to a third party — auditor, compliance, or yourself in six months — and they can confirm tamper-freedom without trusting Renatus.

Open in browser verifier →

The verifier runs entirely in your browser — paste-and-verify, or click "Open in verifier" to auto-fill both fields.

Patches (3)

stories/usePinchZoom.story.tsxproposedconfidence 85%· Updated useRef() calls to provide an initial value (null) to comply with React 19's requirement of an initial argument for useRef().
Before
import { storiesOf } from '@storybook/react';
import * as React from 'react';
import { useEffect, useRef, useState } from 'react';
import { usePinchZoom } from '../src';
import { ZoomState } from '../src/usePinchZoom';
import ShowDocs from './util/ShowDocs';

const Demo = () => {
  const [scale, setState] = useState(1);
  const scaleRef = useRef();
  const { zoomingState, pinchState } = usePinchZoom(scaleRef);

  useEffect(() => {
    if (zoomingState === ZoomState.ZOOMING_IN) {
      // perform zoom in scaling
      setState(scale + 0.1);
    } else if (zoomingState === ZoomState.ZOOMING_OUT) {
      // perform zoom out in scaling
      setState(scale - 0.1);
    }
  }, [zoomingState, pinchState]);

  return (
    <div ref={scaleRef}>
      <img
        src="https://www.olympus-imaging.co.in/content/000107506.jpg"
        style={{
          zoom: scale,
        }}
        alt="scale img"
      />
    </div>
  );
};

storiesOf('Sensors/usePinchZoom', module)
  .add('Docs', () => <ShowDocs md={require('../docs/usePinchZoom.md')} />)
  .add('Default', () => <Demo />);
After
import { storiesOf } from '@storybook/react';
import * as React from 'react';
import { useEffect, useRef, useState } from 'react';
import { usePinchZoom } from '../src';
import { ZoomState } from '../src/usePinchZoom';
import ShowDocs from './util/ShowDocs';

const Demo = () => {
  const [scale, setState] = useState(1);
  const scaleRef = useRef(null);
  const { zoomingState, pinchState } = usePinchZoom(scaleRef);

  useEffect(() => {
    if (zoomingState === ZoomState.ZOOMING_IN) {
      // perform zoom in scaling
      setState(scale + 0.1);
    } else if (zoomingState === ZoomState.ZOOMING_OUT) {
      // perform zoom out in scaling
      setState(scale - 0.1);
    }
  }, [zoomingState, pinchState]);

  return (
    <div ref={scaleRef}>
      <img
        src="https://www.olympus-imaging.co.in/content/000107506.jpg"
        style={{ zoom: scale }}
        alt="scale img"
      />
    </div>
  );
};

storiesOf('Sensors/usePinchZoom', module)
  .add('Docs', () => <ShowDocs md={require('../docs/usePinchZoom.md')} />)
  .add('Default', () => <Demo />);
tests/useEnsuredForwardedRef.test.tsxproposedconfidence 85%· Updated ReactDOM.render to ReactDOM.createRoot to comply with React 19's removal of the legacy ReactDOM.render API.
Before
import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import { renderHook } from '@testing-library/react-hooks';
import TestUtils from 'react-dom/test-utils';
import { ensuredForwardRef, useEnsuredForwardedRef } from '../src';

let container: HTMLDivElement;

beforeEach(() => {
  container = document.createElement('div');
  document.body.appendChild(container);
});

afterEach(() => {
  document.body.removeChild(container);
  container = null!;
});

test('should return a valid ref with existing forwardedRef', () => {
  const { result } = renderHook(() => {
    const ref = useRef(null);
    const ensuredRef = useEnsuredForwardedRef(ref);

    TestUtils.act(() => {
      ReactDOM.render(<div ref={ensuredRef} />, container);
    });

    return {
      initialRef: ref,
      ensuredForwardedRef: ensuredRef,
    };
  });

  const { initialRef, ensuredForwardedRef } = result.current;

  expect(ensuredForwardedRef).toStrictEqual(initialRef);
});

test('should return a valid ref when the forwarded ref is undefined', () => {
  const { result } = renderHook(() => {
    const ref = useEnsuredForwardedRef<HTMLDivElement>(undefined!);

    TestUtils.act(() => {
      ReactDOM.render(<div id="test_id" ref={ref} />, container);
    });

    return { ensuredRef: ref };
  });

  const { ensuredRef } = result.current;

  expect(ensuredRef.current.id).toBe('test_id');
});

test('should return a valid ref when using the wrapper function style', () => {
  const { result } = renderHook(() => {
    const initialRef = useRef<HTMLDivElement | null>(null);

    const WrappedComponent = ensuredForwardRef<HTMLDivElement>((_props, ref) => {
      return <div id="test_id" ref={ref} />;
    });

    TestUtils.act(() => {
      ReactDOM.render(<WrappedComponent ref={initialRef} />, container);
    });

    return { initialRef };
  });

  const { initialRef } = result.current;

  expect(initialRef.current).toBeTruthy();
  expect(initialRef.current?.id).toBe('test_id');
});
After
import React, { useRef } from 'react';
import { createRoot } from 'react-dom/client';
import TestUtils from 'react-dom/test-utils';
import { ensuredForwardRef, useEnsuredForwardedRef } from '../src';

let container: HTMLDivElement;

beforeEach(() => {
  container = document.createElement('div');
  document.body.appendChild(container);
});

afterEach(() => {
  document.body.removeChild(container);
  container = null!; 
});

test('should return a valid ref with existing forwardedRef', () => {
  const { result } = renderHook(() => {
    const ref = useRef(null);
    const ensuredRef = useEnsuredForwardedRef(ref);

    createRoot(container).render(<div ref={ensuredRef} />);

    return { initialRef: ref, ensuredForwardedRef: ensuredRef };
  });

  const { initialRef, ensuredForwardedRef } = result.current;

  expect(ensuredForwardedRef).toStrictEqual(initialRef);
});

test('should return a valid ref when the forwarded ref is undefined', () => {
  const { result } = renderHook(() => {
    const ref = useEnsuredForwardedRef<HTMLDivElement>(undefined!);

    createRoot(container).render(<div id="test_id" ref={ref} />);

    return { ensuredRef: ref };
  });

  const { ensuredRef } = result.current;

  expect(ensuredRef.current.id).toBe('test_id');
});

test('should return a valid ref when using the wrapper function style', () => {
  const { result } = renderHook(() => {
    const initialRef = useRef<HTMLDivElement | null>(null);

    const WrappedComponent = ensuredForwardRef<HTMLDivElement>((_props, ref) => {
      return <div id="test_id" ref={ref} />; 
    });

    createRoot(container).render(<WrappedComponent ref={initialRef} />);

    return { initialRef };
  });

  const { initialRef } = result.current;

  expect(initialRef.current).toBeTruthy();
  expect(initialRef.current?.id).toBe('test_id');
});
tests/useIntersection.test.tsxproposedconfidence 85%· Updated ReactDOM.render to ReactDOM.createRoot to comply with React 19's removal of the legacy ReactDOM.render API.
Before
import React, { createRef } from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-dom/test-utils';
import TestRenderer from 'react-test-renderer';
import { intersectionObserver } from '@shopify/jest-dom-mocks';
import { renderHook } from '@testing-library/react-hooks';
import { useIntersection } from '../src';

beforeEach(() => {
  intersectionObserver.mock();
  const IO = IntersectionObserver;
  jest.spyOn(IO.prototype, 'disconnect');
  jest.spyOn(global as any, 'IntersectionObserver');
  IntersectionObserver.prototype = IO.prototype;
});

afterEach(() => {
  intersectionObserver.restore();
});

describe('useIntersection', () => {
  const container = document.createElement('div');
  let targetRef;

  it('should be defined', () => {
    expect(useIntersection).toBeDefined();
  });

  it('should setup an IntersectionObserver targeting the ref element and using the options provided', () => {
    TestUtils.act(() => {
      targetRef = createRef();
      ReactDOM.render(<div ref={targetRef} />, container);
    });

    expect(intersectionObserver.observers).toHaveLength(0);
    const observerOptions = { root: null, threshold: 0.8 };

    renderHook(() => useIntersection(targetRef, observerOptions));

    expect(intersectionObserver.observers).toHaveLength(1);
    expect(intersectionObserver.observers[0].target).toEqual(targetRef.current);
    expect(intersectionObserver.observers[0].options).toEqual(observerOptions);
  });

  it('should return null if a ref without a current value is provided', () => {
    targetRef = createRef();

    const { result } = renderHook(() => useIntersection(targetRef, { root: null, threshold: 1 }));
    expect(result.current).toBe(null);
  });

  it('should reset an intersectionObserverEntry when the ref changes', () => {
    TestUtils.act(() => {
      targetRef = createRef();
      ReactDOM.render(<div ref={targetRef} />, container);
    });

    const { result, rerender } = renderHook(() =>
      useIntersection(targetRef, { root: container, threshold: 0.8 })
    );

    const mockIntersectionObserverEntry = {
      boundingClientRect: targetRef.current.getBoundingClientRect(),
      intersectionRatio: 0.81,
      intersectionRect: container.getBoundingClientRect(),
      isIntersecting: true,
      rootBounds: container.getBoundingClientRect(),
      target: targetRef.current,
      time: 300,
    };
    TestRenderer.act(() => {
      intersectionObserver.simulate(mockIntersectionObserverEntry);
    });

    expect(result.current).toEqual(mockIntersectionObserverEntry);

    targetRef.current = document.createElement('div');
    rerender();

    expect(result.current).toEqual(null);
  });

  it('should return null if IntersectionObserver is not supported', () => {
    targetRef = createRef();
    targetRef.current = document.createElement('div');
    delete (window as any).IntersectionObserver;

    expect(() => renderHook(() => useIntersection(targetRef, {}))).not.toThrow();
  });

  it('should disconnect an old IntersectionObserver instance when the ref changes', () => {
    targetRef = createRef();
    targetRef.current = document.createElement('div');

    const { rerender } = renderHook(() => useIntersection(targetRef, {}));

    targetRef.current = document.createElement('div');
    rerender();

    targetRef.current = null;
    rerender();

    expect(IntersectionObserver).toHaveBeenCalledTimes(2);
    expect(IntersectionObserver.prototype.disconnect).toHaveBeenCalledTimes(2);
  });

  it('should return the first IntersectionObserverEntry when the IntersectionObserver registers an intersection', () => {
    TestUtils.act(() => {
      targetRef = createRef();
      ReactDOM.render(<div ref={targetRef} />, container);
    });

    const { result } = renderHook(() =>
      useIntersection(targetRef, { root: container, threshold: 0.8 })
    );

    const mockIntersectionObserverEntry = {
      boundingClientRect: targetRef.current.getBoundingClientRect(),
      intersectionRatio: 0.81,
      intersectionRect: container.getBoundingClientRect(),
      isIntersecting: true,
      rootBounds: container.getBoundingClientRect(),
      target: targetRef.current,
      time: 300,
    };
    TestRenderer.act(() => {
      intersectionObserver.simulate(mockIntersectionObserverEntry);
    });

    expect(result.current).toEqual(mockIntersectionObserverEntry);
  });

  it('should setup a new IntersectionObserver when the ref changes', () => {
    let newRef;
    TestUtils.act(() => {
      targetRef = createRef();
      newRef = createRef();
      ReactDOM.render(
        <div ref={targetRef}>
          <span ref={newRef} />
        </div>,
        container
      );
    });

    const observerOptions = { root: null, threshold: 0.8 };
    const { rerender } = renderHook(({ ref, options }) => useIntersection(ref, options), {
      initialProps: { ref: targetRef, options: observerOptions },
    });

    expect(intersectionObserver.observers[0].target).toEqual(targetRef.current);

    TestRenderer.act(() => {
      rerender({ ref: newRef, options: observerOptions });
    });

    expect(intersectionObserver.observers[0].target).toEqual(newRef.current);
  });

  it('should setup a new IntersectionObserver when the options change', () => {
    TestUtils.act(() => {
      targetRef = createRef();
      ReactDOM.render(<div ref={targetRef} />, container);
    });

    const initialObserverOptions = { root: null as HTMLElement | null, threshold: 0.8 };
    const { rerender } = renderHook(({ ref, options }) => useIntersection(ref, options), {
      initialProps: { ref: targetRef, options: initialObserverOptions },
    });

    expect(intersectionObserver.observers[0].options).toEqual(initialObserverOptions);

    const newObserverOptions = { root: container, threshold: 1 };
    TestRenderer.act(() => {
      rerender({ ref: targetRef, options: newObserverOptions });
    });

    expect(intersectionObserver.observers[0].options).toEqual(newObserverOptions);
  });
});
After
import React, { createRef } from 'react';
import ReactDOM from 'react-dom/client';
import TestUtils from 'react-dom/test-utils';
import TestRenderer from 'react-test-renderer';
import { intersectionObserver } from '@shopify/jest-dom-mocks';
import { useIntersection } from '../src';

beforeEach(() => {
  intersectionObserver.mock();
  const IO = IntersectionObserver;
  jest.spyOn(IO.prototype, 'disconnect');
  jest.spyOn(global as any, 'IntersectionObserver');
  IntersectionObserver.prototype = IO.prototype;
});

afterEach(() => {
  intersectionObserver.restore();
});

describe('useIntersection', () => {
  const container = document.createElement('div');
  let targetRef;

  it('should be defined', () => {
    expect(useIntersection).toBeDefined();
  });

  it('should setup an IntersectionObserver targeting the ref element and using the options provided', () => {
    TestUtils.act(() => {
      targetRef = createRef();
      ReactDOM.createRoot(container).render(<div ref={targetRef} />);
    });

    expect(intersectionObserver.observers).toHaveLength(0);
    const observerOptions = { root: null, threshold: 0.8 };

    renderHook(() => useIntersection(targetRef, observerOptions));

    expect(intersectionObserver.observers).toHaveLength(1);
    expect(intersectionObserver.observers[0].target).toEqual(targetRef.current);
    expect(intersectionObserver.observers[0].options).toEqual(observerOptions);
  });

  it('should return null if a ref without a current value is provided', () => {
    targetRef = createRef();

    const { result } = renderHook(() => useIntersection(targetRef, { root: null, threshold: 1 }));
    expect(result.current).toBe(null);
  });

  it('should reset an intersectionObserverEntry when the ref changes', () => {
    TestUtils.act(() => {
      targetRef = createRef();
      ReactDOM.createRoot(container).render(<div ref={targetRef} />);
    });

    const { result, rerender } = renderHook(() =>
      useIntersection(targetRef, { root: container, threshold: 0.8 })
    );

    const mockIntersectionObserverEntry = {
      boundingClientRect: targetRef.current.getBoundingClientRect(),
      intersectionRatio: 0.81,
      intersectionRect: container.getBoundingClientRect(),
      isIntersecting: true,
      rootBounds: container.getBoundingClientRect(),
      target: targetRef.current,
      time: 300,
    };
    TestRenderer.act(() => {
      intersectionObserver.simulate(mockIntersectionObserverEntry);
    });

    expect(result.current).toEqual(mockIntersectionObserverEntry);

    targetRef.current = document.createElement('div');
    rerender();

    expect(result.current).toEqual(null);
  });

  it('should return null if IntersectionObserver is not supported', () => {
    targetRef = createRef();
    targetRef.current = document.createElement('div');
    delete (window as any).IntersectionObserver;

    expect(() => renderHook(() => useIntersection(targetRef, {}))).not.toThrow();
  });

  it('should disconnect an old IntersectionObserver instance when the ref changes', () => {
    targetRef = createRef();
    targetRef.current = document.createElement('div');

    const { rerender } = renderHook(() => useIntersection(targetRef, {}));

    targetRef.current = document.createElement('div');
    rerender();

    targetRef.current = null;
    rerender();

    expect(IntersectionObserver).toHaveBeenCalledTimes(2);
    expect(IntersectionObserver.prototype.disconnect).toHaveBeenCalledTimes(2);
  });

  it('should return the first IntersectionObserverEntry when the IntersectionObserver registers an intersection', () => {
    TestUtils.act(() => {
      targetRef = createRef();
      ReactDOM.createRoot(container).render(<div ref={targetRef} />);
    });

    const { result } = renderHook(() =>
      useIntersection(targetRef, { root: container, threshold: 0.8 })
    );

    const mockIntersectionObserverEntry = {
      boundingClientRect: targetRef.current.getBoundingClientRect(),
      intersectionRatio: 0.81,
      intersectionRect: container.getBoundingClientRect(),
      isIntersecting: true,
      rootBounds: container.getBoundingClientRect(),
      target: targetRef.current,
      time: 300,
    };
    TestRenderer.act(() => {
      intersectionObserver.simulate(mockIntersectionObserverEntry);
    });

    expect(result.current).toEqual(mockIntersectionObserverEntry);
  });

  it('should setup a new IntersectionObserver when the ref changes', () => {
    let newRef;
    TestUtils.act(() => {
      targetRef = createRef();
      newRef = createRef();
      ReactDOM.createRoot(container).render(
        <div ref={targetRef}>
          <span ref={newRef} />
        </div>
      );
    });

    const observerOptions = { root: null as HTMLElement | null, threshold: 0.8 };
    const { rerender } = renderHook(({ ref, options }) => useIntersection(ref, options), { initialProps: { ref: targetRef, options: observerOptions } });

    expect(intersectionObserver.observers[0].target).toEqual(targetRef.current);

    TestRenderer.act(() => {
      rerender({ ref: newRef, options: observerOptions });
    });

    expect(intersectionObserver.observers[0].target).toEqual(newRef.current);
  });

  it('should setup a new IntersectionObserver when the options change', () => {
    TestUtils.act(() => {
      targetRef = createRef();
      ReactDOM.createRoot(container).render(<div ref={targetRef} />);
    });

    const initialObserverOptions = { root: null as HTMLElement | null, threshold: 0.8 };
    const { rerender } = renderHook(({ ref, options }) => useIntersection(ref, options), { initialProps: { ref: targetRef, options: initialObserverOptions } });

    expect(intersectionObserver.observers[0].options).toEqual(initialObserverOptions);

    const newObserverOptions = { root: container, threshold: 1 };
    TestRenderer.act(() => {
      rerender({ ref: targetRef, options: newObserverOptions });
    });

    expect(intersectionObserver.observers[0].options).toEqual(newObserverOptions);
  });
});

Continue with this codebase

Snapshot ID:832e0f3c-0723-4a17-a7aa-49dad4d805c8
Refactor this codebase →Security audit →Ask Q&A (instant) →

Same engine, different agent. Click any to pre-fill the form with this repo.

Generated tests (3)

The full event log is also available via GET /api/jobs/e912325a-7134-46f4-ba85-0e4a072c337c/audit-report as canonical JSON.