@@ -41,84 +41,93 @@ test("map loads and Zurich meetup link works", async ({ page }) => {
4141 expect ( newPage . url ( ) ) . toContain ( "meetup.com/graphql-zurich" )
4242} )
4343
44- test ( "map tooltip appears on marker hover" , async ( { page } ) => {
45- await page . goto ( "/community/events" )
46- const mapCanvas = page . locator ( "canvas" ) . first ( )
47- await expect ( mapCanvas ) . toBeVisible ( { timeout : 10000 } )
48- await expect
49- . poll ( async ( ) => {
50- const box = await mapCanvas . boundingBox ( )
51- return Boolean ( box && box . width > 100 && box . height > 100 )
44+ test (
45+ "map tooltip appears on marker hover" ,
46+ async ( { page } ) => {
47+ await page . goto ( "/community/events" )
48+ const mapCanvas = page . locator ( "canvas" ) . first ( )
49+ await expect ( mapCanvas ) . toBeVisible ( { timeout : 10000 } )
50+ await expect
51+ . poll ( async ( ) => {
52+ const box = await mapCanvas . boundingBox ( )
53+ return Boolean ( box && box . width > 100 && box . height > 100 )
54+ } )
55+ . toBe ( true )
56+ const tooltip = page . getByRole ( "tooltip" )
57+ await expect ( tooltip ) . toHaveCount ( 0 )
58+ await mapCanvas . hover ( )
59+ const { clientX, clientY } = await page . evaluate ( ( ) => {
60+ const canvas = document . querySelector (
61+ "canvas" ,
62+ ) as HTMLCanvasElement | null
63+ if ( ! canvas ) throw new Error ( "Canvas not found" )
64+ const targetLat = 51.51
65+ const targetLon = - 0.12
66+ const aspectRatio = 1.65
67+ const cellSize = 8
68+ const mercatorLimit = 85.05112878
69+ const minDisplayedLatitude = - 60
70+ const baseLatitudeOffset = 4
71+ const baseLongitudeOffset = 0.1
72+ const clamp01 = ( value : number ) => {
73+ if ( value <= 0 ) return 0
74+ if ( value >= 1 ) return 1
75+ return value
76+ }
77+ const normalizeLongitude = ( value : number ) => {
78+ let lon = value
79+ while ( lon <= - 180 ) lon += 360
80+ while ( lon > 180 ) lon -= 360
81+ return lon
82+ }
83+ const latToRawV = ( lat : number ) => {
84+ const clampedLat = Math . max (
85+ - mercatorLimit ,
86+ Math . min ( mercatorLimit , lat ) ,
87+ )
88+ const rad = ( clampedLat * Math . PI ) / 180
89+ return (
90+ 0.5 - Math . log ( Math . tan ( Math . PI * 0.25 + rad * 0.5 ) ) / ( 2 * Math . PI )
91+ )
92+ }
93+ const maxProjectedV = latToRawV ( mercatorLimit )
94+ const minProjectedV = latToRawV ( minDisplayedLatitude )
95+ const lonLatToUV = ( lon : number , lat : number ) => {
96+ const adjustedLon = normalizeLongitude ( lon + baseLongitudeOffset )
97+ const u = ( adjustedLon + 180 ) / 360
98+ const adjustedLat = Math . max (
99+ minDisplayedLatitude ,
100+ Math . min ( mercatorLimit , lat + baseLatitudeOffset ) ,
101+ )
102+ const rawV = latToRawV ( adjustedLat )
103+ const normalizedV = clamp01 (
104+ ( rawV - maxProjectedV ) / ( minProjectedV - maxProjectedV ) ,
105+ )
106+ return [ u , normalizedV ] as const
107+ }
108+ const { width, height } = canvas
109+ const pixelRatio = window . devicePixelRatio || 1
110+ const worldHeight = Math . min ( width / aspectRatio , height )
111+ const worldWidth = worldHeight * aspectRatio
112+ const panX = width * 0.5 - worldWidth * 0.5
113+ const panY = height * 0.5 - worldHeight * 0.5
114+ const [ u , v ] = lonLatToUV ( targetLon , targetLat )
115+ const markerY = 1 - v
116+ const screenX = panX + u * worldWidth
117+ const screenY = panY + markerY * worldHeight
118+ const deviceCell = cellSize * pixelRatio
119+ const cellX = Math . floor ( screenX / deviceCell )
120+ const cellY = Math . floor ( screenY / deviceCell )
121+ const centerX = ( cellX + 0.5 ) * deviceCell
122+ const centerY = ( cellY + 0.5 ) * deviceCell
123+ const rect = canvas . getBoundingClientRect ( )
124+ const clientX = rect . left + centerX / pixelRatio
125+ const clientY = rect . bottom - centerY / pixelRatio
126+ return { clientX, clientY }
52127 } )
53- . toBe ( true )
54- const tooltip = page . getByRole ( "tooltip" )
55- await expect ( tooltip ) . toHaveCount ( 0 )
56- await mapCanvas . hover ( )
57- const { clientX, clientY } = await page . evaluate ( ( ) => {
58- const canvas = document . querySelector ( "canvas" ) as HTMLCanvasElement | null
59- if ( ! canvas ) throw new Error ( "Canvas not found" )
60- const targetLat = 51.51
61- const targetLon = - 0.12
62- const aspectRatio = 1.65
63- const cellSize = 8
64- const mercatorLimit = 85.05112878
65- const minDisplayedLatitude = - 60
66- const baseLatitudeOffset = 4
67- const baseLongitudeOffset = 0.1
68- const clamp01 = ( value : number ) => {
69- if ( value <= 0 ) return 0
70- if ( value >= 1 ) return 1
71- return value
72- }
73- const normalizeLongitude = ( value : number ) => {
74- let lon = value
75- while ( lon <= - 180 ) lon += 360
76- while ( lon > 180 ) lon -= 360
77- return lon
78- }
79- const latToRawV = ( lat : number ) => {
80- const clampedLat = Math . max ( - mercatorLimit , Math . min ( mercatorLimit , lat ) )
81- const rad = ( clampedLat * Math . PI ) / 180
82- return (
83- 0.5 - Math . log ( Math . tan ( Math . PI * 0.25 + rad * 0.5 ) ) / ( 2 * Math . PI )
84- )
85- }
86- const maxProjectedV = latToRawV ( mercatorLimit )
87- const minProjectedV = latToRawV ( minDisplayedLatitude )
88- const lonLatToUV = ( lon : number , lat : number ) => {
89- const adjustedLon = normalizeLongitude ( lon + baseLongitudeOffset )
90- const u = ( adjustedLon + 180 ) / 360
91- const adjustedLat = Math . max (
92- minDisplayedLatitude ,
93- Math . min ( mercatorLimit , lat + baseLatitudeOffset ) ,
94- )
95- const rawV = latToRawV ( adjustedLat )
96- const normalizedV = clamp01 (
97- ( rawV - maxProjectedV ) / ( minProjectedV - maxProjectedV ) ,
98- )
99- return [ u , normalizedV ] as const
100- }
101- const { width, height } = canvas
102- const pixelRatio = window . devicePixelRatio || 1
103- const worldHeight = Math . min ( width / aspectRatio , height )
104- const worldWidth = worldHeight * aspectRatio
105- const panX = width * 0.5 - worldWidth * 0.5
106- const panY = height * 0.5 - worldHeight * 0.5
107- const [ u , v ] = lonLatToUV ( targetLon , targetLat )
108- const markerY = 1 - v
109- const screenX = panX + u * worldWidth
110- const screenY = panY + markerY * worldHeight
111- const deviceCell = cellSize * pixelRatio
112- const cellX = Math . floor ( screenX / deviceCell )
113- const cellY = Math . floor ( screenY / deviceCell )
114- const centerX = ( cellX + 0.5 ) * deviceCell
115- const centerY = ( cellY + 0.5 ) * deviceCell
116- const rect = canvas . getBoundingClientRect ( )
117- const clientX = rect . left + centerX / pixelRatio
118- const clientY = rect . bottom - centerY / pixelRatio
119- return { clientX, clientY }
120- } )
121- await page . mouse . move ( clientX , clientY )
122- await expect ( tooltip ) . toHaveText ( "London GraphQL" , { timeout : 5000 } )
123- await expect ( tooltip ) . toBeVisible ( )
124- } )
128+ await page . mouse . move ( clientX , clientY )
129+ await expect ( tooltip ) . toHaveText ( "London GraphQL" , { timeout : 5000 } )
130+ await expect ( tooltip ) . toBeVisible ( )
131+ } ,
132+ { timeout : 60_000 } ,
133+ )
0 commit comments