Angular and Jest combo has encountered an issue resolving all parameters for the AppComponent. What could be causing this error?

I am currently working within a Typescript Monorepo and I wish to integrate an Angular 8 frontend along with Jest testing into the Monorepo. However, I am facing some challenges.

The tools I am using are:

Angular CLI: 8.3.5

My Approach

I plan to use this repository as my starting point!

1. Setting Up Angular Application

To create the Angular application, I executed the following command in <root>/services:

ng new frontend

After creating the Angular application, I was able to successfully run ng test with positive results:

https://i.sstatic.net/ZBFrJ.png

Everything seemed to be functioning correctly.

2. Incorporating Jest

I opted to utilize https://github.com/briebug/jest-schematic for easily integrating Jest with my Angular application.

yarn global add @briebug/jest-schematic
ng add @briebug/jest-schematic

This led to certain modifications taking place:

https://i.sstatic.net/WnAXN.png

However, when executing jest, it resulted in the given error:

$ jest
 FAIL  src/app/app.component.spec.ts
  ● Test suite failed to run

    File not found: <rootDir>/src/tsconfig.spec.json (resolved as: /home/flo/Desktop/stackoverflow-monorepo-angular-jest/services/frontend/src/tsconfig.spec.json)

      at ConfigSet.resolvePath (node_modules/ts-jest/dist/config/config-set.js:712:19)
      at ConfigSet.get (node_modules/ts-jest/dist/config/config-set.js:202:67)
      at ConfigSet.tsJest (node_modules/ts-jest/dist/util/memoize.js:43:24)
      at ConfigSet.get (node_modules/ts-jest/dist/config/config-set.js:297:41)
      at ConfigSet.versions (node_modules/ts-jest/dist/util/memoize.js:43:24)
      at ConfigSet.get (node_modules/ts-jest/dist/config/config-set.js:583:32)
      at ConfigSet.jsonValue (node_modules/ts-jest/dist/util/memoize.js:43:24)
      at ConfigSet.get [as cacheKey] (node_modules/ts-jest/dist/config/config-set.js:598:25)
      at TsJestTransformer.getCacheKey (node_modules/ts-jest/dist/ts-jest-transformer.js:126:36)
      at ScriptTransformer._getCacheKey (node_modules/@jest/transform/build/ScriptTransformer.js:266:23)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        1.267s
Ran all test suites.

3. Addressing Errors

Jest was attempting to locate the tsconfig.spec.json file in the incorrect directory. Thankfully, I came across a solution. I needed to modify the jest.config.js:

module.exports = {
  preset: 'jest-preset-angular',
  setupFilesAfterEnv: ['<rootDir>/src/setup-jest.ts'],
  globals: {
    'ts-jest': {
      tsConfig: '<rootDir>/tsconfig.spec.json',
      diagnostics: false,
      stringifyContentPathRegex: '\\.html$',
      astTransformers: [require.resolve('jest-preset-angular/InlineHtmlStripStylesTransformer')],
    },
  },
};

Upon running jest again, it performed as expected:

https://i.sstatic.net/MTXBL.png

4. My Challenge

I have now added the Angular HttClient to my AppComponent:

// app.component.ts

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  title = 'frontend';
  constructor(private http: HttpClient) {}
}

Furthermore, I included the HttpClientModule in both app.module.ts and in the imports section of app.component.spec.ts.

// app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, AppRoutingModule, HttpClientModule],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
// app.component.spec.ts

import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
import { HttpClientModule, HttpClient } from '@angular/common/http';

describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule, HttpClientModule],
      declarations: [AppComponent],
    }).compileComponents();
  }));

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  });

  it(`should have as title 'frontend'`, () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app.title).toEqual('frontend');
  });

  it('should render title', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('.content span').textContent).toContain('frontend app is running!');
  });
});

However, upon running jest, I encountered the following errors:

$ jest
 FAIL  src/app/app.component.spec.ts
  AppComponent
    ✕ should create the app (449ms)
    ✕ should have as title 'frontend' (10ms)
    ✕ should render title (10ms)

  ● AppComponent › should create the app

    Can't resolve all parameters for AppComponent: (?).

      at syntaxError (../../../packages/compiler/src/util.ts:100:17)
      at CompileMetadataResolver._getDependenciesMetadata (../../../packages/compiler/src/metadata_resolver.ts:957:27)
      at CompileMetadataResolver._getTypeMetadata (../../../packages/compiler/src/metadata_resolver.ts:836:20)
      at CompileMetadataResolver.getNonNormalizedDirectiveMetadata (../../../packages/compiler/src/metadata_resolver.ts:377:18)
      ...

...

...

...

...

Test Suites: 1 failed, 1 total
Tests:       3 failed, 3 total
Snapshots:   0 total
Time:        1.682s, estimated 2s
Ran all test suites.
error Command failed with exit code 1.

While the tests function properly with Jasmine + Karma, there appears to be an issue related to dependency injection while utilizing jest for testing.

You can access the repository here: https://github.com/flolude/stackoverflow-monorepo-angular-jest/commit/9a2d8cac0dfa25a5f6620f38238c3f577b2acb63 to explore it yourself.

Answer №1

To ensure that the metadata is not lost during TypeScript transpilation, simply set the emitDecoratorMetadata to true in your tsconfig.spec.json.

An unexpected issue arose for the developer of jest-preset-angular after updating Angular to version 8.1. By making this adjustment, you can prevent such problems.

For more information on this issue and how to resolve it, visit the GitHub page for jest-preset-angular: https://github.com/thymikee/jest-preset-angular/issues/288

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

It appears that the Angular 2 HTTP header is being produced or transmitted erroneously

Trying to send a request to my backend that uses HTTP Basic authentication for testing purposes. username: user password: password The correct header should be: Authorization: Basic dXNlcjpwYXNzd29yZA== Request tested with this header in Chrome Advance ...

Organizing files in an ExpressJs project with Angular2

What is the conventional file structure for a mix of ExpressJs and Angular2 projects? Here's my current setup: Project | |--bin |--node_modules |--public |--images |--javascripts |--stylesheets |--routes |--views |--app.js |-- ...

Utilize Lambda Layer to seamlessly share interfaces/types across Lambda Functions

I have a lambda layer file that contains an enum definition (which will be used in various lambda functions) as shown below: exports enum EventTypes { Create, Delete, Update, } Initially, everything was working well as I tested ...

Selecting ion-tabs causes the margin-top of scroll-content to be destroyed

Check out the Stackblitz Demo I'm encountering a major issue with the Navigation of Tabs. On my main page (without Tabs), there are simple buttons that pass different navparams to pre-select a specific tab. If you take a look at the demo and click t ...

When utilizing the ngFor directive with the keyvalue pipe, an error occurs stating that the type 'unknown' cannot be assigned to the type 'NgIterable<any>'

I'm attempting to loop through this object { "2021-11-22": [ { "id": 1, "standard_id": 2, "user_id": 4, "subject_id": 1, "exam_date": "2021-11-22" ...

How do RxJS collection keys compare?

Is there a more efficient way to compare two arrays in RxJS? Let's say we have two separate arrays of objects. For example: A1: [{ name: 'Sue', age: 25 }, { name: 'Joe', age: 30 }, { name: 'Frank', age: 25 }, { name: & ...

How do I define two mutations in a single component using TypeScript and react-apollo?

After exploring this GitHub issue, I have successfully implemented one mutation with Typescript. However, I have been unable to figure out how to use 2 mutations within the same component. Currently, there is only a single mutate() function available in t ...

Using a jQuery plugin with Angular 4 and Webpack is proving to be quite challenging

Having trouble using a jQuery plugin with Angular 4 and webpack. It works with angular cli but not with webpack. I have included the plugin in webpack.config.vendor.js const treeShakableModules = [ ..... '@angular/router', 'zone ...

How can I place an Object in front of an Array in JavaScript?

Currently, I am working on an Angular project where I need to modify a JSON array in order to display it as a tree structure. To achieve this, the objects in the array must be nested within another object. Desired format / output: this.nodes = [ { id ...

Steps for displaying detailed information about a single product on an Ecommerce page

Currently in the process of developing my Ecommerce project, I have successfully created a product grid with links to each specific product. However, I am facing an issue where I am unable to view the data of each individual item. Below is the code for my ...

What's the alternative now that Observable `of` is no longer supported?

I have a situation where I possess an access token, and if it is present, then I will return it as an observable of type string: if (this.accessToken){ return of(this.accessToken); } However, I recently realized that the of method has been deprecated w ...

Surprising fraction of behavior

Looking for some clarification on the types used in this code snippet: interface UserDTO { id: string; email: string; } const input: Partial<UserDTO> = {}; const userDTO: Partial<UserDTO> = { id: "", ...input }; const email = us ...

Encountering issues while trying to run npm install for an Angular 7 application, specifically receiving an error stating: "Module not found: @angular-devkit/build-ng-packagr." This error is hindering

I don't have much experience with JavaScript, node, npm, Angular, etc. My expertise lies in TypeScript as I am still a beginner. However, I recently inherited an application that requires maintenance to resolve a cross-site cookie issue. As I attempt ...

Guide on showing a placeholder image in Angular2 when the image is missing

I am trying to figure out how to display a default image when the image source coming from the backend is null. Can someone assist me with this issue? If the image part is null, then I want to display the following image: "../assets/images/msg.png" Conso ...

Invoking vscode Extension to retrieve data from webview

One task I'm currently working on involves returning a list from the extension to be displayed in the input box of my webview page. The idea is for a JavaScript event within the webview to trigger the extension, receive the list object, and then rend ...

Tips for utilizing array.items in joiful validation?

Can someone provide an example code or a link on how to correctly use the joyful validation for array items? I attempted the array.items validation code using joyful, but I am not sure how to specify the items. Thanks in advance! ...

What is the best way to retain all checkbox selections from a form upon submission?

I have a batch of checkboxes that correspond to the profiles I intend to store in the database. HTML: <tr *ngFor="let profile of profiles | async"> <input type='checkbox' name="profiles" value='{{profile.id}}' ng-model=&apo ...

Steps to obtain the download URL from AngularFireStorage after uploading the file using the getDownloadUrl() method

After successfully uploading images into my firebase storage, I want to retrieve the downloadURL and add it to my firestore database. When console logging "url", I am able to see the desired link. However, I am facing difficulties in using it. When attemp ...

Enhance your images with the Tiptap extension for customizable captions

click here for image description I am looking to include an image along with an editable caption using the tiptap extension Check out this link for more information I found a great example with ProseMirror, but I'm wondering if it's possible ...

The custom pattern validation for Formly Email is malfunctioning

Is there a way to validate email input using ngx-formly? I attempted the code below but it didn't work as expected app.module.ts export function EmailValidator(control: FormControl): ValidationErrors { return /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a ...