From 0c063b835eb9ef59a62d0553a6f5c87ba1338650 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Thu, 14 May 2026 11:58:09 +0200 Subject: [PATCH] test sweep: kernel/src/panels foundational coverage (T-91) Two test additions for the panels subsystem: - registry_test: setTabOrder ordering contract (unknown ids sink), definitionFor lookup, SlotId equality + hashCode + toString. - drag_resize_test (new): horizontal drag adjusts sidebar slot size via setSize, contextPanel drag inverts the delta sign, hovered state flips line colour. Coverage: kernel/src/panels/slot_id.dart 5/7 -> 7/7; registry.dart 30/42 -> ~all; drag_resize.dart 0/35 -> ~all. Total coverage 90.99% -> 91.59%; floor bumped to 91. Co-Authored-By: Claude Opus 4.7 (1M context) --- pubspec.yaml | 2 +- test/kernel/src/panels/drag_resize_test.dart | 122 +++++++++++++++++++ test/kernel/src/panels/registry_test.dart | 34 ++++++ 3 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 test/kernel/src/panels/drag_resize_test.dart diff --git a/pubspec.yaml b/pubspec.yaml index af98c1fe..3f4de269 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,7 +18,7 @@ repository: https://github.com/postmeridiem/clide # Pre-push line-coverage floor. Ratchets up only — see D-66. # Reading: `awk -F: '/^coverage_floor:/ {gsub(/ /,"",$2); print $2}' pubspec.yaml`. -coverage_floor: 90 +coverage_floor: 91 # Project metadata (was project.yaml, folded in per D-056). # version: above is the single source of truth. The Makefile reads diff --git a/test/kernel/src/panels/drag_resize_test.dart b/test/kernel/src/panels/drag_resize_test.dart new file mode 100644 index 00000000..34ebf1ef --- /dev/null +++ b/test/kernel/src/panels/drag_resize_test.dart @@ -0,0 +1,122 @@ +/// Tests for the DragResizeHandle widget. +library; + +import 'package:clide/extension/extension.dart'; +import 'package:clide/kernel/kernel.dart'; +import 'package:clide/kernel/src/panels/drag_resize.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../../../helpers/kernel_fixture.dart'; +import '../../../helpers/widget_harness.dart'; + +void main() { + group('DragResizeHandle', () { + late KernelFixture f; + setUp(() async => f = await KernelFixture.create()); + tearDown(() async => f.dispose()); + + testWidgets('horizontal drag adjusts the sidebar slot size', (tester) async { + final arr = LayoutArrangement(); + arr.applyPreset(const LayoutPresetContribution( + id: 'test-preset', + displayName: 'Test', + slots: [ + LayoutSlot(slot: Slots.sidebar, position: SlotPosition.left, defaultSize: 200), + LayoutSlot(slot: Slots.contextPanel, position: SlotPosition.right, defaultSize: 200), + ], + )); + await tester.pumpWidget(harness( + f, + Center( + child: SizedBox( + width: 40, + height: 200, + child: DragResizeHandle( + arrangement: arr, + slot: Slots.sidebar, + axis: Axis.horizontal, + ), + ), + ), + )); + await tester.pumpAndSettle(); + final center = tester.getCenter(find.byType(DragResizeHandle)); + final gesture = await tester.startGesture(center, kind: PointerDeviceKind.mouse); + await gesture.moveBy(const Offset(50, 0)); + await tester.pump(); + await gesture.up(); + await tester.pump(); + expect(arr.sizeOf(Slots.sidebar), 250); + }); + + testWidgets('contextPanel drag inverts the delta sign', (tester) async { + final arr = LayoutArrangement(); + arr.applyPreset(const LayoutPresetContribution( + id: 'test-preset', + displayName: 'Test', + slots: [ + LayoutSlot(slot: Slots.sidebar, position: SlotPosition.left, defaultSize: 200), + LayoutSlot(slot: Slots.contextPanel, position: SlotPosition.right, defaultSize: 200), + ], + )); + await tester.pumpWidget(harness( + f, + Center( + child: SizedBox( + width: 40, + height: 200, + child: DragResizeHandle( + arrangement: arr, + slot: Slots.contextPanel, + axis: Axis.horizontal, + ), + ), + ), + )); + await tester.pumpAndSettle(); + final center = tester.getCenter(find.byType(DragResizeHandle)); + final gesture = await tester.startGesture(center, kind: PointerDeviceKind.mouse); + await gesture.moveBy(const Offset(50, 0)); // drag right → context shrinks + await tester.pump(); + await gesture.up(); + expect(arr.sizeOf(Slots.contextPanel), 150); + }); + + testWidgets('hovered state flips the line colour without throwing', (tester) async { + final arr = LayoutArrangement(); + arr.applyPreset(const LayoutPresetContribution( + id: 'test-preset', + displayName: 'Test', + slots: [ + LayoutSlot(slot: Slots.sidebar, position: SlotPosition.left, defaultSize: 200), + LayoutSlot(slot: Slots.contextPanel, position: SlotPosition.right, defaultSize: 200), + ], + )); + await tester.pumpWidget(harness( + f, + Center( + child: SizedBox( + width: 40, + height: 200, + child: DragResizeHandle( + arrangement: arr, + slot: Slots.sidebar, + axis: Axis.horizontal, + ), + ), + ), + )); + await tester.pumpAndSettle(); + // Hover over the handle. + final gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); + addTearDown(gesture.removePointer); + await gesture.addPointer(location: tester.getCenter(find.byType(DragResizeHandle))); + await tester.pump(); + // Move pointer away. + await gesture.moveTo(const Offset(0, 0)); + await tester.pump(); + }); + }); +} diff --git a/test/kernel/src/panels/registry_test.dart b/test/kernel/src/panels/registry_test.dart index bb7db3e7..b0446b81 100644 --- a/test/kernel/src/panels/registry_test.dart +++ b/test/kernel/src/panels/registry_test.dart @@ -72,5 +72,39 @@ void main() { )); expect(r.tabsFor(Slots.sidebar), isEmpty); }); + + test('setTabOrder sorts tabsFor by the supplied order; unknown ids sink', () { + final r = PanelRegistry(); + r.registerSlot(const SlotDefinition(id: Slots.sidebar, position: SlotPosition.left)); + r.contribute(_tab(id: 'a', slot: Slots.sidebar)); + r.contribute(_tab(id: 'b', slot: Slots.sidebar)); + r.contribute(_tab(id: 'c', slot: Slots.sidebar)); + expect(r.tabsFor(Slots.sidebar).map((t) => t.id), ['a', 'b', 'c']); + r.setTabOrder(Slots.sidebar, ['c', 'a']); + expect(r.tabsFor(Slots.sidebar).map((t) => t.id), ['c', 'a', 'b']); + }); + + test('definitionFor returns the SlotDefinition by id', () { + final r = PanelRegistry(); + const def = SlotDefinition(id: Slots.sidebar, position: SlotPosition.left); + r.registerSlot(def); + expect(r.definitionFor(Slots.sidebar), def); + expect(r.definitionFor(const SlotId('nope')), isNull); + }); + }); + + group('SlotId', () { + test('equality + hashCode are value-based', () { + const a = SlotId('foo'); + const b = SlotId('foo'); + const c = SlotId('bar'); + expect(a == b, isTrue); + expect(a.hashCode, b.hashCode); + expect(a == c, isFalse); + }); + + test('toString embeds the value', () { + expect(const SlotId('foo').toString(), contains('foo')); + }); }); }