1

How can I test this method with postMessage

navigateTo = (): void => {
    window.parent.postMessage('NESTED_NAVIGATION', 'target_origin');
}

I want to check if the postMessage event is fired when I call the navigateTo method

I tried this but didn't work

it('should post message on click', async () => {
   spyOn(component, 'navigateTo');
   let postMessageSpy = spyOn(window.parent, 'postMessage');
   component.navigateTo();
   expect(postMessageSpy).toHaveBeenCalled();
});
Lin Du
  • 88,126
  • 95
  • 281
  • 483
rennajihi
  • 443
  • 1
  • 6
  • 17
  • Have you tried injecting the window so that you can spy on it instead? https://stackoverflow.com/a/52620181/973651 (there's a few options in the answers) – Mathew Berg Dec 21 '21 at 19:26
  • When you apply `spyOn` on a method (`navigateTo`) without calling `.and.callThrough()`, that method becomes a stub meaning its actual content is not being invoked in your example. Other than that, you do not need at all to spy on `navigateTo`, you need it to be invoked as is (after all, that is the method you want to test). – desertech Dec 24 '21 at 19:03

1 Answers1

3

You are testing the component.navigateTo() method, so you should NOT use spyOn for it. Otherwise, the window.parent.postMessage() will never be called. You should use spyOn for window.parent.postMessage() method.

From the Default Spy Strategy

Normally, the default strategy is .and.stub(), which returns undefined if the spy is called.

So the correct test code should be:

example.component.ts:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'example',
})
export class ExampleComponent implements OnInit {
  ngOnInit() {}
  navigateTo = (): void => {
    window.parent.postMessage('NESTED_NAVIGATION', 'target_origin');
  };
}

example.component.test.ts:

import { ExampleComponent } from './example.component';

describe('70440045', () => {
  it('should post message on click', async () => {
    const component = new ExampleComponent();
    let postMessageSpy: jasmine.Spy<(message: any, targetOrigin: string, transfer?: Transferable[]) => void> = spyOn(
      window.parent,
      'postMessage',
    );
    component.navigateTo();
    expect(postMessageSpy).toHaveBeenCalledWith('NESTED_NAVIGATION', 'target_origin');
  });
});

We specify the overload signature of postMessage to avoid TS type errors.

Test result:

Chrome Headless 95.0.4638.69 (Mac OS 10.15.7): Executed 1 of 1 SUCCESS (0.008 secs / 0.004 secs)
TOTAL: 1 SUCCESS

=============================== Coverage summary ===============================
Statements   : 94.12% ( 16/17 )
Branches     : 100% ( 0/0 )
Functions    : 62.5% ( 5/8 )
Lines        : 100% ( 13/13 )
================================================================================

package version:

"@angular/core": "~11.0.3",
"@angular/cli": "~11.0.3",
"karma-jasmine": "~4.0.0",
"karma": "~5.1.0",
"jasmine-core": "^3.10.1"
Lin Du
  • 88,126
  • 95
  • 281
  • 483