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')); + }); }); }