Skip to content

Commit

Permalink
feat: Filter collections using the request param isPublished (#556)
Browse files Browse the repository at this point in the history
* feat: Filter collections using the param isPublished

* fix: Fix SQL query to fetch published collections

* test: Add test for fetching collections of an address using the param isPublished

* fix: Param is_published received in the req
  • Loading branch information
cyaiox committed Jul 7, 2022
1 parent 48e1d32 commit f44109d
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 68 deletions.
43 changes: 21 additions & 22 deletions src/Collection/Collection.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,28 +122,27 @@ export class Collection extends Model<CollectionAttributes> {
static getPublishedJoinStatement(isPublished: boolean | undefined) {
return isPublished !== undefined
? SQL`
JOIN ${raw(Item.tableName)} items ON items.collection_id = c.id ${
isPublished
? SQL`AND (
(items.blockchain_item_id is NOT NULL AND c.third_party_id IS NULL)
OR c.third_party_id is NOT NULL)`
: SQL`AND (items.blockchain_item_id is NULL AND c.third_party_id IS NULL)`
}
LEFT JOIN ${raw(
ItemCuration.tableName
)} item_curations ON item_curations.item_id = items.id
${
isPublished === false
? SQL`
WHERE (
(SELECT COUNT(*) FROM item_curations
LEFT JOIN items on items.id = item_curations.item_id
LEFT JOIN collections cc on cc.id = items.collection_id
WHERE items.collection_id = c.id AND item_curations.item_id = items.id
) = 0)
`
: SQL``
}
LEFT JOIN ${raw(Item.tableName)} items ON items.collection_id = c.id
LEFT JOIN ${raw(
ItemCuration.tableName
)} item_curations ON item_curations.item_id = items.id
${
isPublished === false
? SQL`
WHERE (
(items.blockchain_item_id is NULL AND c.third_party_id IS NULL) AND
(SELECT COUNT(*) FROM item_curations
LEFT JOIN items on items.id = item_curations.item_id
LEFT JOIN collections cc on cc.id = items.collection_id
WHERE items.collection_id = c.id AND item_curations.item_id = items.id
) = 0)
`
: SQL`
WHERE (
(items.blockchain_item_id is NOT NULL AND c.third_party_id IS NULL)
OR c.third_party_id is NOT NULL))
`
}
`
: SQL``
}
Expand Down
151 changes: 106 additions & 45 deletions src/Collection/Collection.router.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -975,59 +975,120 @@ describe('Collection router', () => {

describe('when retrieving the collections of an address', () => {
beforeEach(() => {
;(Collection.findAll as jest.Mock).mockReturnValueOnce([
dbCollection,
dbTPCollection,
])
;(Collection.findByContractAddresses as jest.Mock).mockReturnValueOnce([])
;(Collection.findByThirdPartyIds as jest.Mock).mockReturnValueOnce([
dbTPCollection,
])
;(collectionAPI.fetchCollectionsByAuthorizedUser as jest.Mock).mockReturnValueOnce(
[]
)
;(thirdPartyAPI.fetchThirdPartiesByManager as jest.Mock).mockReturnValueOnce(
[{ id: dbTPCollection.third_party_id }]
)
;(ItemCuration.findLastByCollectionId as jest.Mock).mockReturnValueOnce(
itemCurationMock
)
mockThirdPartyCollectionIsPublished(dbTPCollection.id, false)
;(collectionAPI.fetchCollections as jest.Mock).mockResolvedValueOnce([])
url = `/${wallet.address}/collections`
})

it('should return the requested collections with the URN', () => {
return server
.get(buildURL(url))
.set(createAuthHeaders('get', url))
.expect(200)
.then((response: any) => {
expect(Collection.findAll).toHaveBeenCalledWith({
address: wallet.address,
limit: undefined,
offset: undefined,
sort: CurationStatusSort.NEWEST,
thirdPartyIds: [dbTPCollection.third_party_id],
remoteIds: [],
})
expect(response.body).toEqual({
data: [
{
...resultingCollectionAttributes,
urn: `urn:decentraland:mumbai:collections-v2:${dbCollection.contract_address}`,
},
{
...toResultCollection(dbTPCollection),
is_published: true,
urn: `${dbTPCollection.third_party_id}:${dbTPCollection.urn_suffix}`,
reviewed_at: itemCurationMock.updated_at.toISOString(),
created_at: itemCurationMock.created_at.toISOString(),
updated_at: itemCurationMock.updated_at.toISOString(),
describe('sending pagination params plus filtering options', () => {
let page: number,
limit: number,
isPublished: string,
totalCollectionsFromDb: number
beforeEach(() => {
page = 1,
limit = 3,
isPublished = 'true',
totalCollectionsFromDb = 1
;(Collection.findAll as jest.Mock).mockReturnValueOnce([
{ ...dbCollection, collection_count: totalCollectionsFromDb },
])
;(Collection.findByThirdPartyIds as jest.Mock).mockReturnValueOnce(
[]
)
;(thirdPartyAPI.fetchThirdPartiesByManager as jest.Mock).mockReturnValueOnce(
[]
)
})

it('should respond with pagination data and should have call the findAll method with the right params', () => {
return server
.get(buildURL(`${url}?limit=${limit}&page=${page}&is_published=${isPublished}`))
.set(createAuthHeaders('get', url))
.expect(200)
.then((response: any) => {
expect(response.body).toEqual({
data: {
total: totalCollectionsFromDb,
pages: totalCollectionsFromDb,
page,
limit,
results: [
{
...resultingCollectionAttributes,
urn: `urn:decentraland:mumbai:collections-v2:${dbCollection.contract_address}`,
},
],
},
],
ok: true,

ok: true,
})
expect(Collection.findAll).toHaveBeenCalledWith({
address: wallet.address,
limit,
offset: page - 1,
sort: CurationStatusSort.NEWEST,
isPublished: true,
thirdPartyIds: [],
remoteIds: [],
})
})
})
})
})

describe('and not sending any pagination params ', () => {
beforeEach(() => {
;(Collection.findAll as jest.Mock).mockReturnValueOnce([
dbCollection,
dbTPCollection,
])
;(Collection.findByThirdPartyIds as jest.Mock).mockReturnValueOnce([
dbTPCollection,
])
;(thirdPartyAPI.fetchThirdPartiesByManager as jest.Mock).mockReturnValueOnce(
[{ id: dbTPCollection.third_party_id }]
)
;(ItemCuration.findLastByCollectionId as jest.Mock).mockReturnValueOnce(
itemCurationMock
)
mockThirdPartyCollectionIsPublished(dbTPCollection.id, false)
})

it('should return the requested collections with the URN', () => {
return server
.get(buildURL(url))
.set(createAuthHeaders('get', url))
.expect(200)
.then((response: any) => {
expect(Collection.findAll).toHaveBeenCalledWith({
address: wallet.address,
limit: undefined,
offset: undefined,
sort: CurationStatusSort.NEWEST,
thirdPartyIds: [dbTPCollection.third_party_id],
remoteIds: [],
})
expect(response.body).toEqual({
data: [
{
...resultingCollectionAttributes,
urn: `urn:decentraland:mumbai:collections-v2:${dbCollection.contract_address}`,
},
{
...toResultCollection(dbTPCollection),
is_published: true,
urn: `${dbTPCollection.third_party_id}:${dbTPCollection.urn_suffix}`,
reviewed_at: itemCurationMock.updated_at.toISOString(),
created_at: itemCurationMock.created_at.toISOString(),
updated_at: itemCurationMock.updated_at.toISOString(),
},
],
ok: true,
})
})
})
})
})

Expand Down
8 changes: 7 additions & 1 deletion src/Collection/Collection.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ export class CollectionRouter extends Router {
req: AuthRequest
): Promise<PaginatedResponse<FullCollection> | FullCollection[]> => {
const { page, limit } = getPaginationParams(req)
const { is_published } = req.query
const eth_address = server.extractFromReq(req, 'address')
const auth_address = req.auth.ethAddress

Expand All @@ -295,6 +296,7 @@ export class CollectionRouter extends Router {
limit,
address: eth_address,
sort: CurationStatusSort.NEWEST,
isPublished: is_published ? is_published === 'true' : undefined,
remoteIds: authorizedRemoteCollections.map(
(remoteCollection) => remoteCollection.id
),
Expand All @@ -305,9 +307,13 @@ export class CollectionRouter extends Router {
const totalCollections =
Number(allCollectionsWithCount[0]?.collection_count) || 0

const dbCollections = allCollectionsWithCount.map((collectionWithCount) =>
omit<CollectionAttributes>(collectionWithCount, ['collection_count'])
)

const consolidated = (
await Bridge.consolidateAllCollections(
allCollectionsWithCount,
dbCollections,
authorizedRemoteCollections
)
).map(toFullCollection)
Expand Down

0 comments on commit f44109d

Please sign in to comment.