mirror of
https://github.com/umami-software/umami.git
synced 2025-12-08 05:12:36 +01:00
Fix #3624: Add IPv6 support tests for location detection
This commit is contained in:
parent
132b18affa
commit
b4599e78b2
1 changed files with 121 additions and 133 deletions
|
|
@ -1,146 +1,134 @@
|
|||
import { getLocation } from '../detect';
|
||||
import isLocalhost from 'is-localhost-ip';
|
||||
import maxmind from 'maxmind';
|
||||
/**
|
||||
* @jest-environment node
|
||||
*/
|
||||
import { getClientInfo, getLocation } from '@/lib/detect';
|
||||
import { getIpAddress } from '@/lib/ip';
|
||||
|
||||
// Mock the dependencies
|
||||
jest.mock('is-localhost-ip', () => jest.fn());
|
||||
jest.mock('maxmind', () => ({
|
||||
open: jest.fn(),
|
||||
}));
|
||||
jest.mock('is-localhost-ip');
|
||||
jest.mock('maxmind');
|
||||
jest.mock('@/lib/ip');
|
||||
|
||||
describe('getLocation', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
delete global.maxmind;
|
||||
});
|
||||
const isLocalhost = (isLocalhost as jest.Mock).mockResolvedValue(false);
|
||||
const maxmind = (maxmind as jest.Mock);
|
||||
const getIpAddressMock = (getIpAddress as jest.Mock).mockReturnValue('127.0.0.1');
|
||||
|
||||
it('should return null for localhost IPs', async () => {
|
||||
(isLocalhost as jest.Mock).mockResolvedValue(true);
|
||||
|
||||
const result = await getLocation('127.0.0.1', new Headers(), false);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
describe('lib/detect', () => {
|
||||
describe('getClientInfo', () => {
|
||||
it('should return client info', async () => {
|
||||
const request = new Request('https://example.com');
|
||||
const payload = {};
|
||||
|
||||
it('should return location data from provider headers', async () => {
|
||||
(isLocalhost as jest.Mock).mockResolvedValue(false);
|
||||
|
||||
const headers = new Headers();
|
||||
headers.set('cf-ipcountry', 'KR');
|
||||
headers.set('cf-region-code', '11');
|
||||
headers.set('cf-ipcity', 'Seoul');
|
||||
|
||||
const result = await getLocation('1.2.3.4', headers, false);
|
||||
|
||||
expect(result).toEqual({
|
||||
country: 'KR',
|
||||
region: 'KR-11',
|
||||
city: 'Seoul',
|
||||
const result = await getClientInfo(request, payload);
|
||||
|
||||
expect(result).toEqual({
|
||||
userAgent: null,
|
||||
browser: null,
|
||||
os: null,
|
||||
ip: '127.0.0.1',
|
||||
country: undefined,
|
||||
region: undefined,
|
||||
city: undefined,
|
||||
device: 'desktop',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return location data from MaxMind database', async () => {
|
||||
(isLocalhost as jest.Mock).mockResolvedValue(false);
|
||||
|
||||
const mockMaxmindDb = {
|
||||
get: jest.fn().mockReturnValue({
|
||||
country: { iso_code: 'KR' },
|
||||
subdivisions: [{ iso_code: '11' }],
|
||||
city: { names: { en: 'Seoul' } },
|
||||
}),
|
||||
};
|
||||
|
||||
(maxmind.open as jest.Mock).mockResolvedValue(mockMaxmindDb);
|
||||
|
||||
const result = await getLocation('1.2.3.4', new Headers(), false);
|
||||
|
||||
expect(result).toEqual({
|
||||
country: 'KR',
|
||||
region: 'KR-11',
|
||||
city: 'Seoul',
|
||||
});
|
||||
});
|
||||
describe('getLocation', () => {
|
||||
it('should return null for localhost', async () => {
|
||||
isLocalhost.mockResolvedValueOnce(true);
|
||||
|
||||
it('should try multiple sources for country code', async () => {
|
||||
(isLocalhost as jest.Mock).mockResolvedValue(false);
|
||||
|
||||
const mockMaxmindDb = {
|
||||
get: jest.fn().mockReturnValue({
|
||||
registered_country: { iso_code: 'KR' },
|
||||
subdivisions: [{ iso_code: '11' }],
|
||||
city: { names: { en: 'Seoul' } },
|
||||
}),
|
||||
};
|
||||
|
||||
(maxmind.open as jest.Mock).mockResolvedValue(mockMaxmindDb);
|
||||
|
||||
const result = await getLocation('1.2.3.4', new Headers(), false);
|
||||
|
||||
expect(result).toEqual({
|
||||
country: 'KR',
|
||||
region: 'KR-11',
|
||||
city: 'Seoul',
|
||||
});
|
||||
});
|
||||
const result = await getLocation('127.0.0.1', new Headers(), false);
|
||||
|
||||
it('should return null if no country code is available', async () => {
|
||||
(isLocalhost as jest.Mock).mockResolvedValue(false);
|
||||
|
||||
const mockMaxmindDb = {
|
||||
get: jest.fn().mockReturnValue({
|
||||
// No country information
|
||||
subdivisions: [{ iso_code: '11' }],
|
||||
city: { names: { en: 'Seoul' } },
|
||||
}),
|
||||
};
|
||||
|
||||
(maxmind.open as jest.Mock).mockResolvedValue(mockMaxmindDb);
|
||||
|
||||
const result = await getLocation('1.2.3.4', new Headers(), false);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should handle errors gracefully', async () => {
|
||||
(isLocalhost as jest.Mock).mockResolvedValue(false);
|
||||
|
||||
(maxmind.open as jest.Mock).mockRejectedValue(new Error('Database error'));
|
||||
|
||||
const result = await getLocation('1.2.3.4', new Headers(), false);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should handle IPv6 addresses correctly', async () => {
|
||||
(isLocalhost as jest.Mock).mockResolvedValue(false);
|
||||
|
||||
const mockMaxmindDb = {
|
||||
get: jest.fn().mockReturnValue({
|
||||
country: { iso_code: 'US' },
|
||||
subdivisions: [{ iso_code: 'CA' }],
|
||||
city: { names: { en: 'Los Angeles' } },
|
||||
}),
|
||||
};
|
||||
|
||||
(maxmind.open as jest.Mock).mockResolvedValue(mockMaxmindDb);
|
||||
|
||||
// Test IPv6 with port
|
||||
const result1 = await getLocation('[2001:db8::1]:8080', new Headers(), false);
|
||||
expect(result1).toEqual({
|
||||
country: 'US',
|
||||
region: 'US-CA',
|
||||
city: 'Los Angeles',
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
// Test IPv6 without port
|
||||
const result2 = await getLocation('2001:db8::1', new Headers(), false);
|
||||
expect(result2).toEqual({
|
||||
country: 'US',
|
||||
region: 'US-CA',
|
||||
city: 'Los Angeles',
|
||||
|
||||
it('should return null when no location data is available', async () => {
|
||||
isLocalhost.mockResolvedValueOnce(false);
|
||||
maxmind.open = jest.fn().mockResolvedValue({
|
||||
get: jest.fn().mockReturnValue(null),
|
||||
});
|
||||
|
||||
const result = await getLocation('8.8.8.8', new Headers(), false);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should return location data from provider headers', async () => {
|
||||
isLocalhost.mockResolvedValueOnce(false);
|
||||
|
||||
const headers = new Headers();
|
||||
headers.set('cf-ipcountry', 'US');
|
||||
headers.set('cf-region-code', 'CA');
|
||||
headers.set('cf-ipcity', 'Los Angeles');
|
||||
|
||||
const result = await getLocation('8.8.8.8', headers, false);
|
||||
|
||||
expect(result).toEqual({
|
||||
country: 'US',
|
||||
region: 'US-CA',
|
||||
city: 'Los Angeles',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return location data from database', async () => {
|
||||
isLocalhost.mockResolvedValueOnce(false);
|
||||
maxmind.open = jest.fn().mockResolvedValue({
|
||||
get: jest.fn().mockReturnValue({
|
||||
country: { iso_code: 'US' },
|
||||
subdivisions: [{ iso_code: 'CA' }],
|
||||
city: { names: { en: 'Los Angeles' } },
|
||||
}),
|
||||
});
|
||||
|
||||
const result = await getLocation('8.8.8.8', new Headers(), false);
|
||||
|
||||
expect(result).toEqual({
|
||||
country: 'US',
|
||||
region: 'US-CA',
|
||||
city: 'Los Angeles',
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle IPv6 addresses correctly', async () => {
|
||||
(isLocalhost as jest.Mock).mockResolvedValue(false);
|
||||
|
||||
const mockMaxmindDb = {
|
||||
get: jest.fn().mockReturnValue({
|
||||
country: { iso_code: 'US' },
|
||||
subdivisions: [{ iso_code: 'CA' }],
|
||||
city: { names: { en: 'Los Angeles' } },
|
||||
}),
|
||||
};
|
||||
|
||||
(maxmind.open as jest.Mock).mockResolvedValue(mockMaxmindDb);
|
||||
|
||||
// Test IPv6 with port
|
||||
const result1 = await getLocation('[2001:db8::1]:8080', new Headers(), false);
|
||||
expect(result1).toEqual({
|
||||
country: 'US',
|
||||
region: 'US-CA',
|
||||
city: 'Los Angeles',
|
||||
});
|
||||
|
||||
// Test IPv6 without port
|
||||
const result2 = await getLocation('2001:db8::1', new Headers(), false);
|
||||
expect(result2).toEqual({
|
||||
country: 'US',
|
||||
region: 'US-CA',
|
||||
city: 'Los Angeles',
|
||||
});
|
||||
|
||||
// Verify that the MaxMind database is called with the cleaned IP
|
||||
expect(mockMaxmindDb.get).toHaveBeenCalledWith('2001:db8::1');
|
||||
});
|
||||
|
||||
it('should handle errors gracefully', async () => {
|
||||
isLocalhost.mockResolvedValueOnce(false);
|
||||
maxmind.open = jest.fn().mockRejectedValue(new Error('Database error'));
|
||||
|
||||
const result = await getLocation('8.8.8.8', new Headers(), false);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
// Verify that the MaxMind database is called with the cleaned IP
|
||||
expect(mockMaxmindDb.get).toHaveBeenCalledWith('2001:db8::1');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue