Skip to content

Commit

Permalink
refactor: Enhance the post forum endpoint after publishing a TP colle…
Browse files Browse the repository at this point in the history
…ction (#661)

* refactor: Enhance the post forum endpoint with the new logic after publishing a TP collection

* fix: Mock with lowercase route to collection service

* fix: Wait for the forum service result and always return the link to the forum
  • Loading branch information
kevinszuchet authored Jun 15, 2023
1 parent 30c2816 commit 94c6290
Show file tree
Hide file tree
Showing 6 changed files with 353 additions and 66 deletions.
38 changes: 8 additions & 30 deletions src/Collection/Collection.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@ import {
} from '../Item/Item.errors'
import { Item, ItemApprovalData } from '../Item'
import { isCommitteeMember } from '../Committee'
import {
buildCollectionForumPost,
buildCollectionForumUpdateReply,
createPost,
getPost,
updatePost,
} from '../Forum'
import { sendDataToWarehouse } from '../warehouse'
import { Cheque } from '../SlotUsageCheque'
import { PaginatedResponse } from '../Pagination'
Expand All @@ -45,14 +38,15 @@ import {
import { CurationStatusFilter } from '../Curation'
import { addCustomMaxAgeCacheControlHeader } from '../common/headers'
import { hasTPCollectionURN, isTPCollection } from '../utils/urn'
import { ForumService } from '../Forum/Forum.service'
import { Collection } from './Collection.model'
import { CollectionService } from './Collection.service'
import {
PublishCollectionResponse,
CollectionAttributes,
FullCollection,
CollectionTypeFilter,
CollectionSort
CollectionSort,
} from './Collection.types'
import { upsertCollectionSchema, saveTOSSchema } from './Collection.schema'
import { hasPublicAccess } from './access'
Expand All @@ -72,6 +66,7 @@ const validator = getValidator()

export class CollectionRouter extends Router {
public service = new CollectionService()
public forumService = new ForumService()

private modelAuthorizationCheck = (
_: OwnableModel,
Expand Down Expand Up @@ -317,7 +312,7 @@ export class CollectionRouter extends Router {
offset: page && limit ? getOffset(page, limit) : undefined,
limit,
address: eth_address,
sort: sort as CollectionSort || CollectionSort.CREATED_AT_DESC,
sort: (sort as CollectionSort) || CollectionSort.CREATED_AT_DESC,
isPublished: is_published ? is_published === 'true' : undefined,
remoteIds: authorizedRemoteCollections.map(
(remoteCollection) => remoteCollection.id
Expand Down Expand Up @@ -400,27 +395,10 @@ export class CollectionRouter extends Router {
// DCL Collections posts are being handled by the front-end at the moment and the backend updated using '/collections/:id/post'
// TODO: Should this be halting the response? Retries?

if (dbCollection.forum_id) {
const postData = await getPost(dbCollection.forum_id)
await updatePost(
dbCollection.forum_id,
buildCollectionForumUpdateReply(
postData.raw,
result.items.slice(0, MAX_FORUM_ITEMS)
)
)
} else {
const { id: postId, link } = await createPost(
buildCollectionForumPost(
result.collection,
result.items.slice(0, MAX_FORUM_ITEMS)
)
)
await Collection.update<CollectionAttributes>(
{ forum_link: link, forum_id: postId },
{ id }
)
}
await this.forumService.upsertThirdPartyCollectionForumPost(
dbCollection,
result.items.slice(0, MAX_FORUM_ITEMS)
)
} else {
const dbItems = await Item.findOrderedByCollectionId(id)
result = await this.service.publishDCLCollection(dbCollection, dbItems)
Expand Down
276 changes: 276 additions & 0 deletions src/Forum/Forum.router.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
import supertest from 'supertest'
import { v4 as uuid } from 'uuid'
import {
dbCollectionMock,
dbTPCollectionMock,
} from '../../spec/mocks/collections'
import {
buildURL,
createAuthHeaders,
mockExistsMiddleware,
} from '../../spec/utils'
import { app } from '../server'
import {
Collection,
CollectionAttributes,
CollectionService,
ThirdPartyCollectionAttributes,
} from '../Collection'
import { Item, ThirdPartyItemAttributes } from '../Item'
import { ForumPost } from './Forum.types'
import { createIdentity, fakePrivateKey, wallet } from '../../spec/mocks/wallet'
import { ethers } from 'ethers'
import { dbTPItemMock } from '../../spec/mocks/items'
import { createPost, getPost, updatePost } from './client'
import {
buildCollectionForumPost,
buildCollectionForumUpdateReply,
} from './utils'
import { MAX_FORUM_ITEMS } from '../Item/utils'

const server = supertest(app.getApp())

jest.mock('../Collection/Collection.service')
jest.mock('../Curation/ItemCuration/ItemCuration.model')
jest.mock('../Curation/CollectionCuration/CollectionCuration.model')
jest.mock('../Collection/Collection.model')
jest.mock('../Item/Item.model')
jest.mock('./client')

describe('Forum router', () => {
let dbTPCollection: ThirdPartyCollectionAttributes
let dbCollection: CollectionAttributes
let url: string
let authHeaders: Record<string, string>
let mockedWallet

beforeEach(() => {
dbTPCollection = { ...dbTPCollectionMock }
dbCollection = { ...dbCollectionMock }
jest.spyOn(ethers.utils, 'verifyTypedData').mockReturnValue(wallet.address)
jest
.spyOn(CollectionService.prototype, 'isOwnedOrManagedBy')
.mockResolvedValue(true)
})

afterEach(() => {
jest.resetAllMocks()
})

describe('when posting a new forum post', () => {
let forumId: number
let forumLink: string

beforeEach(async () => {
forumId = 1234
forumLink = 'https://forum.com/some/forum/link'
})

describe('and the collection is a TP collection', () => {
beforeEach(async () => {
url = `/collections/${dbTPCollection.id}/post`
mockedWallet = new ethers.Wallet(fakePrivateKey)
authHeaders = createAuthHeaders(
'post',
url,
await createIdentity(mockedWallet, mockedWallet, 1)
)
mockExistsMiddleware(Collection, dbTPCollection.id)
// Mocking the function that is used in the custom modelAuthorizationCheck
;(Collection.findByIds as jest.Mock).mockResolvedValueOnce([
dbTPCollection,
])
})

describe('when the supplied data and signature are correct', () => {
let items: ThirdPartyItemAttributes[]

beforeEach(async () => {
items = [
{ ...dbTPItemMock, id: uuid(), local_content_hash: 'hash1' },
{ ...dbTPItemMock, id: uuid(), local_content_hash: 'hash2' },
{ ...dbTPItemMock, id: uuid(), local_content_hash: 'hash3' },
]
;(Item.findOrderedByCollectionId as jest.Mock).mockResolvedValueOnce(
items
)
})

describe('and the server responds correctly', () => {
let post: ForumPost

beforeEach(async () => {
post = {
title: 'The title of the post',
raw: 'The raw text from the post',
} as ForumPost
;(getPost as jest.Mock).mockResolvedValueOnce(post)
})

describe('and the forum post is being created for the first time', () => {
beforeEach(() => {
;(Collection.findOne as jest.Mock).mockResolvedValueOnce(
dbTPCollection
)
;(createPost as jest.Mock).mockResolvedValueOnce({
id: forumId,
link: forumLink,
})
})

it('should create a forum post with the response data', () => {
return server
.post(buildURL(url))
.set(authHeaders)
.send({ forumPost: post })
.then(() => {
expect(createPost).toHaveBeenCalledWith(
buildCollectionForumPost(
dbTPCollection,
items.slice(0, MAX_FORUM_ITEMS) as any
)
)
})
})

it('should update the collection forum_link property with the post creation', () => {
return server
.post(buildURL(url))
.set(authHeaders)
.send({ forumPost: post })
.expect(200)
.then(() => {
expect(Collection.update).toHaveBeenCalledWith(
{ forum_id: forumId, forum_link: forumLink },
{ id: dbTPCollection.id }
)
})
})

it('should return the link of the forum post', () => {
return server
.post(buildURL(url))
.set(authHeaders)
.send({ forumPost: post })
.expect(200)
.then((response: any) => {
expect(response.body).toEqual({ data: forumLink, ok: true })
})
})
})

describe('and the collection already has a forum id', () => {
let forumId: number

beforeEach(() => {
forumId = 1
;(Collection.findOne as jest.Mock).mockResolvedValueOnce({
...dbTPCollection,
forum_id: forumId,
})
;(updatePost as jest.Mock).mockResolvedValueOnce({
id: forumId,
link: forumLink,
})
})

it('should update the forum post with the response data', () => {
return server
.post(buildURL(url))
.set(authHeaders)
.send({
forumPost: post,
})
.expect(200)
.then(() => {
expect(updatePost).toHaveBeenCalledWith(
forumId,
buildCollectionForumUpdateReply(
post.raw,
items.slice(0, MAX_FORUM_ITEMS) as any
)
)
})
})

it('should return the link of the forum post', () => {
return server
.post(buildURL(url))
.set(authHeaders)
.send({ forumPost: post })
.expect(200)
.then((response: any) => {
expect(response.body).toEqual({ data: forumLink, ok: true })
})
})
})
})
})
})

describe('and the collection is a Standard collection', () => {
let post: ForumPost

beforeEach(async () => {
url = `/collections/${dbCollection.id}/post`
mockedWallet = new ethers.Wallet(fakePrivateKey)
authHeaders = createAuthHeaders(
'post',
url,
await createIdentity(mockedWallet, mockedWallet, 1)
)

// Mocking the function that is used in the custom modelAuthorizationCheck
;(Collection.findByIds as jest.Mock).mockResolvedValueOnce([
dbCollection,
])
;(Collection.findOne as jest.Mock).mockResolvedValueOnce(dbCollection)

post = {
title: 'The title of the post',
raw: 'The raw text from the post',
} as ForumPost
;(createPost as jest.Mock).mockResolvedValueOnce({
id: forumId,
link: forumLink,
})
mockExistsMiddleware(Collection, dbCollection.id)
})

it('should create a forum post with the response data', () => {
return server
.post(buildURL(url))
.set(authHeaders)
.send({ forumPost: post })
.then(() => {
expect(createPost).toHaveBeenCalledWith(post)
})
})

it('should update the collection forum_link property with the post creation', () => {
return server
.post(buildURL(url))
.set(authHeaders)
.send({ forumPost: post })
.expect(200)
.then(() => {
expect(Collection.update).toHaveBeenCalledWith(
{ forum_id: forumId, forum_link: forumLink },
{ id: dbCollection.id }
)
})
})

it('should return the link of the forum post', () => {
return server
.post(buildURL(url))
.set(authHeaders)
.send({ forumPost: post })
.expect(200)
.then((response: any) => {
expect(response.body).toEqual({ data: forumLink, ok: true })
})
})
})
})
})
Loading

0 comments on commit 94c6290

Please sign in to comment.