AddPostsFixture.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import { Api } from '../../Api'
  2. import { QueryNodeApi } from '../../QueryNodeApi'
  3. import { MetadataInput, PostAddedEventDetails } from '../../types'
  4. import { SubmittableExtrinsic } from '@polkadot/api/types'
  5. import { Utils } from '../../utils'
  6. import { ISubmittableResult } from '@polkadot/types/types/'
  7. import { ForumPostFieldsFragment, PostAddedEventFieldsFragment } from '../../graphql/generated/queries'
  8. import { assert } from 'chai'
  9. import { StandardizedFixture } from '../../Fixture'
  10. import { CategoryId } from '@joystream/types/forum'
  11. import { MemberId, PostId, ThreadId } from '@joystream/types/common'
  12. import { POST_DEPOSIT } from '../../consts'
  13. import { ForumPostMetadata, IForumPostMetadata } from '@joystream/metadata-protobuf'
  14. export type PostParams = {
  15. categoryId: CategoryId | number
  16. threadId: ThreadId | number
  17. asMember: MemberId
  18. editable?: boolean // defaults to true
  19. metadata: MetadataInput<IForumPostMetadata> & { expectReplyFailure?: boolean }
  20. }
  21. export class AddPostsFixture extends StandardizedFixture {
  22. protected events: PostAddedEventDetails[] = []
  23. protected postsParams: PostParams[]
  24. public constructor(api: Api, query: QueryNodeApi, postsParams: PostParams[]) {
  25. super(api, query)
  26. this.postsParams = postsParams
  27. }
  28. public getCreatedPostsIds(): PostId[] {
  29. if (!this.events.length) {
  30. throw new Error('Trying to get created posts ids before they were created!')
  31. }
  32. return this.events.map((e) => e.postId)
  33. }
  34. protected async getSignerAccountOrAccounts(): Promise<string[]> {
  35. return await Promise.all(
  36. this.postsParams.map(async ({ asMember }) =>
  37. (await this.api.query.members.membershipById(asMember)).controller_account.toString()
  38. )
  39. )
  40. }
  41. public async execute(): Promise<void> {
  42. const accounts = await this.getSignerAccountOrAccounts()
  43. // Send required funds to accounts (PostDeposit)
  44. await Promise.all(accounts.map((a) => this.api.treasuryTransferBalance(a, POST_DEPOSIT)))
  45. await super.execute()
  46. }
  47. protected async getExtrinsics(): Promise<SubmittableExtrinsic<'promise'>[]> {
  48. return this.postsParams.map((params) =>
  49. this.api.tx.forum.addPost(
  50. params.asMember,
  51. params.categoryId,
  52. params.threadId,
  53. Utils.getMetadataBytesFromInput(ForumPostMetadata, params.metadata),
  54. params.editable === undefined || params.editable
  55. )
  56. )
  57. }
  58. protected async getEventFromResult(result: ISubmittableResult): Promise<PostAddedEventDetails> {
  59. return this.api.retrievePostAddedEventDetails(result)
  60. }
  61. protected getPostExpectedText({ metadata: inputMeta }: PostParams): string {
  62. const meta = Utils.getDeserializedMetadataFormInput(ForumPostMetadata, inputMeta)
  63. const metaBytes = Utils.getMetadataBytesFromInput(ForumPostMetadata, inputMeta)
  64. return meta ? meta.text || '' : Utils.bytesToString(metaBytes)
  65. }
  66. protected assertQueriedPostsAreValid(
  67. qPosts: ForumPostFieldsFragment[],
  68. qEvents: PostAddedEventFieldsFragment[]
  69. ): void {
  70. this.events.map((e, i) => {
  71. const qPost = qPosts.find((p) => p.id === e.postId.toString())
  72. const qEvent = this.findMatchingQueryNodeEvent(e, qEvents)
  73. const postParams = this.postsParams[i]
  74. const expectedStatus =
  75. postParams.editable === undefined || postParams.editable ? 'PostStatusActive' : 'PostStatusLocked'
  76. const expectedMetadata = Utils.getDeserializedMetadataFormInput(ForumPostMetadata, postParams.metadata)
  77. Utils.assert(qPost, 'Query node: Post not found')
  78. assert.equal(qPost.thread.id, postParams.threadId.toString())
  79. assert.equal(qPost.author.id, postParams.asMember.toString())
  80. assert.equal(qPost.status.__typename, expectedStatus)
  81. assert.equal(qPost.text, this.getPostExpectedText(postParams))
  82. assert.equal(
  83. qPost.repliesTo?.id,
  84. postParams.metadata.expectReplyFailure ? undefined : expectedMetadata?.repliesTo?.toString()
  85. )
  86. Utils.assert(qPost.origin.__typename === 'PostOriginThreadReply', 'Query node: Invalid post origin')
  87. Utils.assert(qPost.origin.postAddedEvent, 'Query node: PostAddedEvent missing in post origin')
  88. assert.equal(qPost.origin.postAddedEvent.id, qEvent.id)
  89. })
  90. }
  91. protected assertQueryNodeEventIsValid(qEvent: PostAddedEventFieldsFragment, i: number): void {
  92. const params = this.postsParams[i]
  93. assert.equal(qEvent.post.id, this.events[i].postId.toString())
  94. assert.equal(qEvent.text, this.getPostExpectedText(params))
  95. assert.equal(qEvent.isEditable, params.editable === undefined || params.editable)
  96. }
  97. async runQueryNodeChecks(): Promise<void> {
  98. await super.runQueryNodeChecks()
  99. // Query the events
  100. const qEvents = await this.query.tryQueryWithTimeout(
  101. () => this.query.getPostAddedEvents(this.events),
  102. (qEvents) => this.assertQueryNodeEventsAreValid(qEvents)
  103. )
  104. // Query the posts
  105. const qPosts = await this.query.getPostsByIds(this.events.map((e) => e.postId))
  106. this.assertQueriedPostsAreValid(qPosts, qEvents)
  107. }
  108. }