Skip to content

Commit

Permalink
(PC-33463) refactor(Venue): refacto Venue page
Browse files Browse the repository at this point in the history
  • Loading branch information
bpeyrou-pass committed Dec 27, 2024
1 parent 1ff7dcb commit 85b6e7d
Show file tree
Hide file tree
Showing 16 changed files with 5,926 additions and 5,909 deletions.
11,188 changes: 5,585 additions & 5,603 deletions __snapshots__/features/venue/pages/Venue/Venue.native.test.tsx.native-snap

Large diffs are not rendered by default.

29 changes: 0 additions & 29 deletions src/features/venue/components/VenueBody/VenueBody.native.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import mockdate from 'mockdate'
import React from 'react'
import { Linking } from 'react-native'
import Share, { Social } from 'react-native-share'
import { UseQueryResult } from 'react-query'

import { useRoute } from '__mocks__/@react-navigation/native'
Expand All @@ -14,7 +13,6 @@ import { VenueOffersResponseSnap } from 'features/venue/fixtures/venueOffersResp
import { VenueOffers } from 'features/venue/types'
import { analytics } from 'libs/analytics'
import * as useFeatureFlag from 'libs/firebase/firestore/featureFlags/useFeatureFlag'
import { Network } from 'libs/share/types'
import { reactQueryProviderHOC } from 'tests/reactQueryProviderHOC'
import { fireEvent, render, screen } from 'tests/utils'

Expand All @@ -24,7 +22,6 @@ mockdate.set(new Date('2021-08-15T00:00:00Z'))

jest.mock('features/venue/api/useVenue')
jest.mock('@react-native-clipboard/clipboard')
const mockShareSingle = jest.spyOn(Share, 'shareSingle')
const canOpenURLSpy = jest.spyOn(Linking, 'canOpenURL').mockResolvedValue(false)
jest
.spyOn(useGTLPlaylists, 'useGTLPlaylists')
Expand Down Expand Up @@ -52,33 +49,14 @@ describe('<VenueBody />', () => {

it('should display withdrawal details', async () => {
render(reactQueryProviderHOC(<VenueBody venue={venueDataTest} />))
await waitUntilRendered()

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

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

it('should share on Instagram', async () => {
render(reactQueryProviderHOC(<VenueBody venue={venueDataTest} />))

const instagramButton = await screen.findByText(`Envoyer sur ${Network.instagram}`)

fireEvent.press(instagramButton)

expect(mockShareSingle).toHaveBeenCalledWith({
social: Social.Instagram,
message: encodeURIComponent(
`Retrouve "${venueDataTest.name}" sur le pass Culture\u00a0:\nhttps://webapp-v2.example.com/lieu/5543?utm_gen=product&utm_campaign=share_venue&utm_medium=social_media&utm_source=Instagram`
),
type: 'text',
url: undefined,
})
})

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

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

Expand All @@ -89,16 +67,9 @@ describe('<VenueBody />', () => {

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

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

expect(analytics.logConsultVenueOffers).toHaveBeenCalledWith({ venueId: venueDataTest.id })
})
})

const waitUntilRendered = async () => {
// We wait until the full render is done
// This is due to asynchronous calls to check the media on the phone
await screen.findByText(`Envoyer sur ${Network.instagram}`)
}
57 changes: 18 additions & 39 deletions src/features/venue/components/VenueBody/VenueBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,29 @@ import { VenueResponse } from 'api/gen'
import { GtlPlaylistData } from 'features/gtlPlaylist/types'
import { PracticalInformation } from 'features/venue/components/PracticalInformation/PracticalInformation'
import { TabLayout } from 'features/venue/components/TabLayout/TabLayout'
import { VENUE_CTA_HEIGHT_IN_SPACES } from 'features/venue/components/VenueCTA/VenueCTA'
import { VenueMessagingApps } from 'features/venue/components/VenueMessagingApps/VenueMessagingApps'
import { VenueOffers } from 'features/venue/components/VenueOffers/VenueOffers'
import { VenueThematicSection } from 'features/venue/components/VenueThematicSection/VenueThematicSection'
import type { VenueOffersArtists, VenueOffers as VenueOffersType } from 'features/venue/types'
import { Tab } from 'features/venue/types'
import { analytics } from 'libs/analytics'
import { SectionWithDivider } from 'ui/components/SectionWithDivider'
import { Spacer } from 'ui/theme'

interface Props {
venue: VenueResponse
venueArtists?: VenueOffersArtists
venueOffers?: VenueOffersType
playlists?: GtlPlaylistData[]
shouldDisplayCTA?: boolean
}

export const VenueBody: FunctionComponent<Props> = ({
venue,
venueArtists,
venueOffers,
playlists,
shouldDisplayCTA,
}) => {
const { isDesktopViewport, isTabletViewport } = useTheme()
const isLargeScreen = isDesktopViewport || isTabletViewport

const FirstSectionContainer = isLargeScreen ? View : SectionWithDivider
const SectionContainer = isLargeScreen ? View : SectionWithDivider

const tabPanels = {
[Tab.OFFERS]: (
Expand All @@ -49,37 +43,22 @@ export const VenueBody: FunctionComponent<Props> = ({
}

return (
<React.Fragment>
<FirstSectionContainer visible gap={6}>
<TabLayout
tabPanels={tabPanels}
tabs={[{ key: Tab.OFFERS }, { key: Tab.INFOS }]}
defaultTab={Tab.OFFERS}
onTabChange={{
'Offres disponibles': () =>
analytics.logConsultVenueOffers({
venueId: venue.id,
}),
'Infos pratiques': () =>
analytics.logConsultPracticalInformations({
venueId: venue.id,
}),
}}
/>
</FirstSectionContainer>

<Spacer.Column numberOfSpaces={6} />

<VenueThematicSection venue={venue} />

<SectionWithDivider visible margin gap={6}>
<VenueMessagingApps venue={venue} />
<Spacer.Column numberOfSpaces={4} />
</SectionWithDivider>

<SectionWithDivider visible={!!shouldDisplayCTA} gap={VENUE_CTA_HEIGHT_IN_SPACES}>
<Spacer.Column numberOfSpaces={6} />
</SectionWithDivider>
</React.Fragment>
<SectionContainer visible gap={6}>
<TabLayout
tabPanels={tabPanels}
tabs={[{ key: Tab.OFFERS }, { key: Tab.INFOS }]}
defaultTab={Tab.OFFERS}
onTabChange={{
'Offres disponibles': () =>
analytics.logConsultVenueOffers({
venueId: venue.id,
}),
'Infos pratiques': () =>
analytics.logConsultPracticalInformations({
venueId: venue.id,
}),
}}
/>
</SectionContainer>
)
}
40 changes: 23 additions & 17 deletions src/features/venue/components/VenueCTA/VenueCTA.native.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { push } from '__mocks__/@react-navigation/native'
import { SearchState } from 'features/search/types'
import { VenueCTA } from 'features/venue/components/VenueCTA/VenueCTA'
import { venueDataTest } from 'features/venue/fixtures/venueDataTest'
import * as useNavigateToSearchWithVenueOffers from 'features/venue/helpers/useNavigateToSearchWithVenueOffers'
import { SearchNavConfig } from 'features/venue/types'
import { analytics } from 'libs/analytics'
import { LocationMode } from 'libs/location/types'
import { fireEvent, render, screen, waitFor } from 'tests/utils'
import { render, screen, userEvent, waitFor } from 'tests/utils'

const defaultParams: SearchState = {
beginningDatetime: undefined,
Expand All @@ -34,27 +34,28 @@ const defaultParams: SearchState = {
},
} as SearchState

jest
.spyOn(useNavigateToSearchWithVenueOffers, 'useNavigateToSearchWithVenueOffers')
.mockReturnValue({
screen: 'TabNavigator',
const searchNavConfigMock: SearchNavConfig = {
screen: 'TabNavigator',
params: {
screen: 'SearchStackNavigator',
params: {
screen: 'SearchStackNavigator',
params: {
screen: 'SearchResults',
params: defaultParams,
},
screen: 'SearchResults',
params: defaultParams,
},
withPush: true,
})
},
withPush: true,
}

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

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

describe('<VenueCTA />', () => {
it('should navigate to the search page when pressed on', async () => {
render(<VenueCTA venue={venueDataTest} />)
render(<VenueCTA searchNavConfig={searchNavConfigMock} onBeforeNavigate={jest.fn()} />)

fireEvent.press(screen.getByText('Rechercher une offre'))
await user.press(await screen.findByText('Rechercher une offre'))

await waitFor(() => {
expect(push).toHaveBeenCalledWith('TabNavigator', {
Expand All @@ -76,9 +77,14 @@ describe('<VenueCTA />', () => {
})

it('should log event when pressed on', async () => {
render(<VenueCTA venue={venueDataTest} />)
render(
<VenueCTA
searchNavConfig={searchNavConfigMock}
onBeforeNavigate={() => analytics.logVenueSeeAllOffersClicked(venueDataTest.id)}
/>
)

fireEvent.press(screen.getByText('Rechercher une offre'))
await user.press(await screen.findByText('Rechercher une offre'))

expect(analytics.logVenueSeeAllOffersClicked).toHaveBeenCalledWith(venueDataTest.id)
})
Expand Down
12 changes: 5 additions & 7 deletions src/features/venue/components/VenueCTA/VenueCTA.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import React, { FunctionComponent } from 'react'
import styled from 'styled-components/native'

import { VenueResponse } from 'api/gen'
import { useNavigateToSearchWithVenueOffers } from 'features/venue/helpers/useNavigateToSearchWithVenueOffers'
import { analytics } from 'libs/analytics'
import { SearchNavConfig } from 'features/venue/types'
import { ButtonPrimary } from 'ui/components/buttons/ButtonPrimary'
import { StickyBottomWrapper } from 'ui/components/StickyBottomWrapper/StickyBottomWrapper'
import { InternalTouchableLink } from 'ui/components/touchableLink/InternalTouchableLink'
Expand All @@ -13,18 +11,18 @@ import { Spacer } from 'ui/theme'
export const VENUE_CTA_HEIGHT_IN_SPACES = 6 + 10 + 6

interface Props {
venue: VenueResponse
searchNavConfig: SearchNavConfig
onBeforeNavigate: () => void
}

export const VenueCTA: FunctionComponent<Props> = ({ venue }) => {
const searchNavConfig = useNavigateToSearchWithVenueOffers(venue)
export const VenueCTA: FunctionComponent<Props> = ({ searchNavConfig, onBeforeNavigate }) => {
return (
<StickyBottomWrapper>
<CallToActionContainer>
<Spacer.Column numberOfSpaces={6} />
<InternalTouchableLink
navigateTo={searchNavConfig}
onBeforeNavigate={() => analytics.logVenueSeeAllOffersClicked(venue.id)}
onBeforeNavigate={onBeforeNavigate}
as={ButtonPrimary}
wording="Rechercher une offre"
icon={SmallMagnifyingGlass}
Expand Down
Loading

0 comments on commit 85b6e7d

Please sign in to comment.