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
Test if object, array or string. #3457
Comments
No, there isn't. You'll find the list of all available matchers here: https://facebook.github.io/jest/docs/en/expect.html You can also use plain JavaScript or helper library like test('name', () => {
// array
expect(Array.isArray(['value'])).toBe(true);
// string
expect(typeof 'value').toBe('string');
// object
expect({value: 'value'}).toBeTruthy();
expect(typeof {value: 'value'}).toBe('object');
}) |
Minor point - this doesn't help with promise results.
|
@abritinthebay I am in exact that situation and this is the first result in Google, maybe this should be reopened? |
Certainly it should be thought about a bit more. My workaround was to add to the chain so that does the
it works, but it's not exactly clean. |
@thymikee Checking types of things is a common enough use case (universal) that there isn't really any excuse for a testing framework that lacks them. Your alternatives are unacceptable as we lose all context of what we are testing. This
So we either get terrible assertion messages or we have to extend Jest to support these sorts of checks. Doesn't it make more sense for the maintainers of Jest to do this once as opposed to every person that uses requires these features implementing them on their own? |
Create your own matchers with |
A simple toBeType extension for those who want it
Pretty simple to implement. Really should be in core tbh. Note - if you're putting that extend in your setup files then you want it in |
Thanks @abritinthebay |
So I wrapped that up in an npm module if people want it: |
describe("assertion framework", ()=> {
it("should check primitive types", () => {
expect(expect.toBeA).toBeA("function")
})
}) Failed: expect(...).toBeA is not a function |
* Add a useful jest extension to compare types * As posted at: jestjs/jest#3457 (comment)
* Add a useful jest extension to compare types * As posted at: jestjs/jest#3457 (comment)
* Add a useful jest extension to compare types * As posted at: jestjs/jest#3457 (comment)
https://github.com/jest-community/jest-extended has all the type matchers you could want (I think). |
I've been using
|
This comment has been minimized.
This comment has been minimized.
So @abritinthebay did exactly what was requested by @thymikee (which was far more than the standard pull request). Now that that brave soul did all the work, when can the rest of us finally get this matcher (without having to install yet another library)? Are the maintainers still pushing the idea that this doesn't belong in Jest, or did this just fall off their radar? |
We are pretty strict with what makes it into core and don't typically add sugar matchers. Jest core is a fairly large architecture and every matcher we add increases the maintenance cost For sugar, we generally recommend https://github.com/jest-community/jest-extended |
One man's sugar is another man's (or in this case, at least seven other people's) really useful and logical feature that belongs in the core library. Obviously as a maintainer your vote trumps all of ours, and you have all sorts of concerns we don't so I fully respect that. But I'd simply ask that you look at why everyone here considers this feature to belong in the core library (so strongly that one person jumped through multiple hoops to write the code for you). There's a need here, and if you ignore it Jest core library users (and let's be honest, 90% of them will never even hear about jest-extended) will lose out.
|
Yeah I hear ya. To be clear, by "sugar" I meant syntax that is designed to make things easier to read or express. Sugar, by definition, is a variation of a feature that already exists In this case, we have: // Supported
expect(typeof foo).toBe('string');
// Proposed Sugar
expect(foo).toBeType('string'); So it's not that we don't support checking types. We do. We support the first option. This option uses the core There are nearly 60 matchers in jest-extended and many of those are pure sugar. For any of those matchers you could probably find at least 7 other people who find them really useful, so if that was the heuristic we used for adding to core we would probably spend all of our time just maintaining matchers |
To be completely fair - most matchers are "sugar" at some level. I mean Matchers are really almost all sugar around boolean statements ;) (I say this not to dig, just to point out that it's... a very blurred line) |
As abritinthebay suggested, it's not really about sugar, it's about "necessary" and "unnecessary" (for the core library) sugar. You've got a bunch of people in this thread saying "hey, being able to check all types is something that should be in the core of a testing library" (ie. it is necessary). Listen to us or don't, again as maintainer you have lots of other concerns. But I don't think the right response is to come say "your's is just inherently unnecessary sugar" (that's me trying to paraphrase you, not trying to put words in your mouth) when it's not inherent: it's 100% your call whether Jest can check all types or not out of the box. |
what about, isn't that hard :P? expect(Array.isArray(['your', 'array'])).toBe(true);
expect(typeof something === "object").toBe(true);
// - or -
expect(something instanceof Object).toBe(true);
expect(typeof something === "string").toBe(true); |
@nahumzs While it works, the problem is that on your test output when failing, it will say ‘expected false to be true’, which isn’t very helpful ;) |
I think this is the way to go :) describe('type check', () => {
test('should be type string', () => {
expect(typeof '').toBe('string')
})
test('should be type number', () => {
expect(typeof 10).toBe('number')
})
test('should be type boolean', () => {
expect(typeof true).toBe('boolean')
})
test('should be type undefined', () => {
expect(typeof undefined).toBe('undefined')
})
test('should be type object', () => {
expect(typeof { foo: 'bar' }).toBe('object')
})
test('should be type function', () => {
expect(typeof function() {}).toBe('function')
})
test('should be type null', () => {
expect(typeof null).toBe('object')
})
}) |
I refactored the implementation provided by @abritinthebay. It seems for me a little bit comfortable to work with. expect.extend({
/**
* @param {*} received
* @param {string|string[]} arg
* @return {{pass:boolean,message:(function():string)}}
*/
toBeType(received, arg) {
const isCorrectType = arg => {
const receivedType = typeof received;
const checkForSingle = arg => {
const type = receivedType === 'object'
? Array.isArray(received)
? 'array'
: receivedType
: receivedType;
return type === arg;
};
const checkForArr = arg => {
const reducer = (prev, curr) => prev || isCorrectType(curr).isCorrect;
return arg.reduce(reducer, false);
};
return {
receivedType,
isCorrect: Array.isArray(arg)
? checkForArr(arg)
: checkForSingle(arg)
};
};
const {isCorrect, receivedType} = isCorrectType(arg);
return {
pass: isCorrect,
message: () => {
const toBe = Array.isArray(arg)
? arg.join(`' or '`)
: arg;
return `Expected '${received}' of '${receivedType}' type to be of '${toBe}' type(s)`;
}
};
}
}); |
You should check out my module (linked above). It does a bit more than that. But if that works for you: use it! |
It works like a charm as well as more readable and maintainable for the future. |
test('should be type object', () => {
expect(typeof { foo: 'bar' }).toBe('object')
// passes
expect(typeof ['foo', 'bar']).toBe('object')
// passes
expect(typeof null).toBe('object')
}) 😞 |
This is why I suggest my addon above: takes care of this. InstanceOf is slightly better but prone to similar issues. Link to it: |
thanks for solution @abritinthebay |
Another solution: expect('example').toEqual(expect.any(String));
expect(123).toEqual(expect.any(String)); The second one would fail with:
EDIT: keep in mind that null is considered an Object, in which case expect(null).toEqual(expect.any(Object)); // passes
expect(null).toMatchObject({}); // fails In the case of array: expect([]).toEqual(expect.any(Array)); // passes
expect([]).toEqual(expect.any(Object)); // passes
expect([]).toMatchObject({}); // passes
expect({}).toEqual(expect.any(Array)); // fails |
It's extremely weird that Jest doesn't provide so basic functionality out of the box. It's a nonsense that you need to install a third-party library just to check the type of a variable in a clear and semantic manner. |
Agreed, a proper type assessor in the core is long overdue - exemplified by the constant infall from people into this issue. typeof as suggested by @rickhanlonii simply tests wrongly for what devs expect (passes null and array types). Disappointing that jest has been going so long without a proper type assessor in the core.. can only fathom how many devs used typeof and now have unknowingly faulty tests due to this unresolved issue |
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. |
Is there a way to check if a component is an object, array or string? This would be similar to chai's 'should.be.a' Ex.: validationResult.SSN[0].should.be.a('string').
The text was updated successfully, but these errors were encountered: