Comments (15)
@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.
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.
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.
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.
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.
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:
toStrictlyEqual
- makes sense as has a similar name to===
but IMO it implies that it works with primitives.toShallowEqual
- IMO makes even more sense as it implies object comparisontoReferentiallyEqual
- 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.
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.
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.
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.
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.
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.
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.
WDYT?
#94
from earl.
Looks great!
from earl.
Released in https://github.com/earl-js/earl/releases/tag/earljs%400.1.8
from earl.
Related Issues (20)
- Improve mocks error message
- Mock's `executes` wrong signature HOT 1
- Knex object cannot be correctly formatted HOT 1
- `toBeAnArrayWith` error message HOT 1
- Rethink ts-essentials dependency and typescript peer dependency HOT 1
- Current plan for validators in 0.3.x HOT 10
- Use bundler like tsup HOT 2
- ESM does not work HOT 2
- No README on npm despite README.md included in package HOT 1
- "Step by step guide" link results in a 404
- expect.subset() not type-safe HOT 1
- expect.toInclude with expect.subset() does not generate helpful error texts
- Documentation website is down HOT 4
- Feature Request: Custom messages
- Feature request: toThrow() / toBeRejected() should return the objects thrown / rejected with
- Possible bug: mockFn().reset() should also reset calls
- Feature request: reset function for MockObjects
- Bug: Assertions on HTMLElements make earl hang
- Possible performance improvement: Generate messages only if assertions fail HOT 2
- Support node built-in test runner HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from earl.