From bada4022dbf3f3c41f3b6c6890f4b3f4e71178aa Mon Sep 17 00:00:00 2001 From: ChaituVR Date: Thu, 5 Dec 2024 20:41:43 +0530 Subject: [PATCH 01/10] fix: update privacy check logic in proposal --- src/writer/proposal.ts | 5 ++++- src/writer/update-proposal.ts | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/writer/proposal.ts b/src/writer/proposal.ts index f3b28ad8..adbef5f3 100644 --- a/src/writer/proposal.ts +++ b/src/writer/proposal.ts @@ -91,6 +91,7 @@ export async function verify(body): Promise { if (space.voting?.delay) { const isValidDelay = msg.payload.start === created + space.voting.delay; + console.log('isValidDelay', isValidDelay, msg.payload.start, created, space.voting.delay); if (!isValidDelay) return Promise.reject('invalid voting delay'); } @@ -103,7 +104,9 @@ export async function verify(body): Promise { if (msg.payload.type !== space.voting.type) return Promise.reject('invalid voting type'); } - if (space.voting?.privacy !== 'any' && msg.payload.privacy) { + // Allows any value if space's privacy is set to `shutter` (for backward compatibility) + // In this case, we still store `shutter` on proposal's privacy field + if (!space.voting.privacy && msg.payload.privacy) { return Promise.reject('not allowed to set privacy'); } diff --git a/src/writer/update-proposal.ts b/src/writer/update-proposal.ts index 8d187786..e77245cb 100644 --- a/src/writer/update-proposal.ts +++ b/src/writer/update-proposal.ts @@ -49,7 +49,9 @@ export async function verify(body): Promise { if (proposal.author !== body.address) return Promise.reject('Not the author'); - if (space.voting?.privacy !== 'any' && msg.payload.privacy) { + // Allows any value if space's privacy is set to `shutter` (for backward compatibility) + // In this case, we still store `shutter` on proposal's privacy field + if (!space.voting.privacy && msg.payload.privacy) { return Promise.reject('not allowed to set privacy'); } From cfe46919ae66bae9a43e3b39e22eeb646b744c13 Mon Sep 17 00:00:00 2001 From: ChaituVR Date: Thu, 5 Dec 2024 20:42:35 +0530 Subject: [PATCH 02/10] remove unwanted log --- src/writer/proposal.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/writer/proposal.ts b/src/writer/proposal.ts index adbef5f3..8a6e6ed9 100644 --- a/src/writer/proposal.ts +++ b/src/writer/proposal.ts @@ -91,7 +91,6 @@ export async function verify(body): Promise { if (space.voting?.delay) { const isValidDelay = msg.payload.start === created + space.voting.delay; - console.log('isValidDelay', isValidDelay, msg.payload.start, created, space.voting.delay); if (!isValidDelay) return Promise.reject('invalid voting delay'); } From ca5306e94bb4abc99dab5a82a40ae483f845080d Mon Sep 17 00:00:00 2001 From: ChaituVR Date: Thu, 5 Dec 2024 21:13:28 +0530 Subject: [PATCH 03/10] fix --- src/writer/proposal.ts | 8 +++++--- src/writer/update-proposal.ts | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/writer/proposal.ts b/src/writer/proposal.ts index 8a6e6ed9..dd11b432 100644 --- a/src/writer/proposal.ts +++ b/src/writer/proposal.ts @@ -103,9 +103,11 @@ export async function verify(body): Promise { if (msg.payload.type !== space.voting.type) return Promise.reject('invalid voting type'); } - // Allows any value if space's privacy is set to `shutter` (for backward compatibility) - // In this case, we still store `shutter` on proposal's privacy field - if (!space.voting.privacy && msg.payload.privacy) { + if ( + space.voting?.privacy !== 'any' && + msg.payload.privacy && + !(space.voting.privacy === 'shutter' && msg.payload.privacy === 'shutter') + ) { return Promise.reject('not allowed to set privacy'); } diff --git a/src/writer/update-proposal.ts b/src/writer/update-proposal.ts index e77245cb..271f6366 100644 --- a/src/writer/update-proposal.ts +++ b/src/writer/update-proposal.ts @@ -49,9 +49,11 @@ export async function verify(body): Promise { if (proposal.author !== body.address) return Promise.reject('Not the author'); - // Allows any value if space's privacy is set to `shutter` (for backward compatibility) - // In this case, we still store `shutter` on proposal's privacy field - if (!space.voting.privacy && msg.payload.privacy) { + if ( + space.voting?.privacy !== 'any' && + msg.payload.privacy && + !(space.voting.privacy === 'shutter' && msg.payload.privacy === 'shutter') + ) { return Promise.reject('not allowed to set privacy'); } From a9ef94ed5e787b8546bd4608906f0cad9f06cc85 Mon Sep 17 00:00:00 2001 From: Wan Qi Chen <495709+wa0x6e@users.noreply.github.com> Date: Sun, 8 Dec 2024 13:33:29 +0800 Subject: [PATCH 04/10] test: add tests for proposal privacy --- test/unit/writer/proposal.test.ts | 159 ++++++++++++++++++++++++++++-- 1 file changed, 149 insertions(+), 10 deletions(-) diff --git a/test/unit/writer/proposal.test.ts b/test/unit/writer/proposal.test.ts index d2b5f49c..1c99429d 100644 --- a/test/unit/writer/proposal.test.ts +++ b/test/unit/writer/proposal.test.ts @@ -1,21 +1,21 @@ import omit from 'lodash/omit'; -import * as writer from '../../../src/writer/proposal'; -import input from '../../fixtures/writer-payload/proposal.json'; -import { spacesGetSpaceFixtures } from '../../fixtures/space'; import { + ACTIVE_PROPOSAL_BY_AUTHOR_LIMIT, ECOSYSTEM_SPACE_PROPOSAL_DAY_LIMIT, - FLAGGED_SPACE_PROPOSAL_DAY_LIMIT, - SPACE_PROPOSAL_DAY_LIMIT, - VERIFIED_SPACE_PROPOSAL_DAY_LIMIT, ECOSYSTEM_SPACE_PROPOSAL_MONTH_LIMIT, + FLAGGED_SPACE_PROPOSAL_DAY_LIMIT, FLAGGED_SPACE_PROPOSAL_MONTH_LIMIT, - SPACE_PROPOSAL_MONTH_LIMIT, - VERIFIED_SPACE_PROPOSAL_MONTH_LIMIT, MAINNET_ECOSYSTEM_SPACES, - ACTIVE_PROPOSAL_BY_AUTHOR_LIMIT, + SPACE_PROPOSAL_DAY_LIMIT, + SPACE_PROPOSAL_MONTH_LIMIT, TURBO_SPACE_PROPOSAL_DAY_LIMIT, - TURBO_SPACE_PROPOSAL_MONTH_LIMIT + TURBO_SPACE_PROPOSAL_MONTH_LIMIT, + VERIFIED_SPACE_PROPOSAL_DAY_LIMIT, + VERIFIED_SPACE_PROPOSAL_MONTH_LIMIT } from '../../../src/helpers/limits'; +import * as writer from '../../../src/writer/proposal'; +import { spacesGetSpaceFixtures } from '../../fixtures/space'; +import input from '../../fixtures/writer-payload/proposal.json'; const FLAGGED_ADDRESSES = ['0x0']; @@ -69,6 +69,12 @@ mockGetProposalsCount.mockResolvedValue([ } ]); +function updateInputPayload(input: any, payload: any) { + const msg = JSON.parse(input.msg); + + return { ...input, msg: JSON.stringify({ ...msg, payload: { ...msg.payload, ...payload } }) }; +} + describe('writer/proposal', () => { afterEach(jest.clearAllMocks); @@ -294,6 +300,139 @@ describe('writer/proposal', () => { expect(mockSnapshotUtilsValidate).toHaveBeenCalledTimes(0); }); }); + + describe('when the space is using ANY privacy', () => { + beforeEach(() => { + mockGetSpace.mockResolvedValueOnce({ + ...spacesGetSpaceFixtures, + voting: { privacy: 'any' } + }); + }); + + it('accepts a proposal with shutter privacy', async () => { + expect.assertions(2); + await expect( + writer.verify(updateInputPayload(input, { privacy: 'shutter' })) + ).resolves.toBeUndefined(); + expect(mockGetSpace).toHaveBeenCalledTimes(1); + }); + + it('accepts a proposal with undefined privacy', async () => { + expect.assertions(2); + await expect( + writer.verify(updateInputPayload(input, { privacy: undefined })) + ).resolves.toBeUndefined(); + expect(mockGetSpace).toHaveBeenCalledTimes(1); + }); + + it('accepts a proposal with no privacy', async () => { + expect.assertions(2); + await expect( + writer.verify(updateInputPayload(input, { privacy: '' })) + ).resolves.toBeUndefined(); + expect(mockGetSpace).toHaveBeenCalledTimes(1); + }); + }); + + // Fallback as if { privacy: '' } (privacy disabled) + describe('when the space is missing the privacy settings', () => { + beforeEach(() => { + mockGetSpace.mockResolvedValueOnce({ + ...spacesGetSpaceFixtures, + voting: undefined + }); + }); + + it('rejects a proposal with shutter privacy', async () => { + expect.assertions(2); + await expect( + writer.verify(updateInputPayload(input, { privacy: 'shutter' })) + ).rejects.toMatch('not allowed to set privacy'); + expect(mockGetSpace).toHaveBeenCalledTimes(1); + }); + + it('accepts a proposal with undefined privacy', async () => { + expect.assertions(2); + await expect( + writer.verify(updateInputPayload(input, { privacy: undefined })) + ).resolves.toBeUndefined(); + expect(mockGetSpace).toHaveBeenCalledTimes(1); + }); + + it('accepts a proposal with no privacy', async () => { + expect.assertions(2); + await expect( + writer.verify(updateInputPayload(input, { privacy: '' })) + ).resolves.toBeUndefined(); + expect(mockGetSpace).toHaveBeenCalledTimes(1); + }); + }); + + describe('when the space is using NO privacy', () => { + beforeEach(() => { + mockGetSpace.mockResolvedValueOnce({ + ...spacesGetSpaceFixtures, + voting: { privacy: '' } + }); + }); + + it('rejects a proposal with shutter privacy', async () => { + expect.assertions(2); + await expect( + writer.verify(updateInputPayload(input, { privacy: 'shutter' })) + ).rejects.toMatch('not allowed to set privacy'); + expect(mockGetSpace).toHaveBeenCalledTimes(1); + }); + + it('accepts a proposal with undefined privacy', async () => { + expect.assertions(2); + await expect( + writer.verify(updateInputPayload(input, { privacy: undefined })) + ).resolves.toBeUndefined(); + expect(mockGetSpace).toHaveBeenCalledTimes(1); + }); + + it('accepts a proposal with no privacy', async () => { + expect.assertions(2); + await expect( + writer.verify(updateInputPayload(input, { privacy: '' })) + ).resolves.toBeUndefined(); + expect(mockGetSpace).toHaveBeenCalledTimes(1); + }); + }); + + describe('when the space is using SHUTTER privacy', () => { + beforeEach(() => { + mockGetSpace.mockResolvedValueOnce({ + ...spacesGetSpaceFixtures, + voting: { privacy: 'shutter' } + }); + }); + + it('accepts a proposal with shutter privacy', async () => { + expect.assertions(2); + await expect( + writer.verify(updateInputPayload(input, { privacy: 'shutter' })) + ).resolves.toBeUndefined(); + expect(mockGetSpace).toHaveBeenCalledTimes(1); + }); + + it('accepts a proposal with undefined privacy', async () => { + expect.assertions(2); + await expect( + writer.verify(updateInputPayload(input, { privacy: undefined })) + ).resolves.toBeUndefined(); + expect(mockGetSpace).toHaveBeenCalledTimes(1); + }); + + it('rejects a proposal with no privacy', async () => { + expect.assertions(2); + await expect(writer.verify(updateInputPayload(input, { privacy: '' }))).rejects.toMatch( + 'not allowed to set privacy' + ); + expect(mockGetSpace).toHaveBeenCalledTimes(1); + }); + }); }); it('rejects if the snapshot is in the future', async () => { From 2b4c67fc8617c2304846b308f3620249e8ee9f88 Mon Sep 17 00:00:00 2001 From: ChaituVR Date: Sat, 4 Jan 2025 15:23:42 +0530 Subject: [PATCH 05/10] fix tests --- src/writer/proposal.ts | 2 +- test/schema.sql | 1 + test/unit/writer/proposal.test.ts | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/writer/proposal.ts b/src/writer/proposal.ts index 41f44fae..789c0fdf 100644 --- a/src/writer/proposal.ts +++ b/src/writer/proposal.ts @@ -105,7 +105,7 @@ export async function verify(body): Promise { if ( space.voting?.privacy !== 'any' && msg.payload.privacy && - !(space.voting.privacy === 'shutter' && msg.payload.privacy === 'shutter') + !(space.voting?.privacy === 'shutter' && msg.payload.privacy === 'shutter') ) { return Promise.reject('not allowed to set privacy'); } diff --git a/test/schema.sql b/test/schema.sql index c18a8428..9ca520ea 100644 --- a/test/schema.sql +++ b/test/schema.sql @@ -58,6 +58,7 @@ CREATE TABLE proposals ( scores_state VARCHAR(24) NOT NULL, scores_total DECIMAL(64,30) NOT NULL, scores_updated INT(11) NOT NULL, + vp_value_by_strategy JSON DEFAULT NULL, votes INT(12) NOT NULL, flagged INT NOT NULL DEFAULT 0, PRIMARY KEY (id), diff --git a/test/unit/writer/proposal.test.ts b/test/unit/writer/proposal.test.ts index 1c99429d..ecd88e56 100644 --- a/test/unit/writer/proposal.test.ts +++ b/test/unit/writer/proposal.test.ts @@ -425,11 +425,11 @@ describe('writer/proposal', () => { expect(mockGetSpace).toHaveBeenCalledTimes(1); }); - it('rejects a proposal with no privacy', async () => { + it('accepts a proposal with empty string in privacy', async () => { expect.assertions(2); - await expect(writer.verify(updateInputPayload(input, { privacy: '' }))).rejects.toMatch( - 'not allowed to set privacy' - ); + await expect( + writer.verify(updateInputPayload(input, { privacy: '' })) + ).resolves.toBeUndefined(); expect(mockGetSpace).toHaveBeenCalledTimes(1); }); }); From b848c06857d23cd0e2ce9d071190f258694cd095 Mon Sep 17 00:00:00 2001 From: Chaitanya Date: Tue, 7 Jan 2025 11:03:50 +0530 Subject: [PATCH 06/10] Update test/schema.sql --- test/schema.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/test/schema.sql b/test/schema.sql index 9ca520ea..c18a8428 100644 --- a/test/schema.sql +++ b/test/schema.sql @@ -58,7 +58,6 @@ CREATE TABLE proposals ( scores_state VARCHAR(24) NOT NULL, scores_total DECIMAL(64,30) NOT NULL, scores_updated INT(11) NOT NULL, - vp_value_by_strategy JSON DEFAULT NULL, votes INT(12) NOT NULL, flagged INT NOT NULL DEFAULT 0, PRIMARY KEY (id), From 7220696cc1e5851d035319341972f6d103e492a6 Mon Sep 17 00:00:00 2001 From: Chaitanya Date: Tue, 7 Jan 2025 11:13:40 +0530 Subject: [PATCH 07/10] Remove duplicate test --- test/unit/writer/proposal.test.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/unit/writer/proposal.test.ts b/test/unit/writer/proposal.test.ts index ecd88e56..dc76d015 100644 --- a/test/unit/writer/proposal.test.ts +++ b/test/unit/writer/proposal.test.ts @@ -424,14 +424,6 @@ describe('writer/proposal', () => { ).resolves.toBeUndefined(); expect(mockGetSpace).toHaveBeenCalledTimes(1); }); - - it('accepts a proposal with empty string in privacy', async () => { - expect.assertions(2); - await expect( - writer.verify(updateInputPayload(input, { privacy: '' })) - ).resolves.toBeUndefined(); - expect(mockGetSpace).toHaveBeenCalledTimes(1); - }); }); }); From ffafd1945b04f7c1c181c403bdb5dab370ace0f6 Mon Sep 17 00:00:00 2001 From: Wan Qi Chen <495709+wa0x6e@users.noreply.github.com> Date: Tue, 7 Jan 2025 21:21:19 +0400 Subject: [PATCH 08/10] test: remove superfluous assertions --- test/unit/writer/proposal.test.ts | 66 +++++++++++-------------------- 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/test/unit/writer/proposal.test.ts b/test/unit/writer/proposal.test.ts index dc76d015..f8b7268f 100644 --- a/test/unit/writer/proposal.test.ts +++ b/test/unit/writer/proposal.test.ts @@ -309,28 +309,22 @@ describe('writer/proposal', () => { }); }); - it('accepts a proposal with shutter privacy', async () => { - expect.assertions(2); - await expect( + it('accepts a proposal with shutter privacy', () => { + return expect( writer.verify(updateInputPayload(input, { privacy: 'shutter' })) ).resolves.toBeUndefined(); - expect(mockGetSpace).toHaveBeenCalledTimes(1); }); - it('accepts a proposal with undefined privacy', async () => { - expect.assertions(2); - await expect( + it('accepts a proposal with undefined privacy', () => { + return expect( writer.verify(updateInputPayload(input, { privacy: undefined })) ).resolves.toBeUndefined(); - expect(mockGetSpace).toHaveBeenCalledTimes(1); }); - it('accepts a proposal with no privacy', async () => { - expect.assertions(2); - await expect( + it('accepts a proposal with no privacy', () => { + return expect( writer.verify(updateInputPayload(input, { privacy: '' })) ).resolves.toBeUndefined(); - expect(mockGetSpace).toHaveBeenCalledTimes(1); }); }); @@ -343,28 +337,22 @@ describe('writer/proposal', () => { }); }); - it('rejects a proposal with shutter privacy', async () => { - expect.assertions(2); - await expect( + it('rejects a proposal with shutter privacy', () => { + return expect( writer.verify(updateInputPayload(input, { privacy: 'shutter' })) ).rejects.toMatch('not allowed to set privacy'); - expect(mockGetSpace).toHaveBeenCalledTimes(1); }); - it('accepts a proposal with undefined privacy', async () => { - expect.assertions(2); - await expect( + it('accepts a proposal with undefined privacy', () => { + return expect( writer.verify(updateInputPayload(input, { privacy: undefined })) ).resolves.toBeUndefined(); - expect(mockGetSpace).toHaveBeenCalledTimes(1); }); - it('accepts a proposal with no privacy', async () => { - expect.assertions(2); - await expect( + it('accepts a proposal with no privacy', () => { + return expect( writer.verify(updateInputPayload(input, { privacy: '' })) ).resolves.toBeUndefined(); - expect(mockGetSpace).toHaveBeenCalledTimes(1); }); }); @@ -376,28 +364,22 @@ describe('writer/proposal', () => { }); }); - it('rejects a proposal with shutter privacy', async () => { - expect.assertions(2); - await expect( + it('rejects a proposal with shutter privacy', () => { + return expect( writer.verify(updateInputPayload(input, { privacy: 'shutter' })) ).rejects.toMatch('not allowed to set privacy'); - expect(mockGetSpace).toHaveBeenCalledTimes(1); }); - it('accepts a proposal with undefined privacy', async () => { - expect.assertions(2); - await expect( + it('accepts a proposal with undefined privacy', () => { + return expect( writer.verify(updateInputPayload(input, { privacy: undefined })) ).resolves.toBeUndefined(); - expect(mockGetSpace).toHaveBeenCalledTimes(1); }); - it('accepts a proposal with no privacy', async () => { - expect.assertions(2); - await expect( + it('accepts a proposal with no privacy', () => { + return expect( writer.verify(updateInputPayload(input, { privacy: '' })) ).resolves.toBeUndefined(); - expect(mockGetSpace).toHaveBeenCalledTimes(1); }); }); @@ -409,20 +391,16 @@ describe('writer/proposal', () => { }); }); - it('accepts a proposal with shutter privacy', async () => { - expect.assertions(2); - await expect( + it('accepts a proposal with shutter privacy', () => { + return expect( writer.verify(updateInputPayload(input, { privacy: 'shutter' })) ).resolves.toBeUndefined(); - expect(mockGetSpace).toHaveBeenCalledTimes(1); }); - it('accepts a proposal with undefined privacy', async () => { - expect.assertions(2); - await expect( + it('accepts a proposal with undefined privacy', () => { + return expect( writer.verify(updateInputPayload(input, { privacy: undefined })) ).resolves.toBeUndefined(); - expect(mockGetSpace).toHaveBeenCalledTimes(1); }); }); }); From 6ed7a53f561df421e7ebe2979c9bacd8d6d22167 Mon Sep 17 00:00:00 2001 From: ChaituVR Date: Tue, 7 Jan 2025 23:31:47 +0530 Subject: [PATCH 09/10] fix handle both undefined and empty string cases in proposal --- src/ingestor.ts | 4 ++-- src/writer/proposal.ts | 13 ++++++------- src/writer/update-proposal.ts | 13 ++++++------- test/unit/writer/proposal.test.ts | 11 +++++++++-- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/ingestor.ts b/src/ingestor.ts index 192595a2..30b02017 100644 --- a/src/ingestor.ts +++ b/src/ingestor.ts @@ -142,7 +142,7 @@ export default async function ingestor(req) { body: message.body, discussion: message.discussion || '', choices: message.choices, - privacy: message.privacy || '', + privacy: message.privacy, labels: message.labels || [], start: message.start, end: message.end, @@ -169,7 +169,7 @@ export default async function ingestor(req) { name: message.title, body: message.body, discussion: message.discussion || '', - privacy: message.privacy || '', + privacy: message.privacy, choices: message.choices, labels: message.labels || [], metadata: { diff --git a/src/writer/proposal.ts b/src/writer/proposal.ts index 789c0fdf..43817d90 100644 --- a/src/writer/proposal.ts +++ b/src/writer/proposal.ts @@ -102,11 +102,10 @@ export async function verify(body): Promise { if (msg.payload.type !== space.voting.type) return Promise.reject('invalid voting type'); } - if ( - space.voting?.privacy !== 'any' && - msg.payload.privacy && - !(space.voting?.privacy === 'shutter' && msg.payload.privacy === 'shutter') - ) { + const spacePrivacy = space.voting?.privacy ?? 'any'; + const proposalPrivacy = msg.payload.privacy; + + if (proposalPrivacy !== undefined && spacePrivacy !== 'any' && spacePrivacy !== proposalPrivacy) { return Promise.reject('not allowed to set privacy'); } @@ -214,9 +213,9 @@ export async function action(body, ipfs, receipt, id): Promise { const plugins = JSON.stringify(metadata.plugins || {}); const spaceNetwork = spaceSettings.network; const proposalSnapshot = parseInt(msg.payload.snapshot || '0'); - let privacy = spaceSettings.voting?.privacy || ''; + let privacy = spaceSettings.voting?.privacy ?? 'any'; if (privacy === 'any') { - privacy = msg.payload.privacy; + privacy = msg.payload.privacy ?? ''; } let quorum = spaceSettings.voting?.quorum || 0; diff --git a/src/writer/update-proposal.ts b/src/writer/update-proposal.ts index 271f6366..680119cf 100644 --- a/src/writer/update-proposal.ts +++ b/src/writer/update-proposal.ts @@ -49,11 +49,10 @@ export async function verify(body): Promise { if (proposal.author !== body.address) return Promise.reject('Not the author'); - if ( - space.voting?.privacy !== 'any' && - msg.payload.privacy && - !(space.voting.privacy === 'shutter' && msg.payload.privacy === 'shutter') - ) { + const spacePrivacy = space.voting?.privacy ?? 'any'; + const proposalPrivacy = msg.payload.privacy; + + if (proposalPrivacy !== undefined && spacePrivacy !== 'any' && spacePrivacy !== proposalPrivacy) { return Promise.reject('not allowed to set privacy'); } @@ -72,9 +71,9 @@ export async function action(body, ipfs): Promise { const metadata = msg.payload.metadata || {}; const plugins = JSON.stringify(metadata.plugins || {}); const spaceSettings = await getSpace(msg.space); - let privacy = spaceSettings.voting?.privacy || ''; + let privacy = spaceSettings.voting?.privacy ?? 'any'; if (privacy === 'any') { - privacy = msg.payload.privacy; + privacy = msg.payload.privacy ?? ''; } const proposal = { diff --git a/test/unit/writer/proposal.test.ts b/test/unit/writer/proposal.test.ts index f8b7268f..8dd623be 100644 --- a/test/unit/writer/proposal.test.ts +++ b/test/unit/writer/proposal.test.ts @@ -337,10 +337,10 @@ describe('writer/proposal', () => { }); }); - it('rejects a proposal with shutter privacy', () => { + it('accepts a proposal with shutter privacy', () => { return expect( writer.verify(updateInputPayload(input, { privacy: 'shutter' })) - ).rejects.toMatch('not allowed to set privacy'); + ).resolves.toBeUndefined(); }); it('accepts a proposal with undefined privacy', () => { @@ -402,6 +402,13 @@ describe('writer/proposal', () => { writer.verify(updateInputPayload(input, { privacy: undefined })) ).resolves.toBeUndefined(); }); + + it('rejects a proposal with privacy empty string', async () => { + expect.assertions(1); + await expect(writer.verify(updateInputPayload(input, { privacy: '' }))).rejects.toMatch( + 'not allowed to set privacy' + ); + }); }); }); From 66585e0915898c845526f05cdce28c7ea97a3eb2 Mon Sep 17 00:00:00 2001 From: Wan Qi Chen <495709+wa0x6e@users.noreply.github.com> Date: Tue, 7 Jan 2025 22:20:36 +0400 Subject: [PATCH 10/10] test: update test for new privacy behavior when missing --- test/unit/writer/proposal.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/writer/proposal.test.ts b/test/unit/writer/proposal.test.ts index f8b7268f..c880e561 100644 --- a/test/unit/writer/proposal.test.ts +++ b/test/unit/writer/proposal.test.ts @@ -328,7 +328,7 @@ describe('writer/proposal', () => { }); }); - // Fallback as if { privacy: '' } (privacy disabled) + // Fallback as if { privacy: 'any' } describe('when the space is missing the privacy settings', () => { beforeEach(() => { mockGetSpace.mockResolvedValueOnce({ @@ -337,10 +337,10 @@ describe('writer/proposal', () => { }); }); - it('rejects a proposal with shutter privacy', () => { + it('accepts a proposal with shutter privacy', () => { return expect( writer.verify(updateInputPayload(input, { privacy: 'shutter' })) - ).rejects.toMatch('not allowed to set privacy'); + ).resolves.toBeUndefined(); }); it('accepts a proposal with undefined privacy', () => {