Testing the addition of a dynamic class to an HTML button using Jasmine unit tests

I am brand new to Jasmine and currently in the process of grasping how to write Unit tests for my components in Angular 4. One issue I encountered is when I attempt to add a class to the button's classList within the ngOnInit() lifecycle hook of the Component, the test fails with an error stating "cannot find property 'classList' of null." This is my current approach.

Component.ts

ngOnInit() {
  document.querySelector('.button-visible').classList.add('hidden');
}

This is the scenario I'm aiming to address in my spec ts file.

Component.spec.ts

describe('AppComponent', () => {
 let component = AppComponent;
 let fixture: ComponentFixture<AppComponent>;
 let compiledElement;
});

beforeEach(async(() => {
 TestBed.configureTestingModule({
  declarations: [AppComponent]
  .....
}).compileComponents(); 
}));

beforeEach(() => {
 fixture = TestBed.createComponent(AppComponent);
 component = fixture.componentInstance;
 compiledElement = fixture.debugElement.nativeElement;
 fixture.detectChanges();
});

it('should create component', () => {
 expect(compiledElement.querySelector('button.button-visible').classList).toContain('hidden');
 expect(component).toBeTruthy();
});
});

I am struggling to determine the correct testing approach. Any assistance would be greatly appreciated.

Answer №1

When testing a component that relies on external elements, you'll need to set up a test environment that includes all necessary items. In this scenario, create a test harness with a test component containing a DOM node styled with the button-visible class.

You can easily create a test component within your test spec like so:

@Component({
  template: `
    <button class="button-visible">Test Button</button>
    <app-component></app-component>
  `,
})
class TestHostComponent {
}

Adjust your test setup to incorporate and utilize this new test component:

describe('AppComponent', () => {
  let fixture: ComponentFixture<TestHostComponent>;
  let testHostComponent: TestHostComponent;
  let component: AppComponent;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [AppComponent, TestHostComponent]
      .....
    }).compileComponents(); 
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(TestHostComponent);
    testHostComponent = fixture.componentInstance;
    component = fixture.debugElement.query(By.directive(AppComponent)).componentInstance;
    fixture.detectChanges();
  });
});

Run your test to confirm if the button in the test component indeed has the specified class applied:

it('should add "hidden" class to HTML elements with "button-visible" class', () => {
  const buttonElement = fixture.debugElement.query(By.css('.button-visible.hidden'));
  expect(buttonElement).toBeTruthy();
});

Answer №2

Encountering a similar challenge while writing unit tests today led me to devise the following resolution:

describe('AppComponent', () => {
  let component = AppComponent;
  let fixture: ComponentFixture<AppComponent>;
  let compiledElement;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [AppComponent]
      .....
    }).compileComponents(); 
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    compiledElement = fixture.debugElement.nativeElement;
    compiledElement.innerHTML += "<button class='button-visible'>Test Button</button>";
    fixture.detectChanges();
  });

  it('should initialize component successfully', () => {
    expect(compiledElement.querySelector('button.button-visible').classList).toContain('hidden');
    expect(component).toBeTruthy();
  });
});

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

Having trouble retrieving response headers in Angular 5

After sending a post request to a server, I receive a response with two crucial headers for the client: username and access-token. The Chrome debug tool's Network Tab displays the data from the response like this: In addition, I attempt to log the re ...

Definition of a Typescript Global.d.ts module for a function that is nested within another function

Simply put, I have a npm module that exports a function along with another function attached to it: // @mycompany/module ... const someTool = (options) => { // do some cool stuff }; someTool.canUseFeature1 = () => { return canUseSomeFeature1(); ...

What is the best way to retrieve the parameter of ng2-file-upload using endback?

I am attempting to retrieve a parameter using PHP in order to save it into a folder. However, my code is not working as expected. Here is the code snippet: Using the Ionic framework this.uploader.onBeforeUploadItem = (item: any) => { this.uploader ...

We could not find the requested command: nodejs-backend

As part of my latest project, I wanted to create a custom package that could streamline the initial setup process by using the npx command. Previously, I had success with a similar package created with node.js and inquirer. When running the following comma ...

Looking for guidance on writing a JASMINE test case for my method. I've been struggling to mock the event listener. Can you please direct me to a relevant link or share some mock examples

Looking to create a jasmine test for the code snippet below... refreshCacheIfNewVersionIsAvailable(); //Function to check for a new cache version on page load and refresh the app cache if newer files are available function refreshCacheIfNewVersionIsAvail ...

Delivering an Angular2 application from a base URL using Express

I currently have an Angular2 application running alongside a simple express server. Is there a way to only display my application when a user navigates to a specific route, like '/app' for example? If so, how can this functionality be implemented ...

Angular 2 Route offers a blueprint for creating a Component template

Is it possible to assign a specific template to a component within a route in Angular 2? I am working on a component that has the same controller functionality across three different views. My goal is to use the same component for all three views, but wit ...

Extend the express request object with Typescript and then export the modified object

Seeking to enhance the Request object from express with custom fields using typescript. Based on this particular source, I created a file named @types/express/index.d.ts containing the following code : import { MyClass } from "../../src/MyClass" ...

Unable to persist AWS CDK ec2.Instance userData configuration

Trying to launch an ec2 instance with AWS CDK has been successful, but I am struggling to make the userData persistent so it runs on every boot. Despite searching extensively, I couldn't find any documentation on how to achieve this. The code below wo ...

The type 'Observable<void | AuthError>' cannot be assigned to 'Observable<Action>'

I am encountering an error that reads: error TS2322: Type 'Observable<void | AuthError>' is not assignable to type 'Observable<Action>'. Type 'void | AuthError' is not assignable to type 'Action'. Type &a ...

The issue is that TypeScript is indicating that the type 'string | string[]' cannot be assigned to the type 'string'

I recently upgraded to Angular 16 and encountered an issue with an @Input() property of type string | string[]. Prior to the upgrade, everything was functioning correctly, but now I am experiencing errors. I am uncertain about where I may have gone wrong i ...

Tips for optimizing Angular source code to render HTML for better SEO performance

Our web platform utilizes Angular JS for the front-end and node js for the backend, creating dynamic pages. When inspecting the code by viewing the source, it appears like this: For our business to succeed, our website needs to be SEO-friendly in order to ...

Strategies for preventing multi-level inheritance of TypeScript class properties and methods

In my current JavaScript class structure, the DataService is defined as follows: // data.service.ts export class DataService { public url = environment.url; constructor( private uri: string, private httpClient: HttpClient, ) { } ...

An issue has occurred where all parameters for the DataService in the D:/appangular/src/app/services/data.service.ts file cannot be resolved: (?, [object Object])

Upon running the command ng build --prod, an error is encountered. Error in data.service.ts: import { BadInput } from './../common/bad-input'; import { AppError } from './../common/app-error'; import { Injectable } from '@angular ...

Restricting the type of user input in HTML forms

Requirements: Input must be a whole number between 2 and 99, inclusive. Current Solution: <input required type="number" min="2" max="99" oninput="this.value = Math.abs(this.value)" maxLength="2" matInp ...

What is the best way to refresh or reload a child component in Angular?

I have a transaction.component.html file that displays the app-deal-partners component. Every time the delete function is triggered, I want to refresh and reload the child component, which is the app-deal-partners component. I need to reload <app-deal- ...

Exploring the Usage of Jasmine Testing for Subscribing to Observable Service in Angular's OnInit

Currently, I am facing challenges testing a component that contains a subscription within the ngOnInit method. While everything runs smoothly in the actual application environment, testing fails because the subscription object is not accessible. I have att ...

Getting a date object that is three months prior to the current date in Typescript

I need to retrieve the date object that is 3 months before the current date by using the following code snippet: toDate = new Date(); fromDate = this.toDate.getMonth() - 3; The issue I am facing is that the variable fromDate only contains a number, but I ...

Guide on how to switch a class on the body using React's onClick event

There's a button in my code that triggers the display of a modal-like div element. When this button is clicked, I aim to apply a class to the body element; then when the close button is clicked, I'll remove this class. I'm looking for guid ...

The issue with Angular version 15 p-dialogue not displaying HTML content when using a component selector

In my Angular application, I have an issue with rendering a component called urc.component from a different module (variance.module) inside another module (nursing-audit.module). The p-dialogue is opening and displaying the header correctly, but the urc.co ...