Global JavaScript constants are triggering a ReferenceError when utilized within Angular components in Jest

Today I've delved into the world of Jest for UnitTesting our TypeScript files in an Angular project. Setting up Jest initially was a breeze, and creating tests for pure TypeScript methods in our util.ts file was straightforward. Now, as I tackle testing something within an Angular component, I'm facing an issue due to global constants from another imported Component. So, my quest now is to find a solution by:

  1. Providing defaults to these global variables within my Jest UnitTest class itself by initializing them in a beforeAll.
  2. Creating a separate custom-jest-constants.setup.ts file to preset all global variables for all tests.

I won't bore you with the nitty-gritty details of setting up and configuring Jest within Angular this morning, but it led me to make some crucial changes, such as:

Within the angularelements/ root folder:

Added jest.config.ts:

export default {
  clearMocks: true,
  globalSetup: 'jest-preset-angular/global-setup',
  preset: 'jest-preset-angular',
  setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'],
};

Added setup-jest.ts:

import 'jest-preset-angular/setup-jest';

Added tsconfig.spec.json:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/spec",
    "module": "CommonJs",
    "types": ["jest"]
  },
  "include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}

Modified package.json:

{
  ...,
  "scripts": {
    ...,
    "test": "jest"
  },
  "devDependencies": {
    ...,
    "@types/jest": "^28.1.3",
    "jest": "^28.1.1",
    "jest-preset-angular": "^12.1.0"
  }
}

Within a new test folder:

Added util.test.ts and question.component.test.ts, but their specifics are not too pertinent here.

The error that pops up when I execute npm test:

 PASS  test/app/util.test.ts
 FAIL  test/app/questionnaire/runtime/question/question.component.test.ts
  ● Test suite failed to run

    ReferenceError: maxFileUploadSizeInKb is not defined

      42 |   ...
    > 43 |   private static readonly UPLOAD_LIMIT_IN_BYTES = +maxFileUploadSizeInKb * 1000;
         |                                                    ^
      44 |   private static readonly IMAGE_UPLOAD_LIMIT_IN_BYTES = +maxImageFileUploadSizeInKb * 1000;
      45 |   ...

      at Object.<anonymous> (src/app/document-panel/document-uploading/document-uploading.component.ts:43:52)
      at Object.<anonymous> (src/app/questionnaire/runtime/questionnaire-document-panel/questionnaire-document-panel.component.ts:10:1)
      at Object.<anonymous> (src/app/questionnaire/runtime/question/question.component.ts:16:1)
      at Object.<anonymous> (test/app/questionnaire/runtime/question/question.component.test.ts:1:1)

Regarding the relevant code snippet within the document-uploading.component.ts:

declare const maxFileUploadSizeInKb: string;
declare const maxImageFileUploadSizeInKb: string;

@Component({ ... })
export class DocumentUploadingComponent extends ... {
  private static readonly UPLOAD_LIMIT_IN_BYTES = +maxFileUploadSizeInKb * 1000;
  private static readonly IMAGE_UPLOAD_LIMIT_IN_BYTES = +maxImageFileUploadSizeInKb * 1000;

These declared constants are globally defined in our javascriptPre.jspf like so:

...
<script ...>
   var maxFileUploadSizeInKb = '<%=Util.parseInt(SettingManager.get(Setting.maximumFileSizeInKb), Setting.DEFAULT_MAX_FILE_SIZE_KB)%>';
   var maxImageFileUploadSizeInKb = '<%=Util.parseInt(SettingManager.get(Setting.maximumImageFileSizeInKb), Setting.DEFAULT_MAX_IMAGE_FILE_SIZE_KB)%>';
</script>
...

This injects settings from our Java backend into these globally accessible JS variables, which are then utilized within our Angular/Typescript classes as evidenced in the document-uploading.component.ts.

If I temporarily swap out these dynamic constants for hard-coded values like this:

private static readonly UPLOAD_LIMIT_IN_BYTES = 5_000_000;
private static readonly IMAGE_UPLOAD_LIMIT_IN_BYTES = 400_000;

Everything functions smoothly during npm test execution.

So, circling back to the original query: how can I override/set up the maxFileUploadSizeInKb/maxImageFileUploadSizeInKb to default values, either within a custom Jest setup file or via a beforeAll block in my UnitTest file (or any other approach)?

Answer №1

After some trial and error, I finally stumbled upon the solution to my problem, which turned out to be much simpler than anticipated.

In my jest.config.ts file, I made the following addition:

setupFiles: ['<rootDir>/custom-jest-setup.ts'],

Within the newly added custom-jest-setup.ts file located in my angularelements/ folder, I included:

// @ts-ignore
global.maxFileUploadSizeInKb = 5000;
// @ts-ignore
global.maxImageFileUploadSizeInKb = 400;

And just like that, my UnitTests are now running smoothly without any hiccups!

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

Issue with integrating React, Material UI, Typescript, Webpack, and server-side rendering (SSR

I encountered an issue with my server-side rendered app when I tried to integrate Material UI into it. Here is how my directory structure looks: app/ build/ * This directory is generated by webpack server_bundle.js public/ ...

Encountering a RuntimeError during the integration of Angular Js in Rails with ExecJS

Currently, I'm working on integrating Angular Js into a Rails Project and I've been following the tutorial provided at . However, after completing all the steps, I encountered the following error: https://i.sstatic.net/ehYCb.png I've searc ...

What is the best way to transfer text from a paragraph element to an input field without triggering a page refresh?

I have a challenge where I want to replicate the content of a <p> element into an <input> element's value attribute. The text within the paragraph includes values like .30, .31, .6, .38, which are dynamically updated by a jQuery script wi ...

What seems to be the issue with Collapse.js in Bootstrap 3.3.4 on this page?

I am currently utilizing Bootstrap version 3.3.4. All of my resources are linked relatively and the HTML file is in the correct location for access. I am creating a 'Learn More' button that should display a collapsed unordered list either above ...

Is it possible to customize eslint rules for a create-react-app that has been ejected?

Currently, I am in the process of developing an application using React and utilizing NPM. The configuration of my package.json file is as follows: { "name": "mouseflow-react", "version": "0.1.0", "private": true, // Dependencies section with var ...

"Incorporating an onChange event handler to an input field in a React

I'm currently facing a challenge with my input box component as I aim to implement a script that will restrict all inputs except for numbers. function onChangeHandler(e: React.ChangeEvent) { this.value.replace(/(?![0-9])./gmi,''); } expo ...

Can you please provide instructions on how to expand the view in the title bar for a JavaScript/CSS/HTML UPW project?

Struggling to integrate the title bar in a UWP project using JavaScript/CSS/HTML and having trouble accessing the necessary APIs. Came across a custom helper class written in c++ in UWP samples on Github, but unable to reference it in my javascript code. H ...

What are the steps to execute a filter operation on a table by utilizing two select box values with jQuery?

I have a challenge with two dropdown menus. One contains names and the other subjects, along with a table displaying information in three columns: name, subject, and marks. I would like to implement a filter based on the selections in these two dropdowns. ...

Combine items based on their keys and corresponding values

The original question has been updated for clarity. The desired output is to merge an array of objects into a single object with specific conditions. I am attempting to consolidate three sets of keys per object into one instance, choosing the lowest numbe ...

Incorporate visual elements such as images that resemble checkboxes

I'm searching for an innovative approach to replace the traditional checkbox, incorporating images instead. My idea is to have users click on an image, which will then fade out and reveal a tick box overlay. My inspiration comes from Recaptcha 2, whe ...

Exploring the capabilities of arrays within Ajax

Below is the original code I wrote in JavaScript: var wt_val = []; for (i = 0; i<human_wt.length; i++){ var mult; mult = data_list[basket_list[button_port_name][i]].map(x => x*(wt[i]/100)); wt_val.push(mult); ...

Express routing anticipating a layout

I am currently working on a small node application that utilizes Express as its router. I have encountered an issue where, regardless of the URL I provide to it, the application expects a template with the same structure. For example: router.get('enr ...

To extract three records from storage and store them in the dbResult using a promise join technique

How can I efficiently retrieve and store 3 records in dbResult using promise join? Currently, I have code that retrieves a single record as shown below: req.oracleMobile.storage.getById(registry.getIncidentPhotoStorageName(), incident_id + '_01&apos ...

React Native Header Icon Not Showing on the Left Side

I'm brand new to react and currently working on a project where navigation is done through a hamburger menu. I haven't encountered any errors in my code, but for some reason, the hamburger menu icon isn't displaying as expected. Interestingl ...

What is the best way to populate an Angular Bootstrap Table Widget with data obtained from an API request?

I am currently in the process of making an API call and utilizing the received data in a Bootstrap Angular Table Widget. The specific widget I am utilizing can be found here: Complete example (Angular powered bootstrap widget) Ensure you are working with ...

Mastering server requests in Angular 5

I have come across recommendations stating that server requests should be made via services and not components in order to ensure reusability of functions by other components. Ultimately, the server response is needed in the component. My query pertains t ...

The event listener for "popstate" is not triggering on the .document

Struggling with implementing a popstate event handler on an Ajax page using the .document object: document.addEventListener("popstate", myPopState); Despite my efforts, this handler never seems to fire. I was hoping that after reloading the page, the po ...

What causes TypeScript's ReadonlyArrays to become mutable once they are transpiled to JavaScript?

Currently, I am in the process of learning Typescript by referring to the resources provided in the official documentation. Specifically, while going through the Interfaces section, I came across the following statement: TypeScript includes a special t ...

The React function was misusing the useEffect hook, causing it to be

I seem to be encountering a problem when trying to call useEffect within this function. As someone who is relatively new to React, I may have made some noticeable mistakes, but dealing with this issue is becoming quite time-consuming. The function in ques ...

Navigating to a specific element with a smooth scroll in Angular after changing states

While working in Angular, I'm utilizing a node package to enable smooth scrolling on my website. One challenge I'm facing is implementing a feature where clicking on a link in the navbar while on a specific history state will take the user to tha ...