Skip to content

Commit

Permalink
Merge 0f16ea5 into b46045a
Browse files Browse the repository at this point in the history
  • Loading branch information
fzavalia committed Oct 2, 2023
2 parents b46045a + 0f16ea5 commit 8209ab3
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { FETCH_LANDS_REQUEST } from 'modules/land/actions'
import { getLoading as getLandsLoading } from 'modules/land/selectors'
import { isLoggingIn, isLoggedIn } from 'modules/identity/selectors'
import { getProjects } from 'modules/ui/dashboard/selectors'
import { fetchWorldsWalletStatsRequest } from 'modules/worlds/actions'
import { getConnectedWalletStats, getLoading as getLoadingWorlds } from 'modules/worlds/selectors'
import { MapStateProps, MapDispatchProps, MapDispatch } from './WorldListPage.types'
import WorldListPage from './WorldListPage'

Expand All @@ -22,12 +24,15 @@ const mapState = (state: RootState): MapStateProps => ({
isLoadingType(getLoading(state), FETCH_ENS_LIST_REQUEST) ||
isLoadingType(getDeploymentsLoading(state), FETCH_WORLD_DEPLOYMENTS_REQUEST) ||
isLoadingType(getLandsLoading(state), FETCH_LANDS_REQUEST) ||
isLoadingType(getLoadingWorlds(state), FETCH_WORLD_DEPLOYMENTS_REQUEST) ||
isLoggingIn(state),
isLoggedIn: isLoggedIn(state)
isLoggedIn: isLoggedIn(state),
worldsWalletStats: getConnectedWalletStats(state)
})

const mapDispatch = (dispatch: MapDispatch): MapDispatchProps => ({
onNavigate: path => dispatch(push(path))
onNavigate: path => dispatch(push(path)),
onFetchWorldsWalletStats: () => dispatch(fetchWorldsWalletStatsRequest())
})

export default connect(mapState, mapDispatch)(WorldListPage)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback, useState } from 'react'
import React, { useCallback, useEffect, useState } from 'react'
import { t } from 'decentraland-dapps/dist/modules/translation/utils'
import {
Button,
Expand Down Expand Up @@ -32,7 +32,7 @@ const WORLDS_CONTENT_SERVER_URL = config.get('WORLDS_CONTENT_SERVER', '')
const PAGE_SIZE = 12

const WorldListPage: React.FC<Props> = props => {
const { ensList, error, deploymentsByWorlds, isLoading, projects, onNavigate } = props
const { ensList, error, deploymentsByWorlds, isLoading, projects, worldsWalletStats, onNavigate, onFetchWorldsWalletStats } = props
const [sortBy, setSortBy] = useState(SortBy.ASC)
const [page, setPage] = useState(1)

Expand Down Expand Up @@ -233,6 +233,10 @@ const WorldListPage: React.FC<Props> = props => {
)
}

useEffect(() => {
onFetchWorldsWalletStats()
}, [onFetchWorldsWalletStats])

return (
<LoggedInDetailPage
className="WorldListPage view"
Expand All @@ -250,7 +254,9 @@ const WorldListPage: React.FC<Props> = props => {
marginBottom: '1rem'
}}
>
<WorldsStorage maxBytes={100000000} currentBytes={75000000} />
{worldsWalletStats ? (
<WorldsStorage maxBytes={Number(worldsWalletStats.maxAllowedSpace)} currentBytes={Number(worldsWalletStats.usedSpace)} />
) : null}
</div>
</Container>
{/** Old ens list which will be removed or replaced with the new worlds for ens owners feature */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Dispatch } from 'redux'
import { Deployment } from 'modules/deployment/types'
import { ENS } from 'modules/ens/types'
import { Project } from 'modules/project/types'
import { WorldsWalletStats } from 'lib/api/worlds'

export enum SortBy {
DESC = 'DESC',
Expand All @@ -15,14 +16,19 @@ export type Props = {
projects: Project[]
isLoggedIn: boolean
isLoading: boolean
worldsWalletStats?: WorldsWalletStats
onNavigate: (path: string) => void
onFetchWorldsWalletStats: () => void
}

export type State = {
page: number
sortBy: SortBy
}

export type MapStateProps = Pick<Props, 'ensList' | 'deploymentsByWorlds' | 'isLoading' | 'error' | 'projects' | 'isLoggedIn'>
export type MapDispatchProps = Pick<Props, 'onNavigate'>
export type MapStateProps = Pick<
Props,
'ensList' | 'deploymentsByWorlds' | 'isLoading' | 'error' | 'projects' | 'isLoggedIn' | 'worldsWalletStats'
>
export type MapDispatchProps = Pick<Props, 'onNavigate' | 'onFetchWorldsWalletStats'>
export type MapDispatch = Dispatch
4 changes: 3 additions & 1 deletion src/modules/common/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { collectionCurationSaga } from 'modules/curations/collectionCuration/sag
import { getPeerWithNoGBCollectorURL } from './utils'
import { itemCurationSaga } from 'modules/curations/itemCuration/sagas'
import { inspectorSaga } from 'modules/inspector/sagas'
import { worldsSaga } from 'modules/worlds/sagas'
import { RootStore } from './types'

const profileSaga = createProfileSaga({ peerUrl: PEER_URL, peerWithNoGbCollectorUrl: getPeerWithNoGBCollectorURL() })
Expand Down Expand Up @@ -95,6 +96,7 @@ export function* rootSaga(
featuresSaga({ polling: { apps: [ApplicationName.BUILDER], delay: 60000 /** 60 seconds */ } }),
inspectorSaga(builderAPI, store),
loginSaga(),
newsletterSagas(builderAPI)
newsletterSagas(builderAPI),
worldsSaga()
])
}
2 changes: 1 addition & 1 deletion src/modules/worlds/actions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('when creating the failure action to fetch worlds stats for a wallet',
})

it('should return the failure action to fetch worlds stats for a wallet', () => {
expect(fetchWorldsWalletStatsFailure(address, error)).toEqual({
expect(fetchWorldsWalletStatsFailure(error, address)).toEqual({
type: FETCH_WORLDS_WALLET_STATS_FAILURE,
payload: {
address,
Expand Down
4 changes: 2 additions & 2 deletions src/modules/worlds/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ export const FETCH_WORLDS_WALLET_STATS_REQUEST = '[Request] Fetch Worlds Wallet
export const FETCH_WORLDS_WALLET_STATS_SUCCESS = '[Success] Fetch Worlds Wallet Stats'
export const FETCH_WORLDS_WALLET_STATS_FAILURE = '[Failure] Fetch Worlds Wallet Stats'

export const fetchWorldsWalletStatsRequest = (address: string) => action(FETCH_WORLDS_WALLET_STATS_REQUEST, { address })
export const fetchWorldsWalletStatsRequest = (address?: string) => action(FETCH_WORLDS_WALLET_STATS_REQUEST, { address })
export const fetchWorldsWalletStatsSuccess = (address: string, stats: WorldsWalletStats) =>
action(FETCH_WORLDS_WALLET_STATS_SUCCESS, { address, stats })
export const fetchWorldsWalletStatsFailure = (address: string, error: string) =>
export const fetchWorldsWalletStatsFailure = (error: string, address?: string) =>
action(FETCH_WORLDS_WALLET_STATS_FAILURE, { address, error })

export type FetchWalletWorldsStatsRequestAction = ReturnType<typeof fetchWorldsWalletStatsRequest>
Expand Down
2 changes: 1 addition & 1 deletion src/modules/worlds/reducer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('when handling the action to fetch worlds stats for a wallet', () => {
})

it('should remove the action from loading and set the error', () => {
const action = fetchWorldsWalletStatsFailure(address, error)
const action = fetchWorldsWalletStatsFailure(error, address)

expect(worldsReducer(state, action)).toEqual({
...state,
Expand Down
2 changes: 1 addition & 1 deletion src/modules/worlds/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { WorldsWalletStats } from 'lib/api/worlds'

export type WorldsState = {
// TODO: Find a use for the data object when there is something more relevant as the core data for the worlds module.
data: Record<string, any>
data: Record<string, unknown>
walletStats: Record<string, WorldsWalletStats>
loading: LoadingState
error: string | null
Expand Down
180 changes: 140 additions & 40 deletions src/modules/worlds/sagas.spec.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,162 @@
import { expectSaga } from 'redux-saga-test-plan'
import { worldsSaga } from './sagas'
import { call } from 'redux-saga/effects'
import { call, select, take } from 'redux-saga/effects'
import { throwError } from 'redux-saga-test-plan/providers'
import { getAddress } from 'decentraland-dapps/dist/modules/wallet/selectors'
import { Wallet } from 'decentraland-dapps/dist/modules/wallet/types'
import {
CONNECT_WALLET_FAILURE,
CONNECT_WALLET_SUCCESS,
connectWalletFailure,
connectWalletSuccess
} from 'decentraland-dapps/dist/modules/wallet/actions'
import { WorldsWalletStats, content } from 'lib/api/worlds'
import { fetchWorldsWalletStatsFailure, fetchWorldsWalletStatsRequest, fetchWorldsWalletStatsSuccess } from './actions'
import { throwError } from 'redux-saga-test-plan/providers'
import { worldsSaga } from './sagas'

describe('when handling the request action to fetch worlds stats for a wallet', () => {
let address: string
let address: string | undefined
let stats: WorldsWalletStats

beforeEach(() => {
address = '0x123'
})
describe('when the address is provided in the action', () => {
beforeEach(() => {
address = '0x123'
})

describe('when the worlds api request throws an error', () => {
let error: Error
describe('when the worlds api request throws an error', () => {
let error: Error

beforeEach(() => {
error = new Error('some error')
beforeEach(() => {
error = new Error('some error')
})

it('should put the failure action with the request action address and the error message', () => {
return expectSaga(worldsSaga)
.provide([[call([content, content.fetchWalletStats], address!), throwError(error)]])
.put(fetchWorldsWalletStatsFailure(error.message, address))
.dispatch(fetchWorldsWalletStatsRequest(address))
.silentRun()
})
})

it('should put the failure action with the request action address and the error message', () => {
return expectSaga(worldsSaga)
.provide([[call([content, content.fetchWalletStats], address), throwError(error)]])
.put(fetchWorldsWalletStatsFailure(address, error.message))
.dispatch(fetchWorldsWalletStatsRequest(address))
.silentRun()
describe('when the worlds api request returns null', () => {
it('should put the failure action with the request action address and the error message', () => {
return expectSaga(worldsSaga)
.provide([[call([content, content.fetchWalletStats], address!), null]])
.put(fetchWorldsWalletStatsFailure('Could not fetch wallet stats', address))
.dispatch(fetchWorldsWalletStatsRequest(address))
.silentRun()
})
})
})

describe('when the worlds api request returns null', () => {
it('should put the failure action with the request action address and the error message', () => {
return expectSaga(worldsSaga)
.provide([[call([content, content.fetchWalletStats], address), null]])
.put(fetchWorldsWalletStatsFailure(address, 'Could not fetch wallet stats'))
.dispatch(fetchWorldsWalletStatsRequest(address))
.silentRun()
describe('when the worlds api request returns the stats', () => {
beforeEach(() => {
stats = {
dclNames: [],
ensNames: [],
maxAllowedSpace: '',
usedSpace: '',
wallet: address!
}
})

it('should put the success action with the request action address and the stats', () => {
return expectSaga(worldsSaga)
.provide([[call([content, content.fetchWalletStats], address!), stats]])
.put(fetchWorldsWalletStatsSuccess(address!, stats))
.dispatch(fetchWorldsWalletStatsRequest(address))
.silentRun()
})
})
})

describe('when the worlds api request returns the stats', () => {
let stats: WorldsWalletStats
describe('when the address is not provided in the action', () => {
let addressInStore: string | undefined

beforeEach(() => {
stats = {
dclNames: [],
ensNames: [],
maxAllowedSpace: '',
usedSpace: '',
wallet: address
}
address = undefined
})

it('should put the success action with the request action address and the stats', () => {
return expectSaga(worldsSaga)
.provide([[call([content, content.fetchWalletStats], address), stats]])
.put(fetchWorldsWalletStatsSuccess(address, stats))
.dispatch(fetchWorldsWalletStatsRequest(address))
.silentRun()
describe('and there is an address available in the store', () => {
beforeEach(() => {
addressInStore = '0x123'
})

describe('and the request to fetch wallet stats responds with the worlds wallet stats', () => {
beforeEach(() => {
stats = {
dclNames: [],
ensNames: [],
maxAllowedSpace: '',
usedSpace: '',
wallet: addressInStore!
}
})

it('should put the success action with the address in the store and the stats', () => {
return expectSaga(worldsSaga)
.provide([
[select(getAddress), addressInStore],
[call([content, content.fetchWalletStats], addressInStore!), stats]
])
.put(fetchWorldsWalletStatsSuccess(addressInStore!, stats))
.dispatch(fetchWorldsWalletStatsRequest(address))
.silentRun()
})
})
})

describe('and there is no address available in the store', () => {
let connectProvider: any
let connectionAddress: string

beforeEach(() => {
addressInStore = undefined
})

describe('and the wallet connection fails', () => {
beforeEach(() => {
connectProvider = [take(CONNECT_WALLET_FAILURE), connectWalletFailure('some error')]
})

it('should put a failure action with an undefined address and the error message', () => {
return expectSaga(worldsSaga)
.provide([[select(getAddress), addressInStore], connectProvider])
.put(fetchWorldsWalletStatsFailure('An address is required', addressInStore))
.dispatch(fetchWorldsWalletStatsRequest(address))
.silentRun()
})
})

describe('and the wallet connection does not fail', () => {
beforeEach(() => {
connectionAddress = '0x123'
connectProvider = [take(CONNECT_WALLET_SUCCESS), connectWalletSuccess({ address: connectionAddress } as Wallet)]
})

describe('and the request to fetch wallet stats responds with the worlds wallet stats', () => {
beforeEach(() => {
stats = {
dclNames: [],
ensNames: [],
maxAllowedSpace: '',
usedSpace: '',
wallet: connectionAddress
}
})

it('should put the success action with the connection address and the stats', () => {
return expectSaga(worldsSaga)
.provide([
[select(getAddress), addressInStore],
connectProvider,
[call([content, content.fetchWalletStats], connectionAddress), stats]
])
.put(fetchWorldsWalletStatsSuccess(connectionAddress, stats))
.dispatch(fetchWorldsWalletStatsRequest(address))
.silentRun()
})
})
})
})
})
})
Loading

0 comments on commit 8209ab3

Please sign in to comment.