From 41acb7ed40869d734eb4bd880210872b237e3651 Mon Sep 17 00:00:00 2001 From: av-alexander Date: Mon, 18 Jul 2022 09:53:07 +0200 Subject: [PATCH 1/3] Make blank validation based on new config in marking type Also improved tests and added new ones --- lib/av_client/types.ts | 1 + lib/av_client/validate_selections.ts | 13 ++++++-- test/validate_selections.test.ts | 44 +++++++++++++++++++++------- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/lib/av_client/types.ts b/lib/av_client/types.ts index ea80b572..d1bc9261 100644 --- a/lib/av_client/types.ts +++ b/lib/av_client/types.ts @@ -237,6 +237,7 @@ export type ContestConfig = { export type MarkingType = { minMarks: number maxMarks: number + blankSubmission: "disabled" | "active_choice" | "implicit" encoding: { codeSize: 1 | 2 maxSize: number diff --git a/lib/av_client/validate_selections.ts b/lib/av_client/validate_selections.ts index ba045b9e..1b1ff4a3 100644 --- a/lib/av_client/validate_selections.ts +++ b/lib/av_client/validate_selections.ts @@ -22,15 +22,22 @@ export function validateContestSelection( contestConfig: ContestConfig, contestS const { markingType, options } = contestConfig + const isBlank = contestSelection.optionSelections.length === 0 + + // Validate blankSubmission + if( isBlank && markingType.blankSubmission == 'disabled'){ + throw new CorruptSelectionError('Blank submissions are not allowed in this contest') + } + // Validate that mark count is within bounds - if( !withinBounds(markingType.minMarks, contestSelection.optionSelections.length, markingType.maxMarks) ){ + if( !isBlank && !withinBounds(markingType.minMarks, contestSelection.optionSelections.length, markingType.maxMarks) ){ throw new CorruptSelectionError('Contest selection does not contain a valid amount of option selections') - } + } // Validate duplicates - that any vote selection is not referencing the same option multiple times const selectedOptions = contestSelection.optionSelections.map(os => os.reference) if( hasDuplicates(selectedOptions) ){ - throw new CorruptSelectionError('Same option slected multiple times') + throw new CorruptSelectionError('Same option selected multiple times') } const getOption = makeGetOption(options) diff --git a/test/validate_selections.test.ts b/test/validate_selections.test.ts index 2cd29f8f..dc687bed 100644 --- a/test/validate_selections.test.ts +++ b/test/validate_selections.test.ts @@ -8,6 +8,7 @@ const contestOne: ContestConfig = { markingType: { minMarks: 1, maxMarks: 1, + blankSubmission: "disabled", encoding: { codeSize: 1, maxSize: 1, @@ -27,6 +28,13 @@ const contestOne: ContestConfig = { title: { en: 'Option 1' }, subtitle: { en: 'Option 1' }, description: { en: 'Option 1' }, + }, + { + reference: 'option-3', + code: 3, + title: { en: 'Option 3' }, + subtitle: { en: 'Option 3' }, + description: { en: 'Option 3' }, } ] } @@ -36,6 +44,7 @@ const contestTwo: ContestConfig = { markingType: { minMarks: 1, maxMarks: 2, + blankSubmission: "active_choice", encoding: { codeSize: 1, maxSize: 2, @@ -81,33 +90,46 @@ describe('validateContestSelection', () => { { reference: 'option-1' } ] } - it('does not throw error', () => { + it('throws an error', () => { expect(() => { validateContestSelection( contestOne, contestSelection ) }).to.throw(CorruptSelectionError, 'Contest selection is not matching contest config') }) }) - context('when given a contest selection with no selections', () => { + context('when given a contest selection with no selections and blank disabled', () => { const contestSelection = { - reference: 'contest-2', + reference: 'contest-1', optionSelections: [] } - it('does not throw error', () => { + it('throws an error', () => { expect(() => { - validateContestSelection( contestTwo, contestSelection ) - }).to.throw(CorruptSelectionError, 'Contest selection does not contain a valid amount of option selections') + validateContestSelection( contestOne, contestSelection ) + }).to.throw(CorruptSelectionError, 'Blank submissions are not allowed in this contest') }) }) - context('when given a contest selection with two selections', () => { + context('when given a contest selection with no selections and blank enabled', () => { const contestSelection = { reference: 'contest-2', optionSelections: [] } - it('does not throw error', () => { + it('does not throw an error', () => { expect(() => { validateContestSelection( contestTwo, contestSelection ) + }).to.not.throw() + }) + }) + + context('when given a contest selection with two selections', () => { + const contestSelection = { + reference: 'contest-1', + optionSelections: [{ reference: 'option-1' }, + { reference: 'option-3' }] + } + it('throws an error', () => { + expect(() => { + validateContestSelection( contestOne, contestSelection ) }).to.throw(CorruptSelectionError, 'Contest selection does not contain a valid amount of option selections') }) }) @@ -119,7 +141,7 @@ describe('validateContestSelection', () => { { reference: 'option-2' } ] } - it('does not throw error', () => { + it('throws an error', () => { expect(() => { validateContestSelection( contestOne, contestSelection ) }).to.throw(CorruptSelectionError, 'Option config not found') @@ -136,10 +158,10 @@ describe('validateContestSelection', () => { { reference: 'option-a' } ] } - it('does not throw error', () => { + it('throws an error', () => { expect(() => { validateContestSelection( contestTwo, contestSelection ) - }).to.throw(CorruptSelectionError, 'Same option slected multiple times') + }).to.throw(CorruptSelectionError, 'Same option selected multiple times') }) }) }) From 7a1ec6c7550082b0391bf80e911bfe4d249dec1b Mon Sep 17 00:00:00 2001 From: av-alexander Date: Mon, 18 Jul 2022 09:58:21 +0200 Subject: [PATCH 2/3] Update all contest configs with blankSubmission attr --- test/construct_contest_envelopes.test.ts | 1 + test/decrypt_contest_selections.test.ts | 1 + test/encrypt_contest_selections.test.ts | 2 ++ test/replies/otp_flow/get_us_configuration.json | 2 ++ 4 files changed, 6 insertions(+) diff --git a/test/construct_contest_envelopes.test.ts b/test/construct_contest_envelopes.test.ts index e54ded22..8987a4ff 100644 --- a/test/construct_contest_envelopes.test.ts +++ b/test/construct_contest_envelopes.test.ts @@ -7,6 +7,7 @@ const contestOne: ContestConfig = { markingType: { minMarks: 1, maxMarks: 1, + blankSubmission: "disabled", encoding: { codeSize: 1, maxSize: 1, diff --git a/test/decrypt_contest_selections.test.ts b/test/decrypt_contest_selections.test.ts index 545a159a..522dd13c 100644 --- a/test/decrypt_contest_selections.test.ts +++ b/test/decrypt_contest_selections.test.ts @@ -10,6 +10,7 @@ const bigContest: ContestConfig = { markingType: { minMarks: 1, maxMarks: 1, + blankSubmission: "disabled", encoding: { codeSize: 1, maxSize: 41, diff --git a/test/encrypt_contest_selections.test.ts b/test/encrypt_contest_selections.test.ts index f56884a2..e3cb5315 100644 --- a/test/encrypt_contest_selections.test.ts +++ b/test/encrypt_contest_selections.test.ts @@ -9,6 +9,7 @@ const contestOne: ContestConfig = { markingType: { minMarks: 1, maxMarks: 1, + blankSubmission: "disabled", encoding: { codeSize: 1, maxSize: 1, @@ -67,6 +68,7 @@ describe('encryptContestSelections', () => { markingType: { minMarks: 1, maxMarks: 1, + blankSubmission: "disabled", encoding: { codeSize: 1, maxSize: 41, diff --git a/test/replies/otp_flow/get_us_configuration.json b/test/replies/otp_flow/get_us_configuration.json index bf1681c9..109c8daa 100644 --- a/test/replies/otp_flow/get_us_configuration.json +++ b/test/replies/otp_flow/get_us_configuration.json @@ -39,6 +39,7 @@ "markingType": { "minMarks": 1, "maxMarks": 1, + "blankSubmission": "disabled", "encoding": { "codeSize": 1, "maxSize": 1, @@ -73,6 +74,7 @@ "markingType": { "minMarks": 1, "maxMarks": 1, + "blankSubmission": "disabled", "encoding": { "codeSize": 1, "maxSize": 1, From 775847a05f87a6b62865b5a1b26c08a0ba77fa5e Mon Sep 17 00:00:00 2001 From: av-alexander Date: Mon, 18 Jul 2022 09:58:38 +0200 Subject: [PATCH 3/3] Update all contest configs with blankSubmission attr --- test/encoding/byte_encoding.test.ts | 1 + .../benaloh_flow/http_dbb_3003/get__us_configuration.json | 2 ++ test/verifier/readable_contest_selections.test.ts | 2 ++ 3 files changed, 5 insertions(+) diff --git a/test/encoding/byte_encoding.test.ts b/test/encoding/byte_encoding.test.ts index e5637bb7..6fd21858 100644 --- a/test/encoding/byte_encoding.test.ts +++ b/test/encoding/byte_encoding.test.ts @@ -10,6 +10,7 @@ const contestConfig: ContestConfig = { markingType: { minMarks: 1, maxMarks: 3, + blankSubmission: "disabled", encoding: { codeSize: 1, maxSize: 20, diff --git a/test/replies/benaloh_flow/http_dbb_3003/get__us_configuration.json b/test/replies/benaloh_flow/http_dbb_3003/get__us_configuration.json index bf1681c9..109c8daa 100644 --- a/test/replies/benaloh_flow/http_dbb_3003/get__us_configuration.json +++ b/test/replies/benaloh_flow/http_dbb_3003/get__us_configuration.json @@ -39,6 +39,7 @@ "markingType": { "minMarks": 1, "maxMarks": 1, + "blankSubmission": "disabled", "encoding": { "codeSize": 1, "maxSize": 1, @@ -73,6 +74,7 @@ "markingType": { "minMarks": 1, "maxMarks": 1, + "blankSubmission": "disabled", "encoding": { "codeSize": 1, "maxSize": 1, diff --git a/test/verifier/readable_contest_selections.test.ts b/test/verifier/readable_contest_selections.test.ts index 3e2165b2..b2c8a21b 100644 --- a/test/verifier/readable_contest_selections.test.ts +++ b/test/verifier/readable_contest_selections.test.ts @@ -10,6 +10,7 @@ const contestConfigs: ContestConfigMap = { "markingType": { "minMarks": 1, "maxMarks": 1, + "blankSubmission": "disabled", "encoding": { "codeSize": 1, "maxSize": 1, @@ -50,6 +51,7 @@ const contestConfigs: ContestConfigMap = { "markingType": { "minMarks": 1, "maxMarks": 1, + "blankSubmission": "disabled", "encoding": { "codeSize": 1, "maxSize": 1,