Browse Source

integration-tests: refactor flows and fixtures first round

Mokhtar Naamani 4 years ago
parent
commit
3b8329feaa

+ 59 - 79
tests/network-tests/src/Api.ts

@@ -622,12 +622,6 @@ export class Api {
     return council.map((seat) => seat.member.toString())
   }
 
-  // This method is deprecated. Is there a replacement in newer versions of substrate?
-  // Do we even use this method?
-  // public getRuntime(): Promise<Bytes> {
-  //   return this.api.query.substrate.code<Bytes>()
-  // }
-
   public async proposeRuntime(
     account: string,
     stake: BN,
@@ -759,95 +753,79 @@ export class Api {
     return this.getBlockDuration().muln(durationInBlocks).toNumber()
   }
 
-  public expectMemberRegisteredEvent(events: EventRecord[]): MemberId {
-    const record = events.find((record) => record.event.method && record.event.method.toString() === 'MemberRegistered')
-    if (!record) {
-      throw new Error('Expected Event Not Found')
-    }
-    return record.event.data[0] as MemberId
+  public findEventRecord(events: EventRecord[], section: string, method: string): EventRecord | undefined {
+    return events.find((record) => record.event.section === section && record.event.method === method)
   }
 
-  public expectProposalCreatedEvent(events: EventRecord[]): ProposalId {
-    const record = events.find((record) => record.event.method && record.event.method.toString() === 'ProposalCreated')
-    if (!record) {
-      throw new Error('Expected Event Not Found')
+  public findMemberRegisteredEvent(events: EventRecord[]): MemberId | undefined {
+    const record = this.findEventRecord(events, 'members', 'MemberRegistered')
+    if (record) {
+      return record.event.data[0] as MemberId
     }
-    return record.event.data[1] as ProposalId
   }
 
-  public expectOpeningAddedEvent(events: EventRecord[]): OpeningId {
-    const record = events.find((record) => record.event.method && record.event.method.toString() === 'OpeningAdded')
-    if (!record) {
-      throw new Error('Expected Event Not Found')
+  public findProposalCreatedEvent(events: EventRecord[]): ProposalId | undefined {
+    const record = this.findEventRecord(events, 'proposalsEngine', 'ProposalCreated')
+    if (record) {
+      return record.event.data[1] as ProposalId
     }
-    return record.event.data[0] as OpeningId
   }
 
-  public expectLeaderSetEvent(events: EventRecord[]): WorkerId {
-    const record = events.find((record) => record.event.method && record.event.method.toString() === 'LeaderSet')
-    if (!record) {
-      throw new Error('Expected Event Not Found')
+  public findOpeningAddedEvent(events: EventRecord[], workingGroup: WorkingGroups): OpeningId | undefined {
+    const record = this.findEventRecord(events, workingGroup, 'OpeningAdded')
+    if (record) {
+      return record.event.data[0] as OpeningId
     }
-    return (record.event.data as unknown) as WorkerId
   }
 
-  public expectBeganApplicationReviewEvent(events: EventRecord[]): ApplicationId {
-    const record = events.find(
-      (record) => record.event.method && record.event.method.toString() === 'BeganApplicationReview'
-    )
-    if (!record) {
-      throw new Error('Expected Event Not Found')
+  public findLeaderSetEvent(events: EventRecord[], workingGroup: WorkingGroups): WorkerId | undefined {
+    const record = this.findEventRecord(events, workingGroup, 'LeaderSet')
+    if (record) {
+      return (record.event.data as unknown) as WorkerId
     }
-    return (record.event.data as unknown) as ApplicationId
   }
 
-  public expectTerminatedLeaderEvent(events: EventRecord[]): void {
-    const record = events.find((record) => record.event.method && record.event.method.toString() === 'TerminatedLeader')
-    if (!record) {
-      throw new Error('Expected Event Not Found')
+  public findBeganApplicationReviewEvent(
+    events: EventRecord[],
+    workingGroup: WorkingGroups
+  ): ApplicationId | undefined {
+    const record = this.findEventRecord(events, workingGroup, 'BeganApplicationReview')
+    if (record) {
+      return (record.event.data as unknown) as ApplicationId
     }
   }
 
-  public expectWorkerRewardAmountUpdatedEvent(events: EventRecord[]): WorkerId {
-    const record = events.find(
-      (record) => record.event.method && record.event.method.toString() === 'WorkerRewardAmountUpdated'
-    )
-    if (!record) {
-      throw new Error('Expected Event Not Found')
-    }
-    return (record.event.data[0] as unknown) as WorkerId
+  public findTerminatedLeaderEvent(events: EventRecord[], workingGroup: WorkingGroups): EventRecord | undefined {
+    return this.findEventRecord(events, workingGroup, 'TerminatedLeader')
   }
 
-  public expectStakeDecreasedEvent(events: EventRecord[]): void {
-    const record = events.find((record) => record.event.method && record.event.method.toString() === 'StakeDecreased')
-    if (!record) {
-      throw new Error('Expected Event Not Found')
+  public findWorkerRewardAmountUpdatedEvent(events: EventRecord[], workingGroup: WorkingGroups): WorkerId | undefined {
+    const record = this.findEventRecord(events, workingGroup, 'WorkerRewardAmountUpdated')
+    if (record) {
+      return (record.event.data[0] as unknown) as WorkerId
     }
   }
 
-  public expectStakeSlashedEvent(events: EventRecord[]): void {
-    const record = events.find((record) => record.event.method && record.event.method.toString() === 'StakeSlashed')
-    if (!record) {
-      throw new Error('Expected Event Not Found')
-    }
+  public findStakeDecreasedEvent(events: EventRecord[], workingGroup: WorkingGroups): EventRecord | undefined {
+    return this.findEventRecord(events, workingGroup, 'StakeDecreased')
   }
 
-  public expectMintCapacityChangedEvent(events: EventRecord[]): BN {
-    const record = events.find(
-      (record) => record.event.method && record.event.method.toString() === 'MintCapacityChanged'
-    )
-    if (!record) {
-      throw new Error('Expected Event Not Found')
+  public findStakeSlashedEvent(events: EventRecord[], workingGroup: WorkingGroups): EventRecord | undefined {
+    return this.findEventRecord(events, workingGroup, 'StakeSlashed')
+  }
+
+  public findMintCapacityChangedEvent(events: EventRecord[], workingGroup: WorkingGroups): BN | undefined {
+    const record = this.findEventRecord(events, workingGroup, 'MintCapacityChanged')
+    if (record) {
+      return (record.event.data[1] as unknown) as BN
     }
-    return (record.event.data[1] as unknown) as BN
   }
 
-  public async expectRuntimeUpgraded(): Promise<void> {
-    await this.expectSystemEvent('RuntimeUpdated')
+  public async expectRuntimeUpgraded(): Promise<Event> {
+    return this.waitForSystemEvent('RuntimeUpdated')
   }
 
-  // Resolves with events that were emitted at the same time that the proposal
-  // was finalized (I think!)
+  // Resolves with events that were emitted at the same time that the proposal was finalized
   public waitForProposalToFinalize(id: ProposalId): Promise<EventRecord[]> {
     return new Promise(async (resolve) => {
       const unsubscribe = await this.api.query.system.events<Vec<EventRecord>>((events) => {
@@ -874,17 +852,19 @@ export class Api {
     })
   }
 
-  public expectOpeningFilledEvent(events: EventRecord[]): ApplicationIdToWorkerIdMap {
-    const record = events.find((record) => record.event.method && record.event.method.toString() === 'OpeningFilled')
-    if (!record) {
-      throw new Error('Expected Event Not Found')
+  public findOpeningFilledEvent(
+    events: EventRecord[],
+    workingGroup: WorkingGroups
+  ): ApplicationIdToWorkerIdMap | undefined {
+    const record = this.findEventRecord(events, workingGroup, 'OpeningFilled')
+    if (record) {
+      return (record.event.data[1] as unknown) as ApplicationIdToWorkerIdMap
     }
-    return (record.event.data[1] as unknown) as ApplicationIdToWorkerIdMap
   }
 
   // Looks for the first occurance of an expected event, and resolves.
   // Use this when the event we are expecting is not particular to a specific extrinsic
-  public expectSystemEvent(eventName: string): Promise<Event> {
+  public waitForSystemEvent(eventName: string): Promise<Event> {
     return new Promise(async (resolve) => {
       const unsubscribe = await this.api.query.system.events<Vec<EventRecord>>((events) => {
         events.forEach((record) => {
@@ -897,14 +877,14 @@ export class Api {
     })
   }
 
-  public expectApplicationReviewBeganEvent(events: EventRecord[]): ApplicationId {
-    const record = events.find(
-      (record) => record.event.method && record.event.method.toString() === 'BeganApplicationReview'
-    )
-    if (!record) {
-      throw new Error('Expected Event Not Found')
+  public findApplicationReviewBeganEvent(
+    events: EventRecord[],
+    workingGroup: WorkingGroups
+  ): ApplicationId | undefined {
+    const record = this.findEventRecord(events, workingGroup, 'BeganApplicationReview')
+    if (record) {
+      return (record.event.data as unknown) as ApplicationId
     }
-    return (record.event.data as unknown) as ApplicationId
   }
 
   public async getWorkingGroupMintCapacity(module: WorkingGroups): Promise<BN> {

+ 5 - 4
tests/network-tests/src/fixtures/membershipModule.ts

@@ -23,7 +23,6 @@ export class BuyMembershipHappyCaseFixture extends BaseFixture {
   }
 
   async execute(): Promise<void> {
-    this.debug(`Registering ${this.accounts.length} new members`)
     // Fee estimation and transfer
     const membershipFee: BN = await this.api.getMembershipFee(this.paidTerms)
     const membershipTransactionFee: BN = this.api.estimateBuyMembershipFee(
@@ -40,11 +39,13 @@ export class BuyMembershipHappyCaseFixture extends BaseFixture {
           this.api.buyMembership(account, this.paidTerms, `member${account.substring(0, 14)}`)
         )
       )
-    ).map(({ events }) => this.api.expectMemberRegisteredEvent(events))
+    )
+      .map(({ events }) => this.api.findMemberRegisteredEvent(events))
+      .filter((id) => id !== undefined) as MemberId[]
 
-    assert.equal(this.accounts.length, this.memberIds.length)
+    this.debug(`Registered ${this.memberIds.length} new members`)
 
-    this.debug(`New member id(s): ${this.memberIds}`)
+    assert.equal(this.accounts.length, this.memberIds.length)
   }
 }
 

+ 18 - 13
tests/network-tests/src/fixtures/proposalsModule.ts

@@ -68,7 +68,7 @@ export class CreateWorkingGroupLeaderOpeningFixture implements Fixture {
       workingGroup: this.workingGroup,
     })
 
-    this.result = this.api.expectProposalCreatedEvent(result.events)
+    this.result = this.api.findProposalCreatedEvent(result.events)
   }
 }
 
@@ -111,7 +111,7 @@ export class BeginWorkingGroupLeaderApplicationReviewFixture implements Fixture
       this.workingGroup
     )
 
-    this.result = this.api.expectProposalCreatedEvent(result.events)
+    this.result = this.api.findProposalCreatedEvent(result.events)
   }
 }
 
@@ -178,7 +178,7 @@ export class FillLeaderOpeningProposalFixture implements Fixture {
       workingGroup: workingGroupString,
     })
 
-    this.result = this.api.expectProposalCreatedEvent(result.events)
+    this.result = this.api.findProposalCreatedEvent(result.events)
   }
 }
 
@@ -226,7 +226,7 @@ export class TerminateLeaderRoleProposalFixture implements Fixture {
       this.slash,
       workingGroupString
     )
-    this.result = this.api.expectProposalCreatedEvent(result.events)
+    this.result = this.api.findProposalCreatedEvent(result.events)
   }
 }
 
@@ -273,7 +273,7 @@ export class SetLeaderRewardProposalFixture implements Fixture {
       workingGroupString
     )
 
-    this.result = this.api.expectProposalCreatedEvent(result.events)
+    this.result = this.api.findProposalCreatedEvent(result.events)
   }
 }
 
@@ -320,7 +320,7 @@ export class DecreaseLeaderStakeProposalFixture implements Fixture {
       workingGroupString
     )
 
-    this.result = this.api.expectProposalCreatedEvent(result.events)
+    this.result = this.api.findProposalCreatedEvent(result.events)
   }
 }
 
@@ -365,7 +365,7 @@ export class SlashLeaderProposalFixture implements Fixture {
       this.slashAmount,
       workingGroupString
     )
-    this.result = this.api.expectProposalCreatedEvent(result.events)
+    this.result = this.api.findProposalCreatedEvent(result.events)
   }
 }
 
@@ -408,7 +408,7 @@ export class WorkingGroupMintCapacityProposalFixture implements Fixture {
       this.mintCapacity,
       workingGroupString
     )
-    this.result = this.api.expectProposalCreatedEvent(result.events)
+    this.result = this.api.findProposalCreatedEvent(result.events)
   }
 }
 
@@ -483,7 +483,8 @@ export class ElectionParametersProposalFixture implements Fixture {
       proposedMinCouncilStake,
       proposedMinVotingStake
     )
-    const proposalNumber = this.api.expectProposalCreatedEvent(proposalCreationResult.events)
+    const proposalNumber = this.api.findProposalCreatedEvent(proposalCreationResult.events) as ProposalId
+    assert.notEqual(proposalNumber, undefined)
 
     // Approving the proposal
     this.api.batchApproveProposal(proposalNumber)
@@ -576,7 +577,8 @@ export class SpendingProposalFixture implements Fixture {
       this.spendingBalance,
       fundingRecipient
     )
-    const proposalNumber: ProposalId = this.api.expectProposalCreatedEvent(result.events)
+    const proposalNumber: ProposalId = this.api.findProposalCreatedEvent(result.events) as ProposalId
+    assert.notEqual(proposalNumber, undefined)
 
     // Approving spending proposal
     const balanceBeforeMinting: BN = await this.api.getBalance(fundingRecipient)
@@ -624,7 +626,8 @@ export class TextProposalFixture implements Fixture {
     // Proposal creation
 
     const result = await this.api.proposeText(this.proposer, proposalStake, proposalTitle, description, proposalText)
-    const proposalNumber: ProposalId = this.api.expectProposalCreatedEvent(result.events)
+    const proposalNumber = this.api.findProposalCreatedEvent(result.events) as ProposalId
+    assert.notEqual(proposalNumber, undefined)
 
     // Approving text proposal
     this.api.batchApproveProposal(proposalNumber)
@@ -666,7 +669,8 @@ export class ValidatorCountProposalFixture implements Fixture {
       proposalStake,
       proposedValidatorCount
     )
-    const proposalNumber: ProposalId = this.api.expectProposalCreatedEvent(result.events)
+    const proposalNumber: ProposalId = this.api.findProposalCreatedEvent(result.events) as ProposalId
+    assert.notEqual(proposalNumber, undefined)
 
     // Approving the proposal
     this.api.batchApproveProposal(proposalNumber)
@@ -717,7 +721,8 @@ export class UpdateRuntimeFixture implements Fixture {
       'runtime to test proposal functionality' + uuid().substring(0, 8),
       runtime
     )
-    const proposalNumber: ProposalId = this.api.expectProposalCreatedEvent(result.events)
+    const proposalNumber: ProposalId = this.api.findProposalCreatedEvent(result.events) as ProposalId
+    assert.notEqual(proposalNumber, undefined)
 
     // Approving runtime update proposal
     this.api.batchApproveProposal(proposalNumber)

+ 20 - 7
tests/network-tests/src/fixtures/workingGroupModule.ts

@@ -76,7 +76,8 @@ export class AddWorkerOpeningFixture implements Fixture {
       this.module
     )
 
-    this.result = this.api.expectOpeningAddedEvent(result.events)
+    // We don't assert, we allow potential failure
+    this.result = this.api.findOpeningAddedEvent(result.events, this.module)
   }
 }
 
@@ -128,7 +129,8 @@ export class SudoAddLeaderOpeningFixture implements Fixture {
       this.module
     )
 
-    this.result = this.api.expectOpeningAddedEvent(result.events)
+    // We don't assert, we allow potential failure
+    this.result = this.api.findOpeningAddedEvent(result.events, this.module)
   }
 }
 
@@ -271,7 +273,7 @@ export class BeginApplicationReviewFixture implements Fixture {
     // const beginApplicantReviewPromise: Promise<ApplicationId> = this.api.expectApplicationReviewBegan()
     const result = await this.api.beginApplicantReview(leadAccount, this.openingId, this.module)
 
-    this.api.expectApplicationReviewBeganEvent(result.events)
+    assert.notEqual(this.api.findApplicationReviewBeganEvent(result.events, this.module), undefined)
   }
 }
 
@@ -355,7 +357,12 @@ export class FillOpeningFixture implements Fixture {
       this.payoutInterval,
       this.module
     )
-    const applicationIdToWorkerIdMap: ApplicationIdToWorkerIdMap = this.api.expectOpeningFilledEvent(result.events)
+    const applicationIdToWorkerIdMap = this.api.findOpeningFilledEvent(
+      result.events,
+      this.module
+    ) as ApplicationIdToWorkerIdMap
+    assert.notEqual(applicationIdToWorkerIdMap, undefined)
+
     this.workerIds = []
     applicationIdToWorkerIdMap.forEach((workerId) => this.workerIds.push(workerId))
 
@@ -411,12 +418,18 @@ export class SudoFillLeaderOpeningFixture implements Fixture {
     )
 
     // Assertions
-    const applicationIdToWorkerIdMap = this.api.expectOpeningFilledEvent(result.events)
-    assert(applicationIdToWorkerIdMap.size === 1)
+    const applicationIdToWorkerIdMap = this.api.findOpeningFilledEvent(
+      result.events,
+      this.module
+    ) as ApplicationIdToWorkerIdMap
+    assert.notEqual(applicationIdToWorkerIdMap, undefined)
+    assert.equal(applicationIdToWorkerIdMap.size, 1)
+
     applicationIdToWorkerIdMap.forEach(async (workerId, applicationId) => {
       const worker: Worker = await this.api.getWorkerById(workerId, this.module)
       const application: Application = await this.api.getApplicationById(applicationId, this.module)
-      const leadWorkerId: WorkerId = (await this.api.getLeadWorkerId(this.module))!
+      const leadWorkerId = (await this.api.getLeadWorkerId(this.module)) as WorkerId
+      assert.notEqual(leadWorkerId, undefined)
       assert(
         worker.role_account_id.toString() === application.role_account_id.toString(),
         `Role account ids does not match, leader account: ${worker.role_account_id}, application account ${application.role_account_id}`

+ 6 - 3
tests/network-tests/src/flows/proposals/manageLeaderRole.ts

@@ -15,6 +15,7 @@ import { ApplyForOpeningFixture } from '../../fixtures/workingGroupModule'
 import { PaidTermId } from '@joystream/types/members'
 import { OpeningId } from '@joystream/types/hiring'
 import { ProposalId } from '@joystream/types/proposals'
+import { WorkerId } from '@joystream/types/working-group'
 import { assert } from 'chai'
 import { FixtureRunner } from '../../Fixture'
 
@@ -61,11 +62,12 @@ export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv,
   // Approve add opening proposal
   const voteForCreateOpeningProposalFixture = new VoteForProposalFixture(
     api,
-    createWorkingGroupLeaderOpeningFixture.getCreatedProposalId() as OpeningId
+    createWorkingGroupLeaderOpeningFixture.getCreatedProposalId() as ProposalId
   )
 
   await voteForCreateOpeningProposalFixture.runner()
-  const openingId = api.expectOpeningAddedEvent(voteForCreateOpeningProposalFixture.getEvents())
+  const openingId = api.findOpeningAddedEvent(voteForCreateOpeningProposalFixture.getEvents(), group) as OpeningId
+  assert(openingId)
 
   const applyForLeaderOpeningFixture = new ApplyForOpeningFixture(
     api,
@@ -130,7 +132,8 @@ export default async function manageLeaderRole(api: Api, env: NodeJS.ProcessEnv,
 
   const leadId = await api.getLeadWorkerId(group)
   // This check is prone to failure if more than one worker's reward amount was updated
-  const workerId = api.expectWorkerRewardAmountUpdatedEvent(voteForeLeaderRewardFixture.getEvents())
+  const workerId = api.findWorkerRewardAmountUpdatedEvent(voteForeLeaderRewardFixture.getEvents(), group) as WorkerId
+  assert(workerId)
   assert(leadId!.eq(workerId))
   const rewardRelationship = await api.getWorkerRewardRelationship(leadId!, group)
   assert(rewardRelationship.amount_per_payout.eq(alteredPayoutAmount))

+ 12 - 12
tests/network-tests/src/flows/workingGroup/atLeastValueBug.ts

@@ -28,12 +28,12 @@ export default async function zeroAtLeastValueBug(api: Api, env: NodeJS.ProcessE
   )
 
   // 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
-  }
+  await addWorkerOpeningWithoutStakeFixture.runner()
+  assert.equal(
+    addWorkerOpeningWithoutStakeFixture.getCreatedOpeningId(),
+    undefined,
+    'Adding Worker Opening Should have failed'
+  )
 
   const addWorkerOpeningWithoutUnstakingPeriodFixture = new AddWorkerOpeningFixture(
     api,
@@ -45,12 +45,12 @@ export default async function zeroAtLeastValueBug(api: Api, env: NodeJS.ProcessE
   )
 
   // 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
-  }
+  await addWorkerOpeningWithoutUnstakingPeriodFixture.runner()
+  assert.equal(
+    addWorkerOpeningWithoutUnstakingPeriodFixture.getCreatedOpeningId(),
+    undefined,
+    'Adding Worker Opening Should have failed'
+  )
 
   // TODO: close openings
   debug('Passed')

+ 1 - 0
tests/network-tests/src/scenarios/full.ts

@@ -34,6 +34,7 @@ const scenario = async () => {
   // Runtime is configured for MaxActiveProposalLimit = 5
   // So we should ensure we don't exceed that number of active proposals
   // which limits the number of concurrent tests that create proposals
+  api.enableTxLogs()
   await Promise.all([
     electionParametersProposal(api, env),
     spendingProposal(api, env),

+ 9 - 7
tests/network-tests/src/sender.ts

@@ -78,10 +78,11 @@ export class Sender {
             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}`)
+            const { name } = (this.api.registry as TypeRegistry).findMetaError(err.asModule)
+            this.debug('Dispatch Error:', name, sentTx)
+          } else {
+            this.debug('Dispatch Error:', sentTx)
           }
         } else {
           assert(success)
@@ -91,10 +92,11 @@ export class Sender {
             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}`)
+                const { name } = (this.api.registry as TypeRegistry).findMetaError(err.asModule)
+                this.debug('Sudo Dispatch Failed', name, sentTx)
+              } else {
+                this.debug('Sudo Dispatch Failed', sentTx)
               }
             }
           }
@@ -103,7 +105,7 @@ export class Sender {
 
       // Always resolve irrespective of success or failure. Error handling should
       // be dealt with by caller.
-      finalized(result)
+      if (success || failed) finalized(result)
     }
 
     await this.asyncLock.acquire(`${senderKeyPair.address}`, async () => {