CreateUpcomingOpeningsFixture.ts 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import { Api } from '../../Api'
  2. import { QueryNodeApi } from '../../QueryNodeApi'
  3. import { EventDetails, WorkingGroupModuleName } from '../../types'
  4. import { SubmittableExtrinsic } from '@polkadot/api/types'
  5. import { Utils } from '../../utils'
  6. import { ISubmittableResult } from '@polkadot/types/types/'
  7. import { StatusTextChangedEventFieldsFragment, UpcomingOpeningFieldsFragment } from '../../graphql/generated/queries'
  8. import { assert } from 'chai'
  9. import {
  10. IUpcomingOpeningMetadata,
  11. UpcomingOpeningMetadata,
  12. WorkingGroupMetadataAction,
  13. } from '@joystream/metadata-protobuf'
  14. import Long from 'long'
  15. import { Bytes } from '@polkadot/types'
  16. import moment from 'moment'
  17. import { DEFAULT_OPENING_PARAMS } from './CreateOpeningsFixture'
  18. import { createType } from '@joystream/types'
  19. import { assertQueriedOpeningMetadataIsValid } from './utils'
  20. import { BaseWorkingGroupFixture } from './BaseWorkingGroupFixture'
  21. export const DEFAULT_UPCOMING_OPENING_META: IUpcomingOpeningMetadata = {
  22. minApplicationStake: Long.fromString(DEFAULT_OPENING_PARAMS.stake.toString()),
  23. rewardPerBlock: Long.fromString(DEFAULT_OPENING_PARAMS.reward.toString()),
  24. expectedStart: moment().unix() + 3600,
  25. metadata: DEFAULT_OPENING_PARAMS.metadata,
  26. }
  27. export type UpcomingOpeningParams = {
  28. meta: IUpcomingOpeningMetadata | string
  29. expectMetadataFailure?: boolean
  30. }
  31. export class CreateUpcomingOpeningsFixture extends BaseWorkingGroupFixture {
  32. protected upcomingOpeningsParams: UpcomingOpeningParams[]
  33. protected createdUpcomingOpeningIds: string[] = []
  34. public constructor(api: Api, query: QueryNodeApi, group: WorkingGroupModuleName, params?: UpcomingOpeningParams[]) {
  35. super(api, query, group)
  36. this.upcomingOpeningsParams = params || [{ meta: DEFAULT_UPCOMING_OPENING_META }]
  37. }
  38. protected async getSignerAccountOrAccounts(): Promise<string> {
  39. return this.api.getLeadRoleKey(this.group)
  40. }
  41. protected async getExtrinsics(): Promise<SubmittableExtrinsic<'promise'>[]> {
  42. return this.upcomingOpeningsParams.map((params) =>
  43. this.api.tx[this.group].setStatusText(this.getActionMetadataBytes(params))
  44. )
  45. }
  46. protected async getEventFromResult(result: ISubmittableResult): Promise<EventDetails> {
  47. return this.api.retrieveWorkingGroupsEventDetails(result, this.group, 'StatusTextChanged')
  48. }
  49. public getCreatedUpcomingOpeningIds(): string[] {
  50. if (!this.createdUpcomingOpeningIds.length) {
  51. throw new Error('Trying to get created UpcomingOpening ids before they are known')
  52. }
  53. return this.createdUpcomingOpeningIds
  54. }
  55. protected getUpcomingOpeningMeta(params: UpcomingOpeningParams): IUpcomingOpeningMetadata | null {
  56. if (typeof params.meta === 'string') {
  57. try {
  58. return Utils.metadataFromBytes(UpcomingOpeningMetadata, createType('Bytes', params.meta))
  59. } catch (e) {
  60. if (!params.expectMetadataFailure) {
  61. throw e
  62. }
  63. return null
  64. }
  65. }
  66. return params.meta
  67. }
  68. protected getActionMetadataBytes(params: UpcomingOpeningParams): Bytes {
  69. const upcomingOpeningMeta = this.getUpcomingOpeningMeta(params)
  70. if (!upcomingOpeningMeta) {
  71. return createType('Bytes', params.meta)
  72. }
  73. return Utils.metadataToBytes(WorkingGroupMetadataAction, {
  74. addUpcomingOpening: {
  75. metadata: upcomingOpeningMeta,
  76. },
  77. })
  78. }
  79. protected assertQueriedUpcomingOpeningsAreValid(
  80. qUpcomingOpenings: UpcomingOpeningFieldsFragment[],
  81. qEvents: StatusTextChangedEventFieldsFragment[]
  82. ): void {
  83. this.events.forEach((e, i) => {
  84. const expectedMeta = this.getUpcomingOpeningMeta(this.upcomingOpeningsParams[i])
  85. const qEvent = this.findMatchingQueryNodeEvent(e, qEvents)
  86. const qUpcomingOpening = qUpcomingOpenings.find((o) => o.createdInEvent.id === qEvent.id)
  87. if (expectedMeta) {
  88. Utils.assert(qUpcomingOpening)
  89. assert.equal(
  90. qUpcomingOpening.expectedStart
  91. ? new Date(qUpcomingOpening.expectedStart).getTime()
  92. : qUpcomingOpening.expectedStart,
  93. expectedMeta.expectedStart || null
  94. )
  95. assert.equal(qUpcomingOpening.group.name, this.group)
  96. assert.equal(
  97. qUpcomingOpening.rewardPerBlock,
  98. expectedMeta.rewardPerBlock && expectedMeta.rewardPerBlock.toNumber()
  99. ? expectedMeta.rewardPerBlock.toString()
  100. : null
  101. )
  102. assert.equal(
  103. qUpcomingOpening.stakeAmount,
  104. expectedMeta.minApplicationStake && expectedMeta.minApplicationStake.toNumber()
  105. ? expectedMeta.minApplicationStake.toString()
  106. : null
  107. )
  108. Utils.assert(qEvent.result.__typename === 'UpcomingOpeningAdded')
  109. assert.equal(qEvent.result.upcomingOpeningId, qUpcomingOpening.id)
  110. assertQueriedOpeningMetadataIsValid(qUpcomingOpening.metadata, expectedMeta.metadata)
  111. } else {
  112. assert.isUndefined(qUpcomingOpening)
  113. }
  114. })
  115. }
  116. protected assertQueryNodeEventIsValid(qEvent: StatusTextChangedEventFieldsFragment, i: number): void {
  117. const params = this.upcomingOpeningsParams[i]
  118. assert.equal(qEvent.group.name, this.group)
  119. assert.equal(qEvent.metadata, this.getActionMetadataBytes(params).toString())
  120. assert.equal(
  121. qEvent.result.__typename,
  122. params.expectMetadataFailure ? 'InvalidActionMetadata' : 'UpcomingOpeningAdded'
  123. )
  124. }
  125. async runQueryNodeChecks(): Promise<void> {
  126. await super.runQueryNodeChecks()
  127. // Query the event
  128. const qEvents = await this.query.tryQueryWithTimeout(
  129. () => this.query.getStatusTextChangedEvents(this.events),
  130. (qEvents) => this.assertQueryNodeEventsAreValid(qEvents)
  131. )
  132. // Query the opening
  133. const qUpcomingOpenings = await this.query.getUpcomingOpeningsByCreatedInEventIds(qEvents.map((e) => e.id))
  134. this.assertQueriedUpcomingOpeningsAreValid(qUpcomingOpenings, qEvents)
  135. this.createdUpcomingOpeningIds = qUpcomingOpenings.map((o) => o.id)
  136. }
  137. }