-
Notifications
You must be signed in to change notification settings - Fork 5
Core 1060 port separatemap page to ts #2766
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| import createMap from '~/pages/separatemap/map-api'; | ||
| import {waitFor} from '@testing-library/preact'; | ||
| import type {AugmentedInfo} from '~/models/query-schools'; | ||
|
|
||
| const triggers: Record<string, (el?: object) => void> = {}; | ||
| let mockLoaded: jest.Mock; | ||
| let mockResize: jest.Mock; | ||
| let mockSetFilter: jest.Mock; | ||
|
|
||
| jest.mock('~/models/mapbox', () => () => console.info('*** LOADED?')); | ||
| jest.mock('mapbox-gl', () => { | ||
| const functionWithThings = () => ({}); | ||
| const mockMap = { | ||
| on: (...args: unknown[]) => { | ||
| const fn = args.pop() as () => void; | ||
|
|
||
| (args as string[]).forEach((t) => { | ||
| triggers[t] = fn; | ||
| }); | ||
| }, | ||
| loaded: (mockLoaded = jest.fn().mockReturnValue(true)), | ||
| resize: (mockResize = jest.fn()), | ||
| getCanvas: () => ({style: {}}), | ||
| setFilter: (mockSetFilter = jest.fn()), | ||
| easeTo: jest.fn(), | ||
| fitBounds: jest.fn() | ||
| }; | ||
|
|
||
| functionWithThings.Map = jest.fn().mockReturnValue(mockMap); | ||
| functionWithThings.Popup = jest.fn().mockReturnValue({ | ||
| remove: jest.fn() | ||
| }); | ||
| functionWithThings.LngLatBounds = jest.fn().mockReturnValue({ | ||
| extend: jest.fn().mockReturnValue([0, 10]) | ||
| }); | ||
|
|
||
| return { | ||
| __esModule: true, | ||
| default: functionWithThings | ||
| }; | ||
| }); | ||
|
|
||
| describe('map-api', () => { | ||
| it('sets up event handlers', async () => { | ||
| const container = document.createElement('div'); | ||
| const {tooltip} = createMap({container}); | ||
|
|
||
| await waitFor(() => expect(triggers.load).toBeTruthy()); | ||
| triggers.load(); | ||
| expect(mockLoaded).toHaveBeenCalled(); | ||
| expect(mockResize).toHaveBeenCalled(); | ||
| triggers.mouseenter(); | ||
| triggers.mouseleave(); | ||
| triggers.click({}); | ||
| expect(tooltip.remove).toHaveBeenCalled(); | ||
| (tooltip.remove as jest.Mock).mockReset(); | ||
| triggers.click({features: true}); | ||
| expect(tooltip.remove).not.toHaveBeenCalled(); | ||
| }); | ||
| it('shows tooltip for school', async () => { | ||
| const container = document.createElement('div'); | ||
| const {loaded, tooltip, showTooltip} = createMap({container}); | ||
| const schoolInfo = { | ||
| lngLat: [1, 2], | ||
| fields: { | ||
| name: 'Test University' | ||
| }, | ||
| cityState: 'Smallville, KS' | ||
| } as unknown as AugmentedInfo; | ||
|
|
||
| await loaded; | ||
| tooltip.setLngLat = jest.fn(); | ||
| tooltip.setHTML = jest.fn(); | ||
| tooltip.addTo = jest.fn(); | ||
| showTooltip(schoolInfo); | ||
| expect(tooltip.setLngLat).toHaveBeenCalledWith(schoolInfo.lngLat); | ||
| expect(tooltip.setHTML).toHaveBeenCalledWith( | ||
| expect.stringContaining(schoolInfo.cityState) | ||
| ); | ||
| // Handles empty cityState | ||
| schoolInfo.cityState = ''; | ||
| showTooltip(schoolInfo); | ||
| expect(tooltip.setHTML).toHaveBeenCalledWith( | ||
| expect.not.stringMatching('<br>') | ||
| ); | ||
| // Does not display if no lngLat | ||
| jest.clearAllMocks(); | ||
| delete schoolInfo.lngLat; | ||
| showTooltip(schoolInfo); | ||
| expect(tooltip.setLngLat).not.toHaveBeenCalled(); | ||
| expect(tooltip.setHTML).not.toHaveBeenCalled(); | ||
| }); | ||
| it('shows points of schools', async () => { | ||
| const container = document.createElement('div'); | ||
| const {loaded, showPoints} = createMap({container}); | ||
| const schoolInfo = { | ||
| lngLat: [1, 2], | ||
| fields: { | ||
| name: 'Test University' | ||
| }, | ||
| cityState: 'Smallville, KS' | ||
| } as unknown as AugmentedInfo; | ||
|
|
||
| await loaded; | ||
| // Handles empty list (lnglat of 0, 0 gets filtered out) | ||
| showPoints([{...schoolInfo, lngLat: [0, 0]}]); | ||
| await waitFor(() => | ||
| expect(mockSetFilter).toHaveBeenCalledWith('os-schools', undefined) | ||
| ); | ||
| mockSetFilter.mockClear(); | ||
| // Non-empty | ||
| showPoints([schoolInfo]); | ||
| await waitFor(() => | ||
| expect(mockSetFilter).toHaveBeenCalledWith('os-schools', [ | ||
| 'in', | ||
| 'id', | ||
| undefined | ||
| ]) | ||
| ); | ||
| mockSetFilter.mockClear(); | ||
| }); | ||
| }); |
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test was subsumed by separatemap.test |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,202 @@ | ||
| import React from 'react'; | ||
| import {render, screen, waitFor} from '@testing-library/preact'; | ||
| import userEvent from '@testing-library/user-event'; | ||
| import SeparateMap from '~/pages/separatemap/separatemap'; | ||
| import * as DH from '~/helpers/use-document-head'; | ||
| import * as MD from '~/helpers/device'; | ||
|
|
||
| const mockMapbox = jest.fn(); | ||
| const mockQuerySchools = jest.fn(); | ||
| const mockQueryById = jest.fn(); | ||
| let mockOn: jest.Mock; | ||
| let mockRemove: jest.Mock; | ||
|
|
||
| jest.spyOn(DH, 'default').mockReturnValue(); | ||
| const mockIsMobileDisplay = jest | ||
| .spyOn(MD, 'isMobileDisplay') | ||
| .mockReturnValue(false); | ||
|
|
||
| jest.mock('~/models/mapbox', () => () => mockMapbox()); | ||
| jest.mock('mapbox-gl', () => { | ||
| const functionWithThings = () => ({}); | ||
|
|
||
| functionWithThings.Map = jest.fn().mockReturnValue({ | ||
| on: (mockOn = jest.fn()), | ||
| setFilter: jest.fn(), | ||
| fitBounds: jest.fn() | ||
| }); | ||
| functionWithThings.Popup = jest.fn().mockReturnValue({ | ||
| remove: (mockRemove = jest.fn()), | ||
| setLngLat: jest.fn(), | ||
| setHTML: jest.fn(), | ||
| addTo: jest.fn() | ||
| }); | ||
| functionWithThings.LngLatBounds = jest.fn().mockReturnValue({ | ||
| extend: jest.fn().mockReturnValue([0, 10]) | ||
| }); | ||
|
|
||
| return { | ||
| __esModule: true, | ||
| default: functionWithThings | ||
| }; | ||
| }); | ||
| jest.mock('~/models/query-schools', () => ({ | ||
| __esModule: true, | ||
| default: () => mockQuerySchools(), | ||
| queryById: () => mockQueryById() | ||
| })); | ||
| jest.mock('~/helpers/main-class-hooks', () => ({ | ||
| __esModule: true, | ||
| useMainModal: jest.fn() | ||
| })); | ||
|
|
||
| const aSchoolData = { | ||
| cityState: 'Pomfret, Maryland', | ||
| fields: { | ||
| // eslint-disable-next-line camelcase | ||
| salesforce_id: '0016f00002alpsuAAA', | ||
| name: 'Maurice J. McDonough High School', | ||
| phone: '(301) 934-2944', | ||
| website: 'https://www.ccboe.com/schools/mcdonough/', | ||
| type: 'High School' | ||
| }, | ||
| institutionType: 'High School', | ||
| institutionalPartner: false, | ||
| lngLat: [-77.034, 38.555], | ||
| pk: '656595', | ||
| testimonial: { | ||
| text: 'Good stuff', | ||
| name: 'Some Body', | ||
| position: 'Chief Example' | ||
| } | ||
| }; | ||
|
|
||
| describe('separatemap', () => { | ||
| const user = userEvent.setup(); | ||
|
|
||
| mockMapbox.mockResolvedValue({ | ||
| name: 'mock-schools', | ||
| style: 'mapbox-style' | ||
| }); | ||
| mockQuerySchools.mockResolvedValue({TOO_MANY: true}); | ||
|
|
||
| it('renders; popup dismisses', async () => { | ||
| render(<SeparateMap />); | ||
| await user.click( | ||
| await screen.findByRole('button', {name: 'close popup'}) | ||
| ); | ||
| expect(screen.queryByRole('button', {name: 'close popup'})).toBeNull(); | ||
| }); | ||
| it('handles school click', async () => { | ||
| mockOn.mockImplementation( | ||
| (eType: string, what: string, fn: (el: object) => void) => { | ||
| if (eType === 'click' && what === 'os-schools') { | ||
| fn({ | ||
| features: [ | ||
| { | ||
| properties: { | ||
| id: 1 | ||
| } | ||
| } | ||
| ] | ||
| }); | ||
| } | ||
| } | ||
| ); | ||
| mockQueryById.mockResolvedValue(null); | ||
| // cover mapZoom branch | ||
| mockIsMobileDisplay.mockReturnValue(true); | ||
| render(<SeparateMap />); | ||
| await waitFor(() => expect(mockQueryById).toHaveBeenCalled()); | ||
|
|
||
| const mapd = document.getElementById('mapd') as HTMLElement; | ||
|
|
||
| mapd.innerHTML = `<div class="mapboxgl-popup-content"> | ||
| <div class="put-away"> | ||
| <button>Test put-away</button> | ||
| </div> | ||
| </div>`; | ||
|
|
||
| await user.click(screen.getByRole('button', {name: 'Test put-away'})); | ||
| expect(mockRemove).toHaveBeenCalled(); | ||
| mockRemove.mockClear(); | ||
| await user.click(mapd); | ||
| expect(mockRemove).not.toHaveBeenCalled(); | ||
| }); | ||
| it('interacts with search box', async () => { | ||
| mockQuerySchools.mockResolvedValue([aSchoolData]); | ||
|
|
||
| render(<SeparateMap />); | ||
| const inputs = await screen.findAllByRole('textbox'); | ||
|
|
||
| await user.type(inputs[0], 'Test{enter}'); | ||
| await user.click(screen.getByRole('switch')); | ||
| }); | ||
| it('handles too many search results', async () => { | ||
| mockQuerySchools.mockResolvedValue({TOO_MANY: true}); | ||
|
|
||
| render(<SeparateMap />); | ||
| const inputs = await screen.findAllByRole('textbox'); | ||
|
|
||
| await user.type(inputs[0], 'Test{enter}'); | ||
| expect(screen.queryByRole('switch')).toBeNull(); | ||
| }); | ||
| it('handles filter checkboxes; school query returns no promise', async () => { | ||
| mockQueryById.mockClear(); | ||
| mockQuerySchools.mockReturnValue(null); | ||
| render(<SeparateMap />); | ||
| await screen.findAllByRole('textbox'); | ||
| await user.click(screen.getByRole('button', {name: 'Filter by'})); | ||
| await user.click(screen.getAllByRole('checkbox')[0]); | ||
| expect(mockQueryById).toHaveBeenCalledTimes(1); | ||
| // Exercises checkbox unselect code in filters.tsx | ||
| await user.click(screen.getAllByRole('checkbox')[0]); | ||
| // Exercise institution selector | ||
| const select = screen.getByRole('combobox'); | ||
|
|
||
| expect(select.textContent).toBe('Any'); | ||
| await user.click(select); | ||
| await user.click(screen.getByRole('option', {name: 'High School'})); | ||
| expect(select.textContent).toBe('High School'); | ||
| }); | ||
| it('handles school query returning no schools', async () => { | ||
| mockQuerySchools.mockResolvedValue([]); | ||
| mockQueryById.mockResolvedValue(null); | ||
| render(<SeparateMap />); | ||
| const inputs = await screen.findAllByRole('textbox'); | ||
|
|
||
| await user.type(inputs[0], 'Test{enter}'); | ||
| expect(screen.queryByRole('switch')).toBeNull(); | ||
| }); | ||
| it('handles school match and when all schools are filtered out', async () => { | ||
| mockQuerySchools.mockResolvedValue([aSchoolData]); | ||
| mockQueryById.mockResolvedValue(aSchoolData); | ||
| render(<SeparateMap />); | ||
| const inputs = await screen.findAllByRole('textbox'); | ||
|
|
||
| await user.type(inputs[0], 'Test{enter}'); | ||
| mockQuerySchools.mockResolvedValue([]); | ||
| // select/open/fly-to | ||
| await user.click(screen.getByRole('switch')); | ||
| await user.type(inputs[0], 'Oops{enter}'); | ||
| // unselect/close/fly-out-from | ||
| await user.click(screen.getByRole('switch')); | ||
| await user.click( | ||
| screen.getAllByRole('button', {name: 'clear search'})[0] | ||
| ); | ||
| // Clear search button goes away when search is cleared | ||
| expect(screen.queryByRole('button', {name: 'clear search'})).toBeNull(); | ||
| }); | ||
| it('toggles search window open/closed', async () => { | ||
| render(<SeparateMap />); | ||
| const toggle = screen.getAllByRole('button', { | ||
| name: 'toggle search window' | ||
| })[0]; | ||
|
|
||
| expect(toggle.getAttribute('aria-pressed')).toBe('false'); | ||
| await user.click(toggle); | ||
| expect(toggle.getAttribute('aria-pressed')).toBe('true'); | ||
| await user.click(toggle); | ||
| expect(toggle.getAttribute('aria-pressed')).toBe('false'); | ||
| }); | ||
| }); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test subsumed by new tests