Skip to content

Commit

Permalink
feat: introduce logic to fetch catalog from the marketplace-server (#…
Browse files Browse the repository at this point in the history
…1967)

* feat: introduce logic to fetch catalog from the marketplace-server

* feat: use correct URL for the marketplace server

* feat: wait for FFs to be loaded

* fix: card overflow is clickeable

* test: fix broken tests

* feat: add generator getCatalogAPI to abstract the API selection logic

* chore: remove unwanted comment

* fix: wait for identity success action before fetching catalog (#1974)

* feat: remove old import

* test: fix broken test

* chore: reset dev.json values
  • Loading branch information
juanmahidalgo authored Nov 8, 2023
1 parent 5ea5bba commit 14f47d9
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 56 deletions.
1 change: 1 addition & 0 deletions webapp/src/components/AssetCard/AssetCard.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
}

.ui.card.AssetCard.catalog {
overflow: hidden;
height: 360px;
}

Expand Down
123 changes: 92 additions & 31 deletions webapp/src/modules/favorites/sagas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import { locations } from '../routing/locations'
import { SortDirection } from '../routing/types'
import { CatalogAPI } from '../vendor/decentraland/catalog/api'
import { getIsMarketplaceServerEnabled } from '../features/selectors'
import { getData as getItemsData } from '../item/selectors'
import {
BULK_PICK_SUCCESS,
Expand Down Expand Up @@ -100,7 +101,8 @@ describe('when handling the request for fetching favorited items', () => {
return expectSaga(favoritesSaga, getIdentity)
.provide([
[select(getListId), listId],
[select(getAddress), Promise.reject(error)]
[select(getAddress), Promise.reject(error)],
[select(getIsMarketplaceServerEnabled), true]
])
.put(fetchFavoritedItemsFailure(error.message))
.dispatch(fetchFavoritedItemsRequest(options))
Expand All @@ -114,6 +116,7 @@ describe('when handling the request for fetching favorited items', () => {
.provide([
[select(getListId), listId],
[select(getAddress), address],
[select(getIsMarketplaceServerEnabled), true],
[call(getAccountIdentity), Promise.reject(error)]
])
.put(fetchFavoritedItemsFailure(error.message))
Expand All @@ -129,6 +132,7 @@ describe('when handling the request for fetching favorited items', () => {
.provide([
[select(getListId), listId],
[select(getAddress), address],
[select(getIsMarketplaceServerEnabled), true],
[call(getAccountIdentity), Promise.resolve()],
[
matchers.call.fn(FavoritesAPI.prototype.getPicksByList),
Expand All @@ -149,6 +153,7 @@ describe('when handling the request for fetching favorited items', () => {
let favoritedItemIds: FavoritedItems
let createdAt: Record<string, number>
let total: number
let isMarketplaceFFOn: boolean

describe("and there's more than one favorited item", () => {
beforeEach(() => {
Expand All @@ -157,35 +162,79 @@ describe('when handling the request for fetching favorited items', () => {
total = 1
})

describe('and the call to the items api fails', () => {
it('should dispatch an action signaling the failure of the handled action', () => {
return expectSaga(favoritesSaga, getIdentity)
.provide([
[select(getListId), listId],
[select(getAddress), address],
[call(getAccountIdentity), Promise.resolve()],
[
matchers.call.fn(FavoritesAPI.prototype.getPicksByList),
Promise.resolve({ results: favoritedItemIds, total })
],
[
matchers.call.fn(CatalogAPI.prototype.get),
Promise.reject(error)
]
])
.call.like({
fn: CatalogAPI.prototype.get,
args: [
{
...options.filters,
first: 1,
ids: [favoritedItemIds[0].itemId]
}
]
})
.put(fetchFavoritedItemsFailure(error.message))
.dispatch(fetchFavoritedItemsRequest(options))
.run({ silenceTimeout: true })
describe('and the marketplace-server flag is off', () => {
beforeEach(() => {
isMarketplaceFFOn = false
})
describe('and the call to the items api fails', () => {
it('should dispatch an action signaling the failure of the handled action', () => {
return expectSaga(favoritesSaga, getIdentity)
.provide([
[select(getListId), listId],
[select(getIsMarketplaceServerEnabled), isMarketplaceFFOn],
[select(getAddress), address],
[call(getAccountIdentity), Promise.resolve()],
[
matchers.call.fn(FavoritesAPI.prototype.getPicksByList),
Promise.resolve({ results: favoritedItemIds, total })
],
[
matchers.call.fn(CatalogAPI.prototype.get),
Promise.reject(error)
]
])
.call.like({
fn: CatalogAPI.prototype.get,
args: [
{
...options.filters,
first: 1,
ids: [favoritedItemIds[0].itemId]
}
]
})
.put(fetchFavoritedItemsFailure(error.message))
.dispatch(fetchFavoritedItemsRequest(options))
.run({ silenceTimeout: true })
})
})
})

describe('and the marketplace-server flag is on', () => {
beforeEach(() => {
isMarketplaceFFOn = true
})
describe('and the call to the items api fails', () => {
it('should dispatch an action signaling the failure of the handled action', () => {
return expectSaga(favoritesSaga, getIdentity)
.provide([
[select(getListId), listId],
[select(getIsMarketplaceServerEnabled), isMarketplaceFFOn],
[select(getAddress), address],
[call(getAccountIdentity), Promise.resolve()],
[
matchers.call.fn(FavoritesAPI.prototype.getPicksByList),
Promise.resolve({ results: favoritedItemIds, total })
],
[
matchers.call.fn(CatalogAPI.prototype.get),
Promise.reject(error)
]
])
.call.like({
fn: CatalogAPI.prototype.get,
args: [
{
...options.filters,
first: 1,
ids: [favoritedItemIds[0].itemId]
}
]
})
.put(fetchFavoritedItemsFailure(error.message))
.dispatch(fetchFavoritedItemsRequest(options))
.run({ silenceTimeout: true })
})
})
})

Expand All @@ -202,6 +251,7 @@ describe('when handling the request for fetching favorited items', () => {
.provide([
[select(getListId), listId],
[select(getAddress), address],
[select(getIsMarketplaceServerEnabled), true],
[call(getAccountIdentity), Promise.resolve()],
[
matchers.call.fn(FavoritesAPI.prototype.getPicksByList),
Expand Down Expand Up @@ -256,6 +306,7 @@ describe('when handling the request for fetching favorited items', () => {
.provide([
[select(getListId), listId],
[select(getAddress), address],
[select(getIsMarketplaceServerEnabled), true],
[call(getAccountIdentity), Promise.resolve()],
[
matchers.call.fn(FavoritesAPI.prototype.getPicksByList),
Expand Down Expand Up @@ -296,6 +347,7 @@ describe('when handling the request for fetching favorited items', () => {
.provide([
[select(getListId), listId],
[select(getAddress), null],
[select(getIsMarketplaceServerEnabled), true],
[
matchers.call.fn(FavoritesAPI.prototype.getPicksByList),
Promise.reject(error)
Expand Down Expand Up @@ -329,6 +381,7 @@ describe('when handling the request for fetching favorited items', () => {
.provide([
[select(getListId), listId],
[select(getAddress), null],
[select(getIsMarketplaceServerEnabled), true],
[
matchers.call.fn(FavoritesAPI.prototype.getPicksByList),
Promise.resolve({ results: favoritedItemIds, total })
Expand Down Expand Up @@ -367,6 +420,7 @@ describe('when handling the request for fetching favorited items', () => {
.provide([
[select(getListId), listId],
[select(getAddress), null],
[select(getIsMarketplaceServerEnabled), true],
[
matchers.call.fn(FavoritesAPI.prototype.getPicksByList),
Promise.resolve({ results: favoritedItemIds, total })
Expand Down Expand Up @@ -420,6 +474,7 @@ describe('when handling the request for fetching favorited items', () => {
.provide([
[select(getListId), listId],
[select(getAddress), null],
[select(getIsMarketplaceServerEnabled), true],
[
matchers.call.fn(FavoritesAPI.prototype.getPicksByList),
{ results: favoritedItemIds, total }
Expand Down Expand Up @@ -611,11 +666,12 @@ describe('when handling the request for fetching lists', () => {
]
})

describe('and there are not items in the state', () => {
describe('and there are no items in the state', () => {
it('should dispatch an action signaling the success of the handled action', () => {
return expectSaga(favoritesSaga, getIdentity)
.provide([
[call(getAccountIdentity), Promise.resolve()],
[select(getIsMarketplaceServerEnabled), true],
[
matchers.call.fn(FavoritesAPI.prototype.getLists),
Promise.resolve({ results: lists, total })
Expand Down Expand Up @@ -660,6 +716,7 @@ describe('when handling the request for fetching lists', () => {
return expectSaga(favoritesSaga, getIdentity)
.provide([
[call(getAccountIdentity), Promise.resolve()],
[select(getIsMarketplaceServerEnabled), true],
[
matchers.call.fn(FavoritesAPI.prototype.getLists),
Promise.resolve({ results: lists, total })
Expand Down Expand Up @@ -757,6 +814,7 @@ describe('when handling the request for fetching lists', () => {
return expectSaga(favoritesSaga, getIdentity)
.provide([
[call(getAccountIdentity), Promise.resolve()],
[select(getIsMarketplaceServerEnabled), true],
[
matchers.call.fn(FavoritesAPI.prototype.getLists),
Promise.resolve({ results: lists, total })
Expand Down Expand Up @@ -804,6 +862,7 @@ describe('when handling the request for fetching lists', () => {
return expectSaga(favoritesSaga, getIdentity)
.provide([
[call(getAccountIdentity), Promise.resolve()],
[select(getIsMarketplaceServerEnabled), true],
[
matchers.call.fn(FavoritesAPI.prototype.getLists),
Promise.resolve({ results: lists, total })
Expand Down Expand Up @@ -1034,6 +1093,7 @@ describe('when handling the request for getting a list', () => {
matchers.call.fn(FavoritesAPI.prototype.getList),
Promise.resolve(list)
],
[select(getIsMarketplaceServerEnabled), true],
[select(getItemsData), {}],
[
matchers.call.fn(CatalogAPI.prototype.get),
Expand Down Expand Up @@ -1078,6 +1138,7 @@ describe('when handling the request for getting a list', () => {
matchers.call.fn(FavoritesAPI.prototype.getList),
Promise.resolve(list)
],
[select(getIsMarketplaceServerEnabled), true],
[select(getItemsData), { anotherItemId: {} }],
[
matchers.call.fn(CatalogAPI.prototype.get),
Expand Down
24 changes: 18 additions & 6 deletions webapp/src/modules/favorites/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { getIdentity as getAccountIdentity } from '../identity/utils'
import { CatalogAPI } from '../vendor/decentraland/catalog/api'
import { retryParams } from '../vendor/decentraland/utils'
import { getAddress } from '../wallet/selectors'
import { NFT_SERVER_URL } from '../vendor/decentraland'
import { MARKETPLACE_SERVER_URL, NFT_SERVER_URL } from '../vendor/decentraland'
import { locations } from '../routing/locations'
import { SortDirection } from '../routing/types'
import { ListsSortBy } from '../vendor/decentraland/favorites/types'
Expand Down Expand Up @@ -83,6 +83,7 @@ import {
import { convertListsBrowseSortByIntoApiSortBy } from './utils'
import { List } from './types'
import { getData as getItemsData } from '../item/selectors'
import { getIsMarketplaceServerEnabled } from '../features/selectors'

export function* favoritesSaga(getIdentity: () => AuthIdentity | undefined) {
const API_OPTS = {
Expand All @@ -95,6 +96,10 @@ export function* favoritesSaga(getIdentity: () => AuthIdentity | undefined) {
API_OPTS
)
const catalogAPI = new CatalogAPI(NFT_SERVER_URL, API_OPTS)
const marketplaceServerCatalogAPI = new CatalogAPI(
MARKETPLACE_SERVER_URL,
API_OPTS
)

yield takeEvery(
FETCH_FAVORITED_ITEMS_REQUEST,
Expand All @@ -114,6 +119,13 @@ export function* favoritesSaga(getIdentity: () => AuthIdentity | undefined) {
handleBulkPickSuccessOrFailure
)

function* getCatalogAPI() {
const isMarketplaceServerEnabled: boolean = yield select(
getIsMarketplaceServerEnabled
)
return isMarketplaceServerEnabled ? marketplaceServerCatalogAPI : catalogAPI
}

function* fetchPreviewItems(previewListsItemIds: string[]) {
let previewItems: Item[] = []

Expand All @@ -127,10 +139,8 @@ export function* favoritesSaga(getIdentity: () => AuthIdentity | undefined) {
ids: previewListsItemIds
}

const result: { data: Item[] } = yield call(
[catalogAPI, 'get'],
itemFilters
)
const api: CatalogAPI = yield call(getCatalogAPI)
const result: { data: Item[] } = yield call([api, 'get'], itemFilters)
previewItems = result.data
}
}
Expand Down Expand Up @@ -173,9 +183,11 @@ export function* favoritesSaga(getIdentity: () => AuthIdentity | undefined) {
filters: optionsFilters
}

const api: CatalogAPI = yield call(getCatalogAPI)

if (results.length > 0) {
const result: { data: Item[] } = yield call(
[catalogAPI, 'get'],
[api, 'get'],
optionsFilters
)
items = result.data
Expand Down
10 changes: 10 additions & 0 deletions webapp/src/modules/features/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,13 @@ export const getIsNewNavbarDropdownEnabled = (state: RootState) => {
}
return false
}
export const getIsMarketplaceServerEnabled = (state: RootState) => {
if (hasLoadedInitialFlags(state)) {
return getIsFeatureEnabled(
state,
ApplicationName.MARKETPLACE,
FeatureName.MARKETPLACE_SERVER
)
}
return false
}
5 changes: 3 additions & 2 deletions webapp/src/modules/features/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ export enum FeatureName {
MAP_VIEW_FILTERS = 'map-view-filters',
RENTAL_PRICE_FILTER_CHART = 'rental-price-fitler-chart',
HANDS_CATEGORY = 'hands-category',
SMART_WEARABLES_FTU = 'smart-wearables-ftu',
EMOTES_V2 = 'emotes-2.0',
EMOTES_V2_FTU = 'emotes-2.0-ftu',
NEW_NAVBAR_DROPDOWN = 'new-navbar-dropdown'
NEW_NAVBAR_DROPDOWN = 'new-navbar-dropdown',
SMART_WEARABLES_FTU = 'smart-wearables-ftu',
MARKETPLACE_SERVER = 'marketplace-server'
}
32 changes: 32 additions & 0 deletions webapp/src/modules/features/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { expectSaga } from 'redux-saga-test-plan'
import { select } from 'redux-saga/effects'
import { isLoadingFeatureFlags } from 'decentraland-dapps/dist/modules/features/selectors'
import {
FETCH_APPLICATION_FEATURES_FAILURE,
FETCH_APPLICATION_FEATURES_SUCCESS
} from 'decentraland-dapps/dist/modules/features/actions'
import { waitForFeatureFlagsToBeLoaded } from './utils'

describe('waitForFeatureFlagsToBeLoaded Util', () => {
it('should do nothing if feature flags are already loaded', () => {
return expectSaga(waitForFeatureFlagsToBeLoaded)
.provide([[select(isLoadingFeatureFlags), false]])
.not.take(FETCH_APPLICATION_FEATURES_SUCCESS)
.not.take(FETCH_APPLICATION_FEATURES_FAILURE)
.run()
})

it('should wait for FETCH_APPLICATION_FEATURES_SUCCESS if feature flags are being fetched', () => {
return expectSaga(waitForFeatureFlagsToBeLoaded)
.provide([[select(isLoadingFeatureFlags), true]])
.take(FETCH_APPLICATION_FEATURES_SUCCESS)
.run()
})

it('should wait for FETCH_APPLICATION_FEATURES_FAILURE if feature flags are being fetched and there is an error', () => {
return expectSaga(waitForFeatureFlagsToBeLoaded)
.provide([[select(isLoadingFeatureFlags), true]])
.take(FETCH_APPLICATION_FEATURES_FAILURE)
.run()
})
})
Loading

0 comments on commit 14f47d9

Please sign in to comment.