Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to test getBoundingClientRect #2514

Open
2 of 13 tasks
AlexanderVikenfalk opened this issue Apr 23, 2021 · 2 comments
Open
2 of 13 tasks

Unable to test getBoundingClientRect #2514

AlexanderVikenfalk opened this issue Apr 23, 2021 · 2 comments

Comments

@AlexanderVikenfalk
Copy link

AlexanderVikenfalk commented Apr 23, 2021

Current behavior

I have a scroller component which relies on refs. When trying to test it I get an error saying "Cannot read property 'getBoundingClientRect' of null]". Is there anyway to mock these values so that I can test if my functions work correctly?

const ProgressBarScroller = (props) => {
    const [progressbarWrapperRef, progressBarTaskRef, progressBarRef] = [
        useRef(null),
        useRef(null),
        useRef(null)
    ];
    const getElementWidth = (refName) =>
        refName.current.getBoundingClientRect().width;

    useEffect(() => {
        if (!progressBarTaskRef.current)     return;
        const taskWidth = getElementWidth(progressBarTaskRef);
        const progressBarWidth = getElementWidth(progressBarRef);
        const progressbarWrapperWidth = getElementWidth(progressbarWrapperRef);

        const middleOfActiveTask =
            (props.currentTaskIndex + 1) * taskWidth - taskWidth / 2;
        const requestedX = middleOfActiveTask - progressbarWrapperWidth / 2;
        const maxPossibleX = progressBarWidth - progressbarWrapperWidth;

        const scroller = new scrollBooster({
            viewport: progressbarWrapperRef.current,
            direction: 'horizontal',
            scrollMode: 'transform',
            friction: 0.2
        });

        /**
         * returns 0 if requested X position is lower than minimum.
         * returns the highest possible X position if requested X is higher than maximum.
         * Otherwise returns requested X position.
         * @returns {number}
         */
        const getValidXPosition = () => {
            return requestedX <= 0 ? 0
                : requestedX >= maxPossibleX ? maxPossibleX
                    : requestedX;
        };

        (function moveToDefaultPosition() {
            scroller.setPosition({
                x: getValidXPosition(),
                y: 0
            });
        })();

        //Cleans up ScrollBooster on unmount
        return () => {
            scroller.destroy();
        };
    }, []);

    return (
        <div className={'cs-progressbar'} ref={progressbarWrapperRef}>
            <ul className={`cs-progressbar__list`} ref={progressBarRef}>
                {props.tasks.map((task, index) => {
                    return (
                        <ProgressBarTask
                            {...task}
                            key={task.id}
                            innerRef={
                                props.currentTaskIndex === index
                                    ? progressBarTaskRef
                                    : null
                            }
                        />
                    );
                })}
            </ul>
        </div>
    );
};

Expected behavior

That the ref values are mockable so that getBoundingClientRect() doesn't throw an error.

Your environment

API

  • shallow
  • mount
  • render

Version

library version
enzyme 3.11.0
react 16.13.1
react-dom 16.13.1
react-test-renderer 17.0.1
adapter (below)

Adapter

  • enzyme-adapter-react-16
  • enzyme-adapter-react-16.3
  • enzyme-adapter-react-16.2
  • enzyme-adapter-react-16.1
  • enzyme-adapter-react-15
  • enzyme-adapter-react-15.4
  • enzyme-adapter-react-14
  • enzyme-adapter-react-13
  • enzyme-adapter-react-helper
  • others ( )
@ljharb
Copy link
Member

ljharb commented Apr 23, 2021

I believe this is a jsdom limitation. #1233 may be related.

The only time getElementWidth is called is inside a useEffect, and it doesn't make much sense to me that the effect would run but the useRef wouldn't. However, I do notice that your code is checking for when progressBarTaskRef.current is falsy, but not when progressbarWrapperRef is falsy, so this may be a bug in your code - what happens when you check for both being truthy in the useEffect?

@AlexanderVikenfalk
Copy link
Author

I believe this is a jsdom limitation. #1233 may be related.

The only time getElementWidth is called is inside a useEffect, and it doesn't make much sense to me that the effect would run but the useRef wouldn't. However, I do notice that your code is checking for when progressBarTaskRef.current is falsy, but not when progressbarWrapperRef is falsy, so this may be a bug in your code - what happens when you check for both being truthy in the useEffect?

Thanks for the help!
Sorry. My code was a bit sloppy. I should ofc have checked so that any of my refs were falsey and just not progressBarTaskRef.current. I also found a typo in the test implementation which caused the original error. So now I'm instead getting a new error:

Error: Uncaught [ReferenceError: Element is not defined]
    at reportException (/home/vikenfalk/third-party-client/tp-client/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:62:24)
    at innerInvokeEventListeners (/home/vikenfalk/third-party-client/tp-client/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:341:9)
    at invokeEventListeners (/home/vikenfalk/third-party-client/tp-client/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
    at HTMLUnknownElementImpl._dispatch (/home/vikenfalk/third-party-client/tp-client/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
    at HTMLUnknownElementImpl.dispatchEvent (/home/vikenfalk/third-party-client/tp-client/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
    at HTMLUnknownElement.dispatchEvent (/home/vikenfalk/third-party-client/tp-client/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
    at Object.invokeGuardedCallbackDev (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:237:16)
    at invokeGuardedCallback (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:292:31)
    at flushPassiveEffectsImpl (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:22853:9)
    at unstable_runWithPriority (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/node_modules/scheduler/cjs/scheduler.development.js:653:12)
    at runWithPriority$1 (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:11039:10)
    at flushPassiveEffects (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:22820:12)
    at flushWork (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom-test-utils.development.js:876:10)
    at Object.act (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom-test-utils.development.js:994:9)
    at wrapAct (/home/vikenfalk/third-party-client/tp-client/node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:405:13)
    at Object.render (/home/vikenfalk/third-party-client/tp-client/node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:474:16)
    at new ReactWrapper (/home/vikenfalk/third-party-client/tp-client/node_modules/enzyme/src/ReactWrapper.js:115:16)
    at mount (/home/vikenfalk/third-party-client/tp-client/node_modules/enzyme/src/mount.js:10:10)
    at setup (/home/vikenfalk/third-party-client/tp-client/test/components/proposal/progressBar/ProgressBarScroller.test.js:43:25)
    at Context.<anonymous> (/home/vikenfalk/third-party-client/tp-client/test/components/proposal/progressBar/ProgressBarScroller.test.js:51:38)
    at callFn (/home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runnable.js:358:21)
    at Test.Runnable.run (/home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runnable.js:346:5)
    at Runner.runTest (/home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runner.js:621:10)
    at /home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runner.js:745:12
    at next (/home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runner.js:538:14)
    at /home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runner.js:548:7
    at next (/home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runner.js:430:14)
    at Immediate._onImmediate (/home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runner.js:516:5)
    at runCallback (timers.js:705:18)
    at tryOnImmediate (timers.js:676:5)
    at processImmediate (timers.js:658:5) ReferenceError: Element is not defined
    at new t (/home/vikenfalk/third-party-client/tp-client/node_modules/scrollbooster/dist/webpack:/ScrollBooster/src/index.js:76:70)
    at /home/vikenfalk/third-party-client/tp-client/src/components/proposal/progressBar/ProgressBarScroller.js:28:26
    at commitHookEffectListMount (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:19731:26)
    at commitPassiveHookEffects (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:19769:11)
    at HTMLUnknownElement.callCallback (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:188:14)
    at HTMLUnknownElement.callTheUserObjectsOperation (/home/vikenfalk/third-party-client/tp-client/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
    at innerInvokeEventListeners (/home/vikenfalk/third-party-client/tp-client/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:338:25)
    at invokeEventListeners (/home/vikenfalk/third-party-client/tp-client/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
    at HTMLUnknownElementImpl._dispatch (/home/vikenfalk/third-party-client/tp-client/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
    at HTMLUnknownElementImpl.dispatchEvent (/home/vikenfalk/third-party-client/tp-client/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
    at HTMLUnknownElement.dispatchEvent (/home/vikenfalk/third-party-client/tp-client/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
    at Object.invokeGuardedCallbackDev (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:237:16)
    at invokeGuardedCallback (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:292:31)
    at flushPassiveEffectsImpl (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:22853:9)
    at unstable_runWithPriority (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/node_modules/scheduler/cjs/scheduler.development.js:653:12)
    at runWithPriority$1 (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:11039:10)
    at flushPassiveEffects (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom.development.js:22820:12)
    at flushWork (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom-test-utils.development.js:876:10)
    at Object.act (/home/vikenfalk/third-party-client/tp-client/node_modules/react-dom/cjs/react-dom-test-utils.development.js:994:9)
    at wrapAct (/home/vikenfalk/third-party-client/tp-client/node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:405:13)
    at Object.render (/home/vikenfalk/third-party-client/tp-client/node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:474:16)
    at new ReactWrapper (/home/vikenfalk/third-party-client/tp-client/node_modules/enzyme/src/ReactWrapper.js:115:16)
    at mount (/home/vikenfalk/third-party-client/tp-client/node_modules/enzyme/src/mount.js:10:10)
    at setup (/home/vikenfalk/third-party-client/tp-client/test/components/proposal/progressBar/ProgressBarScroller.test.js:43:25)
    at Context.<anonymous> (/home/vikenfalk/third-party-client/tp-client/test/components/proposal/progressBar/ProgressBarScroller.test.js:51:38)
    at callFn (/home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runnable.js:358:21)
    at Test.Runnable.run (/home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runnable.js:346:5)
    at Runner.runTest (/home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runner.js:621:10)
    at /home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runner.js:745:12
    at next (/home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runner.js:538:14)
    at /home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runner.js:548:7
    at next (/home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runner.js:430:14)
    at Immediate._onImmediate (/home/vikenfalk/third-party-client/tp-client/node_modules/mocha/lib/runner.js:516:5)
    at runCallback (timers.js:705:18)
    at tryOnImmediate (timers.js:676:5)
    at processImmediate (timers.js:658:5)
The above error occurred in the <ProgressBarScroller> component:
    in ProgressBarScroller (created by WrapperComponent)
    in WrapperComponent

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.

ReferenceError: Element is not defined
    at new t (node_modules/scrollbooster/dist/webpack:/ScrollBooster/src/index.js:76:70)
    at /home/vikenfalk/third-party-client/tp-client/src/components/proposal/progressBar/ProgressBarScroller.js:28:26
    at commitHookEffectListMount (node_modules/react-dom/cjs/react-dom.development.js:19731:26)
    at commitPassiveHookEffects (node_modules/react-dom/cjs/react-dom.development.js:19769:11)
    at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:188:14)
    at HTMLUnknownElement.callTheUserObjectsOperation (node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
    at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:338:25)
    at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
    at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
    at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
    at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
    at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:237:16)
    at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:292:31)
    at flushPassiveEffectsImpl (node_modules/react-dom/cjs/react-dom.development.js:22853:9)
    at unstable_runWithPriority (node_modules/react-dom/node_modules/scheduler/cjs/scheduler.development.js:653:12)
    at runWithPriority$1 (node_modules/react-dom/cjs/react-dom.development.js:11039:10)
    at flushPassiveEffects (node_modules/react-dom/cjs/react-dom.development.js:22820:12)
    at flushWork (node_modules/react-dom/cjs/react-dom-test-utils.development.js:876:10)
    at Object.act (node_modules/react-dom/cjs/react-dom-test-utils.development.js:994:9)
    at wrapAct (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:405:13)
    at Object.render (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:474:16)
    at new ReactWrapper (node_modules/enzyme/src/ReactWrapper.js:115:16)
    at mount (node_modules/enzyme/src/mount.js:10:10)
    at setup (test/components/proposal/progressBar/ProgressBarScroller.test.js:43:25)
    at Context.<anonymous> (test/components/proposal/progressBar/ProgressBarScroller.test.js:51:38)

Any suggestion on what could be causing the issue or what I could do to work around it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants