feat: sites and authors integration into existing screens (& formated all frontend files kinda accidentally)
This commit is contained in:
1 parent
3d81d2c717
commit
6b8990c55e
239 files changed
+9194
-1354
No files matched your search
@@ -38,7 +38,11 @@ function entries(query: string) {
|
||||
|
||||
describe('Queries', () => {
|
||||
it('always sends range, page and size and nothing else by default', () => {
|
||||
expect(entries(listQuery(filters(), 1, 25))).toEqual({ range: '7d', page: '1', size: '25' })
|
||||
expect(entries(listQuery(filters(), 1, 25))).toEqual({
|
||||
range: '7d',
|
||||
page: '1',
|
||||
size: '25',
|
||||
})
|
||||
})
|
||||
|
||||
it('adds q, actor, category, outcome and security only when set', () => {
|
||||
@@ -69,18 +73,36 @@ describe('Queries', () => {
|
||||
it('sends from and to only with the custom range', () => {
|
||||
expect(
|
||||
entries(
|
||||
listQuery(filters({ range: '30d', from: '2026-09-01', to: '2026-09-30' }), 1, 25),
|
||||
listQuery(
|
||||
filters({
|
||||
range: '30d',
|
||||
from: '2026-09-01',
|
||||
to: '2026-09-30',
|
||||
}),
|
||||
1,
|
||||
25,
|
||||
),
|
||||
),
|
||||
).toEqual({ range: '30d', page: '1', size: '25' })
|
||||
expect(
|
||||
entries(
|
||||
listQuery(
|
||||
filters({ range: 'custom', from: '2026-09-01', to: '2026-09-30' }),
|
||||
filters({
|
||||
range: 'custom',
|
||||
from: '2026-09-01',
|
||||
to: '2026-09-30',
|
||||
}),
|
||||
1,
|
||||
25,
|
||||
),
|
||||
),
|
||||
).toEqual({ range: 'custom', from: '2026-09-01', to: '2026-09-30', page: '1', size: '25' })
|
||||
).toEqual({
|
||||
range: 'custom',
|
||||
from: '2026-09-01',
|
||||
to: '2026-09-30',
|
||||
page: '1',
|
||||
size: '25',
|
||||
})
|
||||
})
|
||||
|
||||
it('never sends an actor for a regular user', () => {
|
||||
@@ -153,10 +175,18 @@ describe('Chips', () => {
|
||||
})
|
||||
|
||||
it('resets one filter at a time', () => {
|
||||
const all = filters({ q: 'a', actor: 'system', actorLabel: 'System', range: '30d' })
|
||||
const all = filters({
|
||||
q: 'a',
|
||||
actor: 'system',
|
||||
actorLabel: 'System',
|
||||
range: '30d',
|
||||
})
|
||||
|
||||
expect(clearChip(all, 'q').q).toBe('')
|
||||
expect(clearChip(all, 'actor')).toMatchObject({ actor: '', actorLabel: '' })
|
||||
expect(clearChip(all, 'actor')).toMatchObject({
|
||||
actor: '',
|
||||
actorLabel: '',
|
||||
})
|
||||
expect(clearChip(all, 'range').range).toBe('7d')
|
||||
})
|
||||
})
|
||||
@@ -280,7 +310,11 @@ describe('Summary strip', () => {
|
||||
|
||||
it('words singulars, the French forms and the flag count', () => {
|
||||
const single = stripCards(
|
||||
{ ...summaryDefault, active_people: { users: 1, api_keys: 1 }, security: 1 },
|
||||
{
|
||||
...summaryDefault,
|
||||
active_people: { users: 1, api_keys: 1 },
|
||||
security: 1,
|
||||
},
|
||||
'7d',
|
||||
)
|
||||
expect(single[1]!.subline).toBe('1 person, 1 API key')
|
||||
|
||||
@@ -38,7 +38,11 @@ const rows: [string, Partial<ActivityItem>, string, string | null][] = [
|
||||
'media.variant_purge_unused success',
|
||||
{
|
||||
action: 'media.variant_purge_unused',
|
||||
params: { purged_files: 312, purged_bytes: 42991616, older_than_days: 30 },
|
||||
params: {
|
||||
purged_files: 312,
|
||||
purged_bytes: 42991616,
|
||||
older_than_days: 30,
|
||||
},
|
||||
},
|
||||
'Purged unused variants',
|
||||
'Removed 312 files (41 MB) not requested for 30 days',
|
||||
@@ -97,14 +101,20 @@ describe('The Activity screen words each cache purge scope', () => {
|
||||
|
||||
it('A partial purge adds the failed count to the detail line', () => {
|
||||
const subject = purgeItem({
|
||||
params: { purged_files: 640, purged_bytes: 111149056, failed_files: 644 },
|
||||
params: {
|
||||
purged_files: 640,
|
||||
purged_bytes: 111149056,
|
||||
failed_files: 644,
|
||||
},
|
||||
})
|
||||
|
||||
expect(detailLine(subject)).toBe('Removed 640 files (106 MB) · 644 failed')
|
||||
})
|
||||
|
||||
it('The singular reads 1 file', () => {
|
||||
const subject = purgeItem({ params: { purged_files: 1, purged_bytes: 2048 } })
|
||||
const subject = purgeItem({
|
||||
params: { purged_files: 1, purged_bytes: 2048 },
|
||||
})
|
||||
|
||||
expect(detailLine(subject)).toBe('Removed 1 file (2 KB)')
|
||||
})
|
||||
|
||||
@@ -16,7 +16,12 @@ function item(overrides: Partial<ActivityItem>): ActivityItem {
|
||||
action: 'article.publish',
|
||||
category: 'articles',
|
||||
actor: { type: 'user', id: 3, name: 'Marta Alves' },
|
||||
target: { type: 'article', id: '8', name: 'Spring release', exists: true },
|
||||
target: {
|
||||
type: 'article',
|
||||
id: '8',
|
||||
name: 'Spring release',
|
||||
exists: true,
|
||||
},
|
||||
outcome: 'success',
|
||||
failure_reason: null,
|
||||
security: false,
|
||||
@@ -55,7 +60,11 @@ describe('Sentences: English and French come from the same code and params', ()
|
||||
],
|
||||
[
|
||||
'media.purge',
|
||||
{ action: 'media.purge', target: null, params: { merged: 3, articles_updated: 5 } },
|
||||
{
|
||||
action: 'media.purge',
|
||||
target: null,
|
||||
params: { merged: 3, articles_updated: 5 },
|
||||
},
|
||||
'Purged duplicate images: 3 merged, 5 articles updated',
|
||||
'Doublons purgés : 3 fusionnées, 5 articles mis à jour',
|
||||
],
|
||||
@@ -81,13 +90,21 @@ describe('Sentences: English and French come from the same code and params', ()
|
||||
],
|
||||
[
|
||||
'system.activity_cleanup singular',
|
||||
{ action: 'system.activity_cleanup', target: null, params: { removed: 1 } },
|
||||
{
|
||||
action: 'system.activity_cleanup',
|
||||
target: null,
|
||||
params: { removed: 1 },
|
||||
},
|
||||
'Removed 1 old event from the activity log',
|
||||
"1 ancien événement supprimé du journal d'activité",
|
||||
],
|
||||
[
|
||||
'system.activity_cleanup plural',
|
||||
{ action: 'system.activity_cleanup', target: null, params: { removed: 1284 } },
|
||||
{
|
||||
action: 'system.activity_cleanup',
|
||||
target: null,
|
||||
params: { removed: 1284 },
|
||||
},
|
||||
'Removed 1,284 old events from the activity log',
|
||||
"1 284 anciens événements supprimés du journal d'activité",
|
||||
],
|
||||
@@ -125,7 +142,12 @@ describe('Sentences: English and French come from the same code and params', ()
|
||||
'system.restart_requested update',
|
||||
{
|
||||
action: 'system.restart_requested',
|
||||
target: { type: 'release', id: 'v1.4.0', name: 'v1.4.0', exists: true },
|
||||
target: {
|
||||
type: 'release',
|
||||
id: 'v1.4.0',
|
||||
name: 'v1.4.0',
|
||||
exists: true,
|
||||
},
|
||||
params: { kind: 'update', tag: 'v1.4.0' },
|
||||
},
|
||||
'Restarted to apply the update v1.4.0',
|
||||
@@ -133,7 +155,11 @@ describe('Sentences: English and French come from the same code and params', ()
|
||||
],
|
||||
[
|
||||
'system.restart_requested restart',
|
||||
{ action: 'system.restart_requested', target: null, params: { kind: 'restart' } },
|
||||
{
|
||||
action: 'system.restart_requested',
|
||||
target: null,
|
||||
params: { kind: 'restart' },
|
||||
},
|
||||
'Requested a restart',
|
||||
'Redémarrage demandé',
|
||||
],
|
||||
@@ -155,7 +181,11 @@ describe('Sentences: English and French come from the same code and params', ()
|
||||
action: 'auth.login_failed',
|
||||
target: null,
|
||||
outcome: 'failed',
|
||||
actor: { type: 'anonymous', id: null, name: 'alex@example.com' },
|
||||
actor: {
|
||||
type: 'anonymous',
|
||||
id: null,
|
||||
name: 'alex@example.com',
|
||||
},
|
||||
},
|
||||
'Failed login attempt for alex@example.com',
|
||||
'Échec de connexion pour alex@example.com',
|
||||
|
||||
@@ -51,7 +51,11 @@ describe('Selecting an inserted image reveals its delete button', () => {
|
||||
const { wrapper, getEditor } = mountHarness()
|
||||
activeWrapper = wrapper
|
||||
const editor = getEditor()
|
||||
editor.commands.setArticleImage({ src: 'photo.png', alt: '', imageId: 10 })
|
||||
editor.commands.setArticleImage({
|
||||
src: 'photo.png',
|
||||
alt: '',
|
||||
imageId: 10,
|
||||
})
|
||||
const pos = findArticleImagePos(editor, 10) as number
|
||||
|
||||
editor.commands.setNodeSelection(pos)
|
||||
@@ -69,7 +73,11 @@ describe('The remove button is labelled and neutral', () => {
|
||||
const { wrapper, getEditor } = mountHarness()
|
||||
activeWrapper = wrapper
|
||||
const editor = getEditor()
|
||||
editor.commands.setArticleImage({ src: 'photo.png', alt: '', imageId: 10 })
|
||||
editor.commands.setArticleImage({
|
||||
src: 'photo.png',
|
||||
alt: '',
|
||||
imageId: 10,
|
||||
})
|
||||
editor.commands.setNodeSelection(findArticleImagePos(editor, 10) as number)
|
||||
await flush()
|
||||
|
||||
@@ -106,7 +114,11 @@ describe('Activating the delete button triggers removal without deleting the nod
|
||||
const { wrapper, getEditor, onRequestRemove } = mountHarness()
|
||||
activeWrapper = wrapper
|
||||
const editor = getEditor()
|
||||
editor.commands.setArticleImage({ src: 'photo.png', alt: '', imageId: 10 })
|
||||
editor.commands.setArticleImage({
|
||||
src: 'photo.png',
|
||||
alt: '',
|
||||
imageId: 10,
|
||||
})
|
||||
const pos = findArticleImagePos(editor, 10) as number
|
||||
editor.commands.setNodeSelection(pos)
|
||||
await flush()
|
||||
@@ -123,7 +135,11 @@ describe('Pressing Backspace on a selected image triggers removal without deleti
|
||||
const { wrapper, getEditor, onRequestRemove } = mountHarness()
|
||||
activeWrapper = wrapper
|
||||
const editor = getEditor()
|
||||
editor.commands.setArticleImage({ src: 'photo.png', alt: '', imageId: 10 })
|
||||
editor.commands.setArticleImage({
|
||||
src: 'photo.png',
|
||||
alt: '',
|
||||
imageId: 10,
|
||||
})
|
||||
const pos = findArticleImagePos(editor, 10) as number
|
||||
editor.commands.setNodeSelection(pos)
|
||||
|
||||
@@ -139,7 +155,11 @@ describe('Pressing Delete on a selected image triggers removal without deleting
|
||||
const { wrapper, getEditor, onRequestRemove } = mountHarness()
|
||||
activeWrapper = wrapper
|
||||
const editor = getEditor()
|
||||
editor.commands.setArticleImage({ src: 'photo.png', alt: '', imageId: 10 })
|
||||
editor.commands.setArticleImage({
|
||||
src: 'photo.png',
|
||||
alt: '',
|
||||
imageId: 10,
|
||||
})
|
||||
const pos = findArticleImagePos(editor, 10) as number
|
||||
editor.commands.setNodeSelection(pos)
|
||||
|
||||
@@ -175,7 +195,11 @@ describe('The custom image node view renders as a block-level element', () => {
|
||||
const { wrapper, getEditor } = mountHarness()
|
||||
activeWrapper = wrapper
|
||||
const editor = getEditor()
|
||||
editor.commands.setArticleImage({ src: 'photo.png', alt: '', imageId: 10 })
|
||||
editor.commands.setArticleImage({
|
||||
src: 'photo.png',
|
||||
alt: '',
|
||||
imageId: 10,
|
||||
})
|
||||
await flush()
|
||||
|
||||
const node = document.body.querySelector<HTMLElement>(
|
||||
@@ -191,7 +215,11 @@ describe('Selecting an image shows a visible selection outline', () => {
|
||||
const { wrapper, getEditor } = mountHarness()
|
||||
activeWrapper = wrapper
|
||||
const editor = getEditor()
|
||||
editor.commands.setArticleImage({ src: 'photo.png', alt: '', imageId: 10 })
|
||||
editor.commands.setArticleImage({
|
||||
src: 'photo.png',
|
||||
alt: '',
|
||||
imageId: 10,
|
||||
})
|
||||
const pos = findArticleImagePos(editor, 10) as number
|
||||
|
||||
editor.commands.setNodeSelection(pos)
|
||||
@@ -236,7 +264,11 @@ describe('The image node is not natively draggable', () => {
|
||||
const { wrapper, getEditor } = mountHarness()
|
||||
activeWrapper = wrapper
|
||||
const editor = getEditor()
|
||||
editor.commands.setArticleImage({ src: 'photo.png', alt: '', imageId: 10 })
|
||||
editor.commands.setArticleImage({
|
||||
src: 'photo.png',
|
||||
alt: '',
|
||||
imageId: 10,
|
||||
})
|
||||
await flush()
|
||||
|
||||
const node = document.body.querySelector<HTMLElement>(
|
||||
@@ -294,7 +326,10 @@ describe('An image that fails to load', () => {
|
||||
const { wrapper, getEditor } = mountHarness()
|
||||
activeWrapper = wrapper
|
||||
const editor = getEditor()
|
||||
editor.commands.setArticleImage({ src: '/static/uploadedImages/gone.png', alt: '' })
|
||||
editor.commands.setArticleImage({
|
||||
src: '/static/uploadedImages/gone.png',
|
||||
alt: '',
|
||||
})
|
||||
await flush()
|
||||
|
||||
document.body.querySelector('img')!.dispatchEvent(new Event('error'))
|
||||
|
||||
@@ -3,7 +3,14 @@ import { nextSort, parseArticleQuery, sameArticleQuery, toRouteQuery } from '@/l
|
||||
|
||||
describe('parseArticleQuery', () => {
|
||||
it('falls back to page 1, size 25, no search and the All tab', () => {
|
||||
expect(parseArticleQuery({})).toEqual({ page: 1, size: 25, q: '', status: '', sort: '' })
|
||||
expect(parseArticleQuery({})).toEqual({
|
||||
page: 1,
|
||||
size: 25,
|
||||
q: '',
|
||||
status: '',
|
||||
sort: '',
|
||||
site: '',
|
||||
})
|
||||
})
|
||||
|
||||
it('reads valid values', () => {
|
||||
@@ -15,7 +22,14 @@ describe('parseArticleQuery', () => {
|
||||
status: 'draft',
|
||||
sort: 'title:asc',
|
||||
}),
|
||||
).toEqual({ page: 7, size: 50, q: 'plaster', status: 'draft', sort: 'title:asc' })
|
||||
).toEqual({
|
||||
page: 7,
|
||||
size: 50,
|
||||
q: 'plaster',
|
||||
status: 'draft',
|
||||
sort: 'title:asc',
|
||||
site: '',
|
||||
})
|
||||
})
|
||||
|
||||
it.each(['abc', '0', '-2', '2.5', '', '1e2'])('treats page "%s" as 1', (page) => {
|
||||
@@ -53,9 +67,11 @@ describe('sort parameter', () => {
|
||||
})
|
||||
|
||||
it('omits the default from the route and treats it as equal to no sort', () => {
|
||||
const base = { page: 1, size: 25, q: '', status: '' as const }
|
||||
const base = { page: 1, size: 25, q: '', status: '' as const, site: '' }
|
||||
expect(toRouteQuery({ ...base, sort: 'updated_at:desc' })).toEqual({})
|
||||
expect(toRouteQuery({ ...base, sort: 'title:asc' })).toEqual({ sort: 'title:asc' })
|
||||
expect(toRouteQuery({ ...base, sort: 'title:asc' })).toEqual({
|
||||
sort: 'title:asc',
|
||||
})
|
||||
expect(sameArticleQuery({ ...base, sort: '' }, { ...base, sort: 'updated_at:desc' })).toBe(
|
||||
true,
|
||||
)
|
||||
@@ -74,12 +90,28 @@ describe('sort parameter', () => {
|
||||
|
||||
describe('toRouteQuery', () => {
|
||||
it('omits every default', () => {
|
||||
expect(toRouteQuery({ page: 1, size: 25, q: '', status: '', sort: '' })).toEqual({})
|
||||
expect(
|
||||
toRouteQuery({
|
||||
page: 1,
|
||||
size: 25,
|
||||
q: '',
|
||||
status: '',
|
||||
sort: '',
|
||||
site: '',
|
||||
}),
|
||||
).toEqual({})
|
||||
})
|
||||
|
||||
it('keeps what differs from the defaults', () => {
|
||||
expect(
|
||||
toRouteQuery({ page: 2, size: 5, q: 'plaster', status: 'online', sort: 'title:desc' }),
|
||||
toRouteQuery({
|
||||
page: 2,
|
||||
size: 5,
|
||||
q: 'plaster',
|
||||
status: 'online',
|
||||
sort: 'title:desc',
|
||||
site: '',
|
||||
}),
|
||||
).toEqual({
|
||||
page: '2',
|
||||
size: '5',
|
||||
@@ -92,7 +124,14 @@ describe('toRouteQuery', () => {
|
||||
|
||||
describe('sameArticleQuery', () => {
|
||||
it('compares every field', () => {
|
||||
const base = { page: 1, size: 25, q: '', status: '' as const, sort: '' }
|
||||
const base = {
|
||||
page: 1,
|
||||
size: 25,
|
||||
q: '',
|
||||
status: '' as const,
|
||||
sort: '',
|
||||
site: '',
|
||||
}
|
||||
expect(sameArticleQuery(base, { ...base })).toBe(true)
|
||||
expect(sameArticleQuery(base, { ...base, page: 2 })).toBe(false)
|
||||
expect(sameArticleQuery(base, { ...base, size: 5 })).toBe(false)
|
||||
@@ -100,3 +139,20 @@ describe('sameArticleQuery', () => {
|
||||
expect(sameArticleQuery(base, { ...base, status: 'draft' })).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('site parameter', () => {
|
||||
it('reads the site key and writes it back to the route', () => {
|
||||
const parsed = parseArticleQuery({ site: 'journal' })
|
||||
expect(parsed.site).toBe('journal')
|
||||
expect(toRouteQuery(parsed)).toEqual({ site: 'journal' })
|
||||
})
|
||||
|
||||
it('omits an empty site and tells two queries apart by their site', () => {
|
||||
const base = { page: 1, size: 25, q: '', status: '' as const, sort: '' }
|
||||
expect(toRouteQuery({ ...base, site: '' })).toEqual({})
|
||||
expect(sameArticleQuery({ ...base, site: 'journal' }, { ...base, site: '' })).toBe(false)
|
||||
expect(sameArticleQuery({ ...base, site: 'journal' }, { ...base, site: 'journal' })).toBe(
|
||||
true,
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,18 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { baseSlugOf } from '@/lib/authorProfile'
|
||||
|
||||
describe('The base slug of an adjusted slug', () => {
|
||||
it.each([
|
||||
['marta-alves-2', 'marta-alves'],
|
||||
['ines-duarte-3', 'ines-duarte'],
|
||||
['jean-luc-o-neil-2', 'jean-luc-o-neil'],
|
||||
['agent-007-2', 'agent-007'],
|
||||
['zoe-muller-12', 'zoe-muller'],
|
||||
])('strips the one collision suffix of "%s"', (slug, base) => {
|
||||
expect(baseSlugOf(slug)).toBe(base)
|
||||
})
|
||||
|
||||
it('leaves a slug without a numeric suffix alone', () => {
|
||||
expect(baseSlugOf('marta-alves')).toBe('marta-alves')
|
||||
})
|
||||
})
|
||||
@@ -35,7 +35,9 @@ describe('hashFile', () => {
|
||||
})
|
||||
|
||||
it('resolves null when the digest rejects', async () => {
|
||||
vi.stubGlobal('crypto', { subtle: { digest: vi.fn().mockRejectedValue(new Error('no')) } })
|
||||
vi.stubGlobal('crypto', {
|
||||
subtle: { digest: vi.fn().mockRejectedValue(new Error('no')) },
|
||||
})
|
||||
|
||||
expect(await hashFile(fileOf([1]))).toBeNull()
|
||||
})
|
||||
|
||||
@@ -32,11 +32,17 @@ describe('rectForRatio', () => {
|
||||
|
||||
describe('computeOutputSize', () => {
|
||||
it('never upscales past the crop width', () => {
|
||||
expect(computeOutputSize(640, 640, 1600)).toEqual({ width: 640, height: 640 })
|
||||
expect(computeOutputSize(640, 640, 1600)).toEqual({
|
||||
width: 640,
|
||||
height: 640,
|
||||
})
|
||||
})
|
||||
|
||||
it('caps to the width preset when the crop is larger', () => {
|
||||
expect(computeOutputSize(4032, 3024, 1600)).toEqual({ width: 1600, height: 1200 })
|
||||
expect(computeOutputSize(4032, 3024, 1600)).toEqual({
|
||||
width: 1600,
|
||||
height: 1200,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -177,10 +183,16 @@ describe('rotateRectBySteps', () => {
|
||||
|
||||
describe('rotatedDimensions', () => {
|
||||
it('swaps dimensions for a 90deg rotation', () => {
|
||||
expect(rotatedDimensions(4032, 3024, 90)).toEqual({ width: 3024, height: 4032 })
|
||||
expect(rotatedDimensions(4032, 3024, 90)).toEqual({
|
||||
width: 3024,
|
||||
height: 4032,
|
||||
})
|
||||
})
|
||||
|
||||
it('keeps dimensions for a 180deg rotation', () => {
|
||||
expect(rotatedDimensions(4032, 3024, 180)).toEqual({ width: 4032, height: 3024 })
|
||||
expect(rotatedDimensions(4032, 3024, 180)).toEqual({
|
||||
width: 4032,
|
||||
height: 3024,
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -21,7 +21,10 @@ describe('validateImageFile', () => {
|
||||
})
|
||||
|
||||
it('needs an allowed MIME type and an allowed extension', () => {
|
||||
expect(validateImageFile(fileOf('a.gif', 'image/gif'))).toEqual({ ok: false, kind: 'type' })
|
||||
expect(validateImageFile(fileOf('a.gif', 'image/gif'))).toEqual({
|
||||
ok: false,
|
||||
kind: 'type',
|
||||
})
|
||||
expect(validateImageFile(fileOf('a.jpg', 'text/plain'))).toEqual({
|
||||
ok: false,
|
||||
kind: 'type',
|
||||
|
||||
@@ -74,8 +74,16 @@ describe('groupDuplicates', () => {
|
||||
|
||||
it('reads Vector for SVG groups and ignores single copies', () => {
|
||||
const groups = groupDuplicates([
|
||||
copy(1, 0, '2026-09-01T12:00:00Z', { width: null, height: null, size: 8192 }),
|
||||
copy(2, 0, '2026-09-02T12:00:00Z', { width: null, height: null, size: 8192 }),
|
||||
copy(1, 0, '2026-09-01T12:00:00Z', {
|
||||
width: null,
|
||||
height: null,
|
||||
size: 8192,
|
||||
}),
|
||||
copy(2, 0, '2026-09-02T12:00:00Z', {
|
||||
width: null,
|
||||
height: null,
|
||||
size: 8192,
|
||||
}),
|
||||
copy(3, 0, '2026-09-02T12:00:00Z', { sha256: 'zz' }),
|
||||
])
|
||||
|
||||
|
||||
@@ -75,9 +75,18 @@ describe('usedInLabel and accessibleName', () => {
|
||||
|
||||
describe('splitFilename', () => {
|
||||
it('separates the stem from the extension', () => {
|
||||
expect(splitFilename('north-wall.jpg')).toEqual({ stem: 'north-wall', extension: '.jpg' })
|
||||
expect(splitFilename('a.b.webp')).toEqual({ stem: 'a.b', extension: '.webp' })
|
||||
expect(splitFilename('noextension')).toEqual({ stem: 'noextension', extension: '' })
|
||||
expect(splitFilename('north-wall.jpg')).toEqual({
|
||||
stem: 'north-wall',
|
||||
extension: '.jpg',
|
||||
})
|
||||
expect(splitFilename('a.b.webp')).toEqual({
|
||||
stem: 'a.b',
|
||||
extension: '.webp',
|
||||
})
|
||||
expect(splitFilename('noextension')).toEqual({
|
||||
stem: 'noextension',
|
||||
extension: '',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -32,7 +32,10 @@ describe('parseMediaControls', () => {
|
||||
[{ view: 'grid' }, {}],
|
||||
[{ sort: 'newest' }, {}],
|
||||
])('maps %j', (query, expected) => {
|
||||
expect(parseMediaControls(query)).toEqual({ ...DEFAULT_CONTROLS, ...expected })
|
||||
expect(parseMediaControls(query)).toEqual({
|
||||
...DEFAULT_CONTROLS,
|
||||
...expected,
|
||||
})
|
||||
})
|
||||
|
||||
it.each([
|
||||
@@ -51,7 +54,10 @@ describe('parseMediaControls', () => {
|
||||
[{ size: '200' }, {}],
|
||||
[{ size: '' }, {}],
|
||||
])('maps the paging of %j', (query, expected) => {
|
||||
expect(parseMediaControls(query)).toEqual({ ...DEFAULT_CONTROLS, ...expected })
|
||||
expect(parseMediaControls(query)).toEqual({
|
||||
...DEFAULT_CONTROLS,
|
||||
...expected,
|
||||
})
|
||||
})
|
||||
|
||||
it('uses the stored size only when the URL has no size', () => {
|
||||
@@ -82,7 +88,12 @@ describe('toRouteQuery', () => {
|
||||
sort: 'largest',
|
||||
view: 'list',
|
||||
}),
|
||||
).toEqual({ q: 'wall', filter: 'unused', sort: 'largest', view: 'list' })
|
||||
).toEqual({
|
||||
q: 'wall',
|
||||
filter: 'unused',
|
||||
sort: 'largest',
|
||||
view: 'list',
|
||||
})
|
||||
})
|
||||
|
||||
it('keeps the page and the size when they are not the defaults', () => {
|
||||
@@ -94,7 +105,12 @@ describe('toRouteQuery', () => {
|
||||
|
||||
it('drops the page and the size on the Duplicates tab', () => {
|
||||
expect(
|
||||
toRouteQuery({ ...DEFAULT_CONTROLS, filter: 'duplicates', page: 4, size: 5 }),
|
||||
toRouteQuery({
|
||||
...DEFAULT_CONTROLS,
|
||||
filter: 'duplicates',
|
||||
page: 4,
|
||||
size: 5,
|
||||
}),
|
||||
).toEqual({ filter: 'duplicates' })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -65,8 +65,12 @@ describe('describeUpload', () => {
|
||||
sub: '2 files need attention',
|
||||
summary: null,
|
||||
})
|
||||
expect(describeUpload(rows('failed'))).toMatchObject({ sub: '1 file needs attention' })
|
||||
expect(describeUpload(rows('rejected'))).toMatchObject({ sub: '1 file was rejected' })
|
||||
expect(describeUpload(rows('failed'))).toMatchObject({
|
||||
sub: '1 file needs attention',
|
||||
})
|
||||
expect(describeUpload(rows('rejected'))).toMatchObject({
|
||||
sub: '1 file was rejected',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in new issue
Block a user