增强变焦功能
This commit is contained in:
@@ -2,6 +2,7 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:recording_tool/features/recording/model/model_recording_session.dart';
|
||||
import 'package:recording_tool/features/recording/platform/recording_channel_names.dart';
|
||||
import 'package:recording_tool/features/recording/view-model/view_model_recording.dart';
|
||||
|
||||
@@ -75,6 +76,83 @@ void main() {
|
||||
expect(session.errorMessage, isNull);
|
||||
});
|
||||
|
||||
test(
|
||||
'passes native ultra-wide ratio when camera capabilities allow it',
|
||||
() async {
|
||||
final calls = <MethodCall>[];
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMethodCallHandler(
|
||||
const MethodChannel(RecordingChannelNames.method),
|
||||
(call) async {
|
||||
calls.add(call);
|
||||
return <String, dynamic>{
|
||||
'zoomRatio': 0.5,
|
||||
'minZoomRatio': 0.5,
|
||||
'maxZoomRatio': 3.0,
|
||||
};
|
||||
},
|
||||
);
|
||||
final container = ProviderContainer();
|
||||
addTearDown(container.dispose);
|
||||
final notifier = container.read(recordingViewModelProvider.notifier);
|
||||
// ignore: invalid_use_of_protected_member
|
||||
notifier.state = container
|
||||
.read(recordingViewModelProvider)
|
||||
.copyWith(
|
||||
session: const RecordingSessionState(
|
||||
zoomRatio: 1.0,
|
||||
minZoomRatio: 0.5,
|
||||
maxZoomRatio: 3.0,
|
||||
),
|
||||
);
|
||||
|
||||
await notifier.setZoomRatio(0.5);
|
||||
|
||||
expect(calls.single.arguments, <String, dynamic>{'zoomRatio': 0.5});
|
||||
final session = container.read(recordingViewModelProvider).session;
|
||||
expect(session.zoomRatio, 0.5);
|
||||
expect(session.minZoomRatio, 0.5);
|
||||
expect(session.maxZoomRatio, 3.0);
|
||||
},
|
||||
);
|
||||
|
||||
test('passes 0.6x to native when camera capabilities allow it', () async {
|
||||
final calls = <MethodCall>[];
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMethodCallHandler(
|
||||
const MethodChannel(RecordingChannelNames.method),
|
||||
(call) async {
|
||||
calls.add(call);
|
||||
return <String, dynamic>{
|
||||
'zoomRatio': 0.6,
|
||||
'minZoomRatio': 0.6,
|
||||
'maxZoomRatio': 3.0,
|
||||
};
|
||||
},
|
||||
);
|
||||
final container = ProviderContainer();
|
||||
addTearDown(container.dispose);
|
||||
final notifier = container.read(recordingViewModelProvider.notifier);
|
||||
// ignore: invalid_use_of_protected_member
|
||||
notifier.state = container
|
||||
.read(recordingViewModelProvider)
|
||||
.copyWith(
|
||||
session: const RecordingSessionState(
|
||||
zoomRatio: 1.0,
|
||||
minZoomRatio: 0.6,
|
||||
maxZoomRatio: 3.0,
|
||||
),
|
||||
);
|
||||
|
||||
await notifier.setZoomRatio(0.6);
|
||||
|
||||
expect(calls.single.arguments, <String, dynamic>{'zoomRatio': 0.6});
|
||||
final session = container.read(recordingViewModelProvider).session;
|
||||
expect(session.zoomRatio, 0.6);
|
||||
expect(session.minZoomRatio, 0.6);
|
||||
expect(session.maxZoomRatio, 3.0);
|
||||
});
|
||||
|
||||
test('clamps requested zoom ratio before invoking native', () async {
|
||||
final calls = <MethodCall>[];
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
@@ -98,6 +176,37 @@ void main() {
|
||||
expect(container.read(recordingViewModelProvider).session.zoomRatio, 1.0);
|
||||
});
|
||||
|
||||
test(
|
||||
'clamps 0.6x to 1x when camera capabilities do not allow it',
|
||||
() async {
|
||||
final calls = <MethodCall>[];
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMethodCallHandler(
|
||||
const MethodChannel(RecordingChannelNames.method),
|
||||
(call) async {
|
||||
calls.add(call);
|
||||
return <String, dynamic>{
|
||||
'zoomRatio': 1.0,
|
||||
'minZoomRatio': 1.0,
|
||||
'maxZoomRatio': 3.0,
|
||||
};
|
||||
},
|
||||
);
|
||||
final container = ProviderContainer();
|
||||
addTearDown(container.dispose);
|
||||
|
||||
await container
|
||||
.read(recordingViewModelProvider.notifier)
|
||||
.setZoomRatio(0.6);
|
||||
|
||||
expect(calls.single.arguments, <String, dynamic>{'zoomRatio': 1.0});
|
||||
expect(
|
||||
container.read(recordingViewModelProvider).session.zoomRatio,
|
||||
1.0,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'keeps previous zoom ratio and stores error when native fails',
|
||||
() async {
|
||||
|
||||
@@ -9,6 +9,7 @@ void main() {
|
||||
double zoomRatio = 1.0,
|
||||
double minZoomRatio = 1.0,
|
||||
double maxZoomRatio = 3.0,
|
||||
bool isRecording = false,
|
||||
ValueChanged<double>? onZoomSelected,
|
||||
}) async {
|
||||
await tester.pumpWidget(
|
||||
@@ -22,7 +23,7 @@ void main() {
|
||||
hasDndAccess: true,
|
||||
isBatteryOptimizedIgnored: true,
|
||||
notificationsGranted: true,
|
||||
isRecording: false,
|
||||
isRecording: isRecording,
|
||||
isStartingRecording: false,
|
||||
isTouchLocked: false,
|
||||
zoomRatio: zoomRatio,
|
||||
@@ -46,35 +47,120 @@ void main() {
|
||||
testWidgets('shows preset zoom buttons', (tester) async {
|
||||
await pumpHud(tester);
|
||||
|
||||
expect(find.text('0.5x'), findsNothing);
|
||||
expect(find.text('0.6x'), findsNothing);
|
||||
expect(find.text('1x'), findsOneWidget);
|
||||
expect(find.text('2x'), findsOneWidget);
|
||||
expect(find.text('3x'), findsOneWidget);
|
||||
expect(find.text('2x'), findsNothing);
|
||||
expect(find.text('3x'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('marks current zoom ratio as selected', (tester) async {
|
||||
await pumpHud(tester, zoomRatio: 2.0);
|
||||
testWidgets('shows 0.6x when 0.5x camera capability supports it', (
|
||||
tester,
|
||||
) async {
|
||||
await pumpHud(tester, minZoomRatio: 0.5);
|
||||
|
||||
expect(find.text('0.5x'), findsNothing);
|
||||
expect(find.text('0.6x'), findsOneWidget);
|
||||
expect(find.text('1x'), findsOneWidget);
|
||||
expect(find.text('2x'), findsNothing);
|
||||
expect(find.text('3x'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('shows 0.6x when 0.6x camera capability supports it', (
|
||||
tester,
|
||||
) async {
|
||||
await pumpHud(tester, minZoomRatio: 0.6);
|
||||
|
||||
expect(find.text('0.6x'), findsOneWidget);
|
||||
expect(find.text('1x'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('marks current 0.5x zoom ratio as selected on 0.6x UI', (
|
||||
tester,
|
||||
) async {
|
||||
await pumpHud(tester, zoomRatio: 0.5, minZoomRatio: 0.5);
|
||||
|
||||
final selectedButton = tester.widget<TextButton>(
|
||||
find.ancestor(of: find.text('2x'), matching: find.byType(TextButton)),
|
||||
find.ancestor(of: find.text('0.6x'), matching: find.byType(TextButton)),
|
||||
);
|
||||
expect(selectedButton.enabled, isFalse);
|
||||
});
|
||||
|
||||
testWidgets('marks current 0.6x zoom ratio as selected', (tester) async {
|
||||
await pumpHud(tester, zoomRatio: 0.6, minZoomRatio: 0.6);
|
||||
|
||||
final selectedButton = tester.widget<TextButton>(
|
||||
find.ancestor(of: find.text('0.6x'), matching: find.byType(TextButton)),
|
||||
);
|
||||
expect(selectedButton.enabled, isFalse);
|
||||
});
|
||||
|
||||
testWidgets('does not expose presets beyond max zoom ratio', (tester) async {
|
||||
await pumpHud(tester, maxZoomRatio: 2.0);
|
||||
await pumpHud(tester, minZoomRatio: 0.5, maxZoomRatio: 0.55);
|
||||
|
||||
expect(find.text('1x'), findsOneWidget);
|
||||
expect(find.text('2x'), findsOneWidget);
|
||||
expect(find.text('3x'), findsNothing);
|
||||
expect(find.text('0.6x'), findsNothing);
|
||||
expect(find.text('1x'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('tapping zoom preset reports selected ratio', (tester) async {
|
||||
testWidgets('tapping 0.6x reports 0.5 when camera supports 0.5x', (
|
||||
tester,
|
||||
) async {
|
||||
double? selected;
|
||||
await pumpHud(tester, onZoomSelected: (ratio) => selected = ratio);
|
||||
await pumpHud(
|
||||
tester,
|
||||
minZoomRatio: 0.5,
|
||||
onZoomSelected: (ratio) => selected = ratio,
|
||||
);
|
||||
|
||||
await tester.tap(find.text('2x'));
|
||||
await tester.tap(find.text('0.6x'));
|
||||
await tester.pump();
|
||||
|
||||
expect(selected, 2.0);
|
||||
expect(selected, 0.5);
|
||||
});
|
||||
|
||||
testWidgets('tapping 0.6x reports 0.6 when camera only supports 0.6x', (
|
||||
tester,
|
||||
) async {
|
||||
double? selected;
|
||||
await pumpHud(
|
||||
tester,
|
||||
minZoomRatio: 0.6,
|
||||
onZoomSelected: (ratio) => selected = ratio,
|
||||
);
|
||||
|
||||
await tester.tap(find.text('0.6x'));
|
||||
await tester.pump();
|
||||
|
||||
expect(selected, 0.6);
|
||||
});
|
||||
|
||||
testWidgets('disables 0.6x while recording on main camera', (tester) async {
|
||||
await pumpHud(tester, minZoomRatio: 0.5, isRecording: true);
|
||||
|
||||
final ultraWideButton = tester.widget<TextButton>(
|
||||
find.ancestor(of: find.text('0.6x'), matching: find.byType(TextButton)),
|
||||
);
|
||||
final mainButton = tester.widget<TextButton>(
|
||||
find.ancestor(of: find.text('1x'), matching: find.byType(TextButton)),
|
||||
);
|
||||
|
||||
expect(ultraWideButton.enabled, isFalse);
|
||||
expect(mainButton.enabled, isFalse);
|
||||
});
|
||||
|
||||
testWidgets('disables main zoom presets while recording on 0.5x', (
|
||||
tester,
|
||||
) async {
|
||||
await pumpHud(tester, zoomRatio: 0.5, minZoomRatio: 0.5, isRecording: true);
|
||||
|
||||
final ultraWideButton = tester.widget<TextButton>(
|
||||
find.ancestor(of: find.text('0.6x'), matching: find.byType(TextButton)),
|
||||
);
|
||||
final mainButton = tester.widget<TextButton>(
|
||||
find.ancestor(of: find.text('1x'), matching: find.byType(TextButton)),
|
||||
);
|
||||
|
||||
expect(ultraWideButton.enabled, isFalse);
|
||||
expect(mainButton.enabled, isFalse);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user