jest-extended
jest-extended copied to clipboard
Testing for type or null
Add toBeObjectContainingOrNull matcher like:
const expect = require("expect");
const okObject = {
message: () => "Ok",
pass: true
};
expect.extend({
toBeTypeOrNull(received, argument) {
if (received === null)
return okObject;
if (expect(received).toEqual(expect.any(argument))) {
return okObject;
} else {
return {
message: () => `expected ${received} to be ${argument} type or null`,
pass: false
};
}
},
toBeObjectContainingOrNull(received, argument) {
if (received === null)
return okObject;
const pass = expect(received).toEqual(expect.objectContaining(argument));
if (pass) {
return okObject;
} else {
return {
message: () => `expected ${received} to be ${argument} type or null`,
pass: false
};
}
}
});
module.exports = { expect };
Then you can use toBeObjectContainingOrNull as follows:
const userImageSchema = {
displayName: expect.any(String),
image: expect.toBeObjectContainingOrNull({
type: "Buffer",
data: expect.any(Array)
}),
orgs: expect.any(Array)
};
I see this in https://stackoverflow.com/a/51507754/7414646
We use something similar for verifying properties which are optional. Would be good addition to the library.
+1 on this
Meanwhile, you can do this:
image: expect.objectContaining({ type: "Buffer", data: expect.any(Array) }) || null,
+1 on this
@makitocode your solution almost worked for me but I had to alter as following
expect(casper).toEqual(
expect.objectContaining({ casperDescription: null }) ||
expect.objectContaining({ casperDescription: expect.any(String) }),
);
This copies the Any
asymmetric matcher in the expect
library to allow a null or undefined object.
export class Nullable extends AsymmetricMatcher<any> {
constructor(sample) {
if (typeof sample === "undefined") {
throw new TypeError(
"nullable() expects to be passed a constructor function."
);
}
super(sample);
}
asymmetricMatch(other) {
if (other === null || other === undefined) {
return true;
}
if (this.sample == String) {
return typeof other == "string" || other instanceof String;
}
if (this.sample == Number) {
return typeof other == "number" || other instanceof Number;
}
if (this.sample == Function) {
return typeof other == "function" || other instanceof Function;
}
if (this.sample == Boolean) {
return typeof other == "boolean" || other instanceof Boolean;
}
if (this.sample == BigInt) {
return typeof other == "bigint" || other instanceof BigInt;
}
if (this.sample == Symbol) {
return typeof other == "symbol" || other instanceof Symbol;
}
if (this.sample == Object) {
return typeof other == "object";
}
return other instanceof this.sample;
}
toString() {
return "Nullable";
}
getExpectedType() {
if (this.sample == String) {
return "string";
}
if (this.sample == Number) {
return "number";
}
if (this.sample == Function) {
return "function";
}
if (this.sample == Object) {
return "object";
}
if (this.sample == Boolean) {
return "boolean";
}
return fnNameFor(this.sample);
}
toAsymmetricMatcher() {
return `Nullable<${fnNameFor(this.sample)}>`;
}
}
function fnNameFor(func) {
if (func.name) {
return func.name;
}
const matches = Function.prototype.toString
.call(func)
.match(/^(?:async)?\s*function\s*\*?\s*([\w$]+)\s*\(/);
return matches ? matches[1] : "<anonymous>";
}
export const nullable = (
sample
) => new Nullable(sample);
Usage
expect(sample).toMatchObject({
modified_at: expect.any(String),
created_at: expect.any(String),
start_date: nullable(String),
});