How do I debug a "[object ErrorEvent] thrown" error in my Karma/Jasmine tests?
Asked Answered
S

17

117

I have several failing tests that only output [object ErrorEvent] thrown. I don't see anything in the console that helps me pinpoint the offending code. Is there something I need to do to track these down?

[EDIT]: I'm running Karma v1.70, Jasmine v2.7.0

Stunt answered 16/8, 2017 at 20:14 Comment(6)
Can you include more of the error? Like multiple lines of the error before and after?Shirring
[object ErrorEvent] thrown is literally all it says. There is nothing before or after.Stunt
As luck would have it, I just got this issue literally the same time you were posting this question, it turned out to be a "rogue" script tag (it could also be css link) which needed to be removed (my issue was related to CORS), or in case of css, I just added crossorigin="anonymous". Check your code for such script/css tags, in my case I found the issue to be caused by a totally different component!Intermission
are you on angular cli aren't you? @DarrellBrogdonCanter
@Intermission How did you narrow down this script? Line by line? Or was there some debug process that helped you narrow down where it was? I'm having the same issue and the only info I have to go on is the message: An error was thrown in afterAll. If I isolate the test itself by changing it() to fit(), even though only that single test is running, the error is still being thrown. Any debug recommendations for this type of error?Amitosis
Have you tried importing HttpClientTestingModule to your unit test? That's what worked for my case.Redingote
C
126

FYI: you can find the exact error thrown just by open DevTools Console once your tests are running.

As a quickfix you can try to run your tests without sourcemaps:

CLI v6.0.8 and above
--source-map=false

CLI v6.0.x early versions
--sourceMap=false

CLI v1.x
--sourcemaps=false

Shortcut ng test -sm=false might also work

There is an open issue on that https://github.com/angular/angular-cli/issues/7296

UPDATE: I had that issue as well, so I just migrated to the latest cli and make sure that all packages are updated in package.json also I fully reinstalled the node_modules so now the issue has gone.

Canter answered 19/10, 2017 at 23:18 Comment(6)
this worked for me. It helped reveal that the problem was with an undefined input binding.Sociability
As of Angular 6 --sourcemaps option is not present.Pskov
For angular-cli 6, --sourceMap=false seems to work.Indelicacy
typical front solutionAssistant
This solution doesn't work anymore. It used to, but in 6.2.4 it doesn'tStereoscope
I get Uncaught [object Object] thrown in random components and in some runs I get nothing... :S I hate Angular Testing.Maidenhood
F
53

If sourcemap=false doesn't help, try to 1) open your browser running the tests 2) click debug button 3) open the console

The error will be there

enter image description here

Futures answered 19/7, 2018 at 10:52 Comment(4)
I didn't even need to click the debug button. Just opening developer console worked for me.Lamond
Brilliant! I added the sourcemap option everywhere, but in the end this gave me the info I neededGuarneri
The --sourcemaps=false thing wasn't working for me, but this worked flawlessly! Thank you!Foreknow
Doesn't really help if the browser closes right after the test. Guess I'll write a bunch of useless tests to keep the window open, like some kind of caveman.Stutzman
F
24

Try if you get a more descriptive error message by running the test from the terminal, like this:

ng test -sm=false

In your test, you can replace

it('should...')

with

fit('should...') 

Now only tests preceded by fit will run. To leave the browser open after running the test, run the test like this:

ng test -sm=false --single-run false

Personally, I have encountered this error twice. Both were only triggered when calling fixture.detectChanges().

The first time, I solved it by using string interpolation more safely in my .html file.

Unsafe example:

<p>{{user.firstName}}</p>

Safe(r) example (note the question mark):

<p>{{user?.firstName}}</p>

The same may apply to property binding:

<p [innerText]="user?.firstName"></p>

The second time, I was using a DatePipe in my .html file, but the mock property that I used it on was not a date.

.html file:

<p>{{startDate | date: 'dd-MM-yyyy'}}</p>

.ts (mock-data) file (wrong):

let startDate = 'blablah';

.ts (mock-data) file (correct):

let startDate = '2018-01-26';
Forgotten answered 26/1, 2018 at 16:13 Comment(2)
Any comment why '?' string interpretation is safer? This work in my scenario.Puss
@DylanKapp this checks if the object is null before trying to read the object's property. See angular.io/guide/template-syntax#safe-navigation-operator for more details.Luthuli
A
18

This is because the jasmine framework can not handle the ErrorEvent type so it does not extract the error message and calls error.toString() on that object instead.

I just filed an issue at jasmine repo https://github.com/jasmine/jasmine/issues/1594

As long as it is not fixed, you can temporarily patch your installed jasmine package in the node_modules folder. In my case it is

node_modules/jasmine/node_modules/lib/jasmine-core/jasmine.js

and then change the implementation of the ExceptionFormatter from this

if (error.name && error.message) {
    message += error.name + ': ' + error.message;
} else {
    message += error.toString() + ' thrown';
}

to this

if (error.name && error.message) {
    message += error.name + ': ' + error.message;
} else if (error.message) {
    message += error.message;
} else {
    message += error.toString() + ' thrown';
}

It helps to identify the issue.

Amanuensis answered 23/8, 2018 at 8:34 Comment(3)
This worked for me in [email protected]. However, I had to patch it in node_modules/jasmine_core/lib/jasmine_core/jasmine.jsSyzran
So good - took a minute to find this post but it saved my butt. Thanks. Same jasmine-core versionSubsellium
After changing this, it only printed uncaught for me which wasn't helpful. So I added code to print error object and its properties. if(error){ // message+=error; for(var propName in error) { propValue = error[propName] message+='error prop: '+propName+', value: '+propValue; } } . This provided extra info which helped me in debugging - egerror prop: filename, value: blob:http://localhost:9881/11777e3a-28d8-414e-9047-cee7d328e843Trapeze
V
7

For me it was related to having a promise resolved in the ngOnInit of a component. I had to use async, fakeAsync and tick as well as stubbing out the async service with spyOn

beforeEach(async(
  //... initialise testbed and component
))
beforeEach(fakeAsync(
  // ... setup mocks then call:
  component.ngOnInit()
  tick()
  fixture.detectChanges()
))

Angular - How to unit test component with asynchronous service call

Various answered 12/1, 2018 at 6:39 Comment(0)
S
4

TL;DR: It may be related to testing routing.

I'm getting [object ErrorEvent] thrown too. An hour later, traced it to one line of code.

this.username = this.userService.getUser(this.route.snapshot.paramMap.get('id'))[0];

The problem lies with the test environment attempting to evaluate this.route.snapshot.paramMap.get('id').

If I replace it with 0, [object ErrorEvent] thrown goes away.

My userService has a user like so:

public users = [ ["admin", "First name", "Surname", etc... ] ].

So 0 just gets this user, at index 0.

Otherwise when normally running my app, this.route.snapshot.paramMap.get('id') is evaluated when the user selects a user to edit from my table of users.

So in my HTML, *ngFor="let user of users; index as i" loops to display all the users then routerLink="/edit/{{i}}" so you can click on edit buttons for each user, which when clicked go to e.g. http://localhost:4200/edit/0 to edit the aforementioned admin user's details.

Sororate answered 4/12, 2017 at 19:19 Comment(0)
C
4

what about cleaning after each test case:

  afterEach(() => {
    TestBed.resetTestingModule();
  })
Cementation answered 21/7, 2018 at 10:14 Comment(2)
I read somewhere that the TestBed is reset anyway for each test.Numbersnumbfish
I my case it helped clean-up for next tests.Cementation
T
3

For me, this was caused by not defining an error handler for an api I was subscribed to.

My fix just involved adding the block of code to handle (err) below:

it('reports an error to subscribers of api calls if not authenticated', (done) => {
    let obsDataFound = dataService.find(1);
    obsDataFound.subscribe((app) => {
        // not expecting this block to be called
        done();
    }, (err) => {
        // This is the err block that I added that solved the problem
        expect(true).toBeTruthy();
        done();
    });

    let testRequest = httpMock.expectOne({method: 'GET'});
    const mockErrorResponse = { status: 401, statusText: 'Unauthorized test status message' };
    testRequest.flush(appTest, mockErrorResponse);
});
Tertias answered 3/10, 2020 at 1:38 Comment(1)
This was my case also, I was multicasting and one of the subscribers was not handling the error.Lordship
K
1

I had the same problem. One way this error happens is when you try to access anything null or undefined in template. Make sure you have safety checking on those variable.

For example this will throw [object: ErrorEvent] when config is undefined on component load.

template.html

<div *ngIf="config.options">
   .....
   ......
</div>

Do this instead

<div *ngIf="config?.options">
   .....
   ......
</div>
Kluge answered 15/6, 2018 at 15:33 Comment(0)
L
1

What can help is, if you have the Chrome window open for your Karma test runner, to open the developer tools and check the console there. For me, this helped me to find out that the app could not use the Array.findIndex method on an undefined array (because the data structure was organized by a date string, such as data[2018][3][28], and I happened to be pointing to the wrong date), but yet instead of just stopping at the error, the test kept running.

Lockage answered 8/1, 2019 at 14:53 Comment(1)
Thanks a bunch! I would have expected the info to be present in the console, you saved a couple of hours of my life :)Cartomancy
M
0

You may have a race or an async test that isn't set up quite right or is used incorrectly. I would assume that the debug case needs to be fixed and ignore that the command line passes. Just keep refreshing the karma test runner (browser) in case the error [object ErrorEvent] thrown appears intermittently, then make sure you have implemented the async condition correctly.

Hopefully this works.

Mongol answered 19/1, 2018 at 8:8 Comment(0)
K
0

For me the issue was that I had a test where I was accidentally using the auth0-lock library.

Klimt answered 7/3, 2018 at 13:29 Comment(0)
P
0

It appeared to be an async problem, because after I added enough its in one of my component specs, I was able to get a usable error message which pointed to a file and line within that file (it was related to paramMap.

In the spec that tested ParamMap, I just added:

  describe('this test', () => {
    it('will succeed', () => {
      expect(true).toBeTruthy();
    });

    it('will succeed', () => {
      expect(true).toBeTruthy();
    });

    it('will succeed', () => {
      expect(true).toBeTruthy();
    });

    it('will succeed', () => {
      expect(true).toBeTruthy();
    });
  });
Parthenopaeus answered 22/6, 2018 at 17:0 Comment(0)
F
0

[object ErrorEvent] thrown

This error shows that you have something undefined. The easiest way to debug it from my experience is :

it('should create', () => {
    console.log(component);
    // You can check in the browser log which property is undefined
    });
Fulvi answered 29/10, 2018 at 8:21 Comment(1)
This has actually turned out to be the most useful reminder of all: in my tests I have a mock authentication service, that missed a method. Seemingly unrelated, one of the tests in a component failed, but not when isolated. I have tracked the obscure [object ErrorEvent] thrown down to that remote missing method only thanks to the console.log :)Severe
D
0

In my case the problem was with the service, as one of the object wil be undefined during tests running.

Service code sample was something like below access to dom,

  const elem = this.document.querySelector(element) as HTMLElement;
  elem.scrollIntoView({param1: ''});

The specs referring to this service were failing with the error '[object ErrorEvent] thrown'.

I mocked my service object inside all the specs which were referring to this and the issue got resolved.

Mock service

class MockService {
serviceMethod(div) : void {
  testElement = document.querySelector('div') as HTMLElement;
  return testElement;
  } 
}

And use this mock service object in providers as below,

beforeEach(async(() => {

TestBed.configureTestingModule({
  declarations: [Component],
  providers: [
     { provide: Service, useClass: MockService },
    ],
})
  .compileComponents();
}));
Denary answered 31/10, 2018 at 5:21 Comment(0)
S
0

I was using a proxy in my application defined in proxy.conf.json like:

'/api': { 'target': 'some path', 'changeOrigin': false }

Because Karma wasn't aware of this proxy, it kept trowing errors in the console that the API endpoint could not be found. So after looking in the Karma documentation, I found out that what I could do was to add the "proxies" property in karma.conf.js with the same object from the proxy.conf.json:

proxies: { '/api': { 'target': 'some path', 'changeOrigin': false }}

The error in the console was gone, and the [object errorEvent] was no longer thrown.

Semination answered 23/1, 2019 at 9:26 Comment(0)
C
-1

In the end, what can worked for me:

    TestBed.resetTestingModule();
  })
Colp answered 19/2, 2019 at 14:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.