question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Object property order and deep equals: expected behavior?

See original GitHub issue

Fantastic library. Thank you!!!

I have a question about object comparison. I’m using @ngrx/effects in an Angular project. I’m using Jest as my testing framework. I have a class called UserEffects that listens for login attempts and deals with the side effects:

@Injectable()
export class UserEffects {
  // Listen for and handle login events
  @Effect() login$: Observable<Action> = this.action$.pipe(
    ofType('[User] Start Login'),
    mergeMap(() => this.auth.login().pipe(
      map((res: AuthResult) => ({ type: '[User] Successful Login', payload: res })),
      catchError(() => of({ type: '[User] Failed Login' }))
    ))
  );
  constructor(private action$: Actions, private auth: AuthService) {}
}

I’ve also got a bunch of helper classes that inherit from Action that can be used to generate actions, e.g.

export class LoginSuccess implements Action {
  readonly type = UserActionTypes.LoginSuccess;
  constructor(public payload: AuthResult) {}
}

My DESIRED test looks like this:

it("should catch login attempts", marbles((m) => {
  const authRes = { accessToken: '12345', idToken: '67890', refreshToken: 'abcde' } as AuthResult;
  const loginStart = new UserActions.LoginStart();
  const loginSuccess = new UserActions.LoginSuccess(authRes); // <-- THIS DOES NOT WORK
  action$        = m.cold("a---", { a: loginStart } );
  const response = m.cold("--r-", { r: authRes } );
  const expected = m.cold("--b-", { b: loginSuccess } );
  auth.login = jest.fn(() => response);

  m.expect(fx.login$).toBeObservable(expected);
}));

However, when I run this test, I get output that looks like this:

    Expected
    	{"frame":20,"notification":{"kind":"N","value":{"type":"[User] Successful Login","payload":{"accessToken":"12345","idToken":"67890","refreshToken":"abcde"}},"hasValue":true}}

    to deep equal
    	{"frame":20,"notification":{"kind":"N","value":{"payload":{"accessToken":"12345","idToken":"67890","refreshToken":"abcde"},"type":"[User] Successful Login"},"hasValue":true}}

If you look at these closely, you can see that the ONLY difference between the actual and expected values is the order of the properties. If I re-write my test like this…

it("should catch login attempts", marbles((m) => {
  const authRes = { accessToken: '12345', idToken: '67890', refreshToken: 'abcde' } as AuthResult;
  const loginStart = new UserActions.LoginStart();
  const loginSuccess = { type: '[User] Successful Login', payload: authRes }; // <-- THIS WORKS!!
  action$        = m.cold("a---", { a: loginStart } );
  const response = m.cold("--r-", { r: authRes } );
  const expected = m.cold("--b-", { b: loginSuccess } );
  auth.login = jest.fn(() => response);

  m.expect(fx.login$).toBeObservable(expected);
}));

…my tests pass.

Is there any way to specify a different function for performing object comparison? I expect that there’s some way I could use configure() or marbles() to specify this, but I couldn’t quite figure it out.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
cartantcommented, Mar 6, 2018

If you are using Jest, you might want to try it with Jest’s matchers. See this issue: https://github.com/cartant/rxjs-marbles/issues/13.

0reactions
cartantcommented, Mar 6, 2018

Glad it’s solved.

However, I don’t know what could have been happening, as I’ve added a test that uses class instances - https://github.com/cartant/rxjs-marbles/commit/3a3cb4074df05d675d510ff18caa670861b612e8 - and it’s fine.

Anyway, the Jest matchers effect much nicer output.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Object comparison in JavaScript [duplicate] - Stack Overflow
JavaScript allows both null and undefined properties and objects have prototypes chains that can lead to very different behaviors if not checked.
Read more >
Object graph comparison - Fluent Assertions
To determine whether Fluent Assertions should recurs into an object's properties or fields, it needs to understand what types have value semantics and...
Read more >
Testing Arrays and Objects with Chai.js | by Titus Stone
Deep equality is an excellent approach, but it enforces both order and contents when comparing arrays. Often the case arises in testing where ......
Read more >
Dart Compare two objects – how to deep equal
This article explains how to compare two objects in Dart. How can we implement if we want to do deep equal? What is...
Read more >
Equality comparisons and sameness - JavaScript | MDN
== — loose equality (double equals); Object.is(). Which operation you choose depends on what sort of comparison you are looking to perform.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found