Angular - failure to detect function execution by spy

I've been trying to test a feature module, but I'm facing some difficulties. The last test is failing because the spy isn't detecting that the method is being called, even when I move the

this.translate.use(this.currentLanguage.i18n)
call outside of the subscribe block.

This is the code for the feature component:

export class LanguagesComponent implements OnDestroy, OnInit {

  public languages = [
    {
      id: '0',
      name: this.translate.stream('LANGUAGES.SWEDISH'),
      i18n: 'sv',
      flag: {
        src: './assets/img/sv.svg'
      }
    },
    {
      id: '1',
      name: this.translate.stream('LANGUAGES.ENGLISH'),
      i18n: 'en',
      flag: {
        src: './assets/img/en.svg'
      }
    }
  ];

  public currentLanguage: any;

  private storageSubscription: Subscription;

  constructor(
    private cs: ClientStorage,
    private notifications: NotificationsApi,
    private router: Router,
    private translate: TranslateService
  ) {}

  ngOnInit() {

    const storedLanguage: any = this.cs.getItem(AppConstants.currentLanguage);

    this.currentLanguage = FindObjectByQuery(this.languages, 'i18n', storedLanguage);

    // Listen for changes in language from sources other than this component
    this.storageSubscription = this.cs.logger$
      .filter(data => data && data.key === AppConstants.currentLanguage)
      .subscribe((currentLanguage: any) => {

        if (currentLanguage) {

          this.currentLanguage = FindObjectByQuery(this.languages, 'i18n', currentLanguage.value);

          // Set the current language to use
          this.translate.use(this.currentLanguage.i18n);
        }
      }
    );
  }

  ngOnDestroy() {
    this.storageSubscription.unsubscribe();
  }

  selectLanguage(language: any): void {

    this.cs.setItem(AppConstants.currentLanguage, language.i18n);

    this.router.navigate(['dashboard']);

    this.notifications.newNotification({message: this.translate.instant('NOTIFICATIONS.LANGUAGES.CHANGED'), theme: 'success'});
  }
}

These are my current tests:

describe('[UNIT] LanguagesComponent', () => {

  let component: LanguagesComponent;
  let fixture: ComponentFixture<LanguagesComponent>;
  let translate: Location;

  beforeEach(() => {

    TestBed.configureTestingModule({
      imports: [
        ModuleImports
      ],
      providers: [
        TranslateService
      ],
      schemas: [NO_ERRORS_SCHEMA],
      declarations: [LanguagesComponent, DummyComponent]
    });

    fixture = TestBed.createComponent(LanguagesComponent);
    component = fixture.componentInstance;
    translate = TestBed.get(TranslateService);

    // Ensure ngOnInit runs
    fixture.detectChanges();
  });

  it('should create the component', async(() => {
    expect(component).toBeTruthy();
  }));

  it('should have a current language when the component has loaded', () => {
    expect(component.currentLanguage).toBeTruthy();
  });

  it('should have the necessary properties in the current language object', () => {

    const currentLanguage = component.currentLanguage;

    expect(currentLanguage.id).toBeTruthy();
    expect(currentLanguage.name).toBeTruthy();
    expect(currentLanguage.i18n).toBeTruthy();
    expect(currentLanguage.flag.src).toBeTruthy();
  });

  it('should trigger the use method of TranslateService with the current language i18n value', () => {

    const spy = spyOn(translate, 'use').and.callThrough();

    expect(spy).toHaveBeenCalledWith(component.currentLanguage.i18n);
  });
});

Answer №1

During your test scenario, you set up a spy but then attempted to verify a call immediately afterwards. However, no call was recorded.

To address this issue, there are two possible solutions:

  1. Ensure that you place the spyOn before making any changes with fixture.detect in the beforeEach block.
  2. After creating the spy, activate the appropriate method that should trigger the expected call. In this case, make sure to execute fixture.detectChanges.

Please note: I have not checked your tests for any other issues aside from the main problem of the missing call between spy creation and usage.

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

Tips for achieving server-side pagination with client-side sorting

Currently utilizing Angular Material's data grid, successfully loading data from the server side with sorting and pagination functionality. However, I am attempting to sort only the items visible on the table instead of sorting from the server side. ...

Understanding how to extract and utilize the display name of enums from a C# Web API within an Angular

Within my C# web API, I have established an enum with a designated display name: public enum Countries { Australia, [Display(Name="New Zealand")] NewZealand } To showcase this list in a dropdown menu within my Angular project, I transmit ...

Issue encountered while defining a component in Angular 16

Currently, I am in the process of learning Angular by following the tutorial provided on Angular.io. As part of this journey, I have declared a home component within my Angular application using the given code: ng generate component home --standalone --in ...

The error message you are encountering is: "Error: Unable to find function axios

Can't figure out why I'm encountering this error message: TypeError: axios.get is not functioning properly 4 | 5 | export const getTotalPayout = async (userId: string) => { > 6 | const response = await axios.get(`${endpoint}ge ...

Issue with handsontable numbro library occurs exclusively in the production build

Encountering an error while attempting to add a row to my handsontable instance: core.js.pre-build-optimizer.js:15724 ERROR RangeError: toFixed() digits argument must be between 0 and 100 at Number.toFixed () at h (numbro.min.js.pre-build-op ...

Angular Universal in combination with AngularFire server experiences a hanging issue due to the first() pipe

I am currently developing an angular/firestore application that requires SSR capabilities. I have integrated angular universal into the project and everything seems to be functioning properly until I utilize the first() pipe on any of the firestore calls, ...

Error in AngularX TS: Trying to invoke a type that does not have a callable signature

Encountering an issue while working on a component, specifically during ng serve/build process. Please note that this error is different from any console errors, despite what some may think. The expected outcome is for the code to successfully build and ru ...

Implementation of a nested interface using a generic and union types

I am seeking to create a custom type that will enable me to specify a property for a react component: type CustomType<T> = { base: T; tablet?: T; desktop?: T; }; export type ResponsiveCustomValue<T> = CustomType<T> | T; This ...

Exploring the Power of SectionList in Typescript

How should SectionList be properly typed? I am encountering an issue where this code works (taken from the official documentation example): <SectionList renderItem={({item, index}) => <Text key={index}>{item}</Text>} renderSectionHea ...

Tips for incorporating child components when creating unit tests in Angular 2

While working on my component, I encountered an issue with the child component during unit testing. An error message is appearing stating that the child component is not defined. Any advice or solutions would be greatly appreciated. Thank you in advance. ...

Troubleshooting problem with Angular Click Outside Directive and unexpected extra click event issue

The challenge I'm facing involves implementing a custom Click Outside Directive for closing modal dialogs, notifications, popovers, and other 'popups' triggered by various actions. One specific issue is that when using the directive with pop ...

Guide on toggling the visibility of two child components using *ngif in Angular 4 without losing the data

Is there a way to preserve data in my child component while using *ngIf to show and hide? I am unable to utilize the [hidden] attribute. <div id="parentcomponent"> <child1 *ngif="child1"></child1> <child2 *ngif="child2"></chi ...

Issue encountered while incorporating a dynamic field in Angular 5

My goal is to dynamically add a row of fields when the add button is clicked. While this functionality works fine, I encounter an issue where clicking the add button clears the values in the first row and adds a new row instead. Below is the code snippet I ...

Guide to displaying the value of a field in an object upon clicking the inline edit button using TypeScript

Is it possible to console log a specific attribute of an object when clicking on the edit button using the code below? Please provide guidance on how to utilize the index to access the value of "name". Refer to the last line in the code with the comment. ...

Unveiling the magic behind using jasmine to spy on a generic

I am trying to spy on a generic method in TypeScript, but Jasmine is not recognizing it. Here is the code snippet: http: HttpClient <- Not actual code, just showing type. ... this.http.get<Customer[]>(url); In this code, I am trying to mock the ...

New feature in Chrome allows credit card suggestions to be displayed in the name input field

On one specific page of my angular app, I have an input field for a name that is showing credit card suggestions. When I disable the autofill for credit cards in Chrome settings, it then shows suggestions for names instead. However, on another page with ...

Exploring the world of interfaces in nested mapping functions

Currently, I'm faced with the challenge of mapping an array inside another map with an array. These are the specific interfaces that I am working with: interface Props { columns: Array<{field: string, headerName: string, width: number}>; row ...

Item removed from the cache despite deletion error

Currently, I am utilizing Angular 8 along with @ngrx/data for handling my entities. An issue arises when a delete operation fails (resulting in a server response of 500), as the entity is being removed from the ngrx client-side cache even though it was not ...

Stop repeated form submissions in Angular using exhaust map

How can we best utilize exhaust Matp to prevent multiple submissions, particularly when a user is spamming the SAVE button? In the example provided in the code snippet below, how do we ensure that only one submission occurs at a time even if the user click ...

Unexpected output from nested loop implementation

Having some arrays, I am now trying to iterate through all tab names and exclude the values present in the exclusion list. json1 ={ "sku Brand": "abc", "strngth": "ALL", "area ...