fix(date) : borne la saisie clavier pour empêcher les dates absurdes (99/99/9999) (#79)
## Problème Sur la famille Date editable, le masque maska n'imposait que la *forme* (`##/##/####`). Une valeur structurellement absurde comme `99/99/9999` était donc **saisissable**, puis rejetée *a posteriori* par la validation. Le métier veut que ce soit **impossible à taper**. ## Solution (masque borné + validation en filet) - `composables/maskTemplate.ts` — `buildBoundedMask(template)` : borne le **premier chiffre de chaque champ** (jour `0-3`, mois `0-1`, heure `0-2`, minute `0-5`). Distingue le mois des minutes (même lettre `M`) selon la présence d'heures dans le gabarit, pour ne pas brider la saisie des minutes du DateTime. - `internal/CalendarField.vue` — branche le builder dans `maskaOptions` (remplace le `replace(/[A-Za-z]/g, '#')`). Les impossibilités plus fines (`31/02`, 29/02 non bissextile, hors `min`/`max`) restent captées par la **validation** (`invalidMessage` + `update:valid=false`). ## Tests - `maskTemplate.test.ts` (5) — bornes par champ, structure du masque, non-confusion mois/minutes. - `Date.test.ts` — test `invalidMessage` adapté (`32/13/2026`, typable→invalide) + garde de non-régression : `99/99/9999` ne s'inscrit jamais et n'émet aucune date. - Suite complète : **1004/1004 verte** (DateTime 36 incluse → saisie d'heure intacte). Doc : `COMPONENTS.md` (MalioDate) + `CHANGELOG.md` (Fixed) à jour. Reviewed-on: #79 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #79.
This commit is contained in:
@@ -62,7 +62,7 @@ describe('MalioSidebar', () => {
|
||||
it('renders expanded by default', () => {
|
||||
const wrapper = mountComponent({sections})
|
||||
const aside = wrapper.find('aside')
|
||||
expect(aside.classes()).toContain('w-[280px]')
|
||||
expect(aside.classes()).toContain('w-[232px]')
|
||||
})
|
||||
|
||||
it('renders section labels with icons when expanded', () => {
|
||||
@@ -89,6 +89,29 @@ describe('MalioSidebar', () => {
|
||||
expect(links[2].attributes('href')).toBe('/fournisseurs')
|
||||
})
|
||||
|
||||
it('hover : fond + couleur + semi-bold tous portés par le <li> (texte non figé sur le <a>)', () => {
|
||||
const wrapper = mountComponent({sections})
|
||||
const li = wrapper.find('li')
|
||||
expect(li.classes()).toContain('hover:bg-m-primary/10')
|
||||
expect(li.classes()).toContain('hover:text-m-primary')
|
||||
expect(li.classes()).toContain('hover:font-semibold')
|
||||
expect(li.classes()).toContain('text-black')
|
||||
expect(li.classes()).toContain('pt-1')
|
||||
expect(li.classes()).toContain('pb-1')
|
||||
// Le <a> ne fige PAS sa couleur (sinon le texte resterait noir sur les bandes
|
||||
// pt-1/pb-1 hors du <a> alors que le fond du <li> est bleu).
|
||||
expect(wrapper.find('a').classes()).not.toContain('text-black')
|
||||
expect(wrapper.find('a').classes()).not.toContain('hover:text-m-primary')
|
||||
})
|
||||
|
||||
it('actif : texte primary + semi-bold, sans fond, via active-class', () => {
|
||||
const wrapper = mountComponent({sections})
|
||||
const activeClass = wrapper.find('a').attributes('active-class') ?? ''
|
||||
expect(activeClass).toContain('text-m-primary')
|
||||
expect(activeClass).toContain('font-semibold')
|
||||
expect(activeClass).not.toContain('bg-')
|
||||
})
|
||||
|
||||
it('renders section icons via IconifyIcon', () => {
|
||||
const wrapper = mountComponent({sections})
|
||||
const icons = wrapper.findAllComponents(IconifyIcon)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<div
|
||||
v-if="section.label"
|
||||
:class="[
|
||||
'flex items-center gap-2 pt-2 pb-3',
|
||||
'flex items-center gap-2 pt-2 pb-2',
|
||||
collapsed ? 'justify-center pt-[40px]' : '',
|
||||
]"
|
||||
>
|
||||
@@ -49,12 +49,13 @@
|
||||
<li
|
||||
v-for="item in section.items"
|
||||
:key="item.to"
|
||||
:class="collapsed ? '' : 'pb-2 last:pb-1'"
|
||||
:class="collapsed ? '' : 'text-black hover:bg-m-primary/10 hover:font-semibold hover:text-m-primary pt-1 pb-1'"
|
||||
>
|
||||
<NuxtLink
|
||||
:to="item.to"
|
||||
active-class="!text-m-primary font-semibold"
|
||||
:class="twMerge(
|
||||
'block truncate rounded-md text-[15px] text-m-text text-black transition-colors hover:bg-m-surface leading-[150%]',
|
||||
'block truncate text-[15px] leading-[150%]',
|
||||
collapsed ? 'px-3 text-center' : 'pl-[32px]',
|
||||
)"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user