@@ -4,9 +4,13 @@ import { InvitePage } from './InvitePage'
44const mockUseParams = jest . fn ( )
55const mockInviteHero = jest . fn ( )
66const mockFetch = jest . fn ( )
7+ const mockPage = jest . fn ( )
8+ let mockIsAnalyticsInitialized = true
9+ const INVITE_PATHNAME = '/invite/Brai'
710
811jest . mock ( 'react-router-dom' , ( ) => ( {
9- useParams : ( ) => mockUseParams ( )
12+ useParams : ( ) => mockUseParams ( ) ,
13+ useLocation : ( ) => ( { pathname : INVITE_PATHNAME } )
1014} ) )
1115
1216jest . mock ( 'decentraland-ui2' , ( ) => ( {
@@ -18,6 +22,7 @@ jest.mock('@dcl/hooks', () => {
1822 const ReactLib = require ( 'react' ) as typeof import ( 'react' )
1923 return {
2024 useTranslation : ( ) => ( { t : ( id : string ) => id } ) ,
25+ useAnalytics : ( ) => ( { isInitialized : mockIsAnalyticsInitialized , page : mockPage } ) ,
2126 useAsyncMemo : < T , > ( factory : ( ) => Promise < T > , deps : unknown [ ] ) => {
2227 const [ state , setState ] = ReactLib . useState < { value : T | null ; loading : boolean } > ( { value : null , loading : true } )
2328 ReactLib . useEffect ( ( ) => {
@@ -83,6 +88,12 @@ afterAll(() => {
8388 global . fetch = originalFetch
8489} )
8590
91+ // Reset the analytics-initialized flag before every test so a test that flips it
92+ // false doesn't leak into the next one.
93+ beforeEach ( ( ) => {
94+ mockIsAnalyticsInitialized = true
95+ } )
96+
8697describe ( 'when the referrer param is a Decentraland name' , ( ) => {
8798 beforeEach ( ( ) => {
8899 mockUseParams . mockReturnValue ( { referrer : 'Brai' } )
@@ -214,3 +225,70 @@ describe('when the referrer is empty', () => {
214225 expect ( mockFetch ) . not . toHaveBeenCalled ( )
215226 } )
216227} )
228+
229+ describe ( 'when tracking the invite pageview' , ( ) => {
230+ beforeEach ( ( ) => {
231+ mockUseParams . mockReturnValue ( { referrer : 'Brai' } )
232+ mockFetch . mockResolvedValue ( { json : ( ) => Promise . resolve ( null ) } )
233+ } )
234+
235+ afterEach ( ( ) => {
236+ jest . resetAllMocks ( )
237+ } )
238+
239+ it ( 'should fire a page() event for the invite path once analytics is initialized' , async ( ) => {
240+ render ( < InvitePage /> )
241+
242+ await waitFor ( ( ) => expect ( mockPage ) . toHaveBeenCalledWith ( INVITE_PATHNAME ) )
243+ expect ( mockPage ) . toHaveBeenCalledTimes ( 1 )
244+ } )
245+
246+ it ( 'should not fire page() before analytics is initialized' , async ( ) => {
247+ mockIsAnalyticsInitialized = false
248+ render ( < InvitePage /> )
249+
250+ await waitFor ( ( ) => expect ( mockInviteHero ) . toHaveBeenCalled ( ) )
251+ expect ( mockPage ) . not . toHaveBeenCalled ( )
252+ } )
253+ } )
254+
255+ describe ( 'when the document head already has meta tags' , ( ) => {
256+ const addMeta = ( attr : 'name' | 'property' , key : string , content : string ) => {
257+ const meta = document . createElement ( 'meta' )
258+ meta . setAttribute ( attr , key )
259+ meta . setAttribute ( 'content' , content )
260+ document . head . appendChild ( meta )
261+ return meta
262+ }
263+ let metaEls : HTMLMetaElement [ ] = [ ]
264+
265+ beforeEach ( ( ) => {
266+ mockUseParams . mockReturnValue ( { referrer : '' } )
267+ metaEls = [
268+ addMeta ( 'name' , 'description' , 'orig-desc' ) ,
269+ addMeta ( 'property' , 'og:title' , 'orig-og-title' ) ,
270+ addMeta ( 'property' , 'og:description' , 'orig-og-desc' )
271+ ]
272+ } )
273+
274+ afterEach ( ( ) => {
275+ metaEls . forEach ( el => el . remove ( ) )
276+ metaEls = [ ]
277+ jest . resetAllMocks ( )
278+ } )
279+
280+ it ( 'should set the invite meta on mount and restore the originals on unmount' , async ( ) => {
281+ const { unmount } = render ( < InvitePage /> )
282+ await waitFor ( ( ) => expect ( mockInviteHero ) . toHaveBeenCalled ( ) )
283+
284+ expect ( document . querySelector ( 'meta[name="description"]' ) ?. getAttribute ( 'content' ) ) . toBe ( 'page_invite.social.description' )
285+ expect ( document . querySelector ( 'meta[property="og:title"]' ) ?. getAttribute ( 'content' ) ) . toBe ( 'page_invite.social.title' )
286+ expect ( document . querySelector ( 'meta[property="og:description"]' ) ?. getAttribute ( 'content' ) ) . toBe ( 'page_invite.social.description' )
287+
288+ unmount ( )
289+
290+ expect ( document . querySelector ( 'meta[name="description"]' ) ?. getAttribute ( 'content' ) ) . toBe ( 'orig-desc' )
291+ expect ( document . querySelector ( 'meta[property="og:title"]' ) ?. getAttribute ( 'content' ) ) . toBe ( 'orig-og-title' )
292+ expect ( document . querySelector ( 'meta[property="og:description"]' ) ?. getAttribute ( 'content' ) ) . toBe ( 'orig-og-desc' )
293+ } )
294+ } )
0 commit comments