diff --git a/app/components/malio/time/internal/TimeWheels.test.ts b/app/components/malio/time/internal/TimeWheels.test.ts
new file mode 100644
index 0000000..9134def
--- /dev/null
+++ b/app/components/malio/time/internal/TimeWheels.test.ts
@@ -0,0 +1,48 @@
+import {describe, expect, it} from 'vitest'
+import {mount} from '@vue/test-utils'
+import TimeWheels from './TimeWheels.vue'
+import TimeWheel from './TimeWheel.vue'
+
+const mountWheels = (modelValue = '09:30') =>
+ mount(TimeWheels, {props: {modelValue}, attachTo: document.body})
+
+describe('MalioTimeWheels', () => {
+ it('rend deux molettes (heures + minutes) et un séparateur', () => {
+ const wrapper = mountWheels('09:30')
+ const wheels = wrapper.findAllComponents(TimeWheel)
+ expect(wheels).toHaveLength(2)
+ expect(wheels[0].props('ariaLabel')).toBe('Heures')
+ expect(wheels[1].props('ariaLabel')).toBe('Minutes')
+ expect(wrapper.text()).toContain(':')
+ })
+
+ it('splitte modelValue vers les bonnes molettes', () => {
+ const wrapper = mountWheels('09:30')
+ const wheels = wrapper.findAllComponents(TimeWheel)
+ expect(wheels[0].props('modelValue')).toBe(9)
+ expect(wheels[1].props('modelValue')).toBe(30)
+ })
+
+ it('recompose et émet HH:MM quand l\'heure change', async () => {
+ const wrapper = mountWheels('09:30')
+ const wheels = wrapper.findAllComponents(TimeWheel)
+ wheels[0].vm.$emit('update:modelValue', 14)
+ await wrapper.vm.$nextTick()
+ expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual(['14:30'])
+ })
+
+ it('recompose et émet HH:MM quand la minute change', async () => {
+ const wrapper = mountWheels('09:30')
+ const wheels = wrapper.findAllComponents(TimeWheel)
+ wheels[1].vm.$emit('update:modelValue', 5)
+ await wrapper.vm.$nextTick()
+ expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual(['09:05'])
+ })
+
+ it('par défaut 00:00 quand modelValue est vide', () => {
+ const wrapper = mountWheels('')
+ const wheels = wrapper.findAllComponents(TimeWheel)
+ expect(wheels[0].props('modelValue')).toBe(0)
+ expect(wheels[1].props('modelValue')).toBe(0)
+ })
+})
diff --git a/app/components/malio/time/internal/TimeWheels.vue b/app/components/malio/time/internal/TimeWheels.vue
new file mode 100644
index 0000000..b1112ab
--- /dev/null
+++ b/app/components/malio/time/internal/TimeWheels.vue
@@ -0,0 +1,54 @@
+
+
+
+
+