@andreasnicolaou/overpass-client
Version:
A wrapper for the Overpass API to query OpenStreetMap data.
158 lines (157 loc) • 5.84 kB
JavaScript
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { take, tap } from 'rxjs/operators';
import { OverpassClient } from './index';
describe('OverpassClient', () => {
let axiosMockAdapter;
let overpassClient;
beforeEach(() => {
axiosMockAdapter = new MockAdapter(axios);
overpassClient = new OverpassClient('http://test-overpass-api', 'json', 60, 2);
// eslint-disable-next-line @typescript-eslint/no-empty-function
jest.spyOn(console, 'warn').mockImplementation(() => { }); // Disable console warnings
});
afterEach(() => {
axiosMockAdapter.reset();
jest.restoreAllMocks();
});
test('should successfully fetch a node', (done) => {
const mockData = { elements: [{ id: 123, type: 'node', lat: 48.85, lon: 2.35 }] };
axiosMockAdapter.onPost('').reply(200, mockData);
overpassClient
.getElement('node', 123)
.pipe(take(1))
.subscribe({
next: (data) => {
expect(data).toEqual(mockData);
done();
},
error: done.fail,
});
});
test('should handle API failure and retry', (done) => {
axiosMockAdapter.onPost('').reply(500);
overpassClient
.getElement('node', 123)
.pipe(take(1))
.subscribe({
next: () => done.fail(new Error('Expected an error, but got success')),
error: (err) => {
expect(err).toBeDefined();
expect(err.message).toContain('Max retries exceeded');
done();
},
});
});
test('should fetch cafe amenities by bounding box', (done) => {
const mockData = { elements: [{ id: 1, type: 'node', lat: 48.85, lon: 2.35, tags: { amenity: 'cafe' } }] };
axiosMockAdapter.onPost('').reply(200, mockData);
overpassClient
.getElementsByBoundingBox({ amenity: ['cafe'] }, [48.85, 2.29, 48.87, 2.35])
.pipe(take(1))
.subscribe({
next: (data) => {
expect(data).toEqual(mockData);
done();
},
error: done.fail,
});
});
test('should fetch restaurant amenities by radius', (done) => {
const mockData = { elements: [{ id: 2, type: 'node', lat: 48.85, lon: 2.35, tags: { amenity: 'restaurant' } }] };
axiosMockAdapter.onPost('').reply(200, mockData);
overpassClient
.getElementsByRadius({ amenity: ['restaurant'] }, 48.85, 2.35, 500)
.pipe(take(1))
.subscribe({
next: (data) => {
expect(data).toEqual(mockData);
done();
},
error: done.fail,
});
});
test('should successfully fetch a way', (done) => {
const mockData = { elements: [{ id: 456, type: 'way', nodes: [1, 2, 3] }] };
axiosMockAdapter.onPost('').reply(200, mockData);
overpassClient
.getElement('way', 456)
.pipe(take(1))
.subscribe({
next: (data) => {
expect(data).toEqual(mockData);
done();
},
error: done.fail,
});
});
test('should handle invalid query format (400)', (done) => {
axiosMockAdapter.onPost('').reply(400, { error: 'Bad query format' });
overpassClient
.getElement('node', 123)
.pipe(take(1))
.subscribe({
next: () => done.fail(new Error('Expected an error, but got success')),
error: (err) => {
expect(err).toBeDefined();
expect(err.message).toContain('Overpass Error');
done();
},
});
});
test('should not retry on success', (done) => {
const mockData = { elements: [{ id: 123, type: 'node', lat: 48.85, lon: 2.35 }] };
const spy = jest.fn();
axiosMockAdapter.onPost('').reply(200, mockData);
overpassClient
.getElement('node', 123)
.pipe(take(1), tap(spy))
.subscribe({
next: (data) => {
expect(data).toEqual(mockData);
expect(spy).toHaveBeenCalledTimes(1);
done();
},
error: done.fail,
});
});
test('should retry on failure with exponential backoff', (done) => {
const mockData = { elements: [{ id: 123, type: 'node', lat: 48.85, lon: 2.35 }] };
const spy = jest.fn();
axiosMockAdapter.onPost('').replyOnce(429);
axiosMockAdapter.onPost('').reply(200, mockData);
overpassClient
.getElement('node', 123)
.pipe(take(1), tap(spy))
.subscribe({
next: (data) => {
expect(data).toEqual(mockData);
expect(spy).toHaveBeenCalledTimes(1);
done();
},
error: done.fail,
});
});
test('should return cached data for repeated requests', (done) => {
const mockData = { elements: [{ id: 123, type: 'node', lat: 48.85, lon: 2.35 }] };
axiosMockAdapter.onPost('').reply(200, mockData);
overpassClient
.getElement('node', 123)
.pipe(take(1))
.subscribe({
next: () => {
overpassClient
.getElement('node', 123)
.pipe(take(1))
.subscribe({
next: (cachedData) => {
expect(cachedData).toEqual(mockData);
done();
},
error: done.fail,
});
},
error: done.fail,
});
});
});