mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2025-01-18 19:30:43 +00:00
added scenarios for timer golden test
This commit is contained in:
parent
c8617ec00b
commit
6abb720b92
5 changed files with 142 additions and 154 deletions
|
@ -1,7 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:lightmeter/data/models/exposure_pair.dart';
|
import 'package:lightmeter/data/models/exposure_pair.dart';
|
||||||
import 'package:lightmeter/interactors/metering_interactor.dart';
|
|
||||||
import 'package:lightmeter/interactors/timer_interactor.dart';
|
import 'package:lightmeter/interactors/timer_interactor.dart';
|
||||||
import 'package:lightmeter/providers/services_provider.dart';
|
import 'package:lightmeter/providers/services_provider.dart';
|
||||||
import 'package:lightmeter/screens/timer/bloc_timer.dart';
|
import 'package:lightmeter/screens/timer/bloc_timer.dart';
|
||||||
|
|
|
@ -22,10 +22,11 @@ class TimerScreen extends StatefulWidget {
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<TimerScreen> createState() => _TimerScreenState();
|
State<TimerScreen> createState() => TimerScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TimerScreenState extends State<TimerScreen> with TickerProviderStateMixin {
|
@visibleForTesting
|
||||||
|
class TimerScreenState extends State<TimerScreen> with TickerProviderStateMixin {
|
||||||
late AnimationController timelineController;
|
late AnimationController timelineController;
|
||||||
late Animation<double> timelineAnimation;
|
late Animation<double> timelineAnimation;
|
||||||
late AnimationController startStopIconController;
|
late AnimationController startStopIconController;
|
||||||
|
@ -47,12 +48,6 @@ class _TimerScreenState extends State<TimerScreen> with TickerProviderStateMixin
|
||||||
startStopIconAnimation = Tween<double>(begin: 0, end: 1).animate(startStopIconController);
|
startStopIconAnimation = Tween<double>(begin: 0, end: 1).animate(startStopIconController);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
context.read<TimerBloc>().add(const StartTimerEvent());
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
timelineController.dispose();
|
timelineController.dispose();
|
||||||
|
@ -113,7 +108,7 @@ class _TimerScreenState extends State<TimerScreen> with TickerProviderStateMixin
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
right: Navigator.of(context).canPop() ? const CloseButton() : null,
|
right: const CloseButton(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
BIN
test/screens/timer/goldens/timer_screen.png
Normal file
BIN
test/screens/timer/goldens/timer_screen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 785 KiB |
|
@ -1,144 +0,0 @@
|
||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:golden_toolkit/golden_toolkit.dart';
|
|
||||||
import 'package:lightmeter/data/models/ev_source_type.dart';
|
|
||||||
import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
|
|
||||||
import 'package:lightmeter/data/models/theme_type.dart';
|
|
||||||
import 'package:lightmeter/data/shared_prefs_service.dart';
|
|
||||||
import 'package:lightmeter/providers/user_preferences_provider.dart';
|
|
||||||
import 'package:lightmeter/screens/metering/flow_metering.dart';
|
|
||||||
import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
|
|
||||||
import '../../../integration_test/utils/finder_actions.dart';
|
|
||||||
import '../../../integration_test/utils/platform_channel_mock.dart';
|
|
||||||
import '../../application_mock.dart';
|
|
||||||
|
|
||||||
class _MeteringScreenConfig {
|
|
||||||
final IAPProductStatus iapProductStatus;
|
|
||||||
final EvSourceType evSourceType;
|
|
||||||
|
|
||||||
_MeteringScreenConfig(
|
|
||||||
this.iapProductStatus,
|
|
||||||
this.evSourceType,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
final buffer = StringBuffer();
|
|
||||||
buffer.write(iapProductStatus.toString().split('.')[1]);
|
|
||||||
buffer.write(' - ');
|
|
||||||
buffer.write(evSourceType.toString().split('.')[1]);
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final _testScenarios = [IAPProductStatus.purchased, IAPProductStatus.purchasable].expand(
|
|
||||||
(iapProductStatus) => EvSourceType.values.map(
|
|
||||||
(evSourceType) => _MeteringScreenConfig(iapProductStatus, evSourceType),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
Future<void> setEvSource(WidgetTester tester, Key scenarioWidgetKey, EvSourceType evSourceType) async {
|
|
||||||
final flow = find.descendant(
|
|
||||||
of: find.byKey(scenarioWidgetKey),
|
|
||||||
matching: find.byType(MeteringFlow),
|
|
||||||
);
|
|
||||||
final BuildContext context = tester.element(flow);
|
|
||||||
if (UserPreferencesProvider.evSourceTypeOf(context) != evSourceType) {
|
|
||||||
UserPreferencesProvider.of(context).toggleEvSourceType();
|
|
||||||
}
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> setTheme(WidgetTester tester, Key scenarioWidgetKey, ThemeType themeType) async {
|
|
||||||
final flow = find.descendant(
|
|
||||||
of: find.byKey(scenarioWidgetKey),
|
|
||||||
matching: find.byType(MeteringFlow),
|
|
||||||
);
|
|
||||||
final BuildContext context = tester.element(flow);
|
|
||||||
UserPreferencesProvider.of(context).setThemeType(themeType);
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> takePhoto(WidgetTester tester, Key scenarioWidgetKey) async {
|
|
||||||
final button = find.descendant(
|
|
||||||
of: find.byKey(scenarioWidgetKey),
|
|
||||||
matching: find.measureButton(),
|
|
||||||
);
|
|
||||||
await tester.tap(button);
|
|
||||||
await tester.pump(const Duration(seconds: 2)); // wait for circular progress indicator
|
|
||||||
await tester.pump(const Duration(seconds: 1)); // wait for circular progress indicator
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> toggleIncidentMetering(WidgetTester tester, Key scenarioWidgetKey, double ev) async {
|
|
||||||
final button = find.descendant(
|
|
||||||
of: find.byKey(scenarioWidgetKey),
|
|
||||||
matching: find.measureButton(),
|
|
||||||
);
|
|
||||||
await tester.tap(button);
|
|
||||||
await sendMockIncidentEv(ev);
|
|
||||||
await tester.tap(button);
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
}
|
|
||||||
|
|
||||||
setUpAll(() {
|
|
||||||
SharedPreferences.setMockInitialValues({
|
|
||||||
UserPreferencesService.evSourceTypeKey: EvSourceType.camera.index,
|
|
||||||
UserPreferencesService.meteringScreenLayoutKey: json.encode(
|
|
||||||
{
|
|
||||||
MeteringScreenLayoutFeature.equipmentProfiles: true,
|
|
||||||
MeteringScreenLayoutFeature.extremeExposurePairs: true,
|
|
||||||
MeteringScreenLayoutFeature.filmPicker: true,
|
|
||||||
}.toJson(),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
testGoldens(
|
|
||||||
'MeteringScreen golden test',
|
|
||||||
(tester) async {
|
|
||||||
final builder = DeviceBuilder();
|
|
||||||
for (final scenario in _testScenarios) {
|
|
||||||
builder.addScenario(
|
|
||||||
name: scenario.toString(),
|
|
||||||
widget: _MockMeteringFlow(productStatus: scenario.iapProductStatus),
|
|
||||||
onCreate: (scenarioWidgetKey) async {
|
|
||||||
await setEvSource(tester, scenarioWidgetKey, scenario.evSourceType);
|
|
||||||
if (scenarioWidgetKey.toString().contains('Dark')) {
|
|
||||||
await setTheme(tester, scenarioWidgetKey, ThemeType.dark);
|
|
||||||
}
|
|
||||||
if (scenario.evSourceType == EvSourceType.camera) {
|
|
||||||
await takePhoto(tester, scenarioWidgetKey);
|
|
||||||
} else {
|
|
||||||
await toggleIncidentMetering(tester, scenarioWidgetKey, 7.3);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
await tester.pumpDeviceBuilder(builder);
|
|
||||||
await screenMatchesGolden(
|
|
||||||
tester,
|
|
||||||
'metering_screen',
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class _MockMeteringFlow extends StatelessWidget {
|
|
||||||
final IAPProductStatus productStatus;
|
|
||||||
|
|
||||||
const _MockMeteringFlow({required this.productStatus});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return GoldenTestApplicationMock(
|
|
||||||
productStatus: productStatus,
|
|
||||||
child: const MeteringFlow(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
138
test/screens/timer/screen_timer_golden_test.dart
Normal file
138
test/screens/timer/screen_timer_golden_test.dart
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:golden_toolkit/golden_toolkit.dart';
|
||||||
|
import 'package:lightmeter/data/models/exposure_pair.dart';
|
||||||
|
import 'package:lightmeter/data/models/theme_type.dart';
|
||||||
|
import 'package:lightmeter/providers/user_preferences_provider.dart';
|
||||||
|
import 'package:lightmeter/res/dimens.dart';
|
||||||
|
import 'package:lightmeter/screens/shared/animated_circular_button/widget_button_circular_animated.dart';
|
||||||
|
import 'package:lightmeter/screens/timer/flow_timer.dart';
|
||||||
|
import 'package:lightmeter/screens/timer/screen_timer.dart';
|
||||||
|
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../../application_mock.dart';
|
||||||
|
|
||||||
|
class _TimerScreenConfig {
|
||||||
|
final ShutterSpeedValue shutterSpeedValue;
|
||||||
|
final bool isStopped;
|
||||||
|
|
||||||
|
_TimerScreenConfig({
|
||||||
|
required this.shutterSpeedValue,
|
||||||
|
required this.isStopped,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
final buffer = StringBuffer();
|
||||||
|
buffer.write(shutterSpeedValue.toString());
|
||||||
|
buffer.write(' - ');
|
||||||
|
buffer.write(isStopped ? 'stopped' : 'resumed');
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final _testScenarios = [
|
||||||
|
const ShutterSpeedValue(
|
||||||
|
74,
|
||||||
|
false,
|
||||||
|
StopType.full,
|
||||||
|
),
|
||||||
|
const ShutterSpeedValue(
|
||||||
|
3642,
|
||||||
|
false,
|
||||||
|
StopType.full,
|
||||||
|
),
|
||||||
|
].expand(
|
||||||
|
(shutterSpeedValue) => [
|
||||||
|
_TimerScreenConfig(shutterSpeedValue: shutterSpeedValue, isStopped: true),
|
||||||
|
_TimerScreenConfig(shutterSpeedValue: shutterSpeedValue, isStopped: false),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
Future<void> setTheme(WidgetTester tester, Key scenarioWidgetKey, ThemeType themeType) async {
|
||||||
|
final flow = find.descendant(
|
||||||
|
of: find.byKey(scenarioWidgetKey),
|
||||||
|
matching: find.byType(TimerFlow),
|
||||||
|
);
|
||||||
|
final BuildContext context = tester.element(flow);
|
||||||
|
UserPreferencesProvider.of(context).setThemeType(themeType);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> toggleTimer(WidgetTester tester, Key scenarioWidgetKey) async {
|
||||||
|
final button = find.descendant(
|
||||||
|
of: find.byKey(scenarioWidgetKey),
|
||||||
|
matching: find.byType(AnimatedCircluarButton),
|
||||||
|
);
|
||||||
|
await tester.tap(button);
|
||||||
|
await tester.pump(Dimens.durationS);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> mockResumedState(WidgetTester tester, Key scenarioWidgetKey) async {
|
||||||
|
final screen = find.descendant(
|
||||||
|
of: find.byKey(scenarioWidgetKey),
|
||||||
|
matching: find.byType(TimerScreen),
|
||||||
|
);
|
||||||
|
final TimerScreenState state = tester.state(screen);
|
||||||
|
state.startStopIconController.stop();
|
||||||
|
state.timelineController.stop();
|
||||||
|
await tester.pump();
|
||||||
|
}
|
||||||
|
|
||||||
|
setUpAll(() {
|
||||||
|
SharedPreferences.setMockInitialValues({});
|
||||||
|
});
|
||||||
|
|
||||||
|
testGoldens(
|
||||||
|
'TimerScreen golden test',
|
||||||
|
(tester) async {
|
||||||
|
final builder = DeviceBuilder();
|
||||||
|
for (final scenario in _testScenarios) {
|
||||||
|
builder.addScenario(
|
||||||
|
name: scenario.toString(),
|
||||||
|
widget: _MockTimerFlow(scenario.shutterSpeedValue),
|
||||||
|
onCreate: (scenarioWidgetKey) async {
|
||||||
|
if (scenarioWidgetKey.toString().contains('Dark')) {
|
||||||
|
await setTheme(tester, scenarioWidgetKey, ThemeType.dark);
|
||||||
|
}
|
||||||
|
await toggleTimer(tester, scenarioWidgetKey);
|
||||||
|
late final skipTimerDuration = Duration(
|
||||||
|
milliseconds: (scenario.shutterSpeedValue.value * 0.35 * Duration.millisecondsPerSecond).toInt(),
|
||||||
|
);
|
||||||
|
await tester.pump(skipTimerDuration);
|
||||||
|
if (scenario.isStopped) {
|
||||||
|
await toggleTimer(tester, scenarioWidgetKey);
|
||||||
|
} else {
|
||||||
|
await mockResumedState(tester, scenarioWidgetKey);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await tester.pumpDeviceBuilder(builder);
|
||||||
|
await screenMatchesGolden(
|
||||||
|
tester,
|
||||||
|
'timer_screen',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MockTimerFlow extends StatelessWidget {
|
||||||
|
final ShutterSpeedValue shutterSpeedValue;
|
||||||
|
|
||||||
|
const _MockTimerFlow(this.shutterSpeedValue);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GoldenTestApplicationMock(
|
||||||
|
child: TimerFlow(
|
||||||
|
exposurePair: ExposurePair(
|
||||||
|
ApertureValue.values.first,
|
||||||
|
shutterSpeedValue,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue