amzn / amazon-payments-magento-2-plugin

Extension to enable Amazon Pay on Magento 2
https://amzn.github.io/amazon-payments-magento-2-plugin/
Apache License 2.0
106 stars 76 forks source link

amazon.pay.renderButton: Cannot read properties of null (reading 'onClick') #1215

Open SamJUK opened 10 months ago

SamJUK commented 10 months ago

What I expected

Frontend JS to run without error.

What happened instead

NewRelic reporting a high occurrence of JS errors:

Looking at the JS file, we rely on the amazon.pay.renderButton method to always return a valid HTML element. Even if it throws a exception and fails to assign the property, the flow is never altered. Ideally we should abort the _draw method if we fail to render the button, or at least check to make sure we've initialised a HTMLElement successfully.

https://github.com/amzn/amazon-payments-magento-2-plugin/blob/spc/view/frontend/web/js/amazon-button.js#L176

Your setup

image
SamJUK commented 10 months ago

To add to this, we are noticing another Amazon Pay JS error within NewRelic.

https://github.com/amzn/amazon-payments-magento-2-plugin/blob/spc/view/frontend/web/js/amazon-button.js#L294

image
sgabhart22 commented 10 months ago

Hello @SamJUK ,

I was able to reproduce the first console error in Firefox only, and the second appears to be from a PDP page; the Amazon Pay button doesn't seem to currently be enabled on product pages on the live site, so I couldn't see that one. Nonetheless, it seemed like the button still rendered correctly and was functional as expected from the /checkout/cart page, even with the error.

The first error is a bit curious, since, if self.amazonPay button doesn't exist at that point, the Promise should have been rejected and that line shouldn't even execute (line 173 of the file you linked). For the second error, if New Relic is consistently reporting that buttonConfig evaluates to null at this point, we could potentially look into splitting this logic and using optional chaining. Something like

let payload = self?.buttonConfig?.createCheckoutSessionConfig?.payloadJson;
payload ??= '';
let cartIdNull = payload.includes('cartId":null');

The same allowance may need to be added on line 300 (self.buttonConfig.spc_enabled) if buttonConfig keeps turning up null here. If you have NR configured to a staging site as well, that would be an ideal place to test, but I'd be interested to hear any feedback regarding this -- or any another -- solution to reduce the noise in New Relic.

Thanks! Spencer

SamJUK commented 10 months ago

Hi Spencer,

Regarding the first error, we trigger the rejection callback but never return / alter the execution flow. So it will just continue processing the rest of the code below. See the following snippet for an example.

(function() {
    let shouldReturn = false;
    const testPromise = (res, rej) => {   
        console.log('Test Promise Running');
        if (shouldReturn) {
            return rej('Rejected');
        } else {
            rej('Rejected');
        }

        console.log('Test Promise Ending');
        res('Resolved');
    }

    console.groupCollapsed('Testing No Return');
    testPromise(console.log, console.error);
    console.groupEnd('Testing No Return');

    shouldReturn = true;
    console.groupCollapsed('Testing With Return');
    testPromise(console.log, console.error);
    console.groupEnd('Testing With Return');

})()

As for the 2nd one, is this a potential race condition within the _create method? Should we be waiting for the _draw promise to resolve before trying to subscribe to the cart?

Thanks Sam

sgabhart22 commented 10 months ago

Hi again @SamJUK ,

Thanks for the feedback, I suppose I misspoke previously; we should not be executing line 173 in the first case, but clearly, we still are. For the second case, some type of race condition seems possible there.

On a related note, we are currently examining some options for restructuring some of the module's frontend code to make it more readable, maintainable, and performant. These issues you've raised are certainly cases to consider toward that end. I am curious, have you seen this affect user experience/functionality in any way? Or is this just creating the New Relic noise and possibly affecting apdex scores? If so, you may be able to temporarily ignore these specific errors in NR until proper fixes can be rolled out.

Thanks, Spencer

SamJUK commented 7 months ago

Is there any movement on the restructuring?

Picking this back up after the holiday period, looking over Sentry & our session recordings. It does appear to be having an effect on conversions. In the few examples we've looked at, once customers encounter the error they get stuck in the checkout process unable to proceed before giving up.

image
SamJUK commented 3 months ago

Hi All,

Any updates on this? This is really starting to affect the feasibility of keep Amazon pay active on the production site.

Thanks Sam

sgabhart22 commented 3 months ago

Apologies @SamJUK , it took unexpectedly longer to get the newest release live on the Marketplace. Version 5.17.0 is now available for installation, and includes the frontend refactoring which may positively affect the behavior you've been seeing. I've just opened the PR to merge these changes into the SPC branch, these should be available soon.

Thanks, Spencer