Skip to content

instances of different classes with same name should not be treated as equal #6767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
sirian opened this issue Jul 27, 2018 · 11 comments
Closed

Comments

@sirian
Copy link

sirian commented Jul 27, 2018

🐛 Bug Report

Look at example. We have two different classes but with the same name Client.

test("", () => {
    const MysqlClient = (function () {
        return class Client{};
    })();
    const HttpClient = (function () {
        return class Client{};
    })();
    
    const clients = [new MysqlClient()];
    expect(clients).toEqual([new HttpClient()]); // pass
    expect(clients).toStrictEqual([new HttpClient()]); // pass, but should not
});

Expected behavior

expect([new MysqlClient()]).toStrictEqual([new HttpClient()]); should fail

@palmerj3
Copy link
Contributor

The constructor is the same in this example. Only difference is ref.

@sirian
Copy link
Author

sirian commented Jul 31, 2018

Ok... More detailed example. @palmerj3

test("", () => {
    class Logger{constructor(level: number){}} // some external logger
    class XMLParser{constructor(file: string){}} // some external parser

    const FooLogger = class Foo extends Logger{};
    const FooParser = class Foo extends XMLParser{};

    const actual = new FooLogger(1);
    const expected = new FooParser("/tmp/1.xml");

    expect(actual).toEqual(expected); // pass 
    expect(actual).toStrictEqual(expected); // pass, but this is two absolutely different objects

    expect(actual).toEqual(new Logger(1)); // pass
    expect(actual).toStrictEqual(new Logger(1)); // fail, but this is more likely instances than logger and parser
});

@sirian
Copy link
Author

sirian commented Jul 31, 2018

At this moment type equality checks only name of constructor, rather than constructors itself
I think it's wrong.
https://github.com/facebook/jest/blob/master/packages/expect/src/utils.js#L215

export const typeEquality = (a: any, b: any) => {
  if (a == null || b == null || a.constructor.name === b.constructor.name) {
    return undefined;
  }

  return false;
};

@sirian
Copy link
Author

sirian commented Jul 31, 2018

This is also related to #6768 and #6784

@SimenB
Copy link
Member

SimenB commented Sep 17, 2018

PR welcome! 🙂 Seems reasonable to check the actual constructors a as well.

@ollelauribostrom
Copy link
Contributor

ollelauribostrom commented Sep 19, 2018

@SimenB I've started looking a bit at this and would love some pointers.

Would it be sufficient to simply modify typeEquality to check if a.constructor === b.constructor instead of a.constructor.name === b.constructor.name? Doing so seems to resolve the unexpected behavior from the example above.

Also guessing that it might be a good idea to add/update some test cases 🙂

@SimenB
Copy link
Member

SimenB commented Sep 19, 2018

Try it and see if it break any tests :)

@olivierbeaulieu
Copy link
Contributor

It looks like this issue can be closed.

@SimenB
Copy link
Member

SimenB commented Jan 30, 2019

Right, thanks!

@SimenB SimenB closed this as completed Jan 30, 2019
@thymikee
Copy link
Collaborator

Thanks!

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 12, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants