Tips for testing an API that relies on an external library such as "<script src="http://stripe[...]"

Currently, I am working on unit testing an API call to verify it has been executed with the correct properties. The API call is reliant on Stripe's external library that is connected to the window through index.html src="http://stripe[...]". However, when trying to execute the function, I encounter an error stating that window.[...] is not recognized as a function.

While I was able to successfully mock the $http.post request, I faced some challenges in dealing with the redirection triggered by Stripe's payment callback which involves calling window.Stripe().redirectToCheckout(). Although mocking window.Stripe was feasible, handling .redirectToCheckout() proved to be more complex and ambiguous for me.

The structure of index.html:

<script src="https://js.stripe.com/v3/"></script>
<link rel="preconnect" href="https://q.stripe.com">
<link rel="preconnect" href="https://checkout.stripe.com">

Code snippet from StripePayment.vue:

async stripe () {
await this.$http.post(process.env.VUE_APP_PAYMENTAPI + 'api/session/', {
        amount: this.cost,
      }).then(response => {
        // Redirecting to the main page using the sessionId provided by Stripe's response.
        window.Stripe(process.env.VUE_APP_STRIPE_KEY).redirectToCheckout({
          sessionId: response.body
        })
      }, response => {
        this.paymentFailed(response)
      })
}

Snippet from StripePayment.spec.js:

let stripeSpy = sinon.spy(StripePayment.methods, 'stripe')
sinon.assert.calledOnce(stripeSpy)

My goal is to validate the successful execution of the API call. Unfortunately, I keep encountering the following error message - "UnhandledPromiseRejectionWarning: TypeError: window.Stripe is not a function". When attempting to stub window.Stripe, a similar error involving .redirectToCheckout() arises, leading me to face difficulties in properly incorporating the stub.

For reference, there is another piece of code similar to mine available at - https://repl.it/@AndrewReinlieb/Checkout-Test.

Answer №1

When conducting isolated unit testing, it is essential to mock all units that are not part of the tested unit. If a unit belongs to an external library, it should be mocked on the window:

const mockedStripe = sinon.stub(window, 'stripe');
const mockedRedirectToCheckout = sinon.stub();
mockedStripe.returns({ redirectToCheckout: mockedRedirectToCheckout });

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Discover the method for invoking a Javascript function within a Leaflet popup using HTML

Upon clicking on a marker on the leaflet map, I aim to trigger a popup box that contains five elements: Title Description Image Button (Next Image) Button (Previous Image) To achieve this, I attempted to include a custom popup for each feature ...

Upon migrating from Vue CLI 2 to 3, an error is thrown stating: "Cannot locate element: #app" and an empty body is

Currently, I am in the process of transitioning my VueJS project from VueCLI 2 to version 3. After moving all the necessary files to the src folder, I attempted to view it in the browser by running npm run serve. However, I encountered a problem where the ...

Is there a method to initiate a 'simple' action when dispatching an action in ngrx?

Here's the scenario I'm facing: When any of the actions listed below are dispatched, I need to update the saving property in the reducer to true. However, currently, I am not handling these actions in the reducer; instead, I handle them in my ef ...

Having trouble with i18n types not functioning correctly in Typescript and Nuxt?

I am currently utilizing NuxtJS/i18n with TypeScript and have included its types in my TS config: { "compilerOptions": { "types": [ "@nuxt/types", "@nuxtjs/i18n", ] } } However, when attempti ...

Can you retrieve data or HTML content from the main Vue 3 component?

I have experience using Vue in previous projects but I'm currently facing some challenges on how to pass information/arguments to a root Vue 3 component. My goal is to set up something like this in my HTML: <div class="nav-app" nav=&quo ...

Tips for aligning the text of a typography element in Material-UI when its parent is fixed

Introduction to Home Component const HomeComponent = ({ mode, setMode }) => { return ( <Box m={-1} sx={{overflowX:'hidden'}}> <Navber/> <Stack direction="row" spacing={2} justifyContent="space-be ...

Engage in Step 2: Receive a response from the server via AJAX request

I've been utilizing AJAX in conjunction with the Play 2 framework to send requests and execute actions on the server side. Learn how to make an AJAX request with a common button in Play 2.x Troubleshooting Jquery and Play Framework 2 JavaScript rout ...

How to prevent jQuery from continually recalculating width on window resize?

Here is the code I've been working on: http://jsfiddle.net/7cXZj/ var callback = function () { $('.progress-bar').width($('.progress-bar').parent().width() - 190); $(".mainpart-background").animate({ width: "80%" }, 80 ...

The bar graph dataset is not correctly configured when utilizing ng2 charts and ng5-slider within an Angular framework

Currently, I am working with a range slider and bar graph. My goal is to dynamically change the color of the bar graph using the range slider. While I have managed to successfully alter the color of the bars, I am facing an issue where the data displayed ...

Unlocking the power of v-model within your custom component

Is there a way to tap into the initial value of a v-model on a vue custom component? I know we can bind the value to a parent component using this.$emit(input, e.target.value). I've already created an upload-button component that uploads files when a ...

The Zip file generated in memory is experiencing corruption

I'm encountering an issue while attempting to serve a zip file generated in memory by Flask to a JavaScript front-end. However, the downloaded file appears corrupted and I am unsure of what mistake I may be making. @app.route('/route') def ...

After updating to Node 15, the Nuxt build process comes to a halt

After updating my nuxt application to Node 15, the building process comes to a halt indefinitely. https://i.sstatic.net/AJ7GO.png The local development server remains stuck with a "Loading..." message. https://i.sstatic.net/jYECv.png The issue I am faci ...

A guide to seamlessly adding calendar events with JSON data using the powerful Ionic Native Calendar Plugin

Hello there, I am in the process of developing an Ionic app and incorporating the Ionic Native Calendar plugin. My goal is to utilize this plugin to dynamically adjust the calendar event parameters through JSON linked to a Firebase database, rather than h ...

Targeting props within a Class Component: A Step-by-Step Guide

I am currently working on a MultiStep Form project. On the final page of the form, my goal is to push all the collected data to Firebase. I have been utilizing props and states to pass values from one page to another. However, I'm facing an issue in t ...

What are the differences between using embedded documents and references in a mongoose design model?

I am currently in the process of developing a discussion forum using Node.js and mongoose. The structure I have in mind involves users being able to participate in multiple forums, with each forum containing multiple comments. Additionally, users should ha ...

The functionality of ngSubmit and ngDisabled seems to be malfunctioning, although ngModel is successfully linked to the

Despite following the usual process of creating a form in AngularJS, the ngSubmit function is not working as expected and the ngDisabled feature is failing to disable the button when the fields are empty. I even tried isolating the section in a new project ...

The IDE is showing an error, but Jest is able to run it flawlessly

I recently created a Jest unit test for a TypeScript function called checkEmail, which internally uses showAlert. The showAlert function in the utils.ts file looks like this: export const showAlert = (message: string) => { toast(message); }; In my ...

Implementing Placeholder Text Across Multiple Lines with Material UI

Currently, for the React App I am developing, I am utilizing Material UI. In order to achieve a multi-line placeholder for a textarea using the TextField component, here is what I have so far: <TextField id="details" ful ...

Adjusting webpage background with JavaScript

I've been struggling with this for the past six hours and can't seem to get it right. I've checked out various solutions on Stack Overflow, but nothing seems to work. What am I missing here?!? My html5 page doesn't have a background an ...

Send an array of data from the view to the Controller in CodeIgniter

I have been searching for a solution to this question. However, for some reason, my code is not functioning properly. Here is what I want to achieve: Data Array -> ajax post -> codeigniter controller(save data in DB and redirect to another page) ...