Skip to content

Commit

Permalink
Scaffolding tests
Browse files Browse the repository at this point in the history
  • Loading branch information
brickpop committed Sep 5, 2023
1 parent b182e74 commit 9f55b30
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 61 deletions.
2 changes: 1 addition & 1 deletion packages/contracts/src/MainVotingPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ contract MainVotingPlugin is MajorityVotingBase {
VoteOption _voteOption,
bool _tryEarlyExecution
) external override returns (uint256 proposalId) {
if (!isEditor(_msgSender())) {
if (!isMember(_msgSender())) {
revert ProposalCreationForbidden(_msgSender());
}

Expand Down
7 changes: 7 additions & 0 deletions packages/contracts/test/unit-testing/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,10 @@ export const defaultMainVotingSettings = {
minProposerVotingPower: 0,
votingMode: EARLY_EXECUTION_MODE,
};

export enum VoteOption {
None = 0,
Abstain = 1,
Yes = 2,
No = 3,
}
201 changes: 153 additions & 48 deletions packages/contracts/test/unit-testing/main-voting-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ import {
EXECUTE_PERMISSION_ID,
MEMBER_PERMISSION_ID,
ROOT_PERMISSION_ID,
UPDATE_MULTISIG_SETTINGS_PERMISSION_ID,
UPDATE_ADDRESSES_PERMISSION_ID,
UPDATE_VOTING_SETTINGS_PERMISSION_ID,
VoteOption,
} from "./common";
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { expect } from "chai";
import { ethers } from "hardhat";
import { defaultMainVotingSettings } from "./common";
import { toUtf8Bytes } from "ethers/lib/utils";

export type InitData = { contentUri: string };
export const defaultInitData: InitData = {
Expand Down Expand Up @@ -57,17 +60,6 @@ describe("Default Main Voting plugin", function () {
new SpacePlugin__factory(alice),
);

await memberAccessPlugin.initialize(dao.address, {
proposalDuration: 60 * 60 * 24 * 5,
mainVotingPlugin: mainVotingPlugin.address,
});
await mainVotingPlugin.initialize(
dao.address,
defaultMainVotingSettings,
alice.address,
);
await spacePlugin.initialize(dao.address, defaultInput.contentUri);

// Alice is an editor
await dao.grant(
mainVotingPlugin.address,
Expand All @@ -89,15 +81,33 @@ describe("Default Main Voting plugin", function () {
// The plugin can execute on the DAO
await dao.grant(
dao.address,
memberAccessPlugin.address,
mainVotingPlugin.address,
EXECUTE_PERMISSION_ID,
);
// The DAO can update the plugin settings
await dao.grant(
memberAccessPlugin.address,
mainVotingPlugin.address,
dao.address,
UPDATE_MULTISIG_SETTINGS_PERMISSION_ID,
UPDATE_VOTING_SETTINGS_PERMISSION_ID,
);
// The DAO can report new/removed editors
await dao.grant(
mainVotingPlugin.address,
dao.address,
UPDATE_ADDRESSES_PERMISSION_ID,
);

// inits
await memberAccessPlugin.initialize(dao.address, {
proposalDuration: 60 * 60 * 24 * 5,
mainVotingPlugin: mainVotingPlugin.address,
});
await mainVotingPlugin.initialize(
dao.address,
defaultMainVotingSettings,
alice.address,
);
await spacePlugin.initialize(dao.address, defaultInput.contentUri);
});

describe("initialize", async () => {
Expand All @@ -121,34 +131,82 @@ describe("Default Main Voting plugin", function () {
});
});

// beforeEach(async () => {
// await dao.grant(memberAccessPlugin.address, alice.address, MEMBER_PERMISSION_ID);
// });

// it("reverts if sender lacks permission", async () => {
// await expect(memberAccessPlugin.connect(bob).storeNumber(newNumber))
// .to.be.revertedWithCustomError(memberAccessPlugin, "DaoUnauthorized")
// .withArgs(
// dao.address,
// memberAccessPlugin.address,
// bob.address,
// MEMBER_PERMISSION_ID,
// );
// });

// it("stores the number", async () => {
// await expect(memberAccessPlugin.storeNumber(newNumber)).to.not.be.reverted;
// expect(await memberAccessPlugin.number()).to.equal(newNumber);
// });

// it("emits the NumberStored event", async () => {
// await expect(memberAccessPlugin.storeNumber(newNumber))
// .to.emit(memberAccessPlugin, "NumberStored")
// .withArgs(newNumber);
// });

it("Only members can create proposals");
it("Only editors can vote on proposals");
it("Only members can create proposals", async () => {
await expect(
mainVotingPlugin.connect(alice).createProposal(
toUtf8Bytes("ipfs://"),
[],
0, // fail safe
0, // start date
0, // end date
VoteOption.Yes,
true, // auto execute
),
).to.not.be.reverted;

await expect(
mainVotingPlugin.connect(bob).createProposal(
toUtf8Bytes("ipfs://"),
[],
0, // fail safe
0, // start date
0, // end date
VoteOption.None,
true, // auto execute
),
).to.not.be.reverted;

await expect(
mainVotingPlugin.connect(charlie).createProposal(
toUtf8Bytes("ipfs://"),
[],
0, // fail safe
0, // start date
0, // end date
VoteOption.None,
true, // auto execute
),
).to.be.revertedWithCustomError(
mainVotingPlugin,
"ProposalCreationForbidden",
)
.withArgs(charlie.address);
});

it("Only editors can vote on proposals", async () => {
await expect(
mainVotingPlugin.connect(bob).createProposal(
toUtf8Bytes("ipfs://"),
[],
0, // fail safe
0, // start date
0, // end date
VoteOption.None,
true, // auto execute
),
).to.not.be.reverted;

let proposal = await mainVotingPlugin.getProposal(0);
expect(proposal.executed).to.eq(false);

// Bob can't vote
await expect(mainVotingPlugin.connect(bob).vote(0, VoteOption.Yes, true)).to
.be
.reverted;

// Alice can vote
await expect(mainVotingPlugin.vote(0, VoteOption.Yes, true)).to.not.be
.reverted;

proposal = await mainVotingPlugin.getProposal(0);
expect(proposal.executed).to.eq(true);
});

it("The plugin has one editor after created", async () => {
expect(await mainVotingPlugin.editorCount()).to.eq(1);
expect(await mainVotingPlugin.totalVotingPower(0)).to.eq(1);
expect(await mainVotingPlugin.totalVotingPower(100)).to.eq(1);
});

it("isMember() returns true when appropriate", async () => {
expect(await memberAccessPlugin.isMember(ADDRESS_ZERO)).to.eq(false);
Expand All @@ -174,7 +232,7 @@ describe("Default Main Voting plugin", function () {
MEMBER_PERMISSION_ID,
);

expect(await memberAccessPlugin.isMember(charlie.address)).to.eq(true);
expect(await memberAccessPlugin.isMember(charlie.address)).to.eq(false);

await dao.grant(
mainVotingPlugin.address,
Expand Down Expand Up @@ -204,19 +262,66 @@ describe("Default Main Voting plugin", function () {
});

describe("One editor", () => {
it("Proposals take immediate effect when created by the only editor");
it("Proposals take immediate effect when created by the only editor", async () => {
expect(await mainVotingPlugin.editorCount()).to.eq(1);

await expect(
mainVotingPlugin.createProposal(
toUtf8Bytes("ipfs://"),
[],
0, // fail safe
0, // start date
0, // end date
VoteOption.Yes,
true, // auto execute
),
).to.not.be.reverted;

const proposal = await mainVotingPlugin.getProposal(0);
expect(proposal.executed).to.eq(true);
});

it("Proposals are unsettled after created by a member", async () => {
expect(await mainVotingPlugin.editorCount()).to.eq(1);

await expect(
mainVotingPlugin.connect(bob).createProposal(
toUtf8Bytes("ipfs://"),
[],
0, // fail safe
0, // start date
0, // end date
VoteOption.None,
true, // auto execute
),
).to.not.be.reverted;

const proposal = await mainVotingPlugin.getProposal(0);
expect(proposal.executed).to.eq(false);
});
});
describe("Multiple editors", () => {
it("Proposals created by a member require editor votes");

it("Proposals created by an editor require additional votes");

it("A minimum participation is required");

it("A minimum support threshold is required");
});

it("Proposals require editor approval when created by a member");
it("Approved proposals can be executed by anyone");
it("Adding an editor increases the editorCount");
it("Removing an editor decreases the editorCount");

it("proposeAddEditor generates the right actions");
it("proposeRemoveEditor generates the right actions");

it("Approved proposals can be executed by anyone after passed");
it("Rejected proposals cannot be executed");
it("Membership proposals can only grant/revoke membership permissions");

it("Only the DAO can call functions on the space plugin");

it("The DAO can update the settings");
it("The DAO can report added/removed editors");
it("The DAO and deployers can upgrade the plugins");
});
25 changes: 13 additions & 12 deletions packages/contracts/test/unit-testing/member-access-voting-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,6 @@ describe("Default Member Access plugin", function () {
new SpacePlugin__factory(alice),
);

await memberAccessPlugin.initialize(dao.address, {
proposalDuration: 60 * 60 * 24 * 5,
mainVotingPlugin: mainVotingPlugin.address,
});
await mainVotingPlugin.initialize(
dao.address,
defaultMainVotingSettings,
alice.address,
);
await spacePlugin.initialize(dao.address, defaultInput.contentUri);

// Alice is an editor
await dao.grant(
mainVotingPlugin.address,
Expand All @@ -87,6 +76,18 @@ describe("Default Member Access plugin", function () {
dao.address,
ROOT_PERMISSION_ID,
);

// inits
await memberAccessPlugin.initialize(dao.address, {
proposalDuration: 60 * 60 * 24 * 5,
mainVotingPlugin: mainVotingPlugin.address,
});
await mainVotingPlugin.initialize(
dao.address,
defaultMainVotingSettings,
alice.address,
);
await spacePlugin.initialize(dao.address, defaultInput.contentUri);
});

describe("initialize", async () => {
Expand Down Expand Up @@ -185,7 +186,7 @@ describe("Default Member Access plugin", function () {
MEMBER_PERMISSION_ID,
);

expect(await memberAccessPlugin.isMember(charlie.address)).to.eq(true);
expect(await memberAccessPlugin.isMember(charlie.address)).to.eq(false);

await dao.grant(
mainVotingPlugin.address,
Expand Down

0 comments on commit 9f55b30

Please sign in to comment.