Skip to content

Commit

Permalink
(PC-33493) refactor(venue): remove all hooks in useVenueOffers and us…
Browse files Browse the repository at this point in the history
…e hooks directly on parent components
  • Loading branch information
clesausse-pass committed Mar 3, 2025
1 parent 743b820 commit fca88e4
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 152 deletions.
145 changes: 20 additions & 125 deletions src/features/venue/api/useVenueOffers.test.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,19 @@
import { SubcategoryIdEnum } from 'api/gen'
import * as UnderageUserAPI from 'features/profile/helpers/useIsUserUnderage'
import { SearchState } from 'features/search/types'
import { useVenueOffers } from 'features/venue/api/useVenueOffers'
import * as useVenueSearchParameters from 'features/venue/helpers/useVenueSearchParameters'
import mockVenueResponse from 'fixtures/venueResponse'
import mockVenueSearchParams from 'fixtures/venueSearchParams'
import { fetchMultipleOffers } from 'libs/algolia/fetchAlgolia/fetchMultipleOffers/fetchMultipleOffers'
import {
filterOfferHitWithImage,
transformOfferHit,
} from 'libs/algolia/fetchAlgolia/transformOfferHit'
import { AlgoliaOffer, HitOffer } from 'libs/algolia/types'
import { LocationMode, Position } from 'libs/location/types'
import * as useNetInfoContextDefault from 'libs/network/NetInfoWrapper'
import { reactQueryProviderHOC } from 'tests/reactQueryProviderHOC'
import { renderHook, waitFor } from 'tests/utils'

const mockLocationMode = LocationMode.AROUND_ME
const mockUserLocation: Position = { latitude: 48.90374, longitude: 2.48171 }
jest.mock('libs/location/LocationWrapper', () => ({
useLocation: () => ({
userLocation: mockUserLocation,
selectedLocationMode: mockLocationMode,
}),
}))

jest.mock('features/search/context/SearchWrapper', () => ({
useSearch: () => ({
resetSearch: jest.fn(),
dispatch: jest.fn(),
}),
}))

const venueSearchParamsMock: SearchState = {
beginningDatetime: undefined,
endingDatetime: undefined,
hitsPerPage: 50,
locationFilter: {
locationType: LocationMode.EVERYWHERE,
},
venue: {
label: mockVenueResponse.publicName || '',
info: mockVenueResponse.city || '',
_geoloc: {
lat: mockVenueResponse.latitude,
lng: mockVenueResponse.longitude,
},
venueId: mockVenueResponse.id,
},
offerCategories: [],
offerSubcategories: [],
offerIsDuo: false,
offerIsFree: false,
isDigital: false,
priceRange: [0, 300],
tags: [],
date: null,
timeRange: null,
query: '',
}

jest
.spyOn(useVenueSearchParameters, 'useVenueSearchParameters')
.mockReturnValue(venueSearchParamsMock)

jest.mock('features/profile/helpers/useIsUserUnderage')
jest.spyOn(UnderageUserAPI, 'useIsUserUnderage').mockReturnValue(false)

jest.mock('libs/algolia/fetchAlgolia/fetchMultipleOffers/fetchMultipleOffers', () => ({
fetchMultipleOffers: jest.fn(),
Expand All @@ -73,19 +22,6 @@ const mockFetchMultipleOffers = fetchMultipleOffers as jest.MockedFunction<
typeof fetchMultipleOffers
>

const mockUseAuthContext = jest.fn().mockReturnValue({
user: undefined,
isLoggedIn: false,
})
jest.mock('features/auth/context/AuthContext', () => ({
useAuthContext: () => mockUseAuthContext(),
}))

jest.mock('libs/firebase/analytics/analytics')

const mockUseNetInfoContext = jest.spyOn(useNetInfoContextDefault, 'useNetInfoContext') as jest.Mock
mockUseNetInfoContext.mockReturnValue({ isConnected: true, isInternetReachable: true })

const EXPECTED_CALL_PARAM = {
isUserUnderage: false,
paramsList: [
Expand All @@ -97,15 +33,7 @@ const EXPECTED_CALL_PARAM = {
selectedLocationMode: 'AROUND_ME',
userLocation: { latitude: 48.90374, longitude: 2.48171 },
},
offerParams: {
hitsPerPage: 50,
venue: {
_geoloc: { lat: 48.8536, lng: 2.34199 },
info: 'PARIS 6',
label: 'Cinéma St André des Arts',
venueId: 26235,
},
},
offerParams: mockVenueSearchParams,
},
{
indexName: 'algoliaTopOffersIndexName',
Expand All @@ -115,28 +43,7 @@ const EXPECTED_CALL_PARAM = {
selectedLocationMode: 'AROUND_ME',
userLocation: { latitude: 48.90374, longitude: 2.48171 },
},
offerParams: {
beginningDatetime: undefined,
date: null,
endingDatetime: undefined,
hitsPerPage: 50,
isDigital: false,
locationFilter: { locationType: 'EVERYWHERE' },
offerCategories: [],
offerIsDuo: false,
offerIsFree: false,
offerSubcategories: [],
priceRange: [0, 300],
query: '',
tags: [],
timeRange: null,
venue: {
_geoloc: { lat: 48.8536, lng: 2.34199 },
info: 'PARIS 6',
label: 'Cinéma St André des Arts',
venueId: 26235,
},
},
offerParams: mockVenueSearchParams,
},
{
indexName: 'algoliaOffersIndexName',
Expand All @@ -146,29 +53,7 @@ const EXPECTED_CALL_PARAM = {
selectedLocationMode: 'AROUND_ME',
userLocation: { latitude: 48.90374, longitude: 2.48171 },
},
offerParams: {
beginningDatetime: undefined,
date: null,
endingDatetime: undefined,
hitsPerPage: 50,
isDigital: false,
isHeadline: true,
locationFilter: { locationType: 'EVERYWHERE' },
offerCategories: [],
offerIsDuo: false,
offerIsFree: false,
offerSubcategories: [],
priceRange: [0, 300],
query: '',
tags: [],
timeRange: null,
venue: {
_geoloc: { lat: 48.8536, lng: 2.34199 },
info: 'PARIS 6',
label: 'Cinéma St André des Arts',
venueId: 26235,
},
},
offerParams: { ...mockVenueSearchParams, isHeadline: true },
},
],
}
Expand Down Expand Up @@ -237,13 +122,23 @@ describe('useVenueOffers', () => {
nbHits: 1,
},
]
mockFetchMultipleOffers
.mockResolvedValueOnce(FETCH_MULTIPLE_OFFERS_RESPONSE)
.mockResolvedValueOnce(FETCH_MULTIPLE_OFFERS_RESPONSE)
mockFetchMultipleOffers.mockResolvedValueOnce(FETCH_MULTIPLE_OFFERS_RESPONSE)

const { result } = renderHook(() => useVenueOffers(mockVenueResponse), {
wrapper: ({ children }) => reactQueryProviderHOC(children),
})
const { result } = renderHook(
() =>
useVenueOffers({
userLocation: mockUserLocation,
selectedLocationMode: mockLocationMode,
venue: mockVenueResponse,
isUserUnderage: false,
venueSearchParams: mockVenueSearchParams,
transformHits: transformOfferHit(),
searchState: mockVenueSearchParams,
}),
{
wrapper: ({ children }) => reactQueryProviderHOC(children),
}
)
await waitFor(() => expect(mockFetchMultipleOffers).toHaveBeenCalledWith(EXPECTED_CALL_PARAM))

expect(result.current.data?.hits).toMatchObject(
Expand Down
38 changes: 23 additions & 15 deletions src/features/venue/api/useVenueOffers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,41 @@ import { useCallback } from 'react'
import { useQuery, UseQueryResult } from 'react-query'

import { VenueResponse } from 'api/gen'
import { useIsUserUnderage } from 'features/profile/helpers/useIsUserUnderage'
import { useSearch } from 'features/search/context/SearchWrapper'
import { MAX_RADIUS } from 'features/search/helpers/reducer.helpers'
import { useVenueSearchParameters } from 'features/venue/helpers/useVenueSearchParameters'
import { SearchState } from 'features/search/types'
import { VenueOffers } from 'features/venue/types'
import { fetchMultipleOffers } from 'libs/algolia/fetchAlgolia/fetchMultipleOffers/fetchMultipleOffers'
import {
filterOfferHitWithImage,
filterValidOfferHit,
useTransformOfferHits,
} from 'libs/algolia/fetchAlgolia/transformOfferHit'
import { SearchQueryParameters } from 'libs/algolia/types'
import { AlgoliaOffer, HitOffer, SearchQueryParameters } from 'libs/algolia/types'
import { env } from 'libs/environment/env'
import { useLocation } from 'libs/location'
import { Position } from 'libs/location'
import { LocationMode } from 'libs/location/types'
import { QueryKeys } from 'libs/queryKeys'

export const useVenueOffers = (
venue?: VenueResponse,
type UseVenueOffersParams = {
userLocation: Position
selectedLocationMode: LocationMode
isUserUnderage: boolean
venueSearchParams: SearchState
searchState: SearchState
transformHits: (hit: AlgoliaOffer<HitOffer>) => AlgoliaOffer<HitOffer>
venue?: VenueResponse
includeHitsWithoutImage?: boolean
): UseQueryResult<VenueOffers> => {
// TODO(PC-33493): hook refacto
const { userLocation, selectedLocationMode } = useLocation()
const transformHits = useTransformOfferHits()
const venueSearchParams = useVenueSearchParameters(venue)
const { searchState } = useSearch()
const isUserUnderage = useIsUserUnderage()
}

export const useVenueOffers = ({
userLocation,
selectedLocationMode,
isUserUnderage,
venueSearchParams,
searchState,
transformHits,
venue,
includeHitsWithoutImage,
}: UseVenueOffersParams): UseQueryResult<VenueOffers> => {
const buildVenueOffersQueryParams = useCallback(
(offerParams: SearchQueryParameters) => ({
locationParams: {
Expand Down
18 changes: 13 additions & 5 deletions src/features/venue/components/VenueBody/VenueBody.native.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@ import mockdate from 'mockdate'
import React from 'react'
import { Linking } from 'react-native'

import { useRoute, navigate } from '__mocks__/@react-navigation/native'
import { navigate, useRoute } from '__mocks__/@react-navigation/native'
import { CategoryIdEnum } from 'api/gen'
import { gtlPlaylistAlgoliaSnapshot } from 'features/gtlPlaylist/fixtures/gtlPlaylistAlgoliaSnapshot'
import * as useGTLPlaylists from 'features/gtlPlaylist/hooks/useGTLPlaylists'
import { useVenueOffers } from 'features/venue/api/useVenueOffers'
import { VenueBody } from 'features/venue/components/VenueBody/VenueBody'
import { venueDataTest } from 'features/venue/fixtures/venueDataTest'
import { VenueOffersResponseSnap } from 'features/venue/fixtures/venueOffersResponseSnap'
import * as useVenueSearchParameters from 'features/venue/helpers/useVenueSearchParameters'
import mockVenueSearchParams from 'fixtures/venueSearchParams'
import { analytics } from 'libs/analytics/provider'
import { setFeatureFlags } from 'libs/firebase/firestore/featureFlags/__tests__/setFeatureFlags'
import { reactQueryProviderHOC } from 'tests/reactQueryProviderHOC'
import { fireEvent, render, screen, userEvent } from 'tests/utils'
import { render, screen, userEvent } from 'tests/utils'

mockdate.set(new Date('2021-08-15T00:00:00Z'))

Expand Down Expand Up @@ -47,6 +49,12 @@ const HEADLINE_OFFER_DATA = {
distance: '500m',
}

jest
.spyOn(useVenueSearchParameters, 'useVenueSearchParameters')
.mockReturnValue(mockVenueSearchParams)

jest.mock('features/search/context/SearchWrapper')

jest.useFakeTimers()
const user = userEvent.setup()

Expand All @@ -68,15 +76,15 @@ describe('<VenueBody />', () => {
it('should display withdrawal details', async () => {
render(reactQueryProviderHOC(<VenueBody venue={venueDataTest} />))

fireEvent.press(screen.getByText('Infos pratiques'))
await user.press(screen.getByText('Infos pratiques'))

expect(screen.getByText('How to withdraw, https://test.com')).toBeOnTheScreen()
})

it('should log event when pressing on Infos pratiques tab', async () => {
render(reactQueryProviderHOC(<VenueBody venue={venueDataTest} />))

fireEvent.press(screen.getByText('Infos pratiques'))
await user.press(screen.getByText('Infos pratiques'))

expect(analytics.logConsultPracticalInformations).toHaveBeenCalledWith({
venueId: venueDataTest.id,
Expand All @@ -86,7 +94,7 @@ describe('<VenueBody />', () => {
it('should log event when pressing on Offres disponibles tab', async () => {
render(reactQueryProviderHOC(<VenueBody venue={venueDataTest} />))

fireEvent.press(screen.getByText('Offres disponibles'))
await user.press(screen.getByText('Offres disponibles'))

expect(analytics.logConsultVenueOffers).toHaveBeenCalledWith({ venueId: venueDataTest.id })
})
Expand Down
22 changes: 20 additions & 2 deletions src/features/venue/components/VenueOffers/VenueOffers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import React from 'react'
import { SubcategoryIdEnum, VenueResponse } from 'api/gen'
import { useGTLPlaylists } from 'features/gtlPlaylist/hooks/useGTLPlaylists'
import { GtlPlaylistData } from 'features/gtlPlaylist/types'
import { useIsUserUnderage } from 'features/profile/helpers/useIsUserUnderage'
import { useSearch } from 'features/search/context/SearchWrapper'
import { useVenueOffers } from 'features/venue/api/useVenueOffers'
import { NoOfferPlaceholder } from 'features/venue/components/Placeholders/NoOfferPlaceholder'
import { VenueMovies } from 'features/venue/components/VenueOffers/VenueMovies'
import { VenueOffersList } from 'features/venue/components/VenueOffers/VenueOffersList'
import type { VenueOffersArtists, VenueOffers } from 'features/venue/types'
import { useVenueSearchParameters } from 'features/venue/helpers/useVenueSearchParameters'
import type { VenueOffers, VenueOffersArtists } from 'features/venue/types'
import { useTransformOfferHits } from 'libs/algolia/fetchAlgolia/transformOfferHit'
import { useLocation } from 'libs/location'
import { CategoryHomeLabelMapping, CategoryIdMapping } from 'libs/subcategories/types'
import { Currency } from 'shared/currency/useGetCurrencyToDisplay'
import { OfferPlaylistSkeleton, TileSize } from 'ui/components/placeholders/OfferPlaylistSkeleton'
Expand Down Expand Up @@ -41,7 +46,20 @@ export function VenueOffers({
currency,
euroToPacificFrancRate,
}: Readonly<VenueOffersProps>) {
const { isLoading: areVenueOffersLoading } = useVenueOffers(venue)
const { userLocation, selectedLocationMode } = useLocation()
const transformHits = useTransformOfferHits()
const venueSearchParams = useVenueSearchParameters(venue)
const { searchState } = useSearch()
const isUserUnderage = useIsUserUnderage()
const { isLoading: areVenueOffersLoading } = useVenueOffers({
userLocation,
selectedLocationMode,
isUserUnderage,
venueSearchParams,
searchState,
transformHits,
venue,
})
const { isLoading: arePlaylistsLoading } = useGTLPlaylists({
venue,
queryKey: 'VENUE_GTL_PLAYLISTS',
Expand Down
2 changes: 1 addition & 1 deletion src/features/venue/pages/Venue/Venue.native.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ describe('<Venue />', () => {
it('should display CTA if venueTypeCode is not Movie and gtlPlaylists have length', async () => {
mockUseVenueOffers.mockReturnValueOnce({
isLoading: false,
data: { hits: {}, nbHits: 0 },
data: { hits: [], nbHits: 0 },
})

renderVenue(venueId)
Expand Down
Loading

0 comments on commit fca88e4

Please sign in to comment.