Skip to content

mapbox component jest tests #311

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 4 commits into from
Oct 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/search-ui-react.mapboxmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ For the map to work properly, be sure to include Mapbox GL stylesheet in the app

For instance, user may add the following import statement in their application's index file or in the file where `MapboxMap` is used: `import 'mapbox-gl/dist/mapbox-gl.css';`

Or, user may add a stylesheet link in their html page: `<link href="https://api.mapbox.com/mapbox-gl-js/VERSION/mapbox-gl.css" rel="stylesheet">`
Or, user may add a stylesheet link in their html page: `<link href="https://api.mapbox.com/mapbox-gl-js/v2.9.2/mapbox-gl.css" rel="stylesheet" />`

2 changes: 1 addition & 1 deletion src/components/MapboxMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export interface MapboxMapProps<T> {
* `import 'mapbox-gl/dist/mapbox-gl.css';`
*
* Or, user may add a stylesheet link in their html page:
* `<link href="https://api.mapbox.com/mapbox-gl-js/VERSION/mapbox-gl.css" rel="stylesheet">`
* `<link href="https://api.mapbox.com/mapbox-gl-js/v2.9.2/mapbox-gl.css" rel="stylesheet" />`
*
* @param props - {@link MapboxMapProps}
* @returns A React element containing a Mapbox Map
Expand Down
114 changes: 114 additions & 0 deletions tests/components/MapboxMap.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { render } from '@testing-library/react';
import { mockAnswersState } from '../__utils__/mocks';
import { CoordinateGetter, MapboxMap, Coordinate } from '../../src/components/MapboxMap';
import { Source, State } from '@yext/search-headless-react';
import { Map, Marker } from 'mapbox-gl';

jest.mock('@yext/search-headless-react');
jest.mock('mapbox-gl');

interface Location {
customCoordinate: Coordinate
}

const mockedStateDefaultCoordinate: Partial<State> = {
vertical: {
verticalKey: 'vertical',
results: [{
rawData: {
yextDisplayCoordinate: {
latitude: 1,
longitude: 1
}
},
source: Source.KnowledgeManager
}]
}
};

const mockedStateCustomCoordinate: Partial<State> = {
vertical: {
verticalKey: 'vertical',
results: [{
rawData: {
customCoordinate: {
latitude: 2,
longitude: 2
}
},
source: Source.KnowledgeManager
}]
}
};

const mockedStateWrongCoordinateType: Partial<State> = {
vertical: {
verticalKey: 'vertical',
results: [{
rawData: {
yextDisplayCoordinate: [1, 1]
},
source: Source.KnowledgeManager
}]
}
};

describe('default "getCoordinate"', () => {
it('uses result\'s "yextDisplayCoordinate" for marker location', () => {
mockAnswersState(mockedStateDefaultCoordinate);
const setLngLat = jest.spyOn(Marker.prototype, 'setLngLat').mockReturnValue(Marker.prototype);
render(<MapboxMap mapboxAccessToken='TEST_KEY' />);
expect(setLngLat).toBeCalledWith({ lat: 1, lng: 1 });
});

it('displays an error when "yextDisplayCoordinate" field is not present in result', () => {
mockAnswersState(mockedStateCustomCoordinate);
const setLngLat = jest.spyOn(Marker.prototype, 'setLngLat').mockReturnValue(Marker.prototype);
const errorSpy = jest.spyOn(console, 'error').mockImplementation();
render(<MapboxMap mapboxAccessToken='TEST_KEY' />);
expect(errorSpy).toBeCalledTimes(1);
const expectedMessage = 'Unable to use the default "yextDisplayCoordinate" field as the result\'s coordinate';
expect(errorSpy).toBeCalledWith(expect.stringContaining(expectedMessage));
expect(setLngLat).not.toBeCalled();
});

it('displays an error when "yextDisplayCoordinate" field is not of type "Coordinate"', () => {
mockAnswersState(mockedStateWrongCoordinateType);
const setLngLat = jest.spyOn(Marker.prototype, 'setLngLat').mockReturnValue(Marker.prototype);
const errorSpy = jest.spyOn(console, 'error').mockImplementation();
render(<MapboxMap mapboxAccessToken='TEST_KEY' />);
expect(errorSpy).toBeCalledTimes(1);
const expectedMessage = 'The default `yextDisplayCoordinate` field from result is not of type "Coordinate".';
expect(errorSpy).toBeCalledWith(expect.stringContaining(expectedMessage));
expect(setLngLat).not.toBeCalled();
});
});

it('executes custom "getCoordinate" and use the derived coordinate for marker location', () => {
mockAnswersState(mockedStateCustomCoordinate);
const setLngLat = jest.spyOn(Marker.prototype, 'setLngLat').mockReturnValue(Marker.prototype);
const customGetCoordinate: CoordinateGetter<Location> = jest.fn().mockImplementation(
result => result.rawData.customCoordinate);

const errorSpy = jest.spyOn(console, 'error').mockImplementation();
render(<MapboxMap mapboxAccessToken='TEST_KEY' getCoordinate={customGetCoordinate} />);
expect(errorSpy).toBeCalledTimes(0);
expect(customGetCoordinate).toBeCalledTimes(1);
expect(setLngLat).toBeCalledWith({ lat: 2, lng: 2 });
});

it('registers "onDrag" callback to Mapbox\'s event listener for "drag to pan" interaction', () => {
jest.useFakeTimers();
jest.spyOn(Marker.prototype, 'setLngLat').mockReturnValue(Marker.prototype);
const mapOnEventListener = jest.spyOn(Map.prototype, 'on')
.mockImplementation((e, cb) => {
e === 'drag' && cb({});
return Map.prototype;
});
const onDragFn = jest.fn();
render(<MapboxMap mapboxAccessToken='TEST_KEY' onDrag={onDragFn} />);
expect(mapOnEventListener).toBeCalledWith('drag', expect.anything());
expect(onDragFn).toBeCalledTimes(0);
jest.advanceTimersByTime(100); //debounce time
expect(onDragFn).toBeCalledTimes(1);
});