Browse Source

integration tests: tx sender always resolves finalized transactions

Mokhtar Naamani 4 years ago
parent
commit
9cac9c601b
27 changed files with 298 additions and 366 deletions
  1. 6 2
      tests/network-tests/src/Api.ts
  2. 74 16
      tests/network-tests/src/Fixture.ts
  3. 3 15
      tests/network-tests/src/fixtures/contentDirectoryModule.ts
  4. 0 34
      tests/network-tests/src/fixtures/councilElectionHappyCase.ts
  5. 10 11
      tests/network-tests/src/fixtures/councilElectionModule.ts
  6. 8 11
      tests/network-tests/src/fixtures/membershipModule.ts
  7. 15 65
      tests/network-tests/src/fixtures/proposalsModule.ts
  8. 6 6
      tests/network-tests/src/fixtures/sudoHireLead.ts
  9. 30 79
      tests/network-tests/src/fixtures/workingGroupModule.ts
  10. 1 1
      tests/network-tests/src/flows/contentDirectory/creatingChannel.ts
  11. 1 1
      tests/network-tests/src/flows/contentDirectory/creatingVideo.ts
  12. 1 1
      tests/network-tests/src/flows/contentDirectory/updatingChannel.ts
  13. 7 9
      tests/network-tests/src/flows/membership/creatingMemberships.ts
  14. 17 13
      tests/network-tests/src/flows/proposals/councilSetup.ts
  15. 1 1
      tests/network-tests/src/flows/proposals/electionParametersProposal.ts
  16. 17 16
      tests/network-tests/src/flows/proposals/manageLeaderRole.ts
  17. 1 1
      tests/network-tests/src/flows/proposals/spendingProposal.ts
  18. 1 1
      tests/network-tests/src/flows/proposals/textProposal.ts
  19. 2 2
      tests/network-tests/src/flows/proposals/updateRuntime.ts
  20. 1 1
      tests/network-tests/src/flows/proposals/validatorCountProposal.ts
  21. 2 2
      tests/network-tests/src/flows/proposals/workingGroupMintCapacityProposal.ts
  22. 16 4
      tests/network-tests/src/flows/workingGroup/atLeastValueBug.ts
  23. 1 1
      tests/network-tests/src/flows/workingGroup/leaderSetup.ts
  24. 8 8
      tests/network-tests/src/flows/workingGroup/manageWorkerAsLead.ts
  25. 8 8
      tests/network-tests/src/flows/workingGroup/manageWorkerAsWorker.ts
  26. 8 8
      tests/network-tests/src/flows/workingGroup/workerPayout.ts
  27. 53 49
      tests/network-tests/src/sender.ts

+ 6 - 2
tests/network-tests/src/Api.ts

@@ -90,6 +90,10 @@ export class Api {
     this.api.disconnect()
   }
 
+  public enableTxLogs(): void {
+    this.sender.enableLogs()
+  }
+
   public createKeyPairs(n: number): KeyringPair[] {
     const nKeyPairs: KeyringPair[] = []
     for (let i = 0; i < n; i++) {
@@ -143,8 +147,8 @@ export class Api {
     return this.transferBalance(this.treasuryAccount, to, amount)
   }
 
-  public treasuryTransferBalanceToAccounts(to: string[], amount: BN): void {
-    to.map((account) => this.transferBalance(this.treasuryAccount, account, amount))
+  public treasuryTransferBalanceToAccounts(to: string[], amount: BN): Promise<ISubmittableResult[]> {
+    return Promise.all(to.map((account) => this.transferBalance(this.treasuryAccount, account, amount)))
   }
 
   public getPaidMembershipTerms(paidTermsId: PaidTermId): Promise<PaidMembershipTerms> {

+ 74 - 16
tests/network-tests/src/Fixture.ts

@@ -1,24 +1,26 @@
 import { Api } from './Api'
+import { assert } from 'chai'
+import { ISubmittableResult } from '@polkadot/types/types/'
+import { DispatchResult } from '@polkadot/types/interfaces/system'
 
 export interface Fixture {
-  run(): Promise<void>
-  executionError(): Error | undefined
+  runner(): Promise<void>
+  // executionError(): Error | undefined
 }
 
 export class BaseFixture implements Fixture {
   protected api: Api
-  private failed = false
   private executed = false
   // The reason of the "Unexpected" failure of running the fixture
-  private err: Error | undefined
+  private err: Error | undefined = undefined
 
   constructor(api: Api) {
     this.api = api
   }
 
-  public async run(): Promise<void> {
+  public async runner(): Promise<void> {
     this.executed = true
-    await this.execute()
+    return this.execute()
   }
 
   protected async execute(): Promise<void> {
@@ -27,7 +29,6 @@ export class BaseFixture implements Fixture {
 
   // Used by execution implementation to signal failure
   protected error(err: Error): void {
-    this.failed = true
     this.err = err
   }
 
@@ -36,7 +37,10 @@ export class BaseFixture implements Fixture {
   }
 
   public didFail(): boolean {
-    return this.failed
+    if (!this.didExecute()) {
+      throw new Error('Trying to check execution result before running fixture')
+    }
+    return this.err !== undefined
   }
 
   public executionError(): Error | undefined {
@@ -45,28 +49,82 @@ export class BaseFixture implements Fixture {
     }
     return this.err
   }
+
+  protected async expectDispatchError(
+    operation: Promise<ISubmittableResult>,
+    errMessage: string
+  ): Promise<ISubmittableResult> {
+    const result = await operation
+    const success = result.findRecord('system', 'ExtrinsicSuccess')
+
+    if (success) {
+      const sudid = result.findRecord('sudo', 'Sudid')
+      if (sudid) {
+        const dispatchResult = sudid.event.data[0] as DispatchResult
+        if (dispatchResult.isOk) {
+          this.error(new Error(errMessage))
+        }
+      } else {
+        this.error(new Error(errMessage))
+      }
+    }
+
+    return result
+  }
+
+  protected async expectDispatchSuccess(
+    operation: Promise<ISubmittableResult>,
+    errMessage: string
+  ): Promise<ISubmittableResult> {
+    const result = await operation
+    const success = result.findRecord('system', 'ExtrinsicSuccess')
+
+    if (success) {
+      const sudid = result.findRecord('sudo', 'Sudid')
+      if (sudid) {
+        const dispatchResult = sudid.event.data[0] as DispatchResult
+        if (dispatchResult.isError) {
+          this.error(new Error(errMessage))
+          // Log DispatchError details
+        }
+      }
+    } else {
+      this.error(new Error(errMessage))
+      // Log DispatchError
+    }
+
+    return result
+  }
 }
 
 // Runs a fixture and measures how long it took to run
-// Ensures fixture only runs once
+// Ensures fixture only runs once, and asserts that it doesn't fail
 export class FixtureRunner {
-  private fixture: Fixture
+  private fixture: BaseFixture
   private ran = false
 
-  constructor(fixture: Fixture) {
+  constructor(fixture: BaseFixture) {
     this.fixture = fixture
   }
 
-  public async run(): Promise<Error | undefined> {
+  public async run(): Promise<void> {
     if (this.ran) {
       throw new Error('Fixture already ran')
     }
 
     this.ran = true
-    // record starting block
-    await this.fixture.run()
-    // record ending block
 
-    return this.fixture.executionError()
+    // TODO: record starting block
+
+    try {
+      await this.fixture.runner()
+      // TODO: record ending block
+      const err = this.fixture.executionError()
+      assert.equal(err, undefined)
+    } catch (err) {
+      // This should make tracking which fixture caused the exception easier
+      console.log(err)
+      throw err
+    }
   }
 }

+ 3 - 15
tests/network-tests/src/fixtures/contentDirectoryModule.ts

@@ -12,12 +12,8 @@ export class CreateChannelFixture implements Fixture {
     this.channelEntity = channelEntity
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     await this.api.createChannelEntity(this.channelEntity)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -30,12 +26,8 @@ export class CreateVideoFixture implements Fixture {
     this.videoEntity = videoEntity
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     await this.api.createVideoEntity(this.videoEntity)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -50,11 +42,7 @@ export class UpdateChannelFixture implements Fixture {
     this.uniquePropValue = uniquePropValue
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     await this.api.updateChannelEntity(this.channelUpdateInput, this.uniquePropValue)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }

+ 0 - 34
tests/network-tests/src/fixtures/councilElectionHappyCase.ts

@@ -1,34 +0,0 @@
-import { Fixture } from '../Fixture'
-import { ElectCouncilFixture } from './councilElectionModule'
-import { Api } from '../Api'
-import BN from 'bn.js'
-
-export class CouncilElectionHappyCaseFixture implements Fixture {
-  private api: Api
-  private voters: string[]
-  private applicants: string[]
-  private k: number
-  private greaterStake: BN
-  private lesserStake: BN
-
-  constructor(api: Api, voters: string[], applicants: string[], k: number, greaterStake: BN, lesserStake: BN) {
-    this.api = api
-    this.voters = voters
-    this.applicants = applicants
-    this.k = k
-    this.greaterStake = greaterStake
-    this.lesserStake = lesserStake
-  }
-
-  public async runner(expectFailure: boolean): Promise<void> {
-    const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture(
-      this.api,
-      this.voters,
-      this.applicants,
-      this.k,
-      this.greaterStake,
-      this.lesserStake
-    )
-    await electCouncilFixture.runner(false)
-  }
-}

+ 10 - 11
tests/network-tests/src/fixtures/councilElectionModule.ts

@@ -4,10 +4,9 @@ import { assert } from 'chai'
 import { Seat } from '@joystream/types/council'
 import { v4 as uuid } from 'uuid'
 import { Utils } from '../utils'
-import { Fixture } from '../Fixture'
+import { BaseFixture } from '../Fixture'
 
-export class ElectCouncilFixture implements Fixture {
-  private api: Api
+export class ElectCouncilFixture extends BaseFixture {
   private voters: string[]
   private applicants: string[]
   private k: number
@@ -15,7 +14,7 @@ export class ElectCouncilFixture implements Fixture {
   private lesserStake: BN
 
   public constructor(api: Api, voters: string[], applicants: string[], k: number, greaterStake: BN, lesserStake: BN) {
-    this.api = api
+    super(api)
     this.voters = voters
     this.applicants = applicants
     this.k = k
@@ -23,9 +22,11 @@ export class ElectCouncilFixture implements Fixture {
     this.lesserStake = lesserStake
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async execute(): Promise<void> {
     // Assert no council exists
-    assert((await this.api.getCouncil()).length === 0)
+    if ((await this.api.getCouncil()).length) {
+      return this.error(new Error('Council election fixture expects no council seats to be filled'))
+    }
 
     let now = await this.api.getBestBlock()
     const applyForCouncilFee: BN = this.api.estimateApplyForCouncilFee(this.greaterStake)
@@ -98,15 +99,13 @@ export class ElectCouncilFixture implements Fixture {
     const seats: Seat[] = await this.api.getCouncil()
 
     // Assert a council was created
-    assert(seats.length)
+    if (!seats.length) {
+      this.error(new Error('Expected council to be elected'))
+    }
 
     // const applicantAddresses: string[] = this.applicantKeyPairs.map((keyPair) => keyPair.address)
     // const voterAddresses: string[] = this.voterKeyPairs.map((keyPair) => keyPair.address)
     // const councilMembers: string[] = seats.map((seat) => seat.member.toString())
     // const backers: string[] = seats.map((seat) => seat.backers.map((backer) => backer.member.toString())).flat()
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }

+ 8 - 11
tests/network-tests/src/fixtures/membershipModule.ts

@@ -4,7 +4,6 @@ import { assert } from 'chai'
 import { BaseFixture } from '../Fixture'
 import { PaidTermId, MemberId } from '@joystream/types/members'
 import Debugger from 'debug'
-// import { DispatchError } from '@polkadot/types/interfaces/system'
 
 export class BuyMembershipHappyCaseFixture extends BaseFixture {
   private accounts: string[]
@@ -32,6 +31,7 @@ export class BuyMembershipHappyCaseFixture extends BaseFixture {
       this.paidTerms,
       'member_name_which_is_longer_than_expected'
     )
+
     this.api.treasuryTransferBalanceToAccounts(this.accounts, membershipTransactionFee.add(new BN(membershipFee)))
 
     this.memberIds = (
@@ -42,7 +42,9 @@ export class BuyMembershipHappyCaseFixture extends BaseFixture {
       )
     ).map(({ events }) => this.api.expectMemberRegisteredEvent(events))
 
-    this.debug(`New member ids: ${this.memberIds}`)
+    assert.equal(this.accounts.length, this.memberIds.length)
+
+    this.debug(`New member id(s): ${this.memberIds}`)
   }
 }
 
@@ -80,14 +82,9 @@ export class BuyMembershipWithInsufficienFundsFixture extends BaseFixture {
       'Account already has sufficient balance to purchase membership'
     )
 
-    try {
-      await this.api.buyMembership(this.account, this.paidTerms, `late_member_${this.account.substring(0, 8)}`)
-      this.error(new Error('Buying membership with insufficient funds should have failed'))
-    } catch (dispatchError) {
-      // We expect buying membership with insuffiencet funds to fail
-      // const err = dispatchError as DispatchError
-      // Assert its the exact error we expect?
-      // assert.eq(err, ... )
-    }
+    await this.expectDispatchError(
+      this.api.buyMembership(this.account, this.paidTerms, `late_member_${this.account.substring(0, 8)}`),
+      'Buying membership with insufficient funds should fail.'
+    )
   }
 }

+ 15 - 65
tests/network-tests/src/fixtures/proposalsModule.ts

@@ -30,7 +30,7 @@ export class CreateWorkingGroupLeaderOpeningFixture implements Fixture {
     return this.result
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8)
     const description: string = 'Testing working group lead opening proposal ' + uuid().substring(0, 8)
@@ -69,10 +69,6 @@ export class CreateWorkingGroupLeaderOpeningFixture implements Fixture {
     })
 
     this.result = this.api.expectProposalCreatedEvent(result.events)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -95,7 +91,7 @@ export class BeginWorkingGroupLeaderApplicationReviewFixture implements Fixture
     return this.result
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8)
     const description: string = 'Testing begin working group lead application review proposal ' + uuid().substring(0, 8)
@@ -114,11 +110,8 @@ export class BeginWorkingGroupLeaderApplicationReviewFixture implements Fixture
       this.openingId,
       this.workingGroup
     )
-    this.result = this.api.expectProposalCreatedEvent(result.events)
 
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
+    this.result = this.api.expectProposalCreatedEvent(result.events)
   }
 }
 
@@ -158,7 +151,7 @@ export class FillLeaderOpeningProposalFixture implements Fixture {
     return this.result
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8)
     const description: string = 'Testing fill opening proposal ' + uuid().substring(0, 8)
@@ -186,10 +179,6 @@ export class FillLeaderOpeningProposalFixture implements Fixture {
     })
 
     this.result = this.api.expectProposalCreatedEvent(result.events)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -212,7 +201,7 @@ export class TerminateLeaderRoleProposalFixture implements Fixture {
     return this.result
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8)
     const description: string = 'Testing begin working group lead application review proposal ' + uuid().substring(0, 8)
@@ -238,10 +227,6 @@ export class TerminateLeaderRoleProposalFixture implements Fixture {
       workingGroupString
     )
     this.result = this.api.expectProposalCreatedEvent(result.events)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -264,7 +249,7 @@ export class SetLeaderRewardProposalFixture implements Fixture {
     return this.result
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8)
     const description: string = 'Testing set leader reward proposal ' + uuid().substring(0, 8)
@@ -289,10 +274,6 @@ export class SetLeaderRewardProposalFixture implements Fixture {
     )
 
     this.result = this.api.expectProposalCreatedEvent(result.events)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -315,7 +296,7 @@ export class DecreaseLeaderStakeProposalFixture implements Fixture {
     return this.result
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8)
     const description: string = 'Testing decrease leader stake proposal ' + uuid().substring(0, 8)
@@ -340,10 +321,6 @@ export class DecreaseLeaderStakeProposalFixture implements Fixture {
     )
 
     this.result = this.api.expectProposalCreatedEvent(result.events)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -366,7 +343,7 @@ export class SlashLeaderProposalFixture implements Fixture {
     return this.result
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8)
     const description: string = 'Testing slash leader stake proposal ' + uuid().substring(0, 8)
@@ -389,9 +366,6 @@ export class SlashLeaderProposalFixture implements Fixture {
       workingGroupString
     )
     this.result = this.api.expectProposalCreatedEvent(result.events)
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -414,7 +388,7 @@ export class WorkingGroupMintCapacityProposalFixture implements Fixture {
     return this.result
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8)
     const description: string = 'Testing working group mint capacity proposal ' + uuid().substring(0, 8)
@@ -435,9 +409,6 @@ export class WorkingGroupMintCapacityProposalFixture implements Fixture {
       workingGroupString
     )
     this.result = this.api.expectProposalCreatedEvent(result.events)
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -450,7 +421,7 @@ export class ElectionParametersProposalFixture implements Fixture {
     this.proposerAccount = proposerAccount
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8)
     const description: string = 'Testing validator count proposal ' + uuid().substring(0, 8)
@@ -559,9 +530,6 @@ export class ElectionParametersProposalFixture implements Fixture {
       proposedMinVotingStake.eq(newMinVotingStake),
       `Min voting stake has unexpected value ${newMinVotingStake}, expected ${proposedMinVotingStake}`
     )
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -578,7 +546,7 @@ export class SpendingProposalFixture implements Fixture {
     this.mintCapacity = mintCapacity
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const description = 'spending proposal which is used for API network testing with some mock data'
     const runtimeVoteFee: BN = this.api.estimateVoteForProposalFee()
@@ -622,9 +590,6 @@ export class SpendingProposalFixture implements Fixture {
         this.spendingBalance
       )}`
     )
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -637,7 +602,7 @@ export class TextProposalFixture implements Fixture {
     this.proposer = proposer
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8)
     const description: string = 'Testing text proposal ' + uuid().substring(0, 8)
@@ -664,10 +629,6 @@ export class TextProposalFixture implements Fixture {
     // Approving text proposal
     this.api.batchApproveProposal(proposalNumber)
     await this.api.waitForProposalToFinalize(proposalNumber)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -682,7 +643,7 @@ export class ValidatorCountProposalFixture implements Fixture {
     this.validatorCountIncrement = validatorCountIncrement
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8)
     const description: string = 'Testing validator count proposal ' + uuid().substring(0, 8)
@@ -716,9 +677,6 @@ export class ValidatorCountProposalFixture implements Fixture {
       proposedValidatorCount.eq(newValidatorCount),
       `Validator count has unexpeccted value ${newValidatorCount}, expected ${proposedValidatorCount}`
     )
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -733,7 +691,7 @@ export class UpdateRuntimeFixture implements Fixture {
     this.runtimePath = runtimePath
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Setup
     const runtime: string = Utils.readRuntimeFromFile(this.runtimePath)
     const description = 'runtime upgrade proposal which is used for API network testing'
@@ -764,10 +722,6 @@ export class UpdateRuntimeFixture implements Fixture {
     // Approving runtime update proposal
     this.api.batchApproveProposal(proposalNumber)
     await this.api.waitForProposalToFinalize(proposalNumber)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -785,7 +739,7 @@ export class VoteForProposalFixture implements Fixture {
     return this.events
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const proposalVoteFee: BN = this.api.estimateVoteForProposalFee()
     const councilAccounts = await this.api.getCouncilAccounts()
     this.api.treasuryTransferBalanceToAccounts(councilAccounts, proposalVoteFee)
@@ -793,9 +747,5 @@ export class VoteForProposalFixture implements Fixture {
     // Approving the proposal
     this.api.batchApproveProposal(this.proposalNumber)
     this.events = await this.api.waitForProposalToFinalize(this.proposalNumber)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }

+ 6 - 6
tests/network-tests/src/fixtures/sudoHireLead.ts

@@ -48,14 +48,14 @@ export class SudoHireLeadFixture implements Fixture {
     this.workingGroup = workingGroup
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const leaderHappyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture(
       this.api,
       [this.leadAccount],
       this.paidTerms
     )
     // Buying membership for leader account
-    await leaderHappyCaseFixture.runner(false)
+    await leaderHappyCaseFixture.runner()
 
     const addLeaderOpeningFixture: SudoAddLeaderOpeningFixture = new SudoAddLeaderOpeningFixture(
       this.api,
@@ -65,7 +65,7 @@ export class SudoHireLeadFixture implements Fixture {
       this.workingGroup
     )
     // Add lead opening
-    await addLeaderOpeningFixture.runner(false)
+    await addLeaderOpeningFixture.runner()
 
     const applyForLeaderOpeningFixture = new ApplyForOpeningFixture(
       this.api,
@@ -75,7 +75,7 @@ export class SudoHireLeadFixture implements Fixture {
       addLeaderOpeningFixture.getCreatedOpeningId() as OpeningId,
       this.workingGroup
     )
-    await applyForLeaderOpeningFixture.runner(false)
+    await applyForLeaderOpeningFixture.runner()
 
     assert(applyForLeaderOpeningFixture.getApplicationIds().length === 1)
 
@@ -84,7 +84,7 @@ export class SudoHireLeadFixture implements Fixture {
       addLeaderOpeningFixture.getCreatedOpeningId() as OpeningId,
       this.workingGroup
     )
-    await beginLeaderApplicationReviewFixture.runner(false)
+    await beginLeaderApplicationReviewFixture.runner()
 
     const fillLeaderOpeningFixture = new SudoFillLeaderOpeningFixture(
       this.api,
@@ -95,6 +95,6 @@ export class SudoHireLeadFixture implements Fixture {
       this.payoutAmount,
       this.workingGroup
     )
-    await fillLeaderOpeningFixture.runner(false)
+    await fillLeaderOpeningFixture.runner()
   }
 }

+ 30 - 79
tests/network-tests/src/fixtures/workingGroupModule.ts

@@ -39,7 +39,7 @@ export class AddWorkerOpeningFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const lead = await this.api.getGroupLead(this.module)
     if (!lead) {
       throw new Error('No Lead')
@@ -73,13 +73,10 @@ export class AddWorkerOpeningFixture implements Fixture {
         text: uuid().substring(0, 8),
         type: 'Worker',
       },
-      this.module,
-      expectFailure
+      this.module
     )
 
-    if (!expectFailure) {
-      this.result = this.api.expectOpeningAddedEvent(result.events)
-    }
+    this.result = this.api.expectOpeningAddedEvent(result.events)
   }
 }
 
@@ -104,7 +101,7 @@ export class SudoAddLeaderOpeningFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const result = await this.api.sudoAddOpening(
       {
         activationDelay: this.activationDelay,
@@ -131,11 +128,7 @@ export class SudoAddLeaderOpeningFixture implements Fixture {
       this.module
     )
 
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    } else {
-      this.result = this.api.expectOpeningAddedEvent(result.events)
-    }
+    this.result = this.api.expectOpeningAddedEvent(result.events)
   }
 }
 
@@ -150,7 +143,7 @@ export class AcceptApplicationsFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const lead = await this.api.getGroupLead(this.module)
     if (!lead) {
       throw new Error('No Lead')
@@ -165,9 +158,6 @@ export class AcceptApplicationsFixture implements Fixture {
     const wgOpening = await this.api.getWorkingGroupOpening(this.openingId, this.module)
     const opening: HiringOpening = await this.api.getHiringOpening(wgOpening.hiring_opening_id)
     assert(opening.is_active, `${this.module} Opening ${this.openingId} is not active`)
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -200,7 +190,7 @@ export class ApplyForOpeningFixture implements Fixture {
     return this.result
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Fee estimation and transfer
     const applyOnOpeningFee: BN = this.api
       .estimateApplyOnOpeningFee(this.applicants[0], this.module)
@@ -215,8 +205,7 @@ export class ApplyForOpeningFixture implements Fixture {
       this.roleStake,
       this.applicationStake,
       uuid().substring(0, 8),
-      this.module,
-      expectFailure
+      this.module
     )
 
     const applicationIds = results.map(({ events }) => {
@@ -244,7 +233,7 @@ export class WithdrawApplicationFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Fee estimation and transfer
     const withdrawApplicaitonFee: BN = this.api.estimateWithdrawApplicationFee(this.module)
 
@@ -254,10 +243,6 @@ export class WithdrawApplicationFixture implements Fixture {
 
     // Application withdrawal
     await this.api.batchWithdrawActiveApplications(this.applicationIds, this.module)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -272,7 +257,7 @@ export class BeginApplicationReviewFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const lead = await this.api.getGroupLead(this.module)
     if (!lead) {
       throw new Error('No Lead')
@@ -287,10 +272,6 @@ export class BeginApplicationReviewFixture implements Fixture {
     const result = await this.api.beginApplicantReview(leadAccount, this.openingId, this.module)
 
     this.api.expectApplicationReviewBeganEvent(result.events)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -305,12 +286,9 @@ export class SudoBeginLeaderApplicationReviewFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Begin application review
     await this.api.sudoBeginApplicantReview(this.openingId, this.module)
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -346,7 +324,7 @@ export class FillOpeningFixture implements Fixture {
     return this.workerIds
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const lead = await this.api.getGroupLead(this.module)
     if (!lead) {
       throw new Error('No Lead')
@@ -390,10 +368,6 @@ export class FillOpeningFixture implements Fixture {
         `Role account ids does not match, worker account: ${worker.role_account_id}, application account ${application.role_account_id}`
       )
     })
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -424,7 +398,7 @@ export class SudoFillLeaderOpeningFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Fill leader opening
     const now: BN = await this.api.getBestBlock()
     const result = await this.api.sudoFillOpening(
@@ -452,10 +426,6 @@ export class SudoFillLeaderOpeningFixture implements Fixture {
         `Role account ids does not match, leader account: ${worker.role_account_id}, application account ${application.role_account_id}`
       )
     })
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -470,7 +440,7 @@ export class IncreaseStakeFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     // Fee estimation and transfer
     const increaseStakeFee: BN = this.api.estimateIncreaseStakeFee(this.module)
     const stakeIncrement: BN = new BN(1)
@@ -488,9 +458,6 @@ export class IncreaseStakeFixture implements Fixture {
       increasedWorkerStake.eq(newWorkerStake),
       `Unexpected worker stake ${newWorkerStake}, expected ${increasedWorkerStake}`
     )
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -505,7 +472,7 @@ export class UpdateRewardAccountFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const worker = await this.api.getWorkerById(this.workerId, this.module)
     const workerRoleAccount = worker.role_account_id.toString()
     // Fee estimation and transfer
@@ -520,9 +487,6 @@ export class UpdateRewardAccountFixture implements Fixture {
       newRewardAccount === createdAccount.address,
       `Unexpected role account ${newRewardAccount}, expected ${createdAccount.address}`
     )
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -537,7 +501,7 @@ export class UpdateRoleAccountFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const worker = await this.api.getWorkerById(this.workerId, this.module)
     const workerRoleAccount = worker.role_account_id.toString()
     // Fee estimation and transfer
@@ -553,10 +517,6 @@ export class UpdateRoleAccountFixture implements Fixture {
       newRoleAccount === createdAccount.address,
       `Unexpected role account ${newRoleAccount}, expected ${createdAccount.address}`
     )
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -571,7 +531,7 @@ export class TerminateApplicationsFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const lead = await this.api.getGroupLead(this.module)
     if (!lead) {
       throw new Error('No Lead')
@@ -584,10 +544,6 @@ export class TerminateApplicationsFixture implements Fixture {
 
     // Terminate worker applications
     await this.api.batchTerminateApplication(leadAccount, this.applicationIds, this.module)
-
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }
 
@@ -602,7 +558,7 @@ export class DecreaseStakeFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const lead = await this.api.getGroupLead(this.module)
     if (!lead) {
       throw new Error('No Lead')
@@ -618,16 +574,14 @@ export class DecreaseStakeFixture implements Fixture {
     const decreasedWorkerStake: BN = (await this.api.getWorkerStakeAmount(this.workerId, this.module)).sub(
       workerStakeDecrement
     )
-    await this.api.decreaseStake(leadAccount, this.workerId, workerStakeDecrement, this.module, expectFailure)
+    await this.api.decreaseStake(leadAccount, this.workerId, workerStakeDecrement, this.module)
     const newWorkerStake: BN = await this.api.getWorkerStakeAmount(this.workerId, this.module)
 
     // Assertions
-    if (!expectFailure) {
-      assert(
-        decreasedWorkerStake.eq(newWorkerStake),
-        `Unexpected worker stake ${newWorkerStake}, expected ${decreasedWorkerStake}`
-      )
-    }
+    assert(
+      decreasedWorkerStake.eq(newWorkerStake),
+      `Unexpected worker stake ${newWorkerStake}, expected ${decreasedWorkerStake}`
+    )
   }
 }
 
@@ -642,7 +596,7 @@ export class SlashFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const lead = await this.api.getGroupLead(this.module)
     if (!lead) {
       throw new Error('No Lead')
@@ -656,7 +610,7 @@ export class SlashFixture implements Fixture {
 
     // Slash worker
     const slashedStake: BN = (await this.api.getWorkerStakeAmount(this.workerId, this.module)).sub(slashAmount)
-    await this.api.slashStake(leadAccount, this.workerId, slashAmount, this.module, expectFailure)
+    await this.api.slashStake(leadAccount, this.workerId, slashAmount, this.module)
     const newStake: BN = await this.api.getWorkerStakeAmount(this.workerId, this.module)
 
     // Assertions
@@ -675,7 +629,7 @@ export class TerminateRoleFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const lead = await this.api.getGroupLead(this.module)
     if (!lead) {
       throw new Error('No Lead')
@@ -687,7 +641,7 @@ export class TerminateRoleFixture implements Fixture {
     this.api.treasuryTransferBalance(leadAccount, terminateRoleFee)
 
     // Terminate worker role
-    await this.api.terminateRole(leadAccount, this.workerId, uuid().substring(0, 8), this.module, expectFailure)
+    await this.api.terminateRole(leadAccount, this.workerId, uuid().substring(0, 8), this.module)
 
     // Assertions
     const isWorker: boolean = await this.api.isWorker(this.workerId, this.module)
@@ -706,13 +660,13 @@ export class LeaveRoleFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const roleAccounts = await this.api.getWorkerRoleAccounts(this.workerIds, this.module)
     // Fee estimation and transfer
     const leaveRoleFee: BN = this.api.estimateLeaveRoleFee(this.module)
     this.api.treasuryTransferBalanceToAccounts(roleAccounts, leaveRoleFee)
 
-    await this.api.batchLeaveRole(this.workerIds, uuid().substring(0, 8), expectFailure, this.module)
+    await this.api.batchLeaveRole(this.workerIds, uuid().substring(0, 8), this.module)
 
     // Assertions
     this.workerIds.forEach(async (workerId) => {
@@ -733,7 +687,7 @@ export class AwaitPayoutFixture implements Fixture {
     this.module = module
   }
 
-  public async runner(expectFailure: boolean): Promise<void> {
+  public async runner(): Promise<void> {
     const worker: Worker = await this.api.getWorkerById(this.workerId, this.module)
     const reward: RewardRelationship = await this.api.getRewardRelationship(worker.reward_relationship.unwrap())
     const now: BN = await this.api.getBestBlock()
@@ -763,8 +717,5 @@ export class AwaitPayoutFixture implements Fixture {
       balanceAfterSecondPayout.eq(expectedBalanceSecond),
       `Unexpected balance, expected ${expectedBalanceSecond} got ${balanceAfterSecondPayout}`
     )
-    if (expectFailure) {
-      throw new Error('Successful fixture run while expecting failure')
-    }
   }
 }

+ 1 - 1
tests/network-tests/src/flows/contentDirectory/creatingChannel.ts

@@ -30,7 +30,7 @@ function assertChannelMatchQueriedResult(queriedChannel: any, channel: ChannelEn
 export default async function channelCreation(api: QueryNodeApi) {
   const createChannelHappyCaseFixture = createSimpleChannelFixture(api)
 
-  await createChannelHappyCaseFixture.runner(false)
+  await createChannelHappyCaseFixture.runner()
 
   // Temporary solution (wait 2 minutes)
   await Utils.wait(120000)

+ 1 - 1
tests/network-tests/src/flows/contentDirectory/creatingVideo.ts

@@ -56,7 +56,7 @@ export default async function createVideo(api: QueryNodeApi) {
   const channelTitle = 'New channel example'
   const createVideoHappyCaseFixture = createVideoReferencingChannelFixture(api, channelTitle)
 
-  await createVideoHappyCaseFixture.runner(false)
+  await createVideoHappyCaseFixture.runner()
 
   // Temporary solution (wait 2 minutes)
   await Utils.wait(120000)

+ 1 - 1
tests/network-tests/src/flows/contentDirectory/updatingChannel.ts

@@ -27,7 +27,7 @@ export default async function updateChannel(api: QueryNodeApi) {
   const description = 'Updated description'
   const createUpdateChannelDescriptionHappyCaseFixture = createUpdateChannelHandleFixture(api, handle, description)
 
-  await createUpdateChannelDescriptionHappyCaseFixture.runner(false)
+  await createUpdateChannelDescriptionHappyCaseFixture.runner()
 
   // Temporary solution (wait 2 minutes)
   await Utils.wait(120000)

+ 7 - 9
tests/network-tests/src/flows/membership/creatingMemberships.ts

@@ -11,7 +11,7 @@ import { assert } from 'chai'
 
 export default async function membershipCreation(api: Api, env: NodeJS.ProcessEnv): Promise<void> {
   const debug = Debugger('flow:memberships')
-  debug('started')
+  debug('Started')
 
   const N: number = +env.MEMBERSHIP_CREATION_N!
   assert(N > 0)
@@ -21,17 +21,15 @@ export default async function membershipCreation(api: Api, env: NodeJS.ProcessEn
 
   // Assert membership can be bought if sufficient funds are available
   const happyCaseFixture = new BuyMembershipHappyCaseFixture(api, nAccounts, paidTerms)
-  assert.equal(await new FixtureRunner(happyCaseFixture).run(), undefined)
+  await new FixtureRunner(happyCaseFixture).run()
 
   // Assert account can not buy the membership with insufficient funds
-  const insufficientFundsFixture: BuyMembershipWithInsufficienFundsFixture = new BuyMembershipWithInsufficienFundsFixture(
-    api,
-    aAccount,
-    paidTerms
-  )
-  assert.equal(await new FixtureRunner(insufficientFundsFixture).run(), undefined)
+  const insufficientFundsFixture = new BuyMembershipWithInsufficienFundsFixture(api, aAccount, paidTerms)
+  await new FixtureRunner(insufficientFundsFixture).run()
 
   // Assert account was able to buy the membership with sufficient funds
   const buyMembershipAfterAccountTopUp = new BuyMembershipHappyCaseFixture(api, [aAccount], paidTerms)
-  assert.equal(await new FixtureRunner(buyMembershipAfterAccountTopUp).run(), undefined)
+  await new FixtureRunner(buyMembershipAfterAccountTopUp).run()
+
+  debug('Done')
 }

+ 17 - 13
tests/network-tests/src/flows/proposals/councilSetup.ts

@@ -1,20 +1,24 @@
 import BN from 'bn.js'
 import { PaidTermId } from '@joystream/types/members'
 import { Api } from '../../Api'
-import { CouncilElectionHappyCaseFixture } from '../../fixtures/councilElectionHappyCase'
+import { ElectCouncilFixture } from '../../fixtures/councilElectionModule'
 import { BuyMembershipHappyCaseFixture } from '../../fixtures/membershipModule'
 import Debugger from 'debug'
-import { assert } from 'chai'
+import { FixtureRunner } from '../../Fixture'
 
-const debug = Debugger('flow:councilSetup')
+export default async function councilSetup(api: Api, env: NodeJS.ProcessEnv): Promise<void> {
+  const label = 'councilSetup'
+  const debug = Debugger(`flow:${label}`)
+
+  debug('Started')
 
-export default async function councilSetup(api: Api, env: NodeJS.ProcessEnv) {
   // Skip creating council if already elected
   if ((await api.getCouncil()).length) {
-    debug('Skipping Council Setup, Council already elected')
-    return
+    return debug('Skipping council setup. A Council is already elected')
   }
 
+  debug('Electing new council')
+
   const numberOfApplicants = (await api.getCouncilSize()).toNumber() * 2
   const applicants = api.createKeyPairs(numberOfApplicants).map((key) => key.address)
   const voters = api.createKeyPairs(5).map((key) => key.address)
@@ -24,13 +28,14 @@ export default async function councilSetup(api: Api, env: NodeJS.ProcessEnv) {
   const greaterStake: BN = new BN(+env.COUNCIL_STAKE_GREATER_AMOUNT!)
   const lesserStake: BN = new BN(+env.COUNCIL_STAKE_LESSER_AMOUNT!)
 
+  // Todo pass the label to the fixture to make debug logs of fixture associated with flow name
   const createMembersFixture = new BuyMembershipHappyCaseFixture(api, [...voters, ...applicants], paidTerms)
-  await createMembersFixture.runner(false)
+  await new FixtureRunner(createMembersFixture).run()
 
-  // The fixture moves manually with sudo the election stages, so proper processing
+  // The fixture uses sudo to transition through the election stages, so proper processing
   // that normally occurs during stage transitions does not happen. This can lead to a council
-  // that is smaller than the council size if not enough members apply.
-  const councilElectionHappyCaseFixture = new CouncilElectionHappyCaseFixture(
+  // that is smaller than the target council size if not enough members apply.
+  const electCouncilFixture = new ElectCouncilFixture(
     api,
     voters, // should be member ids
     applicants, // should be member ids
@@ -39,8 +44,7 @@ export default async function councilSetup(api: Api, env: NodeJS.ProcessEnv) {
     lesserStake
   )
 
-  await councilElectionHappyCaseFixture.runner(false)
+  await new FixtureRunner(electCouncilFixture).run()
 
-  // Elected council
-  assert((await api.getCouncil()).length)
+  debug('Done')
 }

+ 1 - 1
tests/network-tests/src/flows/proposals/electionParametersProposal.ts

@@ -11,5 +11,5 @@ export default async function electionParametersProposal(api: Api, env: NodeJS.P
   const proposer = council[0].member.toString()
 
   const electionParametersProposalFixture = new ElectionParametersProposalFixture(api, proposer)
-  await electionParametersProposalFixture.runner(false)
+  await electionParametersProposalFixture.runner()
 }

+ 17 - 16
tests/network-tests/src/flows/proposals/manageLeaderRole.ts

@@ -16,6 +16,7 @@ import { PaidTermId } from '@joystream/types/members'
 import { OpeningId } from '@joystream/types/hiring'
 import { ProposalId } from '@joystream/types/proposals'
 import { assert } from 'chai'
+import { FixtureRunner } from '../../Fixture'
 
 export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv, group: WorkingGroups) {
   const leaderAccount = api.createKeyPairs(1)[0].address
@@ -45,7 +46,7 @@ export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv,
     paidTerms
   )
   // Buy membership for lead
-  await leaderMembershipFixture.runner(false)
+  await new FixtureRunner(leaderMembershipFixture).run()
 
   const createWorkingGroupLeaderOpeningFixture: CreateWorkingGroupLeaderOpeningFixture = new CreateWorkingGroupLeaderOpeningFixture(
     api,
@@ -55,7 +56,7 @@ export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv,
     api.getWorkingGroupString(group)
   )
   // Propose create leader opening
-  await createWorkingGroupLeaderOpeningFixture.runner(false)
+  await createWorkingGroupLeaderOpeningFixture.runner()
 
   // Approve add opening proposal
   const voteForCreateOpeningProposalFixture = new VoteForProposalFixture(
@@ -63,7 +64,7 @@ export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv,
     createWorkingGroupLeaderOpeningFixture.getCreatedProposalId() as OpeningId
   )
 
-  await voteForCreateOpeningProposalFixture.runner(false)
+  await voteForCreateOpeningProposalFixture.runner()
   const openingId = api.expectOpeningAddedEvent(voteForCreateOpeningProposalFixture.getEvents())
 
   const applyForLeaderOpeningFixture = new ApplyForOpeningFixture(
@@ -74,7 +75,7 @@ export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv,
     openingId,
     group
   )
-  await applyForLeaderOpeningFixture.runner(false)
+  await applyForLeaderOpeningFixture.runner()
   const applicationId = applyForLeaderOpeningFixture.getApplicationIds()[0]
 
   const beginWorkingGroupLeaderApplicationReviewFixture = new BeginWorkingGroupLeaderApplicationReviewFixture(
@@ -84,13 +85,13 @@ export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv,
     api.getWorkingGroupString(group)
   )
   // Propose begin leader application review
-  await beginWorkingGroupLeaderApplicationReviewFixture.runner(false)
+  await beginWorkingGroupLeaderApplicationReviewFixture.runner()
 
   const voteForBeginReviewProposal = new VoteForProposalFixture(
     api,
     beginWorkingGroupLeaderApplicationReviewFixture.getCreatedProposalId() as ProposalId
   )
-  await voteForBeginReviewProposal.runner(false)
+  await voteForBeginReviewProposal.runner()
 
   const fillLeaderOpeningProposalFixture = new FillLeaderOpeningProposalFixture(
     api,
@@ -103,21 +104,21 @@ export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv,
     group
   )
   // Propose fill leader opening
-  await fillLeaderOpeningProposalFixture.runner(false)
+  await fillLeaderOpeningProposalFixture.runner()
 
   const voteForFillLeaderProposalFixture = new VoteForProposalFixture(
     api,
     fillLeaderOpeningProposalFixture.getCreatedProposalId() as ProposalId
   )
   // Approve fill leader opening
-  await voteForFillLeaderProposalFixture.runner(false)
+  await voteForFillLeaderProposalFixture.runner()
 
   const hiredLead = await api.getGroupLead(group)
   assert(hiredLead)
 
   const setLeaderRewardProposalFixture = new SetLeaderRewardProposalFixture(api, proposer, alteredPayoutAmount, group)
   // Propose leader reward
-  await setLeaderRewardProposalFixture.runner(false)
+  await setLeaderRewardProposalFixture.runner()
 
   const voteForeLeaderRewardFixture = new VoteForProposalFixture(
     api,
@@ -125,7 +126,7 @@ export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv,
   )
 
   // Approve new leader reward
-  await voteForeLeaderRewardFixture.runner(false)
+  await voteForeLeaderRewardFixture.runner()
 
   const leadId = await api.getLeadWorkerId(group)
   // This check is prone to failure if more than one worker's reward amount was updated
@@ -142,7 +143,7 @@ export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv,
   )
 
   // Propose decrease stake
-  await decreaseLeaderStakeProposalFixture.runner(false)
+  await decreaseLeaderStakeProposalFixture.runner()
 
   let newStake: BN = applicationStake.sub(stakeDecrement)
   // Approve decreased leader stake
@@ -150,11 +151,11 @@ export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv,
     api,
     decreaseLeaderStakeProposalFixture.getCreatedProposalId() as ProposalId
   )
-  await voteForDecreaseStakeProposal.runner(false)
+  await voteForDecreaseStakeProposal.runner()
 
   const slashLeaderProposalFixture = new SlashLeaderProposalFixture(api, proposer, slashAmount, group)
   // Propose leader slash
-  await slashLeaderProposalFixture.runner(false)
+  await slashLeaderProposalFixture.runner()
 
   // Approve leader slash
   newStake = newStake.sub(slashAmount)
@@ -162,17 +163,17 @@ export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv,
     api,
     slashLeaderProposalFixture.getCreatedProposalId() as ProposalId
   )
-  await voteForSlashProposalFixture.runner(false)
+  await voteForSlashProposalFixture.runner()
 
   const terminateLeaderRoleProposalFixture = new TerminateLeaderRoleProposalFixture(api, proposer, false, group)
   // Propose terminate leader role
-  await terminateLeaderRoleProposalFixture.runner(false)
+  await terminateLeaderRoleProposalFixture.runner()
 
   const voteForLeaderRoleTerminationFixture = new VoteForProposalFixture(
     api,
     terminateLeaderRoleProposalFixture.getCreatedProposalId() as ProposalId
   )
-  await voteForLeaderRoleTerminationFixture.runner(false)
+  await voteForLeaderRoleTerminationFixture.runner()
 
   const maybeLead = await api.getGroupLead(group)
   assert(!maybeLead)

+ 1 - 1
tests/network-tests/src/flows/proposals/spendingProposal.ts

@@ -16,5 +16,5 @@ export default async function spendingProposal(api: Api, env: NodeJS.ProcessEnv)
   const spendingProposalFixture = new SpendingProposalFixture(api, proposer, spendingBalance, mintCapacity)
 
   // Spending proposal test
-  await spendingProposalFixture.runner(false)
+  await spendingProposalFixture.runner()
 }

+ 1 - 1
tests/network-tests/src/flows/proposals/textProposal.ts

@@ -10,5 +10,5 @@ export default async function textProposal(api: Api, env: NodeJS.ProcessEnv) {
   const proposer = council[0].member.toString()
 
   const textProposalFixture: TextProposalFixture = new TextProposalFixture(api, proposer)
-  await textProposalFixture.runner(false)
+  await textProposalFixture.runner()
 }

+ 2 - 2
tests/network-tests/src/flows/proposals/updateRuntime.ts

@@ -16,7 +16,7 @@ export default async function updateRuntime(api: Api, env: NodeJS.ProcessEnv) {
   const proposer = council[0].member.toString()
 
   const updateRuntimeFixture: UpdateRuntimeFixture = new UpdateRuntimeFixture(api, proposer, runtimePath)
-  await updateRuntimeFixture.runner(false)
+  await updateRuntimeFixture.runner()
 
   // Some tests after runtime update
   const createMembershipsFixture = new BuyMembershipHappyCaseFixture(
@@ -24,5 +24,5 @@ export default async function updateRuntime(api: Api, env: NodeJS.ProcessEnv) {
     api.createKeyPairs(1).map((key) => key.address),
     paidTerms
   )
-  await createMembershipsFixture.runner(false)
+  await createMembershipsFixture.runner()
 }

+ 1 - 1
tests/network-tests/src/flows/proposals/validatorCountProposal.ts

@@ -17,5 +17,5 @@ export default async function validatorCount(api: Api, env: NodeJS.ProcessEnv) {
     proposer,
     validatorCountIncrement
   )
-  await validatorCountProposalFixture.runner(false)
+  await validatorCountProposalFixture.runner()
 }

+ 2 - 2
tests/network-tests/src/flows/proposals/workingGroupMintCapacityProposal.ts

@@ -20,7 +20,7 @@ export default async function workingGroupMintCapactiy(api: Api, env: NodeJS.Pro
     group
   )
   // Propose mint capacity
-  await workingGroupMintCapacityProposalFixture.runner(false)
+  await workingGroupMintCapacityProposalFixture.runner()
 
   const voteForProposalFixture: VoteForProposalFixture = new VoteForProposalFixture(
     api,
@@ -28,5 +28,5 @@ export default async function workingGroupMintCapactiy(api: Api, env: NodeJS.Pro
   )
 
   // Approve mint capacity
-  await voteForProposalFixture.runner(false)
+  await voteForProposalFixture.runner()
 }

+ 16 - 4
tests/network-tests/src/flows/workingGroup/atLeastValueBug.ts

@@ -26,8 +26,14 @@ export default async function zeroAtLeastValueBug(api: Api, env: NodeJS.ProcessE
     unstakingPeriod,
     WorkingGroups.StorageWorkingGroup
   )
-  // Add worker opening with 0 stake, expect failure
-  await addWorkerOpeningWithoutStakeFixture.runner(true)
+
+  // Add worker opening with 0 stake, expect failure!
+  try {
+    await addWorkerOpeningWithoutStakeFixture.runner()
+    assert(false, 'Adding Worker Opening Should have failed')
+  } catch (err) {
+    // Expected to fail
+  }
 
   const addWorkerOpeningWithoutUnstakingPeriodFixture = new AddWorkerOpeningFixture(
     api,
@@ -37,8 +43,14 @@ export default async function zeroAtLeastValueBug(api: Api, env: NodeJS.ProcessE
     new BN(0),
     WorkingGroups.StorageWorkingGroup
   )
-  // Add worker opening with 0 unstaking period, expect failure
-  await addWorkerOpeningWithoutUnstakingPeriodFixture.runner(true)
+
+  // Add worker opening with 0 unstaking period, expect failure!
+  try {
+    await addWorkerOpeningWithoutUnstakingPeriodFixture.runner()
+    assert(false, 'Adding Worker Opening Should have failed')
+  } catch (err) {
+    // Expected to fail
+  }
 
   // TODO: close openings
   debug('Passed')

+ 1 - 1
tests/network-tests/src/flows/workingGroup/leaderSetup.ts

@@ -36,7 +36,7 @@ export default async function leaderSetup(
     payoutAmount,
     group
   )
-  await leaderHiringHappyCaseFixture.runner(false)
+  await leaderHiringHappyCaseFixture.runner()
 
   const hiredLead = await api.getGroupLead(group)
   assert(hiredLead, `${group} group Lead was not hired!`)

+ 8 - 8
tests/network-tests/src/flows/workingGroup/manageWorkerAsLead.ts

@@ -31,7 +31,7 @@ export default async function manageWorker(api: Api, env: NodeJS.ProcessEnv, gro
 
   const applicants = api.createKeyPairs(5).map((key) => key.address)
   const memberSetFixture = new BuyMembershipHappyCaseFixture(api, applicants, paidTerms)
-  await memberSetFixture.runner(false)
+  await memberSetFixture.runner()
 
   const addWorkerOpeningFixture: AddWorkerOpeningFixture = new AddWorkerOpeningFixture(
     api,
@@ -42,7 +42,7 @@ export default async function manageWorker(api: Api, env: NodeJS.ProcessEnv, gro
     group
   )
   // Add worker opening
-  await addWorkerOpeningFixture.runner(false)
+  await addWorkerOpeningFixture.runner()
 
   // First apply for worker opening
   const applyForWorkerOpeningFixture = new ApplyForOpeningFixture(
@@ -53,7 +53,7 @@ export default async function manageWorker(api: Api, env: NodeJS.ProcessEnv, gro
     addWorkerOpeningFixture.getCreatedOpeningId() as OpeningId,
     group
   )
-  await applyForWorkerOpeningFixture.runner(false)
+  await applyForWorkerOpeningFixture.runner()
 
   const applicationIdsToHire = applyForWorkerOpeningFixture.getApplicationIds().slice(0, 2)
 
@@ -63,7 +63,7 @@ export default async function manageWorker(api: Api, env: NodeJS.ProcessEnv, gro
     addWorkerOpeningFixture.getCreatedOpeningId() as OpeningId,
     group
   )
-  await beginApplicationReviewFixture.runner(false)
+  await beginApplicationReviewFixture.runner()
 
   // Fill worker opening
   const fillOpeningFixture = new FillOpeningFixture(
@@ -75,20 +75,20 @@ export default async function manageWorker(api: Api, env: NodeJS.ProcessEnv, gro
     payoutAmount,
     group
   )
-  await fillOpeningFixture.runner(false)
+  await fillOpeningFixture.runner()
 
   const firstWorkerId = fillOpeningFixture.getWorkerIds()[0]
 
   const decreaseStakeFixture = new DecreaseStakeFixture(api, firstWorkerId, group)
   // Decrease worker stake
-  await decreaseStakeFixture.runner(false)
+  await decreaseStakeFixture.runner()
 
   const slashFixture: SlashFixture = new SlashFixture(api, firstWorkerId, group)
   // Slash worker
-  await slashFixture.runner(false)
+  await slashFixture.runner()
 
   const terminateRoleFixture = new TerminateRoleFixture(api, firstWorkerId, group)
 
   // Terminate workers
-  await terminateRoleFixture.runner(false)
+  await terminateRoleFixture.runner()
 }

+ 8 - 8
tests/network-tests/src/flows/workingGroup/manageWorkerAsWorker.ts

@@ -30,7 +30,7 @@ export default async function manageWorkerAsWorker(api: Api, env: NodeJS.Process
 
   const memberSetFixture = new BuyMembershipHappyCaseFixture(api, newMembers, paidTerms)
   // Recreating set of members
-  await memberSetFixture.runner(false)
+  await memberSetFixture.runner()
   const applicant = newMembers[0]
 
   const addWorkerOpeningFixture = new AddWorkerOpeningFixture(
@@ -42,7 +42,7 @@ export default async function manageWorkerAsWorker(api: Api, env: NodeJS.Process
     group
   )
   // Add worker opening
-  await addWorkerOpeningFixture.runner(false)
+  await addWorkerOpeningFixture.runner()
 
   // First apply for worker opening
   const applyForWorkerOpeningFixture = new ApplyForOpeningFixture(
@@ -53,7 +53,7 @@ export default async function manageWorkerAsWorker(api: Api, env: NodeJS.Process
     addWorkerOpeningFixture.getCreatedOpeningId() as OpeningId,
     group
   )
-  await applyForWorkerOpeningFixture.runner(false)
+  await applyForWorkerOpeningFixture.runner()
   const applicationIdToHire = applyForWorkerOpeningFixture.getApplicationIds()[0]
 
   // Begin application review
@@ -62,7 +62,7 @@ export default async function manageWorkerAsWorker(api: Api, env: NodeJS.Process
     addWorkerOpeningFixture.getCreatedOpeningId() as OpeningId,
     group
   )
-  await beginApplicationReviewFixture.runner(false)
+  await beginApplicationReviewFixture.runner()
 
   // Fill worker opening
   const fillOpeningFixture = new FillOpeningFixture(
@@ -74,17 +74,17 @@ export default async function manageWorkerAsWorker(api: Api, env: NodeJS.Process
     payoutAmount,
     group
   )
-  await fillOpeningFixture.runner(false)
+  await fillOpeningFixture.runner()
   const workerId = fillOpeningFixture.getWorkerIds()[0]
   const increaseStakeFixture: IncreaseStakeFixture = new IncreaseStakeFixture(api, workerId, group)
   // Increase worker stake
-  await increaseStakeFixture.runner(false)
+  await increaseStakeFixture.runner()
 
   const updateRewardAccountFixture: UpdateRewardAccountFixture = new UpdateRewardAccountFixture(api, workerId, group)
   // Update reward account
-  await updateRewardAccountFixture.runner(false)
+  await updateRewardAccountFixture.runner()
 
   const updateRoleAccountFixture: UpdateRewardAccountFixture = new UpdateRewardAccountFixture(api, workerId, group)
   // Update role account
-  await updateRoleAccountFixture.runner(false)
+  await updateRoleAccountFixture.runner()
 }

+ 8 - 8
tests/network-tests/src/flows/workingGroup/workerPayout.ts

@@ -31,7 +31,7 @@ export default async function workerPayouts(api: Api, env: NodeJS.ProcessEnv, gr
 
   const memberSetFixture = new BuyMembershipHappyCaseFixture(api, newMembers, paidTerms)
   // Recreating set of members
-  await memberSetFixture.runner(false)
+  await memberSetFixture.runner()
 
   const workingGroupMintCapacityProposalFixture = new WorkingGroupMintCapacityProposalFixture(
     api,
@@ -40,14 +40,14 @@ export default async function workerPayouts(api: Api, env: NodeJS.ProcessEnv, gr
     group
   )
   // Propose mint capacity
-  await workingGroupMintCapacityProposalFixture.runner(false)
+  await workingGroupMintCapacityProposalFixture.runner()
 
   // Approve mint capacity
   const voteForProposalFixture = new VoteForProposalFixture(
     api,
     workingGroupMintCapacityProposalFixture.getCreatedProposalId() as ProposalId
   )
-  await voteForProposalFixture.runner(false)
+  await voteForProposalFixture.runner()
 
   const addWorkerOpeningFixture = new AddWorkerOpeningFixture(
     api,
@@ -58,7 +58,7 @@ export default async function workerPayouts(api: Api, env: NodeJS.ProcessEnv, gr
     group
   )
   // Add worker opening
-  await addWorkerOpeningFixture.runner(false)
+  await addWorkerOpeningFixture.runner()
 
   // First apply for worker opening
   const applyForWorkerOpeningFixture = new ApplyForOpeningFixture(
@@ -69,7 +69,7 @@ export default async function workerPayouts(api: Api, env: NodeJS.ProcessEnv, gr
     addWorkerOpeningFixture.getCreatedOpeningId() as OpeningId,
     group
   )
-  await applyForWorkerOpeningFixture.runner(false)
+  await applyForWorkerOpeningFixture.runner()
   const applicationId = applyForWorkerOpeningFixture.getApplicationIds()[0]
 
   // Begin application review
@@ -78,7 +78,7 @@ export default async function workerPayouts(api: Api, env: NodeJS.ProcessEnv, gr
     addWorkerOpeningFixture.getCreatedOpeningId() as OpeningId,
     group
   )
-  await beginApplicationReviewFixture.runner(false)
+  await beginApplicationReviewFixture.runner()
 
   // Fill worker opening
   const fillOpeningFixture = new FillOpeningFixture(
@@ -90,9 +90,9 @@ export default async function workerPayouts(api: Api, env: NodeJS.ProcessEnv, gr
     payoutAmount,
     group
   )
-  await fillOpeningFixture.runner(false)
+  await fillOpeningFixture.runner()
   const workerId = fillOpeningFixture.getWorkerIds()[0]
   const awaitPayoutFixture: AwaitPayoutFixture = new AwaitPayoutFixture(api, workerId, group)
   // Await worker payout
-  await awaitPayoutFixture.runner(false)
+  await awaitPayoutFixture.runner()
 }

+ 53 - 49
tests/network-tests/src/sender.ts

@@ -9,27 +9,34 @@ import Debugger from 'debug'
 import AsyncLock from 'async-lock'
 import { assert } from 'chai'
 
-const debug = Debugger('sender')
-
 export class Sender {
   private readonly api: ApiPromise
   private readonly asyncLock: AsyncLock
   private readonly keyring: Keyring
+  private readonly debug: Debugger.Debugger
+  private logFailedTransactions = false
 
   constructor(api: ApiPromise, keyring: Keyring) {
     this.api = api
     this.asyncLock = new AsyncLock()
     this.keyring = keyring
+    this.debug = Debugger('sender')
   }
 
   // Synchronize all sending of transactions into mempool, so we can always safely read
   // the next account nonce taking mempool into account. This is safe as long as all sending of transactions
-  // from same account occurs in the same process. Returns a promise.
-  // The promise resolves on successful dispatch (normal and sudo dispatches).
-  // The promise is rejected undef following conditions:
-  // - transaction fails to submit to node. (Encoding issues, bad signature or nonce etc.)
-  // - dispatch error after the extrinsic is finalized into a block.
-  // - successful sudo call (correct sudo key used) but dispatched call fails.
+  // from same account occurs in the same process. Returns a promise of the Extrinsic Dispatch Result ISubmittableResult.
+  // The promise resolves on tx finalization (For both Dispatch success and failure)
+  // The promise is rejected if transaction is rejected by node.
+
+  public enableLogs() {
+    this.logFailedTransactions = true
+  }
+
+  public disableLogs() {
+    this.logFailedTransactions = false
+  }
+
   public async signAndSend(
     tx: SubmittableExtrinsic<'promise'>,
     account: AccountId | string
@@ -37,11 +44,9 @@ export class Sender {
     const addr = this.keyring.encodeAddress(account)
     const senderKeyPair: KeyringPair = this.keyring.getPair(addr)
 
-    let finalizedResolve: { (result: ISubmittableResult): void }
-    let finalizedReject: { (err: DispatchError): void }
-    const finalized: Promise<ISubmittableResult> = new Promise(async (resolve, reject) => {
-      finalizedResolve = resolve
-      finalizedReject = reject
+    let finalized: { (result: ISubmittableResult): void }
+    const whenFinalized: Promise<ISubmittableResult> = new Promise(async (resolve, reject) => {
+      finalized = resolve
     })
 
     // saved human representation of the signed tx, will be set before it is submitted.
@@ -50,9 +55,10 @@ export class Sender {
 
     const handleEvents = (result: ISubmittableResult) => {
       if (result.status.isFuture) {
-        // Its virtually impossible for use to continue with tests
+        // Its virtually impossible for us to continue with tests
         // when this occurs and we don't expect the tests to handle this correctly
         // so just abort!
+        console.error('Future Tx, aborting!')
         process.exit(-1)
       }
 
@@ -63,52 +69,50 @@ export class Sender {
       const success = result.findRecord('system', 'ExtrinsicSuccess')
       const failed = result.findRecord('system', 'ExtrinsicFailed')
 
-      if (success) {
-        const sudid = result.findRecord('sudo', 'Sudid')
-        if (sudid) {
-          const dispatchResult = sudid.event.data[0] as DispatchResult
-          if (dispatchResult.isOk) {
-            debug(`Successful Sudo Tx: ${sentTx}`)
-            finalizedResolve(result)
-          } else if (dispatchResult.isError) {
-            const err = dispatchResult.asError
-            debug(`Sudo Error: FailedTx: ${sentTx} dispatch error: ${err.toHuman()}`)
-            if (err.isModule) {
-              const { name, documentation } = (this.api.registry as TypeRegistry).findMetaError(err.asModule)
-              debug(`${name}\n${documentation}`)
-            }
-            finalizedReject(err)
-          } else {
-            // What other result type can it be??
-            assert(false)
+      // Log failed transactions
+      if (this.logFailedTransactions) {
+        if (failed) {
+          const record = failed as EventRecord
+          assert(record)
+          const {
+            event: { data },
+          } = record
+          const err = data[0] as DispatchError
+          this.debug('ExtrinsicFailed:', sentTx, 'DispatchError:', err.toHuman())
+          if (err.isModule) {
+            const { name, documentation } = (this.api.registry as TypeRegistry).findMetaError(err.asModule)
+            this.debug(`Error Details: ${name}\n${documentation}`)
           }
         } else {
-          debug(`Successful Tx: ${sentTx}`)
-          finalizedResolve(result)
-        }
-      } else {
-        assert(failed)
-        const record = failed as EventRecord
-        const {
-          event: { data },
-        } = record
-        const err = (data[0] as DispatchResult).asError // data[0] as DispatchError
-        debug(`FailedTx: ${sentTx} dispatch error: ${err.toHuman()}`)
-        if (err.isModule) {
-          const { name, documentation } = (this.api.registry as TypeRegistry).findMetaError(err.asModule)
-          debug(`${name}\n${documentation}`)
+          assert(success)
+          const sudid = result.findRecord('sudo', 'Sudid')
+          if (sudid) {
+            const dispatchResult = sudid.event.data[0] as DispatchResult
+            assert(dispatchResult)
+            if (dispatchResult.isError) {
+              const err = dispatchResult.asError
+              this.debug('Sudo Dispatch Failed', sentTx, 'DispatchError:', err.toHuman())
+              if (err.isModule) {
+                const { name, documentation } = (this.api.registry as TypeRegistry).findMetaError(err.asModule)
+                this.debug(`Error Details: ${name}\n${documentation}`)
+              }
+            }
+          }
         }
-        finalizedReject(err)
       }
+
+      // Always resolve irrespective of success or failure. Error handling should
+      // be dealt with by caller.
+      finalized(result)
     }
 
     await this.asyncLock.acquire(`${senderKeyPair.address}`, async () => {
       const nonce = await this.api.rpc.system.accountNextIndex(senderKeyPair.address)
       const signedTx = tx.sign(senderKeyPair, { nonce })
       sentTx = signedTx.toHuman()
-      return signedTx.send(handleEvents)
+      await signedTx.send(handleEvents)
     })
 
-    return finalized
+    return whenFinalized
   }
 }