mirror of
https://github.com/immich-app/immich.git
synced 2025-11-18 04:23:19 -05:00
* feat: private view * pr feedback * sql generation * feat: visibility column * fix: set visibility value as the same as the still part after unlinked live photos * fix: test * pr feedback
171 lines
6.0 KiB
TypeScript
171 lines
6.0 KiB
TypeScript
import { AssetVisibility, LoginResponseDto } from '@immich/sdk';
|
|
import { readFile } from 'node:fs/promises';
|
|
import { basename, join } from 'node:path';
|
|
import { Socket } from 'socket.io-client';
|
|
import { errorDto } from 'src/responses';
|
|
import { app, testAssetDir, utils } from 'src/utils';
|
|
import request from 'supertest';
|
|
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
|
|
describe('/map', () => {
|
|
let websocket: Socket;
|
|
let admin: LoginResponseDto;
|
|
|
|
beforeAll(async () => {
|
|
await utils.resetDatabase();
|
|
admin = await utils.adminSetup({ onboarding: false });
|
|
|
|
websocket = await utils.connectWebsocket(admin.accessToken);
|
|
|
|
const files = ['formats/heic/IMG_2682.heic', 'metadata/gps-position/thompson-springs.jpg'];
|
|
utils.resetEvents();
|
|
const uploadFile = async (input: string) => {
|
|
const filepath = join(testAssetDir, input);
|
|
const { id } = await utils.createAsset(admin.accessToken, {
|
|
assetData: { bytes: await readFile(filepath), filename: basename(filepath) },
|
|
});
|
|
await utils.waitForWebsocketEvent({ event: 'assetUpload', id });
|
|
};
|
|
await Promise.all(files.map((f) => uploadFile(f)));
|
|
});
|
|
|
|
afterAll(() => {
|
|
utils.disconnectWebsocket(websocket);
|
|
});
|
|
|
|
describe('GET /map/markers', () => {
|
|
it('should require authentication', async () => {
|
|
const { status, body } = await request(app).get('/map/markers');
|
|
expect(status).toBe(401);
|
|
expect(body).toEqual(errorDto.unauthorized);
|
|
});
|
|
|
|
// TODO archive one of these assets
|
|
it('should get map markers for all non-archived assets', async () => {
|
|
const { status, body } = await request(app)
|
|
.get('/map/markers')
|
|
.query({ visibility: AssetVisibility.Timeline })
|
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
|
|
expect(status).toBe(200);
|
|
expect(body).toHaveLength(2);
|
|
expect(body).toEqual([
|
|
{
|
|
city: 'Palisade',
|
|
country: 'United States of America',
|
|
id: expect.any(String),
|
|
lat: expect.closeTo(39.115),
|
|
lon: expect.closeTo(-108.400_968),
|
|
state: 'Colorado',
|
|
},
|
|
{
|
|
city: 'Ralston',
|
|
country: 'United States of America',
|
|
id: expect.any(String),
|
|
lat: expect.closeTo(41.2203),
|
|
lon: expect.closeTo(-96.071_625),
|
|
state: 'Nebraska',
|
|
},
|
|
]);
|
|
});
|
|
|
|
// TODO archive one of these assets
|
|
it('should get all map markers', async () => {
|
|
const { status, body } = await request(app)
|
|
.get('/map/markers')
|
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
|
|
expect(status).toBe(200);
|
|
expect(body).toEqual([
|
|
{
|
|
city: 'Palisade',
|
|
country: 'United States of America',
|
|
id: expect.any(String),
|
|
lat: expect.closeTo(39.115),
|
|
lon: expect.closeTo(-108.400_968),
|
|
state: 'Colorado',
|
|
},
|
|
{
|
|
city: 'Ralston',
|
|
country: 'United States of America',
|
|
id: expect.any(String),
|
|
lat: expect.closeTo(41.2203),
|
|
lon: expect.closeTo(-96.071_625),
|
|
state: 'Nebraska',
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('GET /map/reverse-geocode', () => {
|
|
it('should require authentication', async () => {
|
|
const { status, body } = await request(app).get('/map/reverse-geocode');
|
|
expect(status).toBe(401);
|
|
expect(body).toEqual(errorDto.unauthorized);
|
|
});
|
|
|
|
it('should throw an error if a lat is not provided', async () => {
|
|
const { status, body } = await request(app)
|
|
.get('/map/reverse-geocode?lon=123')
|
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
expect(status).toBe(400);
|
|
expect(body).toEqual(errorDto.badRequest(['lat must be a number between -90 and 90']));
|
|
});
|
|
|
|
it('should throw an error if a lat is not a number', async () => {
|
|
const { status, body } = await request(app)
|
|
.get('/map/reverse-geocode?lat=abc&lon=123.456')
|
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
expect(status).toBe(400);
|
|
expect(body).toEqual(errorDto.badRequest(['lat must be a number between -90 and 90']));
|
|
});
|
|
|
|
it('should throw an error if a lat is out of range', async () => {
|
|
const { status, body } = await request(app)
|
|
.get('/map/reverse-geocode?lat=91&lon=123.456')
|
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
expect(status).toBe(400);
|
|
expect(body).toEqual(errorDto.badRequest(['lat must be a number between -90 and 90']));
|
|
});
|
|
|
|
it('should throw an error if a lon is not provided', async () => {
|
|
const { status, body } = await request(app)
|
|
.get('/map/reverse-geocode?lat=75')
|
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
expect(status).toBe(400);
|
|
expect(body).toEqual(errorDto.badRequest(['lon must be a number between -180 and 180']));
|
|
});
|
|
|
|
const reverseGeocodeTestCases = [
|
|
{
|
|
name: 'Vaucluse',
|
|
lat: -33.858_977_058_663_13,
|
|
lon: 151.278_490_730_270_48,
|
|
results: [{ city: 'Vaucluse', state: 'New South Wales', country: 'Australia' }],
|
|
},
|
|
{
|
|
name: 'Ravenhall',
|
|
lat: -37.765_732_399_174_75,
|
|
lon: 144.752_453_164_883_3,
|
|
results: [{ city: 'Ravenhall', state: 'Victoria', country: 'Australia' }],
|
|
},
|
|
{
|
|
name: 'Scarborough',
|
|
lat: -31.894_346_156_789_997,
|
|
lon: 115.757_617_103_904_64,
|
|
results: [{ city: 'Scarborough', state: 'Western Australia', country: 'Australia' }],
|
|
},
|
|
];
|
|
|
|
it.each(reverseGeocodeTestCases)(`should resolve to $name`, async ({ lat, lon, results }) => {
|
|
const { status, body } = await request(app)
|
|
.get(`/map/reverse-geocode?lat=${lat}&lon=${lon}`)
|
|
.set('Authorization', `Bearer ${admin.accessToken}`);
|
|
expect(status).toBe(200);
|
|
expect(Array.isArray(body)).toBe(true);
|
|
expect(body.length).toBe(results.length);
|
|
expect(body).toEqual(results);
|
|
});
|
|
});
|
|
});
|