Code Monkey home page Code Monkey logo

Comments (15)

krzkaczor avatar krzkaczor commented on May 19, 2024 1

@sz-piotr So what you're saying is that we shouldn't allow (at least on a type system lvl) comparing primitive values with toBe, right?

It's an interesting point... and I think you're right. But! We can make a signature to be more like:
toBe(value: T) and add condition that T extends object. This way we get type safety.

from earl.

krzkaczor avatar krzkaczor commented on May 19, 2024 1

As per discussion with @sz-piotr I decided to rename it to toStrictlyEqual.

IMO toBe is too short it looks like it's incentivizing by us to use but in reality, 95% of cases should be covered by toEqual. I will fix it and merge it later today.

from earl.

Pajn avatar Pajn commented on May 19, 2024

Hi,

I would advocate for toBe (but I still prefer something without equal in the name). My motivation is:
If I test the identity function, I want the result the be the exact object I put in and not something that is just equal in some kind of definition. toBe conveys this very clearly while toShallowEqual might be doing something else than checking the object reference. React is just one example that has popularized shallow compare to mean that the object itself might be different but the values inside them must be identical https://reactjs.org/docs/shallow-compare.html

Example:

const identity = value => value

const obj = {}
expect(identity(obj)).toBe(obj)

Another alternative is toStrictlyEqual which is clearer than toShallowEqual but I still prefer toBe as I'm testing for identity, not some kind of equality as equality by definition is considering two different object the same by some kind of measure.

from earl.

sz-piotr avatar sz-piotr commented on May 19, 2024

I like toStrictlyEqual and toBe, and I also believe that the signature should be toStrictlyEqual(value: object) instead of value: any - we shouldn't allow writing expect(3).toStrictlyEqual(3), because toEqual already covers that case well.

from earl.

krzkaczor avatar krzkaczor commented on May 19, 2024

I can't understand how toStrictlyEqual is cleaner than toShallowEqual, I think shallow equality is a widely understood concept...

Anyway, I am fine with toBe - it's short, compatible with jest and I think it makes sense. Tmrw. I will implement this.

from earl.

krzkaczor avatar krzkaczor commented on May 19, 2024

The initial implementation is done (#94) but I will need your feedback guys. @sz-piotr @Pajn

Even though at the beginning I was pro toBe name now I have second thoughts because we ended up with behavior different than one of Jest's.

Our implementation (as per @sz-piotr suggestion ) discourages usage with primitive values. The main reason for this behavior is that toEqual works great with those too. So now, toBe is tuned to work only with objects but the name suggests that it works with primitives as well 🤔 Also, it's confusing that it has the same name as in Jest but different behavior.

I am happy to rename it but let's agree on the name:

  1. toStrictlyEqual - makes sense as has a similar name to === but IMO it implies that it works with primitives.
  2. toShallowEqual - IMO makes even more sense as it implies object comparison
  3. toReferentiallyEqual - same

I like option 2 the most.

And just to clarify, the current implementation works with primitives just fine but we want to discourage users from using it in this context.

from earl.

sz-piotr avatar sz-piotr commented on May 19, 2024

I am very much against toShallowEqual. It implies that it checks for equality, but only on the first level. Nothing in the name suggests the ===. The following is how I'd imagine a function like toShallowEqual works

const a = [1, 2, 3]
const b = [1, 2, 3]
expect(a).toShallowEqual(b)

const c = [1, 2, [3, 4]]
const d = [1, 2, [3, 4]]
expect(c).not.toShallowEqual(d)

from earl.

Pajn avatar Pajn commented on May 19, 2024

I'm still very much against toShallowEqual @sz-piotr shows a common example on how it might get misunderstood. toReferentiallyEqual is a great alternative as it's super clear however also a bit long so I personally prefer toBe but toReferentiallyEqual is clearer if you are not already familiar with the name toBe.

One obvious problem I see with limiting it to object is that there is no way to compare symbols in a safe way. There are also some cases with numbers that would not be checkable as toEqual falls back to Object.is:

> NaN === NaN
false
> Object.is(NaN, NaN)
true
> +0 === -0
true
> Object.is(+0, -0)
false

Personally I don't see the reason to limit toBe so I would argue completely dropping this: Expectation<object> but if you do want to limit it, it should at least be this: Expectation<object | symbol | number> but the might be more cases that I can't think of right now. More cases could also come up in the future if you want to increase the smartness of toEqual. For example, it might be reasonable for expect(0.1 + 0.2).toEqual(0.3) to pass but I would then like to be able to do expect(0.1 + 0.2).toBe(0.3) and have a fail if that precision actually is important.

from earl.

krzkaczor avatar krzkaczor commented on May 19, 2024

Okay, so it seems that I was wrong. Shallow comparison is not the same as referential identity checking. More info. Let's drop it 👍

One obvious problem I see with limiting it to object is that there is no way to compare symbols in a safe way. There are also some cases with numbers that would not be checkable as toEqual falls back to Object.is:

All of these are supported correctly by toEqual :-> Check out tests So it really makes sense to focus toBe to work only on objects.

If no one is really against it, I will go with toReferentiallyEqual. It's super explicit what it does and the fact that it's a little bit longer is not a problem since it's not gonna be super popular given toEqual fits most cases.

from earl.

Pajn avatar Pajn commented on May 19, 2024

All of these are supported correctly by toEqual :-> Check out tests So it really makes sense to focus toBe to work only on objects.

I have, which is why I see limiting toBe to objects is a problem. In the tests you have this:

expect(smartEq(Symbol('abc'), Symbol('abc'))).to.be.deep.eq({ result: 'success' })

That is fine for toEqual but toBe would (and should) fail in this case as Symbol('abc') !== Symbol('abc'). The same applies for the number examples that I showed. Symbols are only every equal to themselves and testing that condition is important. See for example:

const foo = {}
const abc = Symbol('abc')

foo[abc] = 'bar'

foo[abc] === 'bar'
foo[Symbol('abc')] === undefined

from earl.

krzkaczor avatar krzkaczor commented on May 19, 2024

Okay, right. Testing for symbols exact equality probably makes sense sometimes. +0 and -0 too (for 000000.1% of devs ;)). NaN not equal to NaN is clearly a bad design in JS.

Having a input type of object | number | symbol and explaining it in docs will be a nightmare.

I think it's just better to either:
a) ignore these cases - people can always opt out and write normal assertion
b) come full circle, back to a design when toBe takes any input and it's named toBe as in jest

from earl.

krzkaczor avatar krzkaczor commented on May 19, 2024

Okay, I am gonna simply follow closely Jest's design here - since I don't think anyone is sure what to do here.

from earl.

krzkaczor avatar krzkaczor commented on May 19, 2024

WDYT?
#94

from earl.

Pajn avatar Pajn commented on May 19, 2024

Looks great!

from earl.

krzkaczor avatar krzkaczor commented on May 19, 2024

Released in https://github.com/earl-js/earl/releases/tag/earljs%400.1.8

from earl.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.