feat(apercu): rend ajustable le partage entre PDF et données
Le volet PDF était figé à 40 % de la fenêtre. C'est le vrai levier de lisibilité : élargir le volet augmente d'autant l'échelle du document, et vers 768 px l'ajustement à la largeur vaut 97 %, soit 100 % de fait. La poignée se glisse, la largeur est mémorisée et partagée entre l'écran d'extraction et celui d'édition, le double-clic revient au défaut — porté de 40 % à 50 % pour que la page tienne presque sans défiler. Un voile couvre la fenêtre pendant le glissement : sans lui l'<iframe> du PDF capte les évènements souris et le redimensionnement se fige dès qu'on la survole. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
81
frontend/tests/voletsAjustables.test.js
Normal file
81
frontend/tests/voletsAjustables.test.js
Normal file
@@ -0,0 +1,81 @@
|
||||
// La largeur du volet PDF est un reglage que l'utilisateur pose une fois et
|
||||
// retrouve ensuite : elle doit survivre au rechargement, rester dans des bornes
|
||||
// utilisables, et ne jamais empecher l'ecran de s'afficher si le stockage
|
||||
// du navigateur est indisponible.
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { createSSRApp } from 'vue'
|
||||
import { renderToString } from 'vue/server-renderer'
|
||||
|
||||
import VoletsAjustables from '../src/components/VoletsAjustables.vue'
|
||||
|
||||
const CLE = 'apercuPdf.largeurVolet'
|
||||
|
||||
/** Remplace le stockage du navigateur, absent sous Node. */
|
||||
function poserStockage(valeur, { leve = false } = {}) {
|
||||
globalThis.localStorage = {
|
||||
getItem: () => {
|
||||
if (leve) throw new Error('stockage indisponible')
|
||||
return valeur
|
||||
},
|
||||
setItem: () => {},
|
||||
removeItem: () => {},
|
||||
}
|
||||
}
|
||||
|
||||
function rendu(proprietes = {}) {
|
||||
return renderToString(
|
||||
createSSRApp(VoletsAjustables, { cleStockage: CLE, largeurDefaut: 50, ...proprietes })
|
||||
)
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
delete globalThis.localStorage
|
||||
})
|
||||
|
||||
describe('VoletsAjustables', () => {
|
||||
it('applique la largeur par defaut quand rien n est memorise', async () => {
|
||||
poserStockage(null)
|
||||
const html = await rendu()
|
||||
|
||||
expect(html).toContain('width:50%')
|
||||
})
|
||||
|
||||
it('reprend la largeur memorisee', async () => {
|
||||
poserStockage('65')
|
||||
const html = await rendu()
|
||||
|
||||
expect(html).toContain('width:65%')
|
||||
// Les deux volets se partagent la totalite : la poignee ne prend pas de
|
||||
// place dans le flux, sinon le second volet deborderait.
|
||||
expect(html).toContain('width:35%')
|
||||
})
|
||||
|
||||
it('ignore une largeur memorisee hors bornes', async () => {
|
||||
// Sans ce garde-fou, une valeur ecrite avant un changement de bornes
|
||||
// resterait coincee et rendrait un volet inutilisable.
|
||||
poserStockage('95')
|
||||
|
||||
expect(await rendu()).toContain('width:50%')
|
||||
})
|
||||
|
||||
it('ignore une valeur memorisee illisible', async () => {
|
||||
poserStockage('beaucoup')
|
||||
|
||||
expect(await rendu()).toContain('width:50%')
|
||||
})
|
||||
|
||||
it("s'affiche quand même si le stockage est indisponible", async () => {
|
||||
// Navigation privee ou stockage bloque : le reglage se perd, pas l'ecran.
|
||||
poserStockage(null, { leve: true })
|
||||
|
||||
expect(await rendu()).toContain('width:50%')
|
||||
})
|
||||
|
||||
it('expose une poignee de redimensionnement atteignable', async () => {
|
||||
poserStockage(null)
|
||||
const html = await rendu()
|
||||
|
||||
expect(html).toContain('role="separator"')
|
||||
expect(html).toContain('cursor-col-resize')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user