Eventos de pruebas de trufa a través de JavaScript

Estoy probando mi contrato a través de las bibliotecas chai y truffle-assertions desde un archivo JavaScript y estoy probando si los eventos devuelven los valores correctos. Tengo un evento llamado Mensaje. En mi función, el evento se llama dos veces consecutivas pero con una identificación y un mensaje diferentes. El problema que tengo es que me da un error cada vez que trato de probar ambos eventos a pesar de que lo verifiqué en remix y todo parece funcionar. Solo probar los eventos (truffleAssert.eventEmitted(result, 'Message');) funciona bien.

No puedo dar a los eventos dos nombres diferentes ya que crearía un lío para el desarrollo posterior de mis contratos y terminaría con una enorme cantidad de eventos.

¿Cómo puedo hacer que las pruebas funcionen? ¿Hay una solución a este error?

Similar al siguiente (aunque no puedo compartir mi código real):

event Message(address id, bytes16 message);

function messages() public {
emit Message(0x1fe..., 'Almost there);
emit Message(0x0, 'Congratulations'); 
}

Y mi archivo de prueba se parece bastante a esto:

const Contract = artifacts.require('./Contract.sol')
const assert = require("chai").assert;
const truffleAssert = require('truffle-assertions');

contract('Contract', function(accounts) {
  let contractInst;
  let owner = accounts[0];
  let user1 = accounts[1];
  let user2 = accounts[2];

  before('getting instance before all Test Cases', async function(){
    contractInst = await Contract.new({from: owner});

  })

it("should check that the correct events are returned", async () => {
  let result = await contractInst.messages();

    truffleAssert.eventEmitted(result, 'Message', (ev) => {
      assert.equal(ev.id, user1, 'Correct id was returned');
      assert.equal(web3.toUtf8(ev.message), "Almost there", 'Correct message was returned.');
      return true;
    }, 'Contract should return the correct message.');

    truffleAssert.eventEmitted(result, 'Message', (ev) => {
      assert.equal(ev.id, user2, 'Correct id was returned');
      assert.equal(web3.toUtf8(ev.message), "Congratulations", 'Correct message was returned.');
      return true;
    }, 'Contract should return the correct message.');

})

})

El último mensaje de error que recibo es que espero que el evento devuelva la dirección 0x1fe... pero, en cambio, devuelve la dirección 0x0, por lo que parece que solo está viendo el regreso del último evento. Al mismo tiempo, incluso si ingreso la dirección 0x0 para ambos eventos, aún devuelve un mensaje de error.

¡Gracias!

Respuestas (3)

Si bien la respuesta de Aquila puede funcionar como una solución alternativa, la forma en que truffleAssert.eventEmitted()funciona es aplicando una función de filtro en los argumentos del evento. El inconveniente de esto es que no puede "afirmar" cada argumento individualmente, pero esto le permitirá ejecutar ambas afirmaciones de esta manera.

Vi en su otra pregunta que está usando Truffle v5 con Solidity v0.5.0, así que actualicé sus pruebas para usar Web3 v1.0.

Usé el siguiente código de solidez para probar:

event Message(address id, bytes16 message);

function messages() public {
    emit Message(address(0), "Almost there");
    emit Message(address(msg.sender), "Congratulations");
}

Y cambió las pruebas de Javascript a:

it("should check that the correct events are returned", async () => {
    let result = await casino.messages();

    truffleAssert.eventEmitted(result, 'Message', (ev) => {
      return ev.id === '0x0000000000000000000000000000000000000000' && web3.utils.hexToUtf8(ev.message) === 'Almost there';
    }, 'Contract should return the correct message.');

    truffleAssert.eventEmitted(result, 'Message', (ev) => {
      return ev.id === accounts[0] && web3.utils.hexToUtf8(ev.message) === 'Congratulations';
    }, 'Contract should return the correct message.');
  })

Ambas pruebas pasan con Truffle v5, Solidity v0.5.0, truffle-assertions v0.7.1.

Tengo el mismo problema que me da el mensaje de error que dice "eventos no emitidos". Por ahora, me decidí por asegurarme de que está probando que los eventos existen pero no lo que hay dentro de los eventos.
Actualicé la respuesta con la solidez exacta y el código de prueba que usé. Esto definitivamente debería funcionar. Si no es así, ¿podría abrir un problema en el repositorio de GitHub con el código que está utilizando?
Lo acabo de probar con tu código y funciona. Incluso agregó un mensaje adicional con la misma identificación pero un mensaje diferente y uno que era idéntico y pasó la prueba.

La primera declaración de truffleAssert.eventEmittedmaneja todos los eventos, es por eso que tiene el problema.

Significa que necesita afirmar todos los eventos en uno solo truffleAssert.eventEmittedo puede usar una solución alternativa como:

it("should check that the correct events are returned", async () => {
    let result = await contractInst.messages({from: user1});

    truffleAssert.eventEmitted(result, 'Message', (ev) => {
        if(ev.id !== user1) return;                               // <- exit in case of second event
        assert.equal(ev.id, user1, 'Correct id was returned');
        assert.equal(web3.toUtf8(ev.message), "Almost there", 'Correct message was returned.');
        return true;
    }, 'Contract should return the correct message.');

    truffleAssert.eventEmitted(result, 'Message', (ev) => {
        if(ev.id === user1) return;                               // <- exit in case of first event
        assert.equal(ev.id, '0x0000000000000000000000000000000000000000', 'Correct id was returned');
        assert.equal(web3.toUtf8(ev.message), "Congratulations", 'Correct message was returned.');
        return true;
    }, 'Contract should return the correct message.');
})

en caso de contrato:

pragma solidity ^0.4.21;

contract Ev {
    event Message(address id, bytes16 message);

    function messages() public {
        emit Message(msg.sender, 'Almost there');
        emit Message(0x0, 'Congratulations'); 
    }
}

https://github.com/rkalis/truffle-afirmaciones

He intentado esto pero no funciona siempre. Funciona cuando los mensajes son completamente diferentes, pero si tengo dos eventos con ID diferentes pero con el mismo mensaje, no funciona.
entonces necesitas reconstruir tu afirmación. mantener uno eventEmittedo construir una afirmación de evento propia basada enresult
Creo que lo hice, aunque reconstruí la afirmación. Esto significa decir truffleAssert.eventEmitted(resultado, ....) ¿verdad? Hago esto para cada evento e incluyo la declaración if dependiendo de la identificación.

Para trufa v5

it("...",async ()=>{
    const result = await contractInst.messages({from: user1});
    const events = await contractInst.getPastEvents('Message');
    // iterate over the events
    // and do the necessary assertions
});