test(i18n): cover the i18n facade, selector, manifest routing + locale (T-462)
Tests for the epic's new code so the 95% floor holds: ClideSettings.i18n string/interpolated null-safe + localizedCommandTitle; settings-renderer localization (section/field/help/select/file, project-scope tag, didUpdateWidget); extension-activation rollback + settings-contribution unregister; the Dutch gate check; RootShell applying app.locale on boot; and prompt/conversation tool-body + file-ref coverage. Also harden the menu toggle re-tap (capture the button point while stable, then tapAt) so it no longer throws getCenter under the serial coverage load. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import 'package:clide/clide.dart' show IpcResponse;
|
||||
import 'package:clide/extension/extension.dart' show CommandContribution;
|
||||
import 'package:clide/widgets/widgets.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@@ -40,4 +42,66 @@ void main() {
|
||||
expect(mono, 'FiraMono');
|
||||
expect(ui, 'Inter');
|
||||
});
|
||||
|
||||
testWidgets('i18n.string returns the placeholder without a kernel (T-462)', (tester) async {
|
||||
late String s;
|
||||
await tester.pumpWidget(
|
||||
Builder(
|
||||
builder: (context) {
|
||||
s = ClideSettings.i18n.string(context, 'k', namespace: 'x', placeholder: 'Fallback');
|
||||
return const SizedBox();
|
||||
},
|
||||
),
|
||||
);
|
||||
expect(s, 'Fallback');
|
||||
});
|
||||
|
||||
testWidgets('i18n.interpolated applies replacers to the placeholder without a kernel', (tester) async {
|
||||
late String s;
|
||||
await tester.pumpWidget(
|
||||
Builder(
|
||||
builder: (context) {
|
||||
s = ClideSettings.i18n.interpolated(
|
||||
context,
|
||||
'k',
|
||||
namespace: 'x',
|
||||
placeholder: 'Hi {name}',
|
||||
replacers: [I18nReplacer(from: '{name}', replace: 'Jeroen')],
|
||||
);
|
||||
return const SizedBox();
|
||||
},
|
||||
),
|
||||
);
|
||||
expect(s, 'Hi Jeroen');
|
||||
});
|
||||
|
||||
testWidgets('localizedCommandTitle resolves titleKey, else falls back to the title (T-462)', (tester) async {
|
||||
final withKey = CommandContribution(
|
||||
id: 'a',
|
||||
command: 'a',
|
||||
title: 'Eng A',
|
||||
titleKey: 'cmd.a',
|
||||
i18nNamespace: 'x',
|
||||
run: (_) async => IpcResponse.ok(id: '', data: const {}),
|
||||
);
|
||||
final noKey = CommandContribution(
|
||||
id: 'b',
|
||||
command: 'b',
|
||||
title: 'Eng B',
|
||||
run: (_) async => IpcResponse.ok(id: '', data: const {}),
|
||||
);
|
||||
late String a;
|
||||
late String b;
|
||||
await tester.pumpWidget(
|
||||
Builder(
|
||||
builder: (context) {
|
||||
a = localizedCommandTitle(context, withKey); // no kernel → placeholder (the title)
|
||||
b = localizedCommandTitle(context, noKey);
|
||||
return const SizedBox();
|
||||
},
|
||||
),
|
||||
);
|
||||
expect(a, 'Eng A');
|
||||
expect(b, 'Eng B');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -162,6 +162,38 @@ void main() {
|
||||
expect(find.text('Hoverable'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('hovering a NON-selected palette row paints the hover background', (tester) async {
|
||||
// The first row is selected (selectedIndex 0), so its color comes from the
|
||||
// `selected` branch. Hovering the SECOND (unselected) row exercises the
|
||||
// `_hover ? listItemHoverBackground` arm that the selected row skips.
|
||||
f.services.commands.register(
|
||||
CommandContribution(
|
||||
id: 'h1',
|
||||
command: 'first.cmd',
|
||||
title: 'FirstRow',
|
||||
run: (_) async => IpcResponse.ok(id: '', data: const {}),
|
||||
),
|
||||
);
|
||||
f.services.commands.register(
|
||||
CommandContribution(
|
||||
id: 'h2',
|
||||
command: 'second.cmd',
|
||||
title: 'SecondRow',
|
||||
run: (_) async => IpcResponse.ok(id: '', data: const {}),
|
||||
),
|
||||
);
|
||||
f.services.palette.open();
|
||||
await tester.pumpWidget(harness(f, Stack(children: const [ClidePalette()])));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
|
||||
addTearDown(gesture.removePointer);
|
||||
await gesture.addPointer(location: Offset.zero);
|
||||
await gesture.moveTo(tester.getCenter(find.text('SecondRow')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('SecondRow'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('arrow keys move the highlighted command (T-100)', (tester) async {
|
||||
for (final id in ['a', 'b', 'c']) {
|
||||
f.services.commands.register(
|
||||
|
||||
Reference in New Issue
Block a user