Below is the graphical definition of the contract tests implemented on the test folder
LockManagerTest
├── Given Deploying the contract
│ ├── When Constructor has invalid unlock mode
│ │ └── It Should revert
│ ├── When Constructor has invalid plugin mode
│ │ └── It Should revert
│ └── When Constructor with valid params
│ ├── It Registers the DAO address
│ ├── It Stores the given settings
│ └── It Stores the given token addresses
├── When calling setPluginAddress
│ ├── Given Invalid plugin
│ │ └── It should revert
│ ├── Given Invalid plugin interface
│ │ └── It should revert
│ ├── When setPluginAddress the first time
│ │ ├── It should set the address
│ │ └── It should revert if trying to update it later
│ └── When setPluginAddress when already set
│ └── It should revert
├── Given No locked tokens
│ ├── Given No token allowance no locked
│ │ ├── When Calling lock 1
│ │ │ └── It Should revert
│ │ ├── When Calling lockAndApprove 1
│ │ │ └── It Should revert
│ │ ├── When Calling approve 1
│ │ │ └── It Should revert
│ │ ├── When Calling lockAndVote 1
│ │ │ └── It Should revert
│ │ └── When Calling vote 1
│ │ └── It Should revert
│ └── Given With token allowance no locked
│ ├── When Calling lock 2
│ │ ├── It Should allow any token holder to lock
│ │ ├── It Should approve with the full token balance
│ │ └── It Should emit an event
│ ├── When Calling lockAndApprove 2
│ │ ├── It Should allow any token holder to lock
│ │ ├── It Should approve with the full token balance
│ │ ├── It The allocated token balance should have the full new balance
│ │ └── It Should emit an event
│ ├── When Calling approve 2
│ │ └── It Should revert
│ ├── When Calling lockAndVote 2
│ │ ├── It Should allow any token holder to lock
│ │ ├── It Should vote with the full token balance
│ │ ├── It The allocated token balance should have the full new balance
│ │ └── It Should emit an event
│ └── When Calling vote 2
│ └── It Should revert
├── Given Locked tokens
│ ├── Given No token allowance some locked
│ │ ├── When Calling lock 3
│ │ │ └── It Should revert
│ │ ├── When Calling lockAndApprove 3
│ │ │ └── It Should revert
│ │ ├── When Calling approve same balance 3
│ │ │ └── It Should revert
│ │ ├── When Calling approve more locked balance 3
│ │ │ ├── It Should approve with the full token balance
│ │ │ └── It Should emit an event
│ │ ├── When Calling lockAndVote 3
│ │ │ └── It Should revert
│ │ ├── When Calling vote same balance 3
│ │ │ └── It Should revert
│ │ └── When Calling vote more locked balance 3
│ │ ├── It Should vote with the full token balance
│ │ └── It Should emit an event
│ └── Given With token allowance some locked
│ ├── When Calling lock 4
│ │ ├── It Should allow any token holder to lock
│ │ ├── It Should approve with the full token balance
│ │ ├── It Should increase the locked amount
│ │ └── It Should emit an event
│ ├── When Calling lockAndApprove no prior power 4
│ │ ├── It Should allow any token holder to lock
│ │ ├── It Should approve with the full token balance
│ │ ├── It Should increase the locked amount
│ │ ├── It The allocated token balance should have the full new balance
│ │ └── It Should emit an event
│ ├── When Calling lockAndApprove with prior power 4
│ │ ├── It Should allow any token holder to lock
│ │ ├── It Should approve with the full token balance
│ │ ├── It Should increase the locked amount
│ │ ├── It The allocated token balance should have the full new balance
│ │ └── It Should emit an event
│ ├── When Calling approve same balance 4
│ │ └── It Should revert
│ ├── When Calling approve more locked balance 4
│ │ ├── It Should approve with the full token balance
│ │ └── It Should emit an event
│ ├── When Calling lockAndVote no prior power 4
│ │ ├── It Should allow any token holder to lock
│ │ ├── It Should vote with the full token balance
│ │ ├── It Should increase the locked amount
│ │ ├── It The allocated token balance should have the full new balance
│ │ └── It Should emit an event
│ ├── When Calling lockAndVote with prior power 4
│ │ ├── It Should allow any token holder to lock
│ │ ├── It Should vote with the full token balance
│ │ ├── It Should increase the locked amount
│ │ ├── It The allocated token balance should have the full new balance
│ │ └── It Should emit an event
│ ├── When Calling vote same balance 4
│ │ └── It Should revert
│ └── When Calling vote more locked balance 4
│ ├── It Should vote with the full token balance
│ └── It Should emit an event
├── Given Calling lock lockAndApprove or lockAndVote
│ ├── Given Empty plugin
│ │ └── It Locking and voting should revert
│ └── Given Invalid token
│ ├── It Locking should revert
│ ├── It Locking and voting should revert
│ └── It Voting should revert
├── Given ProposalCreated is called
│ ├── When The caller is not the plugin proposalCreated
│ │ └── It Should revert
│ └── When The caller is the plugin proposalCreated
│ └── It Adds the proposal ID to the list of known proposals
├── Given ProposalEnded is called
│ ├── When The caller is not the plugin ProposalEnded
│ │ └── It Should revert
│ └── When The caller is the plugin ProposalEnded
│ └── It Removes the proposal ID from the list of known proposals
├── Given Strict mode is set
│ ├── Given Didnt lock anything strict
│ │ └── When Trying to unlock 1 strict
│ │ └── It Should revert
│ ├── Given Locked but didnt approve anywhere strict
│ │ └── When Trying to unlock 2 approval strict
│ │ ├── It Should unlock and refund the full amount right away
│ │ └── It Should emit an event
│ ├── Given Locked but didnt vote anywhere strict
│ │ └── When Trying to unlock 2 voting strict
│ │ ├── It Should unlock and refund the full amount right away
│ │ └── It Should emit an event
│ ├── Given Locked but approved ended or executed proposals strict
│ │ └── When Trying to unlock 3 approved strict
│ │ ├── It Should unlock and refund the full amount right away
│ │ └── It Should emit an event
│ ├── Given Locked but voted on ended or executed proposals strict
│ │ └── When Trying to unlock 3 voted strict
│ │ ├── It Should unlock and refund the full amount right away
│ │ └── It Should emit an event
│ ├── Given Locked and approved currently active proposals strict
│ │ └── When Trying to unlock 4 voted strict
│ │ └── It Should revert
│ └── Given Locked and voted on currently active proposals strict
│ └── When Trying to unlock 4 voted strict 2
│ └── It Should revert
├── Given Flexible mode is set
│ ├── Given Didnt lock anything flexible
│ │ └── When Trying to unlock 1 flexible
│ │ └── It Should revert
│ ├── Given Locked but didnt approve anywhere flexible
│ │ └── When Trying to unlock 2 approval flexible
│ │ ├── It Should unlock and refund the full amount right away
│ │ └── It Should emit an event
│ ├── Given Locked but didnt vote anywhere flexible
│ │ └── When Trying to unlock 2 voting flexible
│ │ ├── It Should unlock and refund the full amount right away
│ │ └── It Should emit an event
│ ├── Given Locked but approved on ended or executed proposals flexible
│ │ └── When Trying to unlock 3 approved flexible
│ │ ├── It Should unlock and refund the full amount right away
│ │ └── It Should emit an event
│ ├── Given Locked but voted on ended or executed proposals flexible
│ │ └── When Trying to unlock 3 flexible
│ │ ├── It Should unlock and refund the full amount right away
│ │ └── It Should emit an event
│ ├── Given Locked and approved currently active proposals flexible
│ │ └── When Trying to unlock 4 approved flexible
│ │ ├── It Should deallocate the existing voting power from active proposals
│ │ ├── It Should unlock and refund the full amount
│ │ └── It Should emit an event
│ └── Given Locked and voted on currently active proposals flexible
│ └── When Trying to unlock 4 voted flexible
│ ├── It Should deallocate the existing voting power from active proposals
│ ├── It Should unlock and refund the full amount
│ └── It Should emit an event
├── When Calling plugin
│ └── It Should return the right address
├── When Calling token
│ └── It Should return the right address
├── Given No underlying token
│ └── When Calling underlyingToken empty
│ └── It Should return the token address
└── Given Underlying token defined
└── When Calling underlyingToken set
└── It Should return the right address
LockToApproveTest
├── When deploying the contract
│ ├── It should disable the initializers
│ └── It should initialize normally
├── Given a deployed contract
│ └── It should refuse to initialize again
├── Given a new proxy
│ └── Given calling initialize
│ ├── It should set the DAO address
│ ├── It should define the approval settings
│ ├── It should define the target config
│ ├── It should define the plugin metadata
│ └── It should define the lock manager
├── When calling updateSettings
│ ├── When updateSettings without the permission
│ │ └── It should revert
│ └── When updateSettings with the permission
│ └── It should update the values
├── When calling supportsInterface
│ ├── It does not support the empty interface
│ ├── It supports IERC165Upgradeable
│ ├── It supports IMembership
│ └── It supports ILockToApprove
├── Given Proposal not created
│ ├── Given No proposal creation permission
│ │ └── When Calling createProposal no perm
│ │ └── It Should revert
│ ├── Given Proposal creation permission granted
│ │ ├── When Calling createProposal empty dates
│ │ │ ├── It Should register the new proposal
│ │ │ ├── It Should assign a unique proposalId to it
│ │ │ ├── It Should register the given parameters
│ │ │ ├── It Should start immediately
│ │ │ ├── It Should end after proposalDuration
│ │ │ ├── It Should emit an event
│ │ │ └── It Should call proposalCreated on the manager
│ │ ├── When Calling createProposal explicit dates
│ │ │ ├── It Should start at the given startDate
│ │ │ ├── It Should revert if endDate is before proposalDuration
│ │ │ ├── It Should end on the given endDate
│ │ │ ├── It Should call proposalCreated on the manager
│ │ │ └── It Should emit an event
│ │ └── When Calling createProposal with duplicate data
│ │ ├── It Should revert
│ │ └── It Different data should produce different proposalId's
│ ├── When Calling the getters not created
│ │ ├── It getProposal should return empty values
│ │ ├── It isProposalOpen should return false
│ │ ├── It canApprove should return false
│ │ ├── It hasSucceeded should return false
│ │ └── It canExecute should return false
│ └── When Calling the rest of methods
│ └── It Should revert, even with the required permissions
├── Given Proposal created
│ ├── When Calling getProposal
│ │ └── It Should return the right values
│ ├── When Calling isProposalOpen
│ │ └── It Should return true
│ ├── When Calling canApprove
│ │ └── It Should return true when there is balance left to allocate
│ ├── Given No lock manager permission
│ │ ├── When Calling approve
│ │ │ └── It Reverts, regardless of the balance
│ │ └── When Calling clearApproval
│ │ └── It Reverts, regardless of the balance
│ ├── Given Lock manager permission is granted
│ │ ├── Given Proposal created unstarted
│ │ │ └── It Calling approve should revert, with or without balance
│ │ └── Given Proposal created and started
│ │ ├── When Calling approve no new locked balance
│ │ │ └── It Should revert
│ │ ├── When Calling approve new locked balance
│ │ │ ├── It Should increase the tally by the new amount
│ │ │ └── It Should emit an event
│ │ ├── When Calling clearApproval no approve balance
│ │ │ └── It Should do nothing
│ │ └── When Calling clearApproval with approve balance
│ │ ├── It Should unassign the current approver's approval
│ │ ├── It Should decrease the proposal tally by the right amount
│ │ ├── It Should emit an event
│ │ └── It usedVotingPower should return the right value
│ ├── When Calling hasSucceeded canExecute created
│ │ ├── It hasSucceeded should return false
│ │ └── It canExecute should return false
│ └── When Calling execute created
│ └── It Should revert, even with the required permission
├── Given Proposal defeated
│ ├── When Calling the getters defeated
│ │ ├── It getProposal should return the right values
│ │ ├── It isProposalOpen should return false
│ │ ├── It canApprove should return false
│ │ ├── It hasSucceeded should return false
│ │ └── It canExecute should return false
│ ├── When Calling approve or clearApproval defeated
│ │ ├── It Should revert for approve, despite having the permission
│ │ └── It Should do nothing for clearApproval
│ └── When Calling execute defeated
│ └── It Should revert, with or without permission
├── Given Proposal passed
│ ├── When Calling the getters passed
│ │ ├── It getProposal should return the right values
│ │ ├── It isProposalOpen should return false
│ │ ├── It canApprove should return false
│ │ ├── It hasSucceeded should return true
│ │ └── It canExecute should return true
│ ├── When Calling approve or clearApproval passed
│ │ └── It Should revert, despite having the permission
│ ├── Given No execute proposal permission
│ │ └── When Calling execute no perm
│ │ └── It Should revert
│ └── Given Execute proposal permission
│ └── When Calling execute passed
│ ├── It Should execute the actions of the proposal on the target
│ ├── It Should call proposalEnded on the LockManager
│ └── It Should emit an event
├── Given Proposal executed
│ ├── When Calling the getters executed
│ │ ├── It getProposal should return the right values
│ │ ├── It isProposalOpen should return false
│ │ ├── It canApprove should return false
│ │ ├── It hasSucceeded should return false
│ │ └── It canExecute should return false
│ ├── When Calling approve or clearApproval executed
│ │ └── It Should revert, despite having the permission
│ └── When Calling execute executed
│ └── It Should revert regardless of the permission
├── When Underlying token is not defined
│ └── It Should use the lockable token's balance to compute the approval ratio
├── When Underlying token is defined
│ └── It Should use the underlying token's balance to compute the approval ratio
├── When Calling isMember
│ ├── It Should return true when the sender has positive balance or locked tokens
│ └── It Should return false otherwise
├── When Calling customProposalParamsABI
│ └── It Should return the right value
├── Given Update approval settings permission granted
│ └── When Calling updatePluginSettings granted
│ ├── It Should set the new values
│ └── It Settings() should return the right values
└── Given No update approval settings permission
└── When Calling updatePluginSettings not granted
└── It Should revert
LockToApprovePluginSetupTest
├── When deploying a new instance
│ └── It completes without errors
├── When preparing an installation
│ ├── When passing an invalid token contract
│ │ └── It should revert
│ ├── It should return the plugin address
│ ├── It should return a list with the 3 helpers
│ ├── It all plugins use the same implementation
│ ├── It the plugin has the given settings
│ ├── It should set the address of the lockManager on the plugin
│ ├── It the plugin should have the right lockManager address
│ └── It the list of permissions should match
└── When preparing an uninstallation
├── Given a list of helpers with more or less than 3
│ └── It should revert
└── It generates a correct list of permission changes
LockToVoteTest
├── When deploying the contract
│ ├── It should disable the initializers
│ └── It should initialize normally
├── Given a deployed contract
│ └── It should refuse to initialize again
├── Given a new proxy
│ └── Given calling initialize
│ ├── It should set the DAO address
│ ├── It should define the voting settings
│ ├── It should define the target config
│ ├── It should define the plugin metadata
│ └── It should define the lock manager
├── When calling updateVotingSettings
│ ├── Given the caller has permission to call updateVotingSettings
│ │ ├── It Should set the new values
│ │ └── It Settings() should return the right values
│ └── Given the caller has no permission to call updateVotingSettings
│ └── It Should revert
├── When calling supportsInterface
│ ├── It does not support the empty interface
│ ├── It supports IERC165Upgradeable
│ ├── It supports IMembership
│ └── It supports ILockToVote
├── When calling createProposal
│ ├── Given create permission
│ │ ├── Given no minimum voting power
│ │ │ └── Given valid parameters
│ │ │ ├── It sets the given failuremap, if any
│ │ │ ├── It proposalIds are predictable and reproducible
│ │ │ ├── It sets the given voting mode, target, params and actions
│ │ │ ├── It emits an event
│ │ │ └── It reports proposalCreated() on the lockManager
│ │ ├── Given minimum voting power above zero
│ │ │ ├── It should succeed when the creator has enough balance
│ │ │ └── It should revert otherwise
│ │ ├── Given invalid dates
│ │ │ └── It should revert
│ │ └── Given duplicate proposal ID
│ │ └── It should revert
│ └── Given no create permission
│ └── It should revert
├── When calling canVote
│ ├── Given the proposal is open
│ │ ├── Given non empty vote
│ │ │ ├── Given submitting the first vote
│ │ │ │ ├── It should return true when the voter locked balance is positive
│ │ │ │ ├── It should return false when the voter has no locked balance
│ │ │ │ └── It should happen in all voting modes
│ │ │ └── Given voting again
│ │ │ ├── Given standard voting mode
│ │ │ │ ├── It should return true when voting the same with more balance
│ │ │ │ └── It should return false otherwise
│ │ │ ├── Given vote replacement mode
│ │ │ │ ├── It should return true when the locked balance is higher
│ │ │ │ └── It should return false otherwise
│ │ │ └── Given early execution mode
│ │ │ └── It should return false
│ │ └── Given empty vote
│ │ └── It should return false
│ ├── Given the proposal ended
│ │ ├── It should return false, regardless of prior votes
│ │ ├── It should return false, regardless of the locked balance
│ │ └── It should return false, regardless of the voting mode
│ └── Given the proposal is not created
│ └── It should revert
├── When calling vote
│ ├── Given canVote returns false // This relies on the tests above for canVote()
│ │ └── It should revert
│ ├── Given standard voting mode 2
│ │ ├── Given Voting the first time
│ │ │ ├── Given Has locked balance
│ │ │ │ ├── It should set the right voter's usedVotingPower
│ │ │ │ ├── It should set the right tally of the voted option
│ │ │ │ ├── It should set the right total voting power
│ │ │ │ └── It should emit an event
│ │ │ └── Given No locked balance // Redundant with canVote being false
│ │ │ └── It should revert
│ │ ├── Given Voting the same option
│ │ │ ├── Given Voting with the same locked balance // Redundant with canVote being false
│ │ │ │ └── It should revert
│ │ │ └── Given Voting with more locked balance
│ │ │ ├── It should increase the voter's usedVotingPower
│ │ │ ├── It should increase the tally of the voted option
│ │ │ ├── It should increase the total voting power
│ │ │ └── It should emit an event
│ │ └── Given Voting another option // Redundant with canVote being false
│ │ ├── Given Voting with the same locked balance 2
│ │ │ └── It should revert
│ │ └── Given Voting with more locked balance 2
│ │ └── It should revert
│ ├── Given vote replacement mode 2
│ │ ├── Given Voting the first time 2
│ │ │ ├── Given Has locked balance 2
│ │ │ │ ├── It should set the right voter's usedVotingPower
│ │ │ │ ├── It should set the right tally of the voted option
│ │ │ │ ├── It should set the right total voting power
│ │ │ │ └── It should emit an event
│ │ │ └── Given No locked balance 2 // Redundant with canVote being false
│ │ │ └── It should revert
│ │ ├── Given Voting the same option 2
│ │ │ ├── Given Voting with the same locked balance 3 // Redundant with canVote being false
│ │ │ │ └── It should revert
│ │ │ └── Given Voting with more locked balance 3
│ │ │ ├── It should increase the voter's usedVotingPower
│ │ │ ├── It should increase the tally of the voted option
│ │ │ ├── It should increase the total voting power
│ │ │ └── It should emit an event
│ │ └── Given Voting another option 2
│ │ ├── Given Voting with the same locked balance 4
│ │ │ ├── It should deallocate the current voting power
│ │ │ └── It should allocate that voting power into the new vote option
│ │ └── Given Voting with more locked balance 4
│ │ ├── It should deallocate the current voting power
│ │ ├── It the voter's usedVotingPower should reflect the new balance
│ │ ├── It should allocate to the tally of the voted option
│ │ ├── It should update the total voting power
│ │ └── It should emit an event
│ └── Given early execution mode 2
│ ├── Given Voting the first time 3
│ │ ├── Given Has locked balance 3
│ │ │ ├── It should set the right voter's usedVotingPower
│ │ │ ├── It should set the right tally of the voted option
│ │ │ ├── It should set the right total voting power
│ │ │ └── It should emit an event
│ │ └── Given No locked balance 3 // Redundant with canVote being false
│ │ └── It should revert
│ ├── Given Voting the same option 3
│ │ ├── Given Voting with the same locked balance 5
│ │ │ └── It should revert
│ │ └── Given Voting with more locked balance 5
│ │ ├── It should increase the voter's usedVotingPower
│ │ ├── It should increase the tally of the voted option
│ │ ├── It should increase the total voting power
│ │ └── It should emit an event
│ ├── Given Voting another option 3
│ │ ├── Given Voting with the same locked balance 6
│ │ │ └── It should revert
│ │ └── Given Voting with more locked balance 6
│ │ └── It should revert
│ └── Given the vote makes the proposal pass // partially redundant with canExecute() below
│ └── Given the caller has permission to call execute
│ ├── It hasSucceeded() should return true
│ ├── It canExecute() should return true
│ ├── It isSupportThresholdReachedEarly() should return true
│ ├── It isMinVotingPowerReached() should return true
│ ├── It isMinApprovalReached() should return true
│ ├── It should execute the proposal
│ ├── It the proposal should be marked as executed
│ └── It should emit an event
├── When calling clearvote
│ ├── Given the voter has no prior voting power
│ │ └── It should do nothing
│ ├── Given the proposal is not open
│ │ └── It should revert
│ ├── Given early execution mode 3
│ │ └── It should revert
│ ├── Given standard voting mode 3
│ │ ├── It should deallocate the current voting power
│ │ └── It should allocate that voting power into the new vote option
│ └── Given vote replacement mode 3
│ ├── It should deallocate the current voting power
│ └── It should allocate that voting power into the new vote option
├── When calling getVote
│ ├── Given the vote exists
│ │ └── It should return the right data
│ └── Given the vote does not exist
│ └── It should return empty values
├── When Calling the proposal getters
│ ├── Given it does not exist
│ │ ├── It getProposal() returns empty values
│ │ ├── It isProposalOpen() returns false
│ │ ├── It hasSucceeded() should return false
│ │ ├── It canExecute() should return false
│ │ ├── It isSupportThresholdReachedEarly() should return false
│ │ ├── It isSupportThresholdReached() should return false
│ │ ├── It isMinVotingPowerReached() should return false
│ │ ├── It isMinApprovalReached() should return false
│ │ └── It usedVotingPower() should return 0 for all voters
│ ├── Given it has not started
│ │ ├── It getProposal() returns the right values
│ │ ├── It isProposalOpen() returns false
│ │ ├── It hasSucceeded() should return false
│ │ ├── It canExecute() should return false
│ │ ├── It isSupportThresholdReachedEarly() should return false
│ │ ├── It isSupportThresholdReached() should return false
│ │ ├── It isMinVotingPowerReached() should return false
│ │ ├── It isMinApprovalReached() should return false
│ │ └── It usedVotingPower() should return 0 for all voters
│ ├── Given it has not passed yet
│ │ ├── It getProposal() returns the right values
│ │ ├── It isProposalOpen() returns true
│ │ ├── It hasSucceeded() should return false
│ │ ├── It canExecute() should return false
│ │ ├── It isSupportThresholdReachedEarly() should return false
│ │ ├── It isSupportThresholdReached() should return false
│ │ ├── It isMinVotingPowerReached() should return false
│ │ ├── It isMinApprovalReached() should return false
│ │ └── It usedVotingPower() should return the appropriate values
│ ├── Given it did not pass after endDate
│ │ ├── It getProposal() returns the right values
│ │ ├── It isProposalOpen() returns false
│ │ ├── It hasSucceeded() should return false
│ │ ├── It canExecute() should return false
│ │ ├── It isSupportThresholdReachedEarly() should return false
│ │ ├── Given the support threshold was not achieved
│ │ │ └── It isSupportThresholdReached() should return false
│ │ ├── Given the support threshold was achieved
│ │ │ └── It isSupportThresholdReached() should return true
│ │ ├── Given the minimum voting power was not reached
│ │ │ └── It isMinVotingPowerReached() should return false
│ │ ├── Given the minimum voting power was reached
│ │ │ └── It isMinVotingPowerReached() should return true
│ │ ├── Given the minimum approval tally was not achieved
│ │ │ └── It isMinApprovalReached() should return false
│ │ ├── Given the minimum approval tally was achieved
│ │ │ └── It isMinApprovalReached() should return true
│ │ └── It usedVotingPower() should return the appropriate values
│ ├── Given it has passed after endDate
│ │ ├── It getProposal() returns the right values
│ │ ├── It isProposalOpen() returns false
│ │ ├── It hasSucceeded() should return false
│ │ ├── Given The proposal has not been executed
│ │ │ └── It canExecute() should return true
│ │ ├── Given The proposal has been executed
│ │ │ └── It canExecute() should return false
│ │ ├── It isSupportThresholdReachedEarly() should return false
│ │ ├── It isSupportThresholdReached() should return true
│ │ ├── It isMinVotingPowerReached() should return true
│ │ ├── It isMinApprovalReached() should return true
│ │ └── It usedVotingPower() should return the appropriate values
│ └── Given it has passed early
│ ├── It getProposal() returns the right values
│ ├── It isProposalOpen() returns false
│ ├── It hasSucceeded() should return false
│ ├── Given The proposal has not been executed 2
│ │ └── It canExecute() should return true
│ ├── Given The proposal has been executed 2
│ │ └── It canExecute() should return false
│ ├── It isSupportThresholdReachedEarly() should return true
│ ├── It isSupportThresholdReached() should return true
│ ├── It isMinVotingPowerReached() should return true
│ ├── It isMinApprovalReached() should return true
│ └── It usedVotingPower() should return the appropriate values
├── When calling canExecute and hasSucceeded
│ ├── Given the proposal exists
│ │ ├── Given the proposal is not executed
│ │ │ ├── Given minVotingPower is reached
│ │ │ │ ├── Given minApproval is reached
│ │ │ │ │ ├── Given isSupportThresholdReachedEarly was reached before endDate
│ │ │ │ │ │ ├── Given the proposal allows early execution
│ │ │ │ │ │ │ ├── It canExecute() should return true
│ │ │ │ │ │ │ └── It hasSucceeded() should return true
│ │ │ │ │ │ └── Given the proposal does not allow early execution
│ │ │ │ │ │ ├── It canExecute() should return false
│ │ │ │ │ │ └── It hasSucceeded() should return false
│ │ │ │ │ ├── Given isSupportThresholdReached is reached
│ │ │ │ │ │ ├── It canExecute() should return false before endDate
│ │ │ │ │ │ ├── It hasSucceeded() should return false before endDate
│ │ │ │ │ │ ├── It canExecute() should return true after endDate
│ │ │ │ │ │ └── It hasSucceeded() should return true after endDate
│ │ │ │ │ └── Given isSupportThresholdReached is not reached
│ │ │ │ │ ├── It canExecute() should return false
│ │ │ │ │ └── It hasSucceeded() should return false
│ │ │ │ └── Given minApproval is not reached
│ │ │ │ ├── It canExecute() should return false
│ │ │ │ └── It hasSucceeded() should return false
│ │ │ └── Given minVotingPower is not reached
│ │ │ ├── It canExecute() should return false
│ │ │ └── It hasSucceeded() should return false
│ │ └── Given the proposal is executed
│ │ ├── It canExecute() should return false
│ │ └── It hasSucceeded() should return true
│ └── Given the proposal does not exist
│ ├── It canExecute() should revert
│ └── It hasSucceeded() should revert
├── When calling execute
│ ├── Given the caller no permission to call execute
│ │ └── It should revert
│ └── Given the caller has permission to call execute 2
│ ├── Given canExecute returns false // This relies on the tests above for canExecute()
│ │ └── It should revert
│ └── Given canExecute returns true
│ ├── It should mark the proposal as executed
│ ├── It should make the target execute the proposal actions
│ ├── It should emit an event
│ └── It should call proposalEnded on the LockManager
├── When Calling isMember
│ ├── It Should return true when the sender has positive balance or locked tokens
│ └── It Should return false otherwise
├── When Calling customProposalParamsABI
│ └── It Should return the right value
├── When Calling currentTokenSupply
│ └── It Should return the right value
├── When Calling supportThresholdRatio
│ └── It Should return the right value
├── When Calling minParticipationRatio
│ └── It Should return the right value
├── When Calling proposalDuration
│ └── It Should return the right value
├── When Calling minProposerVotingPower
│ └── It Should return the right value
├── When Calling minApprovalRatio
│ └── It Should return the right value
├── When Calling votingMode
│ └── It Should return the right value
├── When Calling currentTokenSupply 2
│ └── It Should return the right value
├── When Calling lockManager
│ └── It Should return the right address
├── When Calling token
│ └── It Should return the right address
└── When Calling underlyingToken
├── Given Underlying token is not defined
│ └── It Should use the (lockable) token's balance to compute the approval ratio
└── Given Underlying token is defined
└── It Should use the underlying token's balance to compute the approval ratio
LockToVotePluginSetupTest
├── When deploying a new instance
│ └── It completes without errors
├── When preparing an installation
│ ├── When passing an invalid token contract
│ │ └── It should revert
│ ├── It should return the plugin address
│ ├── It should return a list with the 3 helpers
│ ├── It all plugins use the same implementation
│ ├── It the plugin has the given settings
│ ├── It should set the address of the lockManager on the plugin
│ ├── It the plugin should have the right lockManager address
│ └── It the list of permissions should match
└── When preparing an uninstallation
├── Given a list of helpers with more or less than 3
│ └── It should revert
└── It generates a correct list of permission changes
MinVotingPowerConditionTest
├── When deploying the contract
│ ├── It records the given plugin address
│ └── It records the plugin's token address
└── When calling isGranted
├── Given a plugin with zero minimum voting power
│ └── It should return true
└── Given a plugin with a minimum voting power
├── It should return true when 'who' holds the minimum voting power
└── It should return false when 'who' holds less than the minimum voting power