mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-26 09:20:45 +00:00
wip
This commit is contained in:
parent
deb1ac3282
commit
4a88bad074
5 changed files with 170 additions and 4 deletions
13
.vscode/launch.json
vendored
13
.vscode/launch.json
vendored
|
@ -8,6 +8,7 @@
|
||||||
"name": "dev (android)",
|
"name": "dev (android)",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "dart",
|
"type": "dart",
|
||||||
|
"flutterMode": "profile",
|
||||||
"args": [
|
"args": [
|
||||||
"--flavor",
|
"--flavor",
|
||||||
"dev",
|
"dev",
|
||||||
|
@ -52,5 +53,17 @@
|
||||||
],
|
],
|
||||||
"program": "${workspaceFolder}/lib/main_prod.dart",
|
"program": "${workspaceFolder}/lib/main_prod.dart",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Integration Test",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "dart",
|
||||||
|
"args": [
|
||||||
|
"--flavor",
|
||||||
|
"prod",
|
||||||
|
"--dart-define",
|
||||||
|
"cameraPreviewAspectRatio=240/320",
|
||||||
|
],
|
||||||
|
"program": "${workspaceFolder}/integration_test/widget_dialog_animated_test.dart",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
61
integration_test/mocks/application_mock.dart
Normal file
61
integration_test/mocks/application_mock.dart
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
import 'package:lightmeter/data/models/theme_type.dart';
|
||||||
|
import 'package:lightmeter/data/shared_prefs_service.dart';
|
||||||
|
import 'package:lightmeter/generated/l10n.dart';
|
||||||
|
import 'package:lightmeter/providers/theme_provider.dart';
|
||||||
|
import 'package:lightmeter/utils/inherited_generics.dart';
|
||||||
|
import 'package:mocktail/mocktail.dart';
|
||||||
|
|
||||||
|
class _MockUserPreferencesService extends Mock implements UserPreferencesService {}
|
||||||
|
|
||||||
|
class ApplicationMock extends StatefulWidget {
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const ApplicationMock({required this.child, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ApplicationMock> createState() => _ApplicationMockState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ApplicationMockState extends State<ApplicationMock> {
|
||||||
|
late final _MockUserPreferencesService userPreferencesService;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
userPreferencesService = _MockUserPreferencesService();
|
||||||
|
when(() => userPreferencesService.themeType).thenReturn(ThemeType.light);
|
||||||
|
when(() => userPreferencesService.primaryColor)
|
||||||
|
.thenReturn(ThemeProvider.primaryColorsList.first);
|
||||||
|
when(() => userPreferencesService.dynamicColor).thenReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return InheritedWidgetBase<UserPreferencesService>(
|
||||||
|
data: userPreferencesService,
|
||||||
|
child: ThemeProvider(
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
return MaterialApp(
|
||||||
|
theme: context.listen<ThemeData>(),
|
||||||
|
localizationsDelegates: const [
|
||||||
|
S.delegate,
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
],
|
||||||
|
supportedLocales: S.delegate.supportedLocales,
|
||||||
|
builder: (context, child) => MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
|
||||||
|
child: child!,
|
||||||
|
),
|
||||||
|
home: widget.child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
84
integration_test/widget_dialog_animated_test.dart
Normal file
84
integration_test/widget_dialog_animated_test.dart
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:integration_test/integration_test.dart';
|
||||||
|
import 'package:lightmeter/data/models/film.dart';
|
||||||
|
import 'package:lightmeter/res/dimens.dart';
|
||||||
|
import 'package:lightmeter/screens/metering/components/shared/readings_container/components/animated_dialog_picker/widget_picker_dialog_animated.dart';
|
||||||
|
import 'package:lightmeter/screens/metering/components/shared/readings_container/components/reading_value_container/widget_container_reading_value.dart';
|
||||||
|
|
||||||
|
import 'mocks/application_mock.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
group('AnimatedDialogPicker test', () {
|
||||||
|
testWidgets('Tap on `ReadingValueContainer`, verify opened', (tester) async {
|
||||||
|
await tester.pumpWidget(const ApplicationMock(child: AnimatedPickerTest()));
|
||||||
|
expect(find.text('Film'), findsOneWidget);
|
||||||
|
expect(find.text('None'), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tap(find.byType(AnimatedDialogPicker<Film>));
|
||||||
|
await tester.pumpAndSettle(Dimens.durationL);
|
||||||
|
expect(find.text('Film'), findsNWidgets(2));
|
||||||
|
expect(find.text('None'), findsNWidgets(2));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnimatedPickerTest extends StatefulWidget {
|
||||||
|
const AnimatedPickerTest({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AnimatedPickerTest> createState() => _AnimatedPickerTestState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AnimatedPickerTestState extends State<AnimatedPickerTest> {
|
||||||
|
Film _selectedFilm = Film.values.first;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Center(
|
||||||
|
child: _FilmPicker(
|
||||||
|
values: Film.values,
|
||||||
|
selectedValue: _selectedFilm,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_selectedFilm = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FilmPicker extends StatelessWidget {
|
||||||
|
final List<Film> values;
|
||||||
|
final Film selectedValue;
|
||||||
|
final ValueChanged<Film> onChanged;
|
||||||
|
|
||||||
|
const _FilmPicker({
|
||||||
|
required this.values,
|
||||||
|
required this.selectedValue,
|
||||||
|
required this.onChanged,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnimatedDialogPicker<Film>(
|
||||||
|
icon: Icons.camera_roll,
|
||||||
|
title: "Film",
|
||||||
|
selectedValue: selectedValue,
|
||||||
|
values: values,
|
||||||
|
itemTitleBuilder: (_, value) => Text(value.name.isEmpty ? 'None' : value.name),
|
||||||
|
onChanged: onChanged,
|
||||||
|
closedChild: ReadingValueContainer.singleValue(
|
||||||
|
value: ReadingValue(
|
||||||
|
label: "Film",
|
||||||
|
value: selectedValue.name.isEmpty ? 'None' : selectedValue.name,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -294,6 +294,7 @@ class _AnimatedSwitcher extends StatelessWidget {
|
||||||
return Stack(
|
return Stack(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
// https://api.flutter.dev/flutter/widgets/Opacity-class.html#performance-considerations-for-opacity-animation
|
||||||
Opacity(
|
Opacity(
|
||||||
opacity: closedOpacityAnimation.value,
|
opacity: closedOpacityAnimation.value,
|
||||||
child: Transform.scale(
|
child: Transform.scale(
|
||||||
|
@ -304,10 +305,15 @@ class _AnimatedSwitcher extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Opacity(
|
|
||||||
opacity: openedOpacityAnimation.value,
|
/// When dialog is only started expanding there is too little horizontal space,
|
||||||
child: openedChild,
|
/// which leads to the failed ListTile assertion (listTileWidget != leading.width).
|
||||||
),
|
/// So we show the picker only when it makes sense as it begins to be less opaque.
|
||||||
|
if (openedOpacityAnimation.value != 0)
|
||||||
|
Opacity(
|
||||||
|
opacity: openedOpacityAnimation.value,
|
||||||
|
child: openedChild,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
google_fonts: 3.0.1
|
google_fonts: 3.0.1
|
||||||
|
integration_test:
|
||||||
|
sdk: flutter
|
||||||
lint: 2.1.2
|
lint: 2.1.2
|
||||||
mocktail: 0.3.0
|
mocktail: 0.3.0
|
||||||
test: 1.24.1
|
test: 1.24.1
|
||||||
|
|
Loading…
Reference in a new issue