Testing a ThreeJS application using Jest for unit testing

I encountered challenges while testing a JavaScript file with Jest that involves multiple interactions with ThreeJS. Initially, I attempted to test without mocking ThreeJS, but it resulted in errors:

  ● TestSuite › Should instantiate a renderer attached to a specific element of the DOM

    TypeError: Cannot read property 'getExtension' of null

      36 |      */
      37 |     constructor(containerId: string) {
    > 38 |         this.renderer = new WebGLRenderer({ antialias: true });
      39 |         this.attachRenderer(containerId);
      40 |         this.createCamera();
      41 |         this.createScene();

This issue arose due to the fact that we were testing in an environment resembling a browser without a webgl context. To address this, I decided to mock ThreeJS.

Subsequently, I mocked my external module using jest.mock("three");

  ● TestSuite › Should instantiate a renderer attached to a specific element of the DOM

    TypeError: this.renderer.setSize is not a function

      64 |             throw new Error("Cannot find DOM element object matching the specified ID: " + containerId);
      65 |         }
    > 66 |         this.renderer.setSize(window.innerWidth, window.innerHeight);
      67 |         element.appendChild(this.renderer.domElement);
      68 |     }
      69 |

As expected, this occurred because every jest mock returns undefined, so new WebGLRenderer(); also returns undefined which is not usable.

Currently, my workaround involves defining all ThreeJS components in my test file:

jest.mock("three", () => ({
    Scene: class Scene {
        public add(): void {
            return;
        }
    },
    WebGLRenderer: class WebGlRenderer {
        public render(): void {
            return;
        }
        public setSize(): void {
            return;
        }
    }
    // And a lot more...
}));

However, I understand that this is not the most efficient solution. Previously, I followed a similar approach by creating a file in mocks/three.js (https://jestjs.io/docs/en/manual-mocks), which worked fine but did not fulfill my requirements.

Is there a more effective way to test this file without having to manually mock ThreeJS components extensively?

Answer №1

I am currently exploring webgl and managed to resolve an issue using the following method. https://github.com/AmitTeli/webgl-three-test

This method can be summarized as:

  1. Transfer all global variables such as scene, renderer, and camera to index.html.
  2. Initialize them upon page load. For instance, in this reactjs demo, they are initialized in the componentDidMount() method of the main component. Other functions can access this context. (You can verify this by running yarn start)
  3. When conducting unit tests, initialize them in setupTest.js. You will require extra development dependencies such as the headless webgl - gl and canvas.
  4. With this configuration, tests can be run in a file like App.test.js (You can verify this by running yarn test)

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

How can I set the textbox focus to the end of the text after a postback?

In my ASP.Net form, there is a text box and a button. When the user clicks the button, it adds text to an ASP:TextBox during a postback (it adds a specific "starter text"). After the postback, I want the focus to be set to the end of the text in the textbo ...

Guide to incorporating WebElement scrolling in Selenium using Java?

I need to implement a scroll function for a table on my webpage rather than scrolling the entire page, so using window.scrollBy is not an option. After attempting to find the container responsible for the scroll functionality in the DOM (with no luck), I ...

I recently incorporated Puppeteer along with its necessary dependencies onto Heroku, and as a result, pushing my small app to Heroku now takes approximately 5 to 6 minutes

I am currently using Puppeteer to create a PDF from an HTML page. I installed the npm package by running the following command: npm i puppeteer However, when I deployed to Heroku, I encountered an error: Error while loading shared libraries: libnss3.s ...

How to Handle Errors When Retrieving an AWS S3 Object Stream in Node.js

I am currently working on developing an Express server that will send items from a S3 bucket to the client using Node.js and Express. I came across the following code snippet in the AWS documentation. var s3 = new AWS.S3({apiVersion: '2006-03-01&apo ...

Navigating to the parent node in a treeview within the wijmo flex grid: a step-by-step guide

Utilizing the wijmo flex grid, I've successfully created a tree view for my data. I can determine if a specific node has children and its level, but I'm struggling to navigate to the parent node from a given one. Additionally, I am able to retrie ...

Instructions for enabling the touch slider feature in the Igx carousel component with Angular 6 or higher

Looking to enable the touch slider for Igx carousel using angular 6+? I am trying to implement the igx carousel for image sliding with reference from a stackblitz demo (https://stackblitz.com/edit/github-j6q6ad?file=src%2Fapp%2Fcarousel%2Fcarousel.compone ...

Steps for updating the property "project_id" within a nested JSON array to "project_name"

Issue: [ { "project_id": 1, "project_name": "CDP", "role": "PL" }, { "project_id": 2, "project_name": "Admincer", "role": "PM" }, I am trying to extract the "project_id" property from the above JSON array and add it to another array using a specific ...

Why isn't the click event triggering MVC 5 client-side validation for ajax posts?

To incorporate client-side validation with a click event for ajax posts, I followed a guide found at the following URL: Call MVC 3 Client Side Validation Manually for ajax posts My attempt to implement this involved using the code snippet below: $(&apos ...

Is the input in the array? How to find out?

I am currently facing an issue with a script that I have created to count array elements matching a user input. Strangely, all if statements in the script seem to be returning false. I have verified that both the array element and the input value are stri ...

How to smoothly transition a div from one location to another using animations in an Ionic3-Angular4 application

I'm attempting to incorporate some animation into my Ionic 3 mobile app. Specifically, I want to shift a div from one location to another. In the code snippet provided below, I am looking to move the div with the "upper" class after the timeline-item ...

A blank page is appearing mysteriously, free of any errors

I have experience with ReactJs, but I am new to Redux. Currently, I am working on implementing an async action where I call an API and display the data received from it. Initially, when all the Redux components (actions, reducers, containers) were on a sin ...

What is the best way to generate a random string output from an object in JavaScript?

I'm struggling with extracting a random value from the object provided below, can anyone help me out? const hellos = { English: "Hello", Japanese: "Konnichiwa", German: "Hallo", Spanish: "Hola", Arabic: "Ah ...

Upload files via Ajax request is required

I am in the process of trying to upload a binary file to a server while avoiding a full page refresh when the server responds. I must admit, I am not well-versed in this area and I understand if my approach needs some adjustments. This is how I have appro ...

Update the second dropdown automatically based on the selection in the first dropdown menu

I need assistance with creating two dropdown menus that are linked, so when an option is selected in the first menu, it automatically changes the options available in the second menu. Both menus should be visible at all times. I have set up a fiddle to pr ...

Sorry, but we couldn't locate the page you were looking for. The robots.txt file seems

Hey there everyone, I'm currently working with Nuxt3 and encountering an error when trying to access the robot.txt file. Here's the Robot.txt module that I've integrated. Within my nuxt.config.ts file: export default defineNuxtConfig({ ...

Integrating React js with Layout.cshtml: Mastering the Fusion of React Routing and ASP.NET MVC Routing

My current project involves an ASP.NET MVC core application with the View written in cshtml. The routing follows the conventional asp.net mvc routing pattern. However, I've recently implemented a new module using React JS. Now, I'm faced with the ...

How are "new" and "prototype.constructor" related in the realm of Javascript?

Many people have discussed this issue, but unfortunately, I haven't been able to find a solution yet. Here is a snippet of Javascript code regarding inheritance from a book: function Car() { var self = this; self.type = "Car" self.go = funct ...

Ways to include x-api-key in Angular API request headers

I am attempting to include the x-api-key header in the headers, as shown below: service.ts import { Injectable } from '@angular/core'; import { Http, Headers, RequestOptions, Response } from '@angular/http'; import { Observable } from ...

The event fails to propagate up to the parent component

I have a project structure set up as follows: https://i.stack.imgur.com/bvmK5.jpg The todo-form component triggers the created event and I am looking to handle this event in the todos component. todo-form.component.html: <form class="todo-form" ( ...

The Art of Checkbox Design

Seeking help in replacing the default check mark on a checkbox with an image. Here is the code snippet I am currently using: <html> <head> <style> .bl { background:-webkit-gradient(linear, left top, left bottom, color-stop(0, #175899), c ...