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

decentraland / marketplace / 6468133945

10 Oct 2023 10:36AM UTC coverage: 40.778% (+0.7%) from 40.103%
6468133945

Pull #2030

github

juanmahidalgo
test: add Test for SearchBarDropdown
Pull Request #2030: Feat: new search bar component

2260 of 6951 branches covered (0.0%)

Branch coverage included in aggregate %.

215 of 215 new or added lines in 20 files covered. (100.0%)

4280 of 9087 relevant lines covered (47.1%)

18.0 hits per line

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

57.58
/webapp/src/components/AssetTopbar/SelectedFilters/SelectedFilters.tsx
1
import { useState, useMemo, useCallback, useEffect } from 'react'
2
import { Rarity } from '@dcl/schemas'
3
import { t } from 'decentraland-dapps/dist/modules/translation/utils'
4
import {
5
  getEstateSizeLabel,
6
  getGenderFilterLabel,
7
  getLandLabel,
8
  getNetwork,
9
  getPriceLabel
10
} from '../../../utils/filters'
11
import { CreatorAccount } from '../../../modules/account/types'
12
import ProfilesCache from '../../../lib/profiles'
13
import { AssetStatusFilter } from '../../../utils/filters'
14
import { profileToCreatorAccount } from '../../AssetFilters/CreatorsFilter/utils'
15
import { AssetType } from '../../../modules/asset/types'
16
import { Pill } from './Pill/Pill'
17
import { Props } from './SelectedFilters.types'
18
import { getCollectionByAddress } from './utils'
19
import styles from './SelectedFilters.module.css'
20

21
export const SelectedFilters = ({
2✔
22
  browseOptions,
23
  isLandSection,
24
  category,
25
  onBrowse
26
}: Props) => {
27
  const {
28
    rarities,
29
    network,
30
    onlySmart,
31
    contracts,
32
    creators,
33
    wearableGenders,
34
    onlyOnSale,
35
    emotePlayMode,
36
    minPrice,
37
    maxPrice,
38
    onlyOnRent,
39
    minEstateSize,
40
    maxEstateSize,
41
    adjacentToRoad,
42
    minDistanceToPlaza,
43
    maxDistanceToPlaza,
44
    rentalDays,
45
    assetType,
46
    status,
47
    emoteHasSound,
48
    emoteHasGeometry
49
  } = browseOptions
3✔
50
  const [collections, setCollections] = useState<Record<string, string>[] | []>(
3✔
51
    []
52
  )
53

54
  const [selectedCreators, setSelectedCreators] = useState<
3✔
55
    Pick<CreatorAccount, 'address' | 'name'>[]
56
  >()
57

58
  useEffect(() => {
3✔
59
    const fetchData = async (contract: string) => {
1✔
60
      const collection = await getCollectionByAddress(contract)
2✔
61
      return collection
2✔
62
    }
63

64
    if (contracts?.length) {
1!
65
      const promises = contracts.map(contract => fetchData(contract))
2✔
66
      Promise.all(promises).then(collections => {
1✔
67
        setCollections(
1✔
68
          collections.map(collection => ({
2✔
69
            address: collection.contractAddress,
70
            name: collection.name
71
          }))
72
        )
73
      })
74
    } else if (!contracts?.length) {
×
75
      setCollections([])
×
76
    }
77
  }, [contracts, onlyOnSale])
78

79
  useEffect(() => {
3✔
80
    if (creators?.length) {
1!
81
      ProfilesCache.fetchProfile(creators).then(profiles => {
×
82
        setSelectedCreators(profileToCreatorAccount(profiles))
×
83
      })
84
    } else if (!creators?.length) {
1!
85
      setSelectedCreators([])
1✔
86
    }
87
  }, [creators])
88

89
  const priceLabel = useMemo(
3✔
90
    () => getPriceLabel(minPrice, maxPrice, getNetwork(network, category)),
1✔
91
    [minPrice, maxPrice, network, category]
92
  )
93

94
  const estateSizeLabel = useMemo(
3✔
95
    () => getEstateSizeLabel(minEstateSize, maxEstateSize),
1✔
96
    [minEstateSize, maxEstateSize]
97
  )
98

99
  const landStatusLabel = useMemo(() => {
3✔
100
    if (isLandSection && (onlyOnSale || onlyOnRent)) {
1!
101
      return getLandLabel({ onlyOnRent, onlyOnSale })
×
102
    }
103
    return undefined
1✔
104
  }, [onlyOnRent, onlyOnSale, isLandSection])
105

106
  const handleDeleteRarity = useCallback(
3✔
107
    (rarity: string) => {
108
      onBrowse({ rarities: rarities?.filter((r: Rarity) => r !== rarity) })
×
109
    },
110
    [onBrowse, rarities]
111
  )
112

113
  const handleDeleteCreator = useCallback(
3✔
114
    (address: string) => {
115
      onBrowse({ creators: creators?.filter(creator => creator !== address) })
×
116
    },
117
    [creators, onBrowse]
118
  )
119

120
  const handleDeleteCollection = useCallback(
3✔
121
    contract => {
122
      onBrowse({
×
123
        contracts: contracts?.filter(collection => collection !== contract)
×
124
      })
125
    },
126
    [contracts, onBrowse]
127
  )
128

129
  const handleDeleteNetwork = useCallback(() => {
3✔
130
    onBrowse({ network: undefined })
×
131
  }, [onBrowse])
132

133
  const handleDeleteOnlySmart = useCallback(() => {
3✔
134
    onBrowse({ onlySmart: undefined })
×
135
  }, [onBrowse])
136

137
  const handleDeleteOnlySale = useCallback(() => {
3✔
138
    onBrowse({ onlyOnSale: true })
×
139
  }, [onBrowse])
140

141
  const handleDeleteGender = useCallback(() => {
3✔
142
    onBrowse({ wearableGenders: [] })
×
143
  }, [onBrowse])
144

145
  const handleDeleteEmotePlayMode = useCallback(
3✔
146
    playMode => {
147
      onBrowse({
×
148
        emotePlayMode: emotePlayMode?.filter(mode => playMode !== mode)
×
149
      })
150
    },
151
    [onBrowse, emotePlayMode]
152
  )
153

154
  const handleDeletePrice = useCallback(() => {
3✔
155
    onBrowse({ minPrice: undefined, maxPrice: undefined })
×
156
  }, [onBrowse])
157

158
  const handleDeleteEstateSize = useCallback(() => {
3✔
159
    onBrowse({ minEstateSize: undefined, maxEstateSize: undefined })
×
160
  }, [onBrowse])
161

162
  const handleDeleteLandStatus = useCallback(() => {
3✔
163
    onBrowse({ onlyOnRent: undefined, onlyOnSale: undefined })
×
164
  }, [onBrowse])
165

166
  const handleDeleteDistanceToPlaza = useCallback(() => {
3✔
167
    onBrowse({ minDistanceToPlaza: undefined, maxDistanceToPlaza: undefined })
×
168
  }, [onBrowse])
169

170
  const handleDeleteAdjacentToRoad = useCallback(() => {
3✔
171
    onBrowse({ adjacentToRoad: undefined })
×
172
  }, [onBrowse])
173

174
  const handleDeleteStatus = useCallback(() => {
3✔
175
    onBrowse({ status: AssetStatusFilter.ON_SALE })
×
176
  }, [onBrowse])
177

178
  const handleDeleteRentalDays = useCallback(
3✔
179
    removeDays => {
180
      onBrowse({
×
181
        rentalDays: rentalDays?.filter(
182
          day => removeDays.toString() !== day.toString()
×
183
        )
184
      })
185
    },
186
    [onBrowse, rentalDays]
187
  )
188

189
  const handleDeleteEmoteHasSound = useCallback(() => {
3✔
190
    onBrowse({ emoteHasSound: undefined })
×
191
  }, [onBrowse])
192

193
  const handleDeleteEmoteHasGeometry = useCallback(() => {
3✔
194
    onBrowse({ emoteHasGeometry: undefined })
×
195
  }, [onBrowse])
196

197
  return (
3✔
198
    <div className={styles.pillContainer}>
199
      {emoteHasSound ? (
3!
200
        <Pill
201
          label={t('nft_filters.emote_attributes.with_sound')}
202
          id="emoteHasSound"
203
          onDelete={handleDeleteEmoteHasSound}
204
        />
205
      ) : null}
206
      {emoteHasGeometry ? (
3!
207
        <Pill
208
          label={t('nft_filters.emote_attributes.with_props')}
209
          id="emoteHasGeomtry"
210
          onDelete={handleDeleteEmoteHasGeometry}
211
        />
212
      ) : null}
213
      {rarities?.map(rarity => (
214
        <Pill
×
215
          key={rarity}
216
          label={rarity}
217
          id={rarity}
218
          onDelete={handleDeleteRarity}
219
        />
220
      ))}
221
      {network ? (
3!
222
        <Pill
223
          label={t(`networks.${network.toLowerCase()}`)}
224
          id="network"
225
          onDelete={handleDeleteNetwork}
226
        />
227
      ) : null}
228
      {onlySmart ? (
3!
229
        <Pill
230
          label={t('nft_filters.only_smart.selected')}
231
          id="onlySmart"
232
          onDelete={handleDeleteOnlySmart}
233
        />
234
      ) : null}
235
      {collections.length
3✔
236
        ? collections.map(collection => (
237
            <Pill
2✔
238
              key={collection.address}
239
              id={`collection-${collection.address}`}
240
              label={collection.name}
241
              onDelete={() => handleDeleteCollection(collection.address)}
×
242
            />
243
          ))
244
        : null}
245
      {selectedCreators?.length
3!
246
        ? selectedCreators.map(creator => (
247
            <Pill
×
248
              key={creator.address}
249
              label={creator.name}
250
              id={creator.address}
251
              onDelete={() => handleDeleteCreator(creator.address)}
×
252
            />
253
          ))
254
        : null}
255
      {wearableGenders?.length ? (
3!
256
        <Pill
257
          label={t(getGenderFilterLabel(wearableGenders))}
258
          id="wearable_genders"
259
          onDelete={handleDeleteGender}
260
        />
261
      ) : null}
262
      {!onlyOnSale && !isLandSection && assetType !== AssetType.ITEM ? ( // TODO UNIFIED: CHECK THIS
12!
263
        <Pill
264
          label={t('nft_filters.not_on_sale')}
265
          id="onlyOnSale"
266
          onDelete={handleDeleteOnlySale}
267
        />
268
      ) : null}
269
      {emotePlayMode?.map(playMode => (
270
        <Pill
×
271
          key={playMode}
272
          label={t(`emote.play_mode.${playMode}`)}
273
          onDelete={handleDeleteEmotePlayMode}
274
          id={playMode}
275
        />
276
      ))}
277
      {minPrice || maxPrice ? (
9!
278
        <Pill
279
          label={priceLabel}
280
          className={styles.pricePill}
281
          onDelete={handleDeletePrice}
282
          id="price"
283
        />
284
      ) : null}
285
      {minEstateSize || maxEstateSize ? (
9!
286
        <Pill
287
          label={estateSizeLabel}
288
          onDelete={handleDeleteEstateSize}
289
          id="estateSize"
290
        />
291
      ) : null}
292
      {isLandSection && landStatusLabel ? (
6!
293
        <Pill
294
          label={landStatusLabel}
295
          onDelete={handleDeleteLandStatus}
296
          id="land_filter"
297
        />
298
      ) : null}
299
      {adjacentToRoad ? (
3!
300
        <Pill
301
          label={t('nft_filters.adjacent_to_road')}
302
          onDelete={handleDeleteAdjacentToRoad}
303
          id="adjacentToRoad"
304
        />
305
      ) : null}
306
      {minDistanceToPlaza || maxDistanceToPlaza ? (
9!
307
        <Pill
308
          label={t('nft_filters.distance_to_plaza.selection', {
309
            from: minDistanceToPlaza,
310
            to: maxDistanceToPlaza
311
          })}
312
          onDelete={handleDeleteDistanceToPlaza}
313
          id="distanceToPlaza"
314
        />
315
      ) : null}
316
      {rentalDays && rentalDays.length
6!
317
        ? rentalDays.map(days => (
318
            <Pill
×
319
              key={days}
320
              label={t('nft_filters.periods.selection', { rentalDays: days })}
321
              onDelete={handleDeleteRentalDays}
322
              id={days.toString()}
323
            />
324
          ))
325
        : null}
326
      {status && status !== AssetStatusFilter.ON_SALE ? (
6!
327
        <Pill
328
          key={status}
329
          label={t(`nft_filters.status.${status}`)}
330
          onDelete={handleDeleteStatus}
331
          id={status.toString()}
332
        />
333
      ) : null}
334
    </div>
335
  )
336
}
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

© 2025 Coveralls, Inc