Index

Ethereum

  1. Election
  2. Accounts
  3. Test
  4. Frontend
  5. Voting
  6. Validation
  7. Events

Validation

function vote(uint _candidateId) public {
        // record that voter has voted
        voters[msg.sender] = true;

        // update candidate vote Count
        candidates[_candidateId].voteCount ++;
    }


Conditions
Execute below lines only if conditions are true

function vote(uint _candidateId) public {
        // require that they haven't voted before
        require(!voters[msg.sender], "Sender not authorized");

        // require a valid candidate
        require(_candidateId > 0 && _candidateId <= candidatesCount, "Candidate is not valid");

        // record that voter has voted
        voters[msg.sender] = true;

        // update candidate vote Count
        candidates[_candidateId].voteCount ++;
    }



Tests:
Election.js
 it("throws an exception for invalid candidates"function() {
        return Election.deployed().then(function(instance) {
          electionInstance = instance;
          return electionInstance.vote(99, { from: accounts[1] })
        }).then(assert.fail).catch(function(error) {
          assert(error.message.indexOf('Candidate is not valid')>= 0"error message must contain 'Candidate is not valid'")
          assert(error.message.indexOf('revert') >= 0"error message must contain revert");
          return electionInstance.candidates(1);
        }).then(function(candidate1) {
          var voteCount = candidate1[2];
          assert.equal(voteCount, 1"candidate 1 did not receive any votes");
          return electionInstance.candidates(2);
        }).then(function(candidate2) {
          var voteCount = candidate2[2];
          assert.equal(voteCount, 0"candidate 2 did not receive any votes");
        });
      });
    
      it("throws an exception for double voting"function() {
        return Election.deployed().then(function(instance) {
          electionInstance = instance;
          candidateId = 2;
          electionInstance.vote(candidateId, { from: accounts[1] });
          return electionInstance.candidates(candidateId);
        }).then(function(candidate) {
          var voteCount = candidate[2];
          assert.equal(voteCount, 1"accepts first vote");
          // Try to vote again
          return electionInstance.vote(candidateId, { from: accounts[1] });
        }).then(assert.fail).catch(function(error) {
          assert(error.message.indexOf('Sender not authorized') >= 0"error message must contain 'Sender not authorized'")
          assert(error.message.indexOf('revert') >= 0"error message must contain revert");
          return electionInstance.candidates(1);
        }).then(function(candidate1) {
          var voteCount = candidate1[2];
          assert.equal(voteCount, 1"candidate 1 did not receive any votes");
          return electionInstance.candidates(2);
        }).then(function(candidate2) {
          var voteCount = candidate2[2];
          assert.equal(voteCount, 1"candidate 2 did not receive any votes");
        });
      });


Complete code:
Election.js
var Election = artifacts.require('./Election.sol')

contract("Election"function(accounts){
    var electionInstance;
    it("initializes with two candidates"function(){
        return Election.deployed().then(function(instance){
            return instance.candidatesCount();
        }).then(function(count){
            assert.equal(count, 2)
        });
    });

    it("it initializes the candidates with the correct values"function(){
        return Election.deployed().then(function(instance){
            electionInstance = instance;
            return electionInstance.candidates(1);
        }).then(function(candidate){
            assert.equal(candidate[0], 1"contains the correct id");
            assert.equal(candidate[1], "Candidate 1""contains the correct name");
            assert.equal(candidate[2], 0"contains the correct votes count");
            return electionInstance.candidates(2);
        }).then(function(candidate){
            assert.equal(candidate[0], 2"contains the correct id");
            assert.equal(candidate[1], "Candidate 2""contains the correct name");
            assert.equal(candidate[2], 0"contains the correct votes count");
        });
    });

    it("allows a voter to cast a vote"function(){
        return Election.deployed().then(function(instance) {
            electionInstance = instance;
            candidateId = 1;
            return electionInstance.vote(candidateId, { from: accounts[0]});
        }).then(function(receipt) {
            return electionInstance.voters(accounts[0]);
        }).then(function(voted){
            assert(voted, "the voter was marked as voted");
            return electionInstance.candidates(candidateId);
        }).then(function(candidate){
            var voteCount = candidate[2];
            assert.equal(voteCount, 1"increments the candidate's vote count");
        })
    });


      it("throws an exception for invalid candidates"function() {
        return Election.deployed().then(function(instance) {
          electionInstance = instance;
          return electionInstance.vote(99, { from: accounts[1] })
        }).then(assert.fail).catch(function(error) {
          assert(error.message.indexOf('Candidate is not valid')>= 0"error message must contain 'Candidate is not valid'")
          assert(error.message.indexOf('revert') >= 0"error message must contain revert");
          return electionInstance.candidates(1);
        }).then(function(candidate1) {
          var voteCount = candidate1[2];
          assert.equal(voteCount, 1"candidate 1 did not receive any votes");
          return electionInstance.candidates(2);
        }).then(function(candidate2) {
          var voteCount = candidate2[2];
          assert.equal(voteCount, 0"candidate 2 did not receive any votes");
        });
      });
    
      it("throws an exception for double voting"function() {
        return Election.deployed().then(function(instance) {
          electionInstance = instance;
          candidateId = 2;
          electionInstance.vote(candidateId, { from: accounts[1] });
          return electionInstance.candidates(candidateId);
        }).then(function(candidate) {
          var voteCount = candidate[2];
          assert.equal(voteCount, 1"accepts first vote");
          // Try to vote again
          return electionInstance.vote(candidateId, { from: accounts[1] });
        }).then(assert.fail).catch(function(error) {
          assert(error.message.indexOf('Sender not authorized') >= 0"error message must contain 'Sender not authorized'")
          assert(error.message.indexOf('revert') >= 0"error message must contain revert");
          return electionInstance.candidates(1);
        }).then(function(candidate1) {
          var voteCount = candidate1[2];
          assert.equal(voteCount, 1"candidate 1 did not receive any votes");
          return electionInstance.candidates(2);
        }).then(function(candidate2) {
          var voteCount = candidate2[2];
          assert.equal(voteCount, 1"candidate 2 did not receive any votes");
        });
      });
    

});


Election.sol
pragma solidity >=0.4.22 <0.7.0;


contract Election {

    // Model a candidate
    struct Candidate {
        uint id;
        string name;
        uint voteCount;
    }
    // Storing accounts that have voted
    mapping(address => bool) public voters;

    // Store candidate
    // Fetch Candidate
    mapping(uint => Candidate) public candidates;

     // Store candidate count
    uint public candidatesCount;

    constructor () public {
       addCandidate("Candidate 1");
       addCandidate("Candidate 2");
    }

    function addCandidate(string memory _name) private {
        candidatesCount ++;
        candidates[candidatesCount] = Candidate(candidatesCount, _name, 0);
    }
    function vote(uint _candidateId) public {
        // require that they haven't voted before
        require(!voters[msg.sender], "Sender not authorized");

        // require a valid candidate
        require(_candidateId > 0 && _candidateId <= candidatesCount, "Candidate is not valid");

        // record that voter has voted
        voters[msg.sender] = true;

        // update candidate vote Count
        candidates[_candidateId].voteCount ++;
    }
}