react-ga / react-ga

React Google Analytics Module
Other
5.13k stars 449 forks source link

Error on jest environment: Uncaught [TypeError: Cannot read property 'parentNode' of undefined] #322

Open emibcn opened 5 years ago

emibcn commented 5 years ago

I'm getting this error while constructing and testing my app at TravisCI (removed tons of unrelated lines):

      at node_modules/react-ga/dist/react-ga.js:923:7
      at _default (node_modules/react-ga/dist/react-ga.js:924:5)
      at Object.initialize (node_modules/react-ga/dist/react-ga.js:261:25)

console.error node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/virtual-console.js:29
    Error: Uncaught [TypeError: Cannot read property 'parentNode' of undefined]
        at reportException (/home/travis/build/emibcn/Rac1.js/app/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:24)
        at invokeEventListeners (/home/travis/build/emibcn/Rac1.js/app/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:209:9)
        at HTMLUnknownElementImpl._dispatch (/home/travis/build/emibcn/Rac1.js/app/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
        at HTMLUnknownElementImpl.dispatchEvent (/home/travis/build/emibcn/Rac1.js/app/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
        at HTMLUnknownElementImpl.dispatchEvent (/home/travis/build/emibcn/Rac1.js/app/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:30:27)
        at HTMLUnknownElement.dispatchEvent (/home/travis/build/emibcn/Rac1.js/app/node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
        at Object.invokeGuardedCallbackDev (/home/travis/build/emibcn/Rac1.js/app/node_modules/react-dom/cjs/react-dom.development.js:199:16)
        at invokeGuardedCallback (/home/travis/build/emibcn/Rac1.js/app/node_modules/react-dom/cjs/react-dom.development.js:256:31)
        at replayUnitOfWork (/home/travis/build/emibcn/Rac1.js/app/node_modules/react-dom/cjs/react-dom.development.js:17107:5)
        at renderRoot (/home/travis/build/emibcn/Rac1.js/app/node_modules/react-dom/cjs/react-dom.development.js:17979:13) TypeError: Cannot read property 'parentNode' of undefined
        at /home/travis/build/emibcn/Rac1.js/app/node_modules/react-ga/dist/react-ga.js:923:7
        at _default (/home/travis/build/emibcn/Rac1.js/app/node_modules/react-ga/dist/react-ga.js:924:5)
        at Object.initialize (/home/travis/build/emibcn/Rac1.js/app/node_modules/react-ga/dist/react-ga.js:261:25)

The related code is the GA loader, when inserting the tag to node (in file react-ga/src/utils/loadGA.js, at line m.parentNode.insertBefore):

export default function (options) {                                                                              
  let gaAddress = 'https://www.google-analytics.com/analytics.js';                                               
  if (options && options.gaAddress) {                                                                            
    gaAddress = options.gaAddress;                                                                               
  } else if (options && options.debug) {
    gaAddress = 'https://www.google-analytics.com/analytics_debug.js';                                           
  }                                                                                                              

  // https://developers.google.com/analytics/devguides/collection/analyticsjs/                                   
  /* eslint-disable */                                                                                           
  (function (i, s, o, g, r, a, m) {                                                                              
    i['GoogleAnalyticsObject'] = r;
    i[r] = i[r] || function () {
      (i[r].q = i[r].q || []).push(arguments);                                                                   
    }, i[r].l = 1 * new Date();
    a = s.createElement(o),                                                                                      
      m = s.getElementsByTagName(o)[0];
    a.async = 1;
    a.src = g;
    m.parentNode.insertBefore(a, m);
})(window, document, 'script', gaAddress, 'ga');                                                                 
  /* eslint-enable */                                                                                            
}

Is there anything I can do to prevent this to fail? Or maybe it's better to only try to insert the node when the DOM is a real one?

webdevbyjoss commented 5 years ago

Getting the same issue with my ReactJS WEB app after React Scripts upgrade to the latest version. @emibcn did you figured out the way to overcome this?

emibcn commented 5 years ago

@webdevbyjoss Yes: don't load GA if process.env.NODE_ENV !== 'production': https://github.com/emibcn/Rac1.js/blob/master/app/src/GAListener.jsx#L56

alxvallejo commented 5 years ago

@emibcn I don't see that check: https://github.com/emibcn/Rac1.js/blob/master/app/src/GAListener.jsx#L15

Also, if that's the case, why is that not in the README?

Also, if that's the case, would you need to add that conditional at EVERY ReactGA call? That's a lot of bloat. Why would that not be part of the initialize and pageview methods in the lib?

emibcn commented 5 years ago

@alxvallejo

I don't see that check:

I changed this project a little bit, since I don't want to track users with DoNotTrack activated.

Also, if that's the case, why is that not in the README?

I am changing some things, but could not dedicate all the time I'd like. I will add it to README and add some UI elements to better control tracking from the UI.

Also, if that's the case, would you need to add that conditional at EVERY ReactGA call? That's a lot of bloat. Why would that not be part of the initialize and pageview methods in the lib?

I have moved the condition to the Component constructor at https://github.com/emibcn/Rac1.js/blob/master/app/src/GAListener.jsx#L72 :

const dnt = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
this.dnt = process.env.NODE_ENV !== 'production' || dnt === "1" || dnt === "yes";
emibcn commented 5 years ago

@alxvallejo I have changed a bit the logic:

refayathaque commented 4 years ago

https://github.com/react-ga/react-ga#test-mode - this helped me! Thanks for maintaining such an useful library guys! :)

jerrychong25 commented 4 years ago

https://github.com/react-ga/react-ga#test-mode - this helped me! Thanks for maintaining such an useful library guys! :)

Thanks, this solved my issue.