8

I am using truffle to develop a simple smart contract.

I have the following contract:

contract Puppy {

  enum State { good, bad }

  State public status;
  State public constant INITIAL_STATUS = State.good;

  function Puppy() {
    status = INITIAL_STATUS;
  }
}

And I wish to test it as follows:

const Puppy = artifacts.require('./Puppy.sol')

contract('Puppy', () => {
  it('sets the initial status to \'good\'', () => Puppy.deployed()
    .then(instance => instance.status())
    .then((status) => {
      assert.equal(status, Puppy.State.good, 'Expected the status to be \'good\'')
    }))
})

This throws TypeError: Cannot read property 'good' of undefined

If I change the test to

const Puppy = artifacts.require('./Puppy.sol')

contract('Puppy', () => {
  it('sets the initial status to \'good\'', () => Puppy.deployed()
    .then(instance => instance.status())
    .then((status) => {
      assert.equal(status, 0, 'Expected the status to be \'good\'')
    }))
})

it passes.

How do I refer to the enum from within the test?

1

Let's take the test-contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;

contract Test {
    enum Stages {
        stage_01,
        stage_02,
        stage_03,
        stage_04,
        stage_05
    }

    Stages public stage = Stages.stage_01;

    function setStage(Stages _stage) public {
        stage = _stage;
    }
}

and test it such way:

const TestContract = artifacts.require('Test');

contract('Test', function (accounts) {
    const [owner] = accounts;
    const txParams = { from: owner };

    beforeEach(async function () {
        this.testContract = await TestContract.new(txParams);
    });

    it('test initial stage', async function () {
        expect((await this.testContract.stage()).toString()).to.equal(TestContract.Stages.stage_01.toString());
    });

    it('assign custom stage', async function () {
        this.testContract.setStage(TestContract.Stages.stage_05, txParams);
        expect((await this.testContract.stage()).toString()).to.equal(TestContract.Stages.stage_05.toString());
    });
    
    it('assign custom number to stage', async function () {
        this.testContract.setStage(3, txParams); // take into account that enum indexed from zero
        expect((await this.testContract.stage()).toString()).to.equal(TestContract.Stages.stage_04.toString());
    });      
});
5

You can't (for now), as enums are not supported by the ABI.

See https://solidity.readthedocs.io/en/latest/frequently-asked-questions.html#if-i-return-an-enum-i-only-get-integer-values-in-web3-js-how-to-get-the-named-values

There is a proposal to change that https://github.com/ethereum/EIPs/issues/47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.