No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Implementar provider mock

9/16
Recursos

Aportes 29

Preguntas 17

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Probablemente muchos se hagan esta pregunta:
驴Cu谩ndo utilizar mount y cu谩ndo utilizar shallow?
.
mount --> Cuando necesitas el DOM
shallow --> Solo necesitas algo particular del componente. No ocupas todo el DOM

Shallow permite traer elementos y probarlos como una unidad. Es 煤til cuando solo necesito algo particular de ese componente y no necesito toda su estructura y elementos del DOM

La prueba solo me funcion贸 poniendo un

return(
<Provider store={store}>
<Router history={history}>
{props.children}
</Router>
</Provider>
)

por si le pasa a alguien

Formas de crear Mock Functions

/
En jest, podemos crear mock functions de tres formas distintas, esto se debe a que aunque todas tienen como objetivo testear funciones, hay diferentes formas de crear funciones en JavaScript.
/

  • jest.fn(): Este m茅todo es la forma principal de crear una funci贸n de imitaci贸n, si declaramos la funci贸n de imitaci贸n de esta manera, no es obligatorio a帽adir una implementaci贸n (conocida como la funci贸n que espiamos tambi茅n), pero como es normal a帽adimos la implementaci贸n, y para ello, tenemos que pasar la funci贸n como par谩metro del m茅todo.
    /
    Ejemplo:
    /
const mockFunction = jest.fn((a,b) => {
  return a + b
})

/

  • jest.spyOn(): Este m茅todo es otra forma de crear una funci贸n mock, sin embargo, este se enfoca en mockear los m茅todos de alguna instancia creada como de su clase principal, y este m茅todo solo puede ser usado para ellas, cabe mencionar que no podemos usar este m茅todo para el modelo de la clase original, solo para sus instancias, este m茅todo recibe dos par谩metros, el primero es la instancia declarada como de la clase principal y el segundo es el nombre del m茅todo que vamos a espiar.
    /
    Ejemplo:
    /
class Computer {

  constructor(brand, size, price, ram) {
    this.brand = brand;
    this.size = size;
    this.price = price;
    this.ram = ram;
  }

  getInformation(){

    return {
      brand: this.brand,
      size: this.size,
      price: this.price,
      ram: this.ram,
    }

  }

  setInformation(brand, size, price, ram) {
    
    this.brand = brand;
    this.size = size;
    this.price = price;
    this.ram = ram;

    return {
      brand: this.brand,
      size: this.size,
      price: this.price,
      ram: this.ram,
    }

  }
}

const MackBookPro = new Computer('Apple', '3000px', 5000, 36)

const getInformationSpier = jest.spyOn(MackBookPro, 'getInformation')
const setInformationSpier = jest.spyOn(MackBookPro, 'setInformation')

test('testing the methods of the class computer', () => {

  expect(MackBookPro.getInformation()).toEqual({
    brand: 'Apple',
    size: '3000px',
    price: 5000,
    ram: 36,
  })

  expect(MackBookPro.setInformation('Toshiba', '2500px', 1000, 20)).toEqual({
      brand: 'Toshiba',
      size: '2500px',
      price: 1000,
      ram: 20,
  })

  expect(getInformationSpier).toHaveBeenCalled()

  expect(setInformationSpier).toHaveBeenCalledTimes(1)

})

/

  • jest.mock(): Este m茅todo sirve para burlarse autom谩ticamente de todas las funciones (s贸lo funciones autosuficientes, no m茅todos de alguna clase) que tenga un determinado fichero, sin necesidad de burlarse de todas y cada una de las funciones de ese determinado fichero, este m茅todo recibe dos par谩metros (el segundo par谩metro no es obligatorio), el primero es el fichero cuyas funciones queremos burlar, y el segundo es una funci贸n que se ejecutar谩 en lugar de todas las funciones que hayamos definido dentro del otro fichero y que queramos probar, si s贸lo utilizamos el primer par谩metro, entonces cuando utilicemos las funciones del fichero importado, 茅stas no devolver谩n nada, ya que las funciones fueron burladas, y si queremos obtener un determinado valor despu茅s de utilizar las funciones del fichero importado, tenemos que utilizar el segundo par谩metro, pero 茅ste tiene que devolver una funci贸n burlada utilizando jest. fn().
    /
    Ejemplo 1:
    /
// anotherFile.js

const addition = (a, b) => {
  return a + b;
}

const subtraction = (a, b) => {
  return a - b;
}

module.exports = {
    addition, 
    subtraction,
}
jest.mock('./anotherFile')

const additionFunction = require('./anotherFile').addition
const subtractionFunction = require('./anotherFile').subtraction

additionFunction(1,2)
additionFunction(3,4)

subtractionFunction(4,3)
subtractionFunction(2,1)

test('testing mathematical functions', () => {

  console.log(additionFunction.mock)
  console.log(subtractionFunction.mock)

  expect(additionFunction).toHaveBeenCalled()
  expect(subtractionFunction).toHaveBeenCalled()

})

/

  • jest.createMockFromModule(): Este m茅todo (tambi茅n conocido bajo el alias .genMockFromModule()), nos permite transformar las funciones burladas de otro fichero por jest. mock() en funciones normales, de esta manera, ser谩n funciones normales o funciones no burladas y funciones burladas al mismo tiempo, lo que significa que podemos manejarlas como si fueran funciones normales, y adem谩s utilizar las propiedades y m茅todos de una funci贸n burlada, esto es 煤til ya que cuando burlamos todas las funciones de un determinado fichero, estas funciones no pueden ser utilizadas como funciones normales, por ejemplo, esto hace que no obtengamos lo que devuelven las funciones burladas por s铆 mismas, ya que al ser burladas, este m茅todo solo debe recibir un par谩metro, este par谩metro es el archivo cuyas funciones queremos burlar, entonces para des-bloquear la funci贸n de ese archivo, tenemos que invocar esas funciones, y usarlas como variables, y luego debemos usar jest. fn(), y como par谩metro de jest.fn(), tenemos que implementar el c贸digo de la funci贸n original que fue mockeada, y ahora, podemos usar las funciones como si fueran funciones normales y como funciones mockeadas, adem谩s de lo que dijimos anteriormente, si estamos exportando diferentes tipos de datos de un determinado archivo, tambi茅n podemos usarlos en otro archivo, al usar este m茅todo, s贸lo necesitamos llamar a esos datos, pero el m茅todo trata los diferentes tipos de variables de diferentes maneras, aqu铆 explicamos eso:
    /
    Funci贸n: Crea una nueva funci贸n, y esta ser谩 burlada, por lo que los par谩metros de dicha funci贸n ser谩n eliminados y por lo tanto cuando intentemos acceder a los par谩metros, estos no aparecer谩n, y cuando la funci贸n lo sea, esta devolver谩 undefined. Estos cambios tambi茅n se aplican a las funciones async.
    /
    Clase: Crea una nueva clase, se mantendr谩 la estructura de la clase original, pero se burlar谩n todas las propiedades y los m茅todos de sus instancias, por lo tanto lo que ocurr铆a con la funci贸n normal al ser burlada tambi茅n ocurrir谩 con los m茅todos de la clase burlada.
    /
    Objeto: Crea un nuevo objeto, que ser谩 exactamente igual al objeto original, por lo que se mantienen las claves del objeto y se burlan los valores de las claves.
    /
    Array: Crea un nuevo array vac铆o, ignorando el original.
    /
    Primitiva: Crea una nueva variable con el mismo valor primitivo que la variable original.
    /
    Ejemplo 1:
    /
// anotherFile.js

const addition = (a, b) => {
  return a + b;
}

const subtraction = (a, b) => {
  return a - b;
}

module.exports = {
    addition, 
    subtraction,
}

/

const mathematicalFunctions = jest.createMockFromModule('./anotherFile')

mathematicalFunctions.addition = jest.fn((a, b) => {
  return a + b;
})

mathematicalFunctions.subtraction = jest.fn((a, b) => {
  return a - b;
})

const additionFunction = mathematicalFunctions.addition
const subtractionFunction = mathematicalFunctions.addition

test('testing an addition function', () => {

  console.log(additionFunction(12,23))
  console.log(additionFunction.mock)

  console.log(subtractionFunction(20,5))
  console.log(subtractionFunction.mock)

})

/
Ejemplo 2:
/

const typesOfData = jest.createMockFromModule('./anotherFile');

test('should run example code', () => {

  expect(typesOfData.theFunction.name).toEqual('workSomethingOut');
  expect(typesOfData.theFunction.length).toEqual(0);

  expect(typesOfData.theClass.constructor.name).toEqual('User');
  expect(typesOfData.theClass.toGreet.name).toEqual('toGreet');

  expect(typesOfData.theObject).toEqual({
    brand: 'Apple',
    price: 1000,
  });

  expect(typesOfData.theArray.length).toEqual(0);

  expect(typesOfData.theNumber).toEqual(12);

  expect(typesOfData.theString).toEqual('RAM');

  expect(typesOfData.theBoolean).toEqual(true);
});

/
Saludos.

El curso parece un tutorial en lugar de un curso.

Si tienen el siguiente error:

 ProviderMock(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.

Lo pude solucionar agregando un return en el ProviderMock, quedando asi:

return (
        <Provider store={store}>
            <Router history={history}>
                {props.children}
            </Router>
        </Provider>
    )

En la 煤ltima prueba, en la de la funci贸n, no es necesario envolver el componente <Product/> con el <ProviderMock />, ya que al hacer 鈥淩ender鈥 con la funcion mount, se le estan pasando los dato a travez de las props del componente, dejando de lado Redux para adquirir esos datos!

De igual forma al revisar el archivo de <Product/> se puede notar que en ning煤n lado se esta usando Redux.

Al usar shallow es lo m铆smo, mientras le pasemos props al componente se puede prescindir del <ProviderMock/>.

Si se topan el error Invariant failed: Browser history needs a DOM, pueden usar createMemoryHistory.

La verdad no estoy seguro si la prueba de simular el click sea del todo cierta o que realmente compruebe el funcionamiento del bot贸n, me explico:

Si comentan la linea de c贸digo donde simulan el click igual la prueba sigue siendo exitosa, de hecho cambi茅 el n煤mero de veces que se llama la funci贸n solo para generar error y pareciera que el agregar la funci贸n al evento onClick del boton se considerara como un llamado a la funci贸n. Tambi茅n probe usando un expect diferente al del ejercicio. Adjunto c贸digo y outputs para verificar entre todos este caso,

test('Test button Add to cart', () => {
    const handleAddToCart = jest.fn();
    const wrapper = mount(
      <ProviderMock>
        <Product product={ProductMock} handleAddToCart={handleAddToCart} />
      </ProviderMock>,
    );
    //wrapper.find('button').simulate('click');
    //expect(handleAddToCart).toHaveBeenCalledTimes(1);
    expect(handleAddToCart.mock.calls.length).toEqual(1);
  });

	# con cualquiera de los dos expect siempre se llama una vez a la funci贸n y el test es positivo sin simular un click

Esta salida es cuando cambio el valor a 2 para verificar cuantos llamados a la funci贸n se estan haciendo, como ven sin necesidad de simular el click, ya hay un llamado.

para poder realizar el curso es necesario tener las Sifuentes versiones


    "enzyme": "^3.10.0",
    "enzyme-adapter-react-16": "^1.15.1",
    "jest": "^24.9.0",

Nota
El providerMock sirve para dar conexto a enzime de los keywords usados por redux en la app (como 鈥渟tore鈥). Corri un test sin provicerMock y da el siguiente error

Could not find 鈥渟tore鈥 in the context of 鈥淐onnect(Header)鈥. Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(Header) in connect options

Al a帽adir el mock evitamos este tipo de errores donde nuestra testing library podria no entender el codigo

La diferencia entre shallow y mount es que shallow prueba los componentes de forma aislada de los componentes secundarios que representan, mientras que mount profundiza y prueba los elementos secundarios de un componente. En el caso de shallow, esto significa que si el componente principal representa otro componente que no se procesa, se seguir谩 procesando una representaci贸n superficial en el elemento principal.

tengo este problema, alguien le paso y lo pudo resolver?

ReactShallowRenderer render(): Shallow rendering works only with custom components, but the provided element type was `object`.

       6 | describe('<Header />', () => {
       7 |   test('Prueba de Header', () => {
    >  8 |     const header = shallow(
         |                    ^
       9 |       <ProviderMock>
      10 |         <Header />
      11 |       </ProviderMock>,```

Critica constructiva. El profesor deberia mejorar su forma de explicar. Esta bien que no nos digan todo, pero a veces uno que otro porque de las cosas que hace no estaria mal. Simplemente narra lo que hace y ya sin explicar el porque de las cosas

Nuevamente vuelve a pasar lo mismo con los cursos de React de Platzi, desactualizad铆simas, se pierde much铆simo tiempo buscando como solucionar los errores al seguir lo que hace el profesor en los videos. Desmotiva, y relentece el avance.
Si alguien de Platzi lee esto, p贸nganse a ACTUALIZAR TODOS LOS CURSOS DE REACT.

En el caso de que estuvieran usando Hooks y useContext se har铆a de la siguiente manera:
.

import React from 'react';
import AppContext from '../context/AppContext';
import {createBrowserHistory} from 'history';
import {Router} from 'react-router-dom';
import useInitialState from '../hooks/useInitialState';

const history = createBrowserHistory()

const ProviderMock = (props) =>{
  const state = useInitialState()
  return(
    <AppContext.Provider value={state}>
      <Router history={history}>
        {props.children}
      </Router>
    </AppContext.Provider>
  )
}

export default ProviderMock;

Aqu铆 les dejo como estar铆a estructurado App con AppContext en vez de Redux:
.

import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import Layout from './components/Layout';
import AppContext from './context/AppContext';
import useInitialState from './hooks/useInitialState';
import Home from './pages/Home';
import Checkout from './pages/Checkout';
import Information from './pages/Information';
import NotFound from './pages/NotFound';
import Payment from './pages/Payment';
import Success from './pages/Success';

const App = () => {
  const state = useInitialState()
  return (
    <AppContext.Provider value={state}>
      <BrowserRouter>
        <Layout>
          <Switch>
            <Route exact path="/" component={Home} />
            <Route exact path="/checkout" component={Checkout} />
            <Route exact path="/information" component={Information} />
            <Route exact path="/payment" component={Payment} />
            <Route exact path="/success" component={Success} />
            <Route component={NotFound} />
          </Switch>
        </Layout>
      </BrowserRouter>
    </AppContext.Provider>
  )
}

export default App;

Que interesante que esta este curso聽馃槺

Alguien le ha pasado? Me sale el siguiente error: Unable to resolve path to module 鈥榟istory鈥

Algo a tener en cuenta a la hora de realizar nuestros tests unitarios es que debemos validar el comportamiento deseado.

El c贸digo actual tiene un error, y es que ejecuta la funci贸n de handleAddToCart en cuanto se renderiza el componente. Osea que incluso sin hacer click la funci贸n es llamada en el test.

Esto se arregla agregando la sintaxis
()=>prop.function() en el onclick del bot贸n.

Muy complicado seguir el curso, el proyecto no para dar errores por todo lados, se pierde mucho tiempo en ello, deber铆an actualizarlo a cosas m谩s eficientes y pr谩cticas con vite y vitest, es b谩sicamente el mismo testing de jest pero m谩s eficiente y con menos errores

Para la prueba Product.test.js no es necesario usar el ProviderMock ya que el componente que se est脿 testeando (Product) no est脿 usando Redux. Esto funciona ok:

test('Comprobar el bot贸n de comprar',()=>{
        const handleAddToCart = jest.fn();
        const wrapper = mount(
            // <ProviderMock>
                <Product 
                    product={ProductMock}
                    handleAddToCart={handleAddToCart}
                />
            // </ProviderMock>
        )
        wrapper.find('button').simulate('click')
        expect(handleAddToCart).toHaveBeenCalledTimes(1);
    }) 

Mount vs Shallow

Les recomiendo esta lectura sobre las diferencias entre mount y shallow

Mount vs Shallow

Shallow - Bring elements and test them as a Unit

si tienen problemas con el error ReferenceError: regeneratorRuntime is not defined o con async / await, el problema est谩 en la configuracion de babel en el archivo .babelrc. Se debe definir un target para el preset @babel/preset-env. En mi caso necesitaba dirigir babel a mi version actual de node, asi que mi .babelrc quedo asi:

{
  "presets": [
    ["@babel/preset-env", { "targets": { "node": "current" } }],
    "@babel/preset-react"
  ]
}

Que significa lo siguiente?
Me sale un error:

console.error node_modules/prop-types/checkPropTypes.js:20
Warning: Failed prop type: The prop history is marked as required in Router, but its value is undefined.
in Router

Shallow nos permite traer un elemento y probarlo

Funci贸n toHaveBeenCalledTimes()

Method 鈥渢ext鈥 is meant to be run on 1 node. 0 found instead. Me da ese error, alguien sabe como lo soluciono?

Alguien pudo pasar los test con el proyecto terminado del curso de Hooks? porque al terminar, los actions quedan en un hook, no en el reducer