Files
sky_phone/frontend/src/utils/media.test.ts
T
Leon.Schmidt 7b4e445394 FIX - restore FiveManage camera and memo uploads (#19)
* TRY - isolate FiveManage media upload verification

* TRY - verify unindexed FiveManage storage objects

* FIX - bind FiveManage uploads by storage key

* FIX - match FiveManage camera upload flow

* FIX - match FiveManage memo upload flow
2026-08-21 01:29:56 +02:00

171 lines
4.7 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import {
bottomRightGridPosition,
filterMedia,
formatMediaSize,
formatRecordingDuration,
hasNextMediaPage,
mediaErrorKey,
mergeMedia,
orderMedia,
orderMediaOldestFirst,
} from './media'
const media = [
{
createdAt: 10,
favorite: false,
id: 1,
mediaType: 'photo' as const,
url: 'photo',
},
{
createdAt: 20,
favorite: false,
id: 2,
mediaType: 'video' as const,
url: 'video',
},
]
describe('media utilities', () => {
it('filters gallery media by explicit type', () => {
expect(filterMedia(media, 'all')).toHaveLength(2)
expect(filterMedia(media, 'photo').map((entry) => entry.id)).toEqual([1])
expect(filterMedia(media, 'video').map((entry) => entry.id)).toEqual([2])
})
it('merges pages without duplicates and keeps newest first', () => {
expect(
mergeMedia(media, [
{
createdAt: 30,
favorite: true,
id: 1,
mediaType: 'photo',
url: 'updated',
},
{
createdAt: 25,
favorite: false,
id: 3,
mediaType: 'photo',
url: 'new',
},
]).map((entry) => [entry.id, entry.url]),
).toEqual([
[1, 'updated'],
[3, 'new'],
[2, 'video'],
])
})
it('orders the photo grid from oldest to newest', () => {
expect(orderMediaOldestFirst(media).map((entry) => entry.id)).toEqual([
1, 2,
])
})
it('orders the photo grid in the selected direction', () => {
expect(orderMedia(media, 'oldest').map((entry) => entry.id)).toEqual([1, 2])
expect(orderMedia(media, 'newest').map((entry) => entry.id)).toEqual([2, 1])
})
it('fills the gallery from bottom-right to top-left', () => {
expect(bottomRightGridPosition(0, 1)).toEqual({ column: 3, row: 1 })
expect(bottomRightGridPosition(0, 3)).toEqual({ column: 3, row: 1 })
expect(bottomRightGridPosition(1, 3)).toEqual({ column: 2, row: 1 })
expect(bottomRightGridPosition(2, 3)).toEqual({ column: 1, row: 1 })
expect(bottomRightGridPosition(0, 4)).toEqual({ column: 3, row: 2 })
expect(bottomRightGridPosition(3, 4)).toEqual({ column: 3, row: 1 })
expect(bottomRightGridPosition(4, 5)).toEqual({ column: 2, row: 1 })
expect(bottomRightGridPosition(10, 11)).toEqual({ column: 2, row: 1 })
})
it('places newest-first media from the bottom-right toward older rows', () => {
const newestFirst = orderMedia(
[
{
createdAt: 10,
favorite: false,
id: 1,
mediaType: 'photo',
url: 'oldest',
},
{
createdAt: 20,
favorite: false,
id: 2,
mediaType: 'photo',
url: 'middle',
},
{
createdAt: 30,
favorite: false,
id: 3,
mediaType: 'photo',
url: 'newest',
},
{
createdAt: 5,
favorite: false,
id: 4,
mediaType: 'photo',
url: 'older-row',
},
],
'newest',
)
expect(
newestFirst.map((entry, index) => ({
id: entry.id,
...bottomRightGridPosition(index, newestFirst.length),
})),
).toEqual([
{ column: 3, id: 3, row: 2 },
{ column: 2, id: 2, row: 2 },
{ column: 1, id: 1, row: 2 },
{ column: 3, id: 4, row: 1 },
])
})
it('loads another gallery page only after a full 30-item batch', () => {
expect(hasNextMediaPage(30)).toBe(true)
expect(hasNextMediaPage(29)).toBe(false)
expect(hasNextMediaPage(0)).toBe(false)
})
it('formats unlimited recording durations', () => {
expect(formatRecordingDuration(0)).toBe('00:00')
expect(formatRecordingDuration(3_725_000)).toBe('62:05')
})
it('formats imported media sizes with the active locale', () => {
expect(formatMediaSize(512, 'en')).toBe('512 B')
expect(formatMediaSize(1_572_864, 'en')).toBe('1.5 MB')
})
it('maps unknown server failures to the localized default', () => {
expect(mediaErrorKey('upload_timeout')).toBe('upload_timeout')
expect(mediaErrorKey('import_media_too_large')).toBe(
'import_media_too_large',
)
expect(mediaErrorKey('import_url_not_allowed')).toBe(
'import_url_not_allowed',
)
expect(mediaErrorKey('profile_photo_required')).toBe(
'profile_photo_required',
)
expect(mediaErrorKey('media_provider_failed')).toBe('media_provider_failed')
expect(mediaErrorKey('media_provider_rate_limited')).toBe(
'media_provider_rate_limited',
)
expect(mediaErrorKey('media_provider_unauthorized')).toBe(
'media_provider_unauthorized',
)
expect(mediaErrorKey('private_provider_error')).toBe('request_failed')
})
})