factom-vote
Version:
JS implementation of the Factom voting specification
173 lines (152 loc) • 6.1 kB
JavaScript
const assert = require('chai').assert,
{ computeResult } = require('../src/read-vote/compute-vote-result');
describe('Compute vote result', function () {
it('Should compute binary voting result', function () {
const definition = {
type: 0,
config: {
options: ['A', 'B'],
computeResultsAgainst: 'ALL_ELIGIBLE_VOTERS',
allowAbstention: false,
winnerCriteria: {
minSupport: {
'A': {
weighted: 0.55
}
}
}
}
};
const eligibleVoters = {
ID_1: 6,
ID_2: 7,
ID_3: 1,
ID_4: 10,
ID_5: 6
};
const validVotes = {
ID_1: ['A'],
ID_2: ['B'],
ID_3: ['B'],
ID_4: ['A']
};
const vote = { definition, eligibleVoters, validVotes };
const result = computeResult(vote);
assert.deepEqual(result.options.A, { count: 2, weight: 16, support: 2 / 5, weightedSupport: 16 / 30 });
assert.deepEqual(result.options.B, { count: 2, weight: 8, support: 2 / 5, weightedSupport: 8 / 30 });
assert.equal(result.votersCount.nbEligibleVoters, 5);
assert.equal(result.votersCount.nbEffectiveVoters, 4);
assert.equal(result.votersCount.weightOfEligibleVoters, 30);
assert.equal(result.votersCount.weightOfEffectiveVoters, 24);
assert.equal(result.abstention.count, 0);
assert.equal(result.abstention.weight, 0);
assert.equal(result.turnout.unweighted, 4 / 5);
assert.equal(result.turnout.weighted, 24 / 30);
assert.isTrue(result.valid);
assert.equal(result.winner, 'B');
});
it('Should compute approval voting result', function () {
const definition = {
type: 1,
config: {
options: ['A', 'B', 'Z'],
computeResultsAgainst: 'PARTICIPANTS_ONLY',
allowAbstention: true
}
};
const eligibleVoters = {
ID_1: 6,
ID_2: 7,
ID_3: 1,
ID_4: 10,
ID_5: 3
};
const validVotes = {
ID_1: ['A', 'B'],
ID_2: ['B'],
ID_3: ['Z', 'B'],
ID_4: []
};
const vote = { definition, eligibleVoters, validVotes };
const result = computeResult(vote);
assert.deepEqual(result.options.A, { count: 1, weight: 6, support: 1 / 4, weightedSupport: 6 / 24 });
assert.deepEqual(result.options.B, { count: 3, weight: 14, support: 3 / 4, weightedSupport: 14 / 24 });
assert.deepEqual(result.options.Z, { count: 1, weight: 1, support: 1 / 4, weightedSupport: 1 / 24 });
assert.equal(result.votersCount.nbEligibleVoters, 5);
assert.equal(result.votersCount.nbEffectiveVoters, 4);
assert.equal(result.votersCount.weightOfEligibleVoters, 27);
assert.equal(result.votersCount.weightOfEffectiveVoters, 24);
assert.equal(result.abstention.count, 1);
assert.equal(result.abstention.weight, 10);
assert.equal(result.turnout.unweighted, 4 / 5);
assert.equal(result.turnout.weighted, 24 / 27);
assert.isTrue(result.valid);
assert.equal(result.winner, 'B');
});
it('Should compute instand run-off voting result', function () {
const definition = {
type: 2,
config: {
options: ['Bob', 'Sue', 'Bill']
}
};
const eligibleVoters = {};
const validVotes = {
ID_1: ['Bob', 'Bill', 'Sue'],
ID_2: ['Sue', 'Bob', 'Bill'],
ID_3: ['Bill', 'Sue', 'Bob'],
ID_4: ['Bob', 'Bill', 'Sue'],
ID_5: ['Sue', 'Bob', 'Bill']
};
const vote = { definition, eligibleVoters, validVotes };
const result = computeResult(vote);
assert.equal(result.winner, 'Sue');
assert.lengthOf(result.roundsResults, 2);
assert.deepEqual(result.roundsResults[0], { 'Bob': 2, 'Sue': 2, 'Bill': 1 });
assert.deepEqual(result.roundsResults[1], { 'Bob': 2, 'Sue': 3 });
});
it('Should compute IRV tie', function () {
const definition = {
type: 2,
config: {
options: ['Bob', 'Sue', 'Bill']
}
};
const validVotes = {
ID_1: ['Bob', 'Bill', 'Sue'],
ID_2: ['Sue', 'Bob', 'Bill'],
ID_3: ['Bill'],
ID_4: ['Bob', 'Bill', 'Sue'],
ID_5: ['Sue', 'Bob', 'Bill']
};
const vote = { definition, validVotes };
const result = computeResult(vote);
assert.isUndefined(result.winner);
assert.lengthOf(result.roundsResults, 2);
assert.deepEqual(result.roundsResults[0], { 'Bob': 2, 'Sue': 2, 'Bill': 1 });
assert.deepEqual(result.roundsResults[1], { 'Bob': 2, 'Sue': 2 });
});
it('Should compute IRV edge case no vote for Bill at 1st round', function () {
const definition = {
type: 2,
config: {
options: ['Bob', 'Sue', 'Bill', 'Paul']
}
};
const validVotes = {
ID_1: ['Bob', 'Bill', 'Sue'],
ID_2: ['Sue', 'Bill', 'Bob'],
ID_3: ['Paul', 'Bill', 'Sue'],
ID_4: ['Bob', 'Bill', 'Sue'],
ID_5: ['Sue', 'Bob', 'Bill'],
ID_6: ['Sue', 'Bill', 'Bob']
};
const vote = { definition, validVotes };
const result = computeResult(vote);
assert.equal(result.winner, 'Sue');
assert.lengthOf(result.roundsResults, 3);
assert.deepEqual(result.roundsResults[0], { 'Bob': 2, 'Sue': 3, 'Bill': 0, 'Paul': 1 });
assert.deepEqual(result.roundsResults[1], { 'Bob': 2, 'Sue': 3, 'Paul': 1 });
assert.deepEqual(result.roundsResults[2], { 'Bob': 2, 'Sue': 4 });
});
});