Skip to content

Commit

Permalink
fix: Marker click bug (#208)
Browse files Browse the repository at this point in the history
  • Loading branch information
ccallendar authored Aug 1, 2024
1 parent 48c6b01 commit 95333e7
Show file tree
Hide file tree
Showing 24 changed files with 408 additions and 38 deletions.
2 changes: 1 addition & 1 deletion frontend/src/components/DataLayersToggleGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react'
import { useState } from 'react'
import {
Button,
Checkbox,
Expand Down
1 change: 0 additions & 1 deletion frontend/src/components/Footer.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react'
import { screen } from '@testing-library/react'

import { render } from '@/test-utils'
Expand Down
1 change: 0 additions & 1 deletion frontend/src/components/LocationIconButton.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react'
import { screen } from '@testing-library/react'
import { LatLngTuple } from 'leaflet'

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/SearchByRadioGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ChangeEvent } from 'react'
import { ChangeEvent } from 'react'
import { useDispatch } from 'react-redux'
import { FormControlLabel, Radio, RadioGroup } from '@mui/material'
import { RadioGroupProps } from '@mui/material/RadioGroup/RadioGroup'
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/components/SearchInput.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React, { MouseEventHandler } from 'react'
import { MouseEventHandler } from 'react'
import { IconButton, InputAdornment, TextField } from '@mui/material'
import { TextFieldProps } from '@mui/material/TextField/TextField'
import clsx from 'clsx'

import { LocationIconButton } from './LocationIconButton'

import SearchIcon from '@/assets/svgs/fa-search.svg?react'
import CloseIcon from '@/assets/svgs/fa-close.svg?react'

import './SearchInput.css'
import { LocationIconButton } from '@/components/LocationIconButton'

interface Props extends Omit<TextFieldProps, 'variant'> {
showSearchIcon?: boolean
Expand Down
7 changes: 0 additions & 7 deletions frontend/src/features/omrr/omrr-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,6 @@ export const useHasSearchTextFilter = () =>
useSearchTextFilter().length >= MIN_SEARCH_LENGTH

export const selectAllResults = (state: RootState) => state.omrr.allResults
const selectAllResultsCount = (state: RootState) => state.omrr.allResults.length

export const selectFilteredResults = (state: RootState) =>
state.omrr.filteredResults
Expand Down Expand Up @@ -267,12 +266,6 @@ export const useFindByAuthorizationNumber = (
return undefined
}

export const useAllResultsShowing = () => {
const allResultsCount = useSelector(selectAllResultsCount)
const filteredResultsCount = useSelector(selectFilteredResultsCount)
return filteredResultsCount === allResultsCount
}

const selectLastSearchTime = (state: RootState) => state.omrr.lastSearchTime
export const useLastSearchTime = () => useSelector(selectLastSearchTime)

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/hooks/useSwipe.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef } from 'react'
import { useRef } from 'react'
import { fireEvent, render, screen } from '@testing-library/react'

import { SwipeCallback, useSwipe } from './useSwipe'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect } from 'react'
import { useEffect } from 'react'
import { useNavigate } from 'react-router'
import { useParams } from 'react-router-dom'
import { Grid, Stack, Typography } from '@mui/material'
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/authorizationDetails/DetailsSection.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ReactNode } from 'react'
import { ReactNode } from 'react'
import { Grid, Stack, Typography } from '@mui/material'

import OmrrData from '@/interfaces/omrr'
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/authorizationList/ListSearchInput.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ChangeEvent } from 'react'
import { ChangeEvent } from 'react'
import { useDispatch } from 'react-redux'

import {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/pages/authorizationList/ListSearchSection.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { useState } from 'react'
import { useState } from 'react'
import { Box, Button } from '@mui/material'
import { ArrowDropDown, ArrowDropUp } from '@mui/icons-material'
import clsx from 'clsx'

import { FilterByCheckboxGroup } from '@/components/FilterByCheckboxGroup'
import { ListSearchInput } from './ListSearchInput'
import { ListSearchByGroup } from './ListSearchByGroup'
import { FilterByCheckboxGroup } from '@/components/FilterByCheckboxGroup'
import clsx from 'clsx'

const styles = {
searchByRow: {
Expand Down
1 change: 0 additions & 1 deletion frontend/src/pages/contactUs/ContactUs.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react'
import { screen } from '@testing-library/react'

import { render } from '@/test-utils'
Expand Down
1 change: 0 additions & 1 deletion frontend/src/pages/guidance/GuidancePage.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react'
import { screen } from '@testing-library/react'

import { DATA_LAYER_GROUPS } from '@/constants/data-layers'
Expand Down
17 changes: 13 additions & 4 deletions frontend/src/pages/map/MapView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('Test suite for MapView', () => {
})
}
it('should render the MapView with markers', async () => {
renderComponent(themeBreakpointValues.xxl)
const { user } = renderComponent(themeBreakpointValues.xxl)

const mapView = screen.getByTestId('map-view')
expect(mapView).not.toHaveClass('map-view--small')
Expand All @@ -43,11 +43,20 @@ describe('Test suite for MapView', () => {
expect(markers.length > 0).toBe(true)

screen.getByPlaceholderText('Search')
screen.getByRole('button', { name: 'Find Me' })
await screen.findByRole('button', { name: 'Find Me' })
expect(screen.queryByTitle('Show the data layers')).not.toBeInTheDocument()
expect(
screen.queryByTitle('Show my location on the map'),
).not.toBeInTheDocument()

const showResults = screen.getByRole('button', { name: 'Show Results' })
await user.click(showResults)

const zoomToBtn = screen.getByRole('button', { name: 'Zoom To Results' })
await user.click(zoomToBtn)

const hideResults = screen.getByRole('button', { name: 'Hide Results' })
await user.click(hideResults)
})

it('should render the MapView with no markers on a small screen', async () => {
Expand Down Expand Up @@ -140,10 +149,10 @@ describe('Test suite for MapView', () => {
it('should render the MapView and test polygon search', async () => {
const { user } = renderComponent(themeBreakpointValues.xxl, mockOmrrData)

const pointSearchBtn = screen.getByRole('button', {
const polygonSearchBtn = screen.getByRole('button', {
name: 'Polygon Search',
})
await user.click(pointSearchBtn)
await user.click(polygonSearchBtn)

const cancelBtn = screen.getByRole('button', { name: 'Cancel' })
const deleteBtn = screen.getByRole('button', { name: 'Delete Last Point' })
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/pages/map/hooks/useSetSelectedItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useDispatch } from 'react-redux'
import OmrrData from '@/interfaces/omrr'
import { setSelectedItem } from '@/features/map/map-slice'
import { useZoomToAuthorization } from './useZoomTo'
import { isTest } from '@/constants/env'

/**
* Selects a single OmrrData item.
Expand All @@ -20,7 +21,7 @@ export function useSetSelectedItem() {
dispatch(setSelectedItem(item))
// Make sure this item is visible on the map
// Delay the map zoom until the sidebar/bottom drawer finish expanding
zoomTo(item, 300)
zoomTo(item, isTest ? 0 : 300)
},
[dispatch],
)
Expand Down
16 changes: 7 additions & 9 deletions frontend/src/pages/map/layers/AuthorizationMarker.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import { Tooltip } from 'react-leaflet'

import OmrrData from '@/interfaces/omrr'
import { useSetSelectedItem } from '../hooks/useSetSelectedItem'
import { IconMarker } from './IconMarker'
import { blueIcon1x, blueIcon2x } from '@/constants/marker-icons'
import { IconMarker } from './IconMarker'

interface Props {
item: OmrrData
isSmall: boolean
onClick: () => void
}

export function AuthorizationMarker({ item, isSmall }: Readonly<Props>) {
const selectItem = useSetSelectedItem()

const onClick = () => {
selectItem(item)
}

export function AuthorizationMarker({
item,
isSmall,
onClick,
}: Readonly<Props>) {
const title = item['Regulated Party']
return (
<IconMarker
Expand Down
153 changes: 153 additions & 0 deletions frontend/src/pages/map/layers/AuthorizationMarkers.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { screen } from '@testing-library/react'
import { useSelector } from 'react-redux'

import { render } from '@/test-utils'
import {
initialState as initialOmrrState,
OmrrSliceState,
} from '@/features/omrr/omrr-slice'
import { mockOmrrData } from '@/mocks/mock-omrr-data'
import {
initialState as initialMapState,
MapSliceState,
selectZoomPosition,
useSelectedItem,
ZoomPosition,
} from '@/features/map/map-slice'
import OmrrData from '@/interfaces/omrr'
import { TestMapContainer } from './TestMapContainer'
import { AuthorizationMarkers } from './AuthorizationMarkers'
import { ActiveToolEnum, MIN_CIRCLE_RADIUS } from '@/constants/constants'

interface State {
selectedItem?: OmrrData
zoomPosition?: ZoomPosition
}

describe('Test suite for AuthorizationMarkers', () => {
function renderComponent(
omrrState: Partial<OmrrSliceState> = {},
mapState: Partial<MapSliceState> = {},
screenWidth = 1500,
) {
const state: State = {}

const TestComponent = () => {
Object.assign(state, {
selectedItem: useSelectedItem(),
zoomPosition: useSelector(selectZoomPosition),
})
return (
<TestMapContainer>
<AuthorizationMarkers />
</TestMapContainer>
)
}

const { user } = render(<TestComponent />, {
screenWidth,
withStateProvider: true,
initialState: {
omrr: {
...initialOmrrState,
status: 'succeeded',
filteredResults: mockOmrrData,
...omrrState,
},
map: {
...initialMapState,
...mapState,
},
},
})
return { user, state }
}

it('should not render AuthorizationMarkers if status is not succeeded', () => {
renderComponent({ status: 'failed' })
expect(
screen.queryByAltText('Authorization marker'),
).not.toBeInTheDocument()
})

it('should not render AuthorizationMarkers if no items', () => {
renderComponent({ filteredResults: [] })
expect(
screen.queryByAltText('Authorization marker'),
).not.toBeInTheDocument()
})

it('should render AuthorizationMarkers and click on marker', async () => {
const { user, state } = renderComponent()

const markers = screen.getAllByAltText('Authorization marker')
expect(markers).toHaveLength(mockOmrrData.length)

const [marker] = markers
await user.click(marker)

expect(state.selectedItem).toBe(mockOmrrData[0])
expect(state.zoomPosition).toBeDefined()
})

it('should render AuthorizationMarkers in polygon search mode and click on marker', async () => {
const { user, state } = renderComponent(
{},
{ activeTool: ActiveToolEnum.polygonSearch },
)

const markers = screen.getAllByAltText('Authorization marker')
const [marker] = markers
// Click is ignored when in polygon search mode
await user.click(marker)

expect(state.selectedItem).toBeUndefined()
})

it('should render AuthorizationMarkers in polygon search mode with positions', async () => {
const { user, state } = renderComponent(
{
polygonFilter: {
positions: [[48.123, -123.123]],
finished: false,
},
},
{ activeTool: ActiveToolEnum.polygonSearch },
)

const marker = screen.getAllByAltText('Authorization marker')[0]
expect(marker).toBeDefined()
await user.click(marker)

expect(state.selectedItem).toBeUndefined()
})

it('should render AuthorizationMarkers in point search mode and click on marker', async () => {
const { user, state } = renderComponent(
{},
{ activeTool: ActiveToolEnum.pointSearch },
)

const markers = screen.getAllByAltText('Authorization marker')
const [marker] = markers
await user.click(marker)

expect(state.selectedItem).toBeUndefined()
})

it('should render AuthorizationMarkers in point search mode with radius', async () => {
const { user, state } = renderComponent(
{
circleFilter: { radius: MIN_CIRCLE_RADIUS },
},
{ activeTool: ActiveToolEnum.pointSearch },
500,
)

const marker = screen.getAllByAltText('Authorization marker')[0]
expect(marker).toBeDefined()
await user.click(marker)

expect(state.selectedItem).toBeUndefined()
})
})
Loading

0 comments on commit 95333e7

Please sign in to comment.