• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

decentraland / marketplace / 20438811440

22 Dec 2025 05:10PM UTC coverage: 66.424% (-0.07%) from 66.495%
20438811440

push

github

web-flow
feat: upgrade to React 18 (#2549)

* feat: migrate from render to createRoot for React 18 (#2546)

* fix: migrate tests from @testing-library/react-hooks to @testing-library/react (#2547)

* chore: update dependencies for React 18

- Update react and react-dom to ^18.3.1
- Update @types/react and @types/react-dom to ^18.2.0
- Update @testing-library/react to ^14.0.0

* chore: update decentraland-dapps v26.0.0

* chore: decentraland-transactions v 2.24.2

* fix: date-fns imports (#2560)

* fix: store translations (#2559)

* refactor: fix React types (#2558)

* test: fix mocks and test setup (#2557)

* chore: update config files (#2556)

* fix: dispatch fetchTranslationsRequest on store init

* refactor: fix React types (ReactNode, FormEvent, CheckboxProps)

* ci: remove --legacy-peer-deps from workflows (#2561)

* test: added libsodium-wrappers-sumo mock file

## Breaking Changes
React 18 upgrade and related tooling changes.

2813 of 5513 branches covered (51.02%)

Branch coverage included in aggregate %.

13 of 20 new or added lines in 9 files covered. (65.0%)

4 existing lines in 4 files now uncovered.

8250 of 11142 relevant lines covered (74.04%)

75.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

38.04
/webapp/src/modules/store.ts
1
import { createBrowserHistory, History, Location } from 'history'
28✔
2
import { Action, applyMiddleware, compose, createStore, Middleware } from 'redux'
28✔
3
import { createLogger } from 'redux-logger'
28✔
4
import createSagasMiddleware from 'redux-saga'
28✔
5
import { Env } from '@dcl/ui-env'
28✔
6
import { createAnalyticsMiddleware } from 'decentraland-dapps/dist/modules/analytics/middleware'
28✔
7
import { fetchCampaignRequest } from 'decentraland-dapps/dist/modules/campaign/actions'
28✔
8
import { createStorageMiddleware } from 'decentraland-dapps/dist/modules/storage/middleware'
28✔
9
import { storageReducerWrapper } from 'decentraland-dapps/dist/modules/storage/reducer'
28✔
10
import { CLEAR_TRANSACTIONS } from 'decentraland-dapps/dist/modules/transaction/actions'
28✔
11
import { createTransactionMiddleware } from 'decentraland-dapps/dist/modules/transaction/middleware'
28✔
12
import { fetchTranslationsRequest } from 'decentraland-dapps/dist/modules/translation/actions'
28✔
13
import { getPreferredLocale } from 'decentraland-dapps/dist/modules/translation/utils'
28✔
14
import { AuthIdentity } from 'decentraland-crypto-fetch'
15
import { Locale } from 'decentraland-ui'
16
import { config } from '../config'
28✔
17
import { ARCHIVE_BID, UNARCHIVE_BID } from './bid/actions'
28✔
18
import { getCurrentIdentity } from './identity/selectors'
28✔
19
import { createRootReducer, RootState } from './reducer'
28✔
20
import { rootSaga } from './sagas'
28✔
21
import { fetchTilesRequest } from './tile/actions'
28✔
22
import { ExtendedHistory } from './types'
23
import { SET_IS_TRYING_ON } from './ui/preview/actions'
28✔
24

25
const basename = /^decentraland.(zone|org|today)$/.test(window.location.host) ? '/marketplace' : undefined
28!
26

27
export const createHistory = () => {
28✔
28
  const history = createBrowserHistory({ basename }) as ExtendedHistory
×
29
  const locations: Location[] = []
×
30

31
  history.listen((location, action) => {
×
32
    if (action === 'PUSH') {
×
33
      locations.push(location)
×
34
      if (locations.length > 5) {
×
35
        locations.shift()
×
36
      }
37
    }
38
  })
39

40
  history.getLastVisitedLocations = (n?: number) => {
×
41
    if (n) {
×
42
      return locations.slice(-n)
×
43
    }
44
    return locations
×
45
  }
46

47
  return history
×
48
}
49

50
export function initStore(history: History) {
×
51
  const anyWindow = window as unknown as Window & { __REDUX_DEVTOOLS_EXTENSION_COMPOSE__: any; getState: any }
×
52

53
  const isDev = config.is(Env.DEVELOPMENT)
×
54

55
  const composeEnhancers = (
56
    isDev && anyWindow.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
×
57
      ? anyWindow.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
58
          stateSanitizer: (state: RootState) => {
59
            const { tile, proximity, ...sanitized } = { ...state }
×
60
            return sanitized
×
61
          }
62
        })
63
      : compose
64
  ) as typeof compose
65

66
  const rootReducer = storageReducerWrapper(createRootReducer())
×
67

68
  const sagasMiddleware = createSagasMiddleware({ context: { history } })
×
69
  const loggerMiddleware = createLogger({
×
70
    collapsed: () => true,
×
71
    predicate: (_: any, action: Action<string>) => isDev || action.type.includes('Failure')
×
72
  })
73
  const transactionMiddleware = createTransactionMiddleware()
×
74
  const { storageMiddleware, loadStorageMiddleware } = createStorageMiddleware({
×
75
    storageKey: 'marketplace-v2', // this is the key used to save the state in localStorage (required)
76
    paths: [
77
      ['ui', 'archivedBidIds'],
78
      ['ui', 'preview', 'isTryingOn']
79
    ], // array of paths from state to be persisted (optional)
80
    actions: [CLEAR_TRANSACTIONS, ARCHIVE_BID, UNARCHIVE_BID, SET_IS_TRYING_ON], // array of actions types that will trigger a SAVE (optional)
81
    migrations: {} // migration object that will migrate your localstorage (optional)
82
  }) as { storageMiddleware: Middleware; loadStorageMiddleware: Middleware }
83
  const analyticsMiddleware = createAnalyticsMiddleware(config.get('SEGMENT_API_KEY'))
×
84

85
  const middleware = applyMiddleware(sagasMiddleware, loggerMiddleware, transactionMiddleware, storageMiddleware, analyticsMiddleware)
×
86
  const enhancer = composeEnhancers(middleware)
×
87
  const store = createStore(rootReducer as unknown as ReturnType<typeof createRootReducer>, enhancer)
×
88
  const getIdentity = () => {
×
89
    return (getCurrentIdentity(store.getState()) as AuthIdentity | null) ?? undefined
×
90
  }
91
  sagasMiddleware.run(rootSaga, getIdentity)
×
92
  loadStorageMiddleware(store)
×
93

94
  if (isDev) {
×
95
    anyWindow.getState = store.getState.bind(store)
×
96
  }
97

98
  // fetch tiles and translations
99
  store.dispatch(fetchTilesRequest())
×
100
  store.dispatch(fetchCampaignRequest())
×
101

102
  // Fetch translations - needed because TranslationProvider's componentDidUpdate
103
  // doesn't fire when locale is already set on first render
NEW
104
  const locales = ['en', 'es', 'zh'] as Locale[]
×
NEW
105
  const preferredLocale = getPreferredLocale(locales) || locales[0]
×
NEW
106
  store.dispatch(fetchTranslationsRequest(preferredLocale))
×
107

UNCOV
108
  return store
×
109
}
110

111
export function initTestStore(preloadedState = {}) {
248!
112
  const rootReducer = storageReducerWrapper(createRootReducer())
248✔
113
  const sagasMiddleware = createSagasMiddleware()
248✔
114
  const transactionMiddleware = createTransactionMiddleware()
248✔
115
  const { storageMiddleware, loadStorageMiddleware } = createStorageMiddleware({
248✔
116
    storageKey: 'marketplace-v2', // this is the key used to save the state in localStorage (required)
117
    paths: [
118
      ['ui', 'archivedBidIds'],
119
      ['ui', 'preview', 'isTryingOn']
120
    ], // array of paths from state to be persisted (optional)
121
    actions: [CLEAR_TRANSACTIONS, ARCHIVE_BID, UNARCHIVE_BID, SET_IS_TRYING_ON], // array of actions types that will trigger a SAVE (optional)
122
    migrations: {} // migration object that will migrate your localstorage (optional)
123
  }) as { storageMiddleware: Middleware; loadStorageMiddleware: Middleware }
124

125
  const middleware = applyMiddleware(sagasMiddleware, transactionMiddleware, storageMiddleware)
248✔
126
  const enhancer = compose(middleware)
248✔
127
  const store = createStore(rootReducer, preloadedState, enhancer)
248✔
128
  sagasMiddleware.run(rootSaga, () => undefined)
248✔
129
  loadStorageMiddleware(store)
248✔
130
  store.dispatch(fetchTilesRequest())
248✔
131

132
  return store
248✔
133
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc