Skip to content

Commit

Permalink
Merge pull request #1012 from votingworks/caro/fix/either_neither_pri…
Browse files Browse the repository at this point in the history
…mary

fix(types): fix bug in losing party when expanding either/neither
  • Loading branch information
carolinemodic authored Oct 18, 2021
2 parents e3e50bc + fadbceb commit 37912b9
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 0 deletions.
22 changes: 22 additions & 0 deletions libs/types/src/election.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
election,
electionWithMsEitherNeither,
primaryElection,
electionMinimalExhaustive,
} from '../test/election'
import {
CandidateContest,
Expand Down Expand Up @@ -95,6 +96,27 @@ test('can expand ms-either-neither contests into yes no contests', () => {
}
})

test('can expand ms-either-neither contests into yes no contests in a primary', () => {
const expandedContests = expandEitherNeitherContests(
electionMinimalExhaustive.contests
)
// There is 1 contest that should have expanded into two.
expect(expandedContests).toHaveLength(
1 + electionMinimalExhaustive.contests.length
)
for (let i = 0; i < electionWithMsEitherNeither.contests.length; i += 1) {
const originalContest = electionMinimalExhaustive.contests[i]
if (originalContest.type !== 'ms-either-neither') {
expect(originalContest).toEqual(expandedContests[i])
} else {
expect(expandedContests[i].type).toBe('yesno')
expect(expandedContests[i + 1].type).toBe('yesno')
expect(expandedContests[i].partyId === originalContest.partyId)
expect(expandedContests[i + 1].partyId === originalContest.partyId)
}
}
})

test('can build votes from a candidates array', () => {
const contests = election.contests.filter((c) => c.id === 'CC')
const contest = contests[0] as CandidateContest
Expand Down
2 changes: 2 additions & 0 deletions libs/types/src/election.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,7 @@ export const expandEitherNeitherContests = (
description: contest.description,
yesOption: contest.eitherOption,
noOption: contest.neitherOption,
...(contest.partyId ? { partyId: contest.partyId } : {}),
},
{
type: 'yesno',
Expand All @@ -1238,6 +1239,7 @@ export const expandEitherNeitherContests = (
description: contest.description,
yesOption: contest.firstOption,
noOption: contest.secondOption,
...(contest.partyId ? { partyId: contest.partyId } : {}),
},
]
)
Expand Down
223 changes: 223 additions & 0 deletions libs/types/test/election.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,226 @@ export const electionWithMsEitherNeither: Election = {
},
],
}

const electionMinimalExhaustiveData = `
{
"title": "Example Primary Election",
"state": "State of Sample",
"county": {
"id": "sample-county",
"name": "Sample County"
},
"date": "2021-09-08T00:00:00-08:00",
"ballotLayout": {
"paperSize": "letter"
},
"districts": [
{
"id": "district-1",
"name": "District 1"
}
],
"parties": [
{
"id": "0",
"name": "Mammal",
"fullName": "Mammal Party",
"abbrev": "Ma"
},
{
"id": "1",
"name": "Fish",
"fullName": "Fish Party",
"abbrev": "F"
}
],
"contests": [
{
"id": "best-animal-mammal",
"districtId": "district-1",
"type": "candidate",
"section": "State",
"title": "Best Animal",
"seats": 1,
"partyId": "0",
"candidates": [
{
"id": "horse",
"name": "Horse",
"partyId": "0"
},
{
"id": "otter",
"name": "Otter",
"partyId": "0"
},
{
"id": "fox",
"name": "Fox",
"partyId": "0"
}
],
"allowWriteIns": false
},
{
"id": "best-animal-fish",
"districtId": "district-1",
"type": "candidate",
"section": "State",
"title": "Best Animal",
"seats": 1,
"partyId": "1",
"candidates": [
{
"id": "seahorse",
"name": "Seahorse",
"partyId": "1"
},
{
"id": "salmon",
"name": "Salmon",
"partyId": "1"
}
],
"allowWriteIns": false
},
{
"id": "zoo-council-mammal",
"districtId": "district-1",
"type": "candidate",
"section": "City",
"title": "Zoo Council",
"seats": 3,
"partyId": "0",
"candidates": [
{
"id": "zebra",
"name": "Zebra",
"partyId": "0"
},
{
"id": "lion",
"name": "Lion",
"partyId": "0"
},
{
"id": "kangaroo",
"name": "Kangaroo",
"partyId": "0"
},
{
"id": "elephant",
"name": "Elephant",
"partyId": "0"
}
],
"allowWriteIns": true
},
{
"id": "aquarium-council-fish",
"districtId": "district-1",
"type": "candidate",
"section": "City",
"title": "Zoo Council",
"seats": 2,
"partyId": "1",
"candidates": [
{
"id": "manta-ray",
"name": "Manta Ray",
"partyId": "1"
},
{
"id": "pufferfish",
"name": "Pufferfish",
"partyId": "1"
},
{
"id": "rockfish",
"name": "Rockfish",
"partyId": "1"
},
{
"id": "triggerfish",
"name": "Triggerfish",
"partyId": "1"
}
],
"allowWriteIns": true
},
{
"id": "new-zoo-either-neither",
"section": "City",
"districtId": "district-1",
"type": "ms-either-neither",
"title": "Ballot Measure 1",
"partyId": "0",
"eitherNeitherContestId": "new-zoo-either",
"pickOneContestId": "new-zoo-pick",
"description": "Initiative Measure No. 12, Should Sample City establish a new safari-style zoo costing 2,000,000? Alternative Measure 12 A, Should Sample City establish a new traditional zoo costing 1,000,000",
"eitherNeitherLabel": "VOTE FOR APPROVAL OF EITHER, OR AGAINST BOTH",
"pickOneLabel": "AND VOTE FOR ONE",
"eitherOption": {
"id": "new-zoo-either-approved",
"label": "FOR APPROVAL OF EITHER Initiative No. 12 OR Alternative Initiative No. 12 A"
},
"neitherOption": {
"id": "new-zoo-neither-approved",
"label": "AGAINST BOTH Initiative No. 12 AND Alternative Measure 12 A"
},
"firstOption": {
"id": "new-zoo-safari",
"label": "FOR Initiative No. 12"
},
"secondOption": {
"id": "new-zoo-traditional",
"label": "FOR Alternative Measure No. 12 A"
}
},
{
"id": "fishing",
"section": "City",
"districtId": "district-1",
"type": "yesno",
"title": "Ballot Measure 3",
"partyId": "1",
"description": "Should fishing be banned in all city owned lakes and rivers?",
"yesOption": {
"id": "ban-fishing",
"label": "YES"
},
"noOption": {
"id": "allow-fishing",
"label": "NO"
}
}
],
"precincts": [
{
"id": "precinct-1",
"name": "Precinct 1"
},
{
"id": "precinct-2",
"name": "Precinct 2"
}
],
"ballotStyles": [
{
"id": "1M",
"precincts": ["precinct-1", "precinct-2"],
"districts": ["district-1"],
"partyId": "0"
},
{
"id": "2F",
"precincts": ["precinct-1", "precinct-2"],
"districts": ["district-1"],
"partyId": "1"
}
],
"sealURL": "/seals/Sample-Seal.svg"
}`
export const electionMinimalExhaustive: Election = safeParseElection(
electionMinimalExhaustiveData
).unsafeUnwrap()

0 comments on commit 37912b9

Please sign in to comment.