test sweep: cover WelcomeView open-project dialog (T-91) — crosses 90%
test / unit + widget + golden + a11y (push) Failing after 33s
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
test / unit + widget + golden + a11y (push) Failing after 33s
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
Four widget tests in test/builtin/welcome/dialog_test.dart driving the WelcomeView open-folder fallback dialog. Uses a custom harness that wraps the standard widget harness in a DialogHost so the kernel.dialog.show() call inside _openFolder actually renders. - MissingPluginException on pickDirectory → _OpenProjectDialog appears with the expected title / hint / Cancel / Open chrome. - Cancel dismisses the modal cleanly. - Open with an empty path is a no-op (early return in _submit). - Open with a non-repo path keeps the dialog (project.open returns false, _loading flag flips back). Coverage clears the **90% T-91 target**: 89.93% -> 90.53%. Floor bumped to 90. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -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: 89
|
||||
coverage_floor: 90
|
||||
|
||||
# Project metadata (was project.yaml, folded in per D-056).
|
||||
# version: above is the single source of truth. The Makefile reads
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/// Tests for the welcome view's open-project + not-a-repo dialogs.
|
||||
/// Uses a custom harness that wraps the standard widget harness in a
|
||||
/// DialogHost so kernel.dialog.show calls actually render their
|
||||
/// builder into the tree.
|
||||
library;
|
||||
|
||||
import 'package:clide/builtin/welcome/src/welcome_view.dart';
|
||||
import 'package:clide/kernel/kernel.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../helpers/kernel_fixture.dart';
|
||||
import '../../helpers/widget_harness.dart';
|
||||
|
||||
/// Wraps [harness] in a DialogHost rooted on the fixture's dialog
|
||||
/// router so kernel.dialog.show(...) calls render into the tree.
|
||||
Widget _harness(KernelFixture f, Widget child) {
|
||||
return harness(
|
||||
f,
|
||||
DialogHost(router: f.services.dialog, child: child),
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
group('WelcomeView dialogs', () {
|
||||
late KernelFixture f;
|
||||
setUp(() async {
|
||||
f = await KernelFixture.create(
|
||||
i18nCatalogs: {
|
||||
'builtin.welcome': {
|
||||
const Locale('en', 'US'): const {
|
||||
'title': {'translation': 'clide'},
|
||||
'subtitle': {'translation': 'IDE'},
|
||||
'open-project': {'translation': 'Open project'},
|
||||
'open-project.hint': {'translation': 'Pick a git repository'},
|
||||
'tab.title': {'translation': 'Welcome'},
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
tearDown(() async => f.dispose());
|
||||
|
||||
testWidgets('MissingPluginException path renders the OpenProjectDialog', (tester) async {
|
||||
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||
const MethodChannel('clide/window'),
|
||||
(call) async {
|
||||
if (call.method == 'pickDirectory') {
|
||||
throw MissingPluginException();
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
tester.view.physicalSize = const Size(1200, 800);
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
await tester.pumpWidget(_harness(f, const WelcomeView()));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Open folder…'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Open project'), findsOneWidget);
|
||||
expect(find.text('Enter the path to a git repository.'), findsOneWidget);
|
||||
expect(find.text('Cancel'), findsOneWidget);
|
||||
expect(find.text('Open'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('OpenProjectDialog Cancel dismisses the modal', (tester) async {
|
||||
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||
const MethodChannel('clide/window'),
|
||||
(call) async => throw MissingPluginException(),
|
||||
);
|
||||
tester.view.physicalSize = const Size(1200, 800);
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
await tester.pumpWidget(_harness(f, const WelcomeView()));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Open folder…'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Cancel'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Open project'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('OpenProjectDialog Open with empty path is a no-op', (tester) async {
|
||||
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||
const MethodChannel('clide/window'),
|
||||
(call) async => throw MissingPluginException(),
|
||||
);
|
||||
tester.view.physicalSize = const Size(1200, 800);
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
await tester.pumpWidget(_harness(f, const WelcomeView()));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Open folder…'));
|
||||
await tester.pumpAndSettle();
|
||||
// Press Open with the text field empty.
|
||||
await tester.tap(find.text('Open'));
|
||||
await tester.pumpAndSettle();
|
||||
// Dialog stays.
|
||||
expect(find.text('Open project'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('OpenProjectDialog Open with a non-repo path keeps the dialog (project.open returns false)', (tester) async {
|
||||
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||
const MethodChannel('clide/window'),
|
||||
(call) async => throw MissingPluginException(),
|
||||
);
|
||||
tester.view.physicalSize = const Size(1200, 800);
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
addTearDown(tester.view.resetPhysicalSize);
|
||||
addTearDown(tester.view.resetDevicePixelRatio);
|
||||
await tester.pumpWidget(_harness(f, const WelcomeView()));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Open folder…'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.enterText(find.byType(EditableText).last, '/tmp/clide-not-a-repo-${DateTime.now().microsecondsSinceEpoch}');
|
||||
await tester.testTextInput.receiveAction(TextInputAction.done);
|
||||
await tester.pumpAndSettle();
|
||||
// project.open returns false → dialog stays open, "Opening…" no
|
||||
// longer shows.
|
||||
expect(find.text('Open project'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user