test sweep: kernel/src/panels foundational coverage (T-91)
test / unit + widget + golden + a11y (push) Failing after 30s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
test / dart doc (lib API) (push) Failing after 1m2s

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) <noreply@anthropic.com>
This commit is contained in:
2026-05-14 11:58:09 +02:00
co-authored by Claude Opus 4.7
parent 72a3dce4a3
commit 0c063b835e
3 changed files with 157 additions and 1 deletions
+1 -1
View File
@@ -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
@@ -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();
});
});
}
+34
View File
@@ -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'));
});
});
}