javascript - toBe(true) vs toBeTruthy() vs toBeTrue()
¿Cuál es la diferencia entre expect(something).toBe(true), expect(something).toBeTruthy() y expect(something).toBeTrue()?
Ten en cuenta que toBeTrue() es un matcher personalizado introducido en jasmine-matchers entre otros matchers útiles y prácticos como toHaveMethod() o toBeArrayOfStrings().
La pregunta está destinada a ser genérica, pero, como ejemplo del mundo real, estoy probando que un elemento se muestre en protractor. ¿Qué comparador debería usar en este caso?
expect(elm.isDisplayed()).toBe(true);
expect(elm.isDisplayed()).toBeTruthy();
expect(elm.isDisplayed()).toBeTrue();
Respuesta #1
Lo que hago cuando me pregunto algo como la pregunta planteada aquí es ir a la fuente.
toBe()
expect().toBe() se define como:
function toBe() {
return {
compare: function(actual, expected) {
return {
pass: actual === expected
};
}
};
}
Realiza su prueba con ===, lo que significa que cuando se usa como expect(foo).toBe(true), pasará solo si foo realmente tiene el valor true. Los valores verdaderos no harán que la prueba pase.
toBeTruthy()
expect().toBeTruthy() se define como:
function toBeTruthy() {
return {
compare: function(actual) {
return {
pass: !!actual
};
}
};
}
Coerción de tipo
Un valor es verdadero si la coerción de este valor a un booleano produce el valor true. La operación !! prueba la veracidad coercionando el valor pasado a expect a un booleano. Ten en cuenta que, contrariamente a lo que implica la respuesta actualmente aceptada, == true no es una prueba correcta de veracidad. Obtendrás cosas curiosas como
> "hello" == true
false
> "" == true
false
> [] == true
false
> [1, 2, 3] == true
false
Mientras que usar !! produce:
> !!"hello"
true
> !!""
false
> !![1, 2, 3]
true
> !![]
true
(Sí, vacío o no, un arreglo es verdadero.)
toBeTrue()
expect().toBeTrue() es parte de Jasmine-Matchers (que está registrado en npm como jasmine-expect después de que un proyecto posterior registró jasmine-matchers primero).
expect().toBeTrue() se define como:
function toBeTrue(actual) {
return actual === true ||
is(actual, 'Boolean') &&
actual.valueOf();
}
La diferencia entre expect().toBeTrue() y expect().toBe(true) es que expect().toBeTrue() prueba si se está tratando con un objeto Boolean. expect(new Boolean(true)).toBe(true) fallaría mientras que expect(new Boolean(true)).toBeTrue() pasaría. Esto se debe a esta curiosa situación:
> new Boolean(true) === true
false
> new Boolean(true) === false
false
Al menos es verdadero:
> !!new Boolean(true)
true
¿Cuál es más adecuado para usar con elem.isDisplayed()?
En última instancia, Protractor entrega esta solicitud a Selenium. La documentación indica que el valor producido por .isDisplayed() es una promesa que se resuelve en un boolean. Yo lo tomaría tal cual y usaría .toBeTrue() o .toBe(true). Si encontrara un caso en el que la implementación devuelve valores verdaderos/falsos, presentaría un informe de errores.
Respuesta #2
Descargo de responsabilidad: Esto es solo una suposición salvaje
Sé que a todo el mundo le encanta una lista fácil de leer:
toBe(<valor>)- El valor devuelto es el mismo que<valor>toBeTrue()- Comprueba si el valor devuelto estruetoBeTruthy()- Verifica si el valor, al convertirse a booleano, será un valor verdaderoLos valores truthy son todos los valores que no son
0,''(cadena vacía),false,null,NaN,undefinedo[](array vacío)*.* Observa que cuando ejecutas
!![], devuelvetrue, pero cuando ejecutas[] == falsetambién devuelvetrue. Depende de cómo esté implementado. En otras palabras:(!![]) === ([] == false)
En tu ejemplo, toBe(true) y toBeTrue() producirán los mismos resultados.
Respuesta #3
En JavaScript hay trues y truthys. Cuando algo es true, obviamente es verdadero o falso. Cuando algo es truthy, puede o no ser un booleano, pero el valor "convertido" es un booleano.
Ejemplos.
true == true; // (true) true
1 == true; // (true) truthy
"hello" == true; // (true) truthy
[1, 2, 3] == true; // (true) truthy
[] == false; // (true) truthy
false == false; // (true) true
0 == false; // (true) truthy
"" == false; // (true) truthy
undefined == false; // (true) truthy
null == false; // (true) truthy
Esto puede hacer las cosas más simples si quieres comprobar si una cadena está definida o si un arreglo tiene algún valor.
var users = [];
if(users) {
// this array is populated. do something with the array
}
var name = "";
if(!name) {
// you forgot to enter your name!
}
Y como se indicó. expect(something).toBe(true) y expect(something).toBeTrue() son lo mismo. Pero expect(something).toBeTruthy() no es lo mismo que ninguno de esos.
Respuesta #4
A medida que leas los ejemplos a continuación, solo ten en cuenta esta diferencia
true === true // true
"string" === true // false
1 === true // false
{} === true // false
Pero
Boolean("string") === true // true
Boolean(1) === true // true
Boolean({}) === true // true
1. esperar(declaración).ser(verdadero)
La aserción pasa cuando la declaración pasada a expect() se evalúa como true
expect(true).toBe(true) // pass
expect("123" === "123").toBe(true) // pass
En todos los demás casos fallaría
expect("string").toBe(true) // fail
expect(1).toBe(true); // fail
expect({}).toBe(true) // fail
A pesar de que todas estas afirmaciones se evaluarían como true al usar Boolean():
Así que puedes pensarlo como una comparación 'estricta'
2. expect(statement).toBeTrue()
Este hace exactamente el mismo tipo de comparación que .toBe(true), pero se introdujo en Jasmine recientemente en la versión 3.5.0 el 20 de septiembre de 2019
3. expect(statement).toBeTruthy()
toBeTruthy, por otro lado, evalúa primero la salida de la declaración en booleano y luego realiza la comparación
expect(false).toBeTruthy() // fail
expect(null).toBeTruthy() // fail
expect(undefined).toBeTruthy() // fail
expect(NaN).toBeTruthy() // fail
expect("").toBeTruthy() // fail
expect(0).toBeTruthy() // fail
Y EN TODOS LOS DEMÁS CASOS pasaría, por ejemplo
expect("string").toBeTruthy() // pass
expect(1).toBeTruthy() // pass
expect({}).toBeTruthy() // pass
