oke
This commit is contained in:
parent
5913bd0366
commit
f3ab71616e
|
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:monitoring_repository/monitoring_repository.dart';
|
import 'package:monitoring_repository/monitoring_repository.dart';
|
||||||
import '../../../blocs/authentication_bloc/authentication_bloc.dart';
|
import '../../../blocs/authentication_bloc/authentication_bloc.dart';
|
||||||
<<<<<<< HEAD
|
|
||||||
import '../../../blocs/notification_bloc/notification_bloc.dart';
|
import '../../../blocs/notification_bloc/notification_bloc.dart';
|
||||||
import '../../monitoring/wind_speed/blocs/wind_speed_bloc.dart';
|
import '../../monitoring/wind_speed/blocs/wind_speed_bloc.dart';
|
||||||
import '../../monitoring/evaporasi/blocs/evaporasi_bloc.dart';
|
import '../../monitoring/evaporasi/blocs/evaporasi_bloc.dart';
|
||||||
|
|
@ -10,8 +9,6 @@ import '../../monitoring/atmospheric_conditions/blocs/atmospheric_conditions_blo
|
||||||
import '../widgets/notification_panel.dart';
|
import '../widgets/notification_panel.dart';
|
||||||
import '../widgets/sensor_grid.dart';
|
import '../widgets/sensor_grid.dart';
|
||||||
import '../widgets/dashboard_charts.dart';
|
import '../widgets/dashboard_charts.dart';
|
||||||
=======
|
|
||||||
>>>>>>> parent of 6f38d3b (update evaporsi)
|
|
||||||
import 'main_drawer.dart';
|
import 'main_drawer.dart';
|
||||||
|
|
||||||
class HomeScreen extends StatefulWidget {
|
class HomeScreen extends StatefulWidget {
|
||||||
|
|
@ -100,7 +97,6 @@ class _HomeScreenState extends State<HomeScreen>
|
||||||
height: 90,
|
height: 90,
|
||||||
fit: BoxFit.contain,
|
fit: BoxFit.contain,
|
||||||
),
|
),
|
||||||
<<<<<<< HEAD
|
|
||||||
actions: [
|
actions: [
|
||||||
// Icon lonceng dengan badge
|
// Icon lonceng dengan badge
|
||||||
BlocBuilder<NotificationBloc, NotificationState>(
|
BlocBuilder<NotificationBloc, NotificationState>(
|
||||||
|
|
@ -178,17 +174,6 @@ class _HomeScreenState extends State<HomeScreen>
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
=======
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.notifications_none, color: Colors.black),
|
|
||||||
onPressed: () {
|
|
||||||
// Aksi notifikasi
|
|
||||||
},
|
|
||||||
>>>>>>> parent of 6f38d3b (update evaporsi)
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -79,11 +79,16 @@ class EvaporasiBloc extends Bloc<EvaporasiEvent, EvaporasiState> {
|
||||||
);
|
);
|
||||||
|
|
||||||
final lastValue = history.isNotEmpty ? history.last.evaporasi : 0.0;
|
final lastValue = history.isNotEmpty ? history.last.evaporasi : 0.0;
|
||||||
|
final lastWaterLevel = history.isNotEmpty ? history.last.tinggiAir : 0.0;
|
||||||
|
final lastTemperature = history.isNotEmpty ? history.last.suhu : 0.0;
|
||||||
final (status, rain) = _computeWeatherStatus(lastValue);
|
final (status, rain) = _computeWeatherStatus(lastValue);
|
||||||
_emitEvaporasiAlert(status, rain, lastValue);
|
_emitEvaporasiAlert(status, rain, lastValue);
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
history: history,
|
history: history,
|
||||||
|
currentValue: lastValue,
|
||||||
|
waterLevel: lastWaterLevel,
|
||||||
|
temperature: lastTemperature,
|
||||||
dailyValues: dailyGraph,
|
dailyValues: dailyGraph,
|
||||||
dailyTemperatures: dailyTempGraph,
|
dailyTemperatures: dailyTempGraph,
|
||||||
weeklyValues: weeklyGraph,
|
weeklyValues: weeklyGraph,
|
||||||
|
|
@ -299,4 +304,3 @@ class _EvaporasiRealtimeUpdated extends EvaporasiEvent {
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [data];
|
List<Object> get props => [data];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,170 @@
|
||||||
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class EvaporasiChartWidget extends StatelessWidget {
|
||||||
|
final List<double> dailyValues;
|
||||||
|
final List<double> dailyTemperatures;
|
||||||
|
final String period;
|
||||||
|
final List<String> chartLabels;
|
||||||
|
|
||||||
|
const EvaporasiChartWidget({
|
||||||
|
super.key,
|
||||||
|
required this.dailyValues,
|
||||||
|
required this.dailyTemperatures,
|
||||||
|
required this.period,
|
||||||
|
required this.chartLabels,
|
||||||
|
});
|
||||||
|
|
||||||
|
double _safeValue(double value) {
|
||||||
|
if (value.isNaN || value.isInfinite) return 0.0;
|
||||||
|
return value < 0 ? 0.0 : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
double _maxY() {
|
||||||
|
final values = [
|
||||||
|
...dailyValues.map(_safeValue),
|
||||||
|
...dailyTemperatures.map(_safeValue),
|
||||||
|
];
|
||||||
|
if (values.isEmpty) return 10;
|
||||||
|
final maxValue = values.reduce((a, b) => a > b ? a : b);
|
||||||
|
return (maxValue * 1.4).clamp(10.0, 100.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<FlSpot> _lineSpots(List<double> series) {
|
||||||
|
return series.asMap().entries.map((entry) {
|
||||||
|
return FlSpot(entry.key.toDouble(), _safeValue(entry.value));
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
String _getBottomLabel(int index) {
|
||||||
|
if (chartLabels.isEmpty || index < 0 || index >= chartLabels.length) {
|
||||||
|
return index.toString();
|
||||||
|
}
|
||||||
|
return chartLabels[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final values = _lineSpots(dailyValues);
|
||||||
|
final temperatures = _lineSpots(dailyTemperatures);
|
||||||
|
|
||||||
|
if (values.isEmpty && temperatures.isEmpty) {
|
||||||
|
return Container(
|
||||||
|
height: 240,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(25),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withAlpha(13),
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 5),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: const Text('Tidak ada data chart'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
height: 300,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(25),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withAlpha(13),
|
||||||
|
blurRadius: 10,
|
||||||
|
offset: const Offset(0, 5),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(25),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
child: LineChart(
|
||||||
|
LineChartData(
|
||||||
|
minY: 0,
|
||||||
|
maxY: _maxY(),
|
||||||
|
gridData: FlGridData(show: false),
|
||||||
|
borderData: FlBorderData(show: false),
|
||||||
|
titlesData: FlTitlesData(
|
||||||
|
bottomTitles: AxisTitles(
|
||||||
|
sideTitles: SideTitles(
|
||||||
|
showTitles: true,
|
||||||
|
reservedSize: 32,
|
||||||
|
interval: 1,
|
||||||
|
getTitlesWidget: (value, meta) {
|
||||||
|
final index = value.toInt();
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8),
|
||||||
|
child: Text(
|
||||||
|
_getBottomLabel(index),
|
||||||
|
style:
|
||||||
|
const TextStyle(color: Colors.grey, fontSize: 10),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
leftTitles: const AxisTitles(
|
||||||
|
sideTitles: SideTitles(showTitles: false),
|
||||||
|
),
|
||||||
|
topTitles: const AxisTitles(
|
||||||
|
sideTitles: SideTitles(showTitles: false),
|
||||||
|
),
|
||||||
|
rightTitles: const AxisTitles(
|
||||||
|
sideTitles: SideTitles(showTitles: false),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
lineTouchData: LineTouchData(
|
||||||
|
handleBuiltInTouches: true,
|
||||||
|
touchTooltipData: LineTouchTooltipData(
|
||||||
|
getTooltipItems: (spots) {
|
||||||
|
return spots.map((spot) {
|
||||||
|
return LineTooltipItem(
|
||||||
|
spot.y.toStringAsFixed(1),
|
||||||
|
const TextStyle(color: Colors.white, fontSize: 12),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
lineBarsData: [
|
||||||
|
if (values.isNotEmpty)
|
||||||
|
LineChartBarData(
|
||||||
|
spots: values,
|
||||||
|
isCurved: true,
|
||||||
|
color: Colors.blue.shade700,
|
||||||
|
barWidth: 3,
|
||||||
|
dotData: FlDotData(show: false),
|
||||||
|
belowBarData: BarAreaData(
|
||||||
|
show: true,
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [
|
||||||
|
Colors.blue.withAlpha(64),
|
||||||
|
Colors.blue.withAlpha(13),
|
||||||
|
],
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (temperatures.isNotEmpty)
|
||||||
|
LineChartBarData(
|
||||||
|
spots: temperatures,
|
||||||
|
isCurved: true,
|
||||||
|
color: Colors.orange.shade700,
|
||||||
|
barWidth: 3,
|
||||||
|
dotData: FlDotData(show: false),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -83,6 +83,7 @@ class _EvaporasiDatePickerState extends State<EvaporasiDatePicker> {
|
||||||
),
|
),
|
||||||
// Calendar
|
// Calendar
|
||||||
Expanded(
|
Expanded(
|
||||||
|
child: SingleChildScrollView(
|
||||||
child: TableCalendar(
|
child: TableCalendar(
|
||||||
firstDay: DateTime.utc(2020, 1, 1),
|
firstDay: DateTime.utc(2020, 1, 1),
|
||||||
lastDay: DateTime.now(),
|
lastDay: DateTime.now(),
|
||||||
|
|
@ -174,6 +175,7 @@ class _EvaporasiDatePickerState extends State<EvaporasiDatePicker> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
// Selected date display
|
// Selected date display
|
||||||
if (_selectedDay != null)
|
if (_selectedDay != null)
|
||||||
Container(
|
Container(
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
|
||||||
|
|
||||||
import 'package:monitoring_repository/monitoring_repository.dart';
|
|
||||||
|
|
||||||
class EvaporasiDateSearchBar extends StatefulWidget {
|
class EvaporasiDateSearchBar extends StatefulWidget {
|
||||||
final String initialQuery;
|
final String initialQuery;
|
||||||
|
|
@ -13,14 +10,12 @@ class EvaporasiDateSearchBar extends StatefulWidget {
|
||||||
required this.onQueryChanged,
|
required this.onQueryChanged,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<EvaporasiDateSearchBar> createState() => _EvaporasiDateSearchBarState();
|
State<EvaporasiDateSearchBar> createState() => _EvaporasiDateSearchBarState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _EvaporasiDateSearchBarState extends State<EvaporasiDateSearchBar> {
|
class _EvaporasiDateSearchBarState extends State<EvaporasiDateSearchBar> {
|
||||||
late final TextEditingController _controller;
|
late final TextEditingController _controller;
|
||||||
DateTime? _selected;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
|
@ -34,21 +29,9 @@ class _EvaporasiDateSearchBarState extends State<EvaporasiDateSearchBar> {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _matches(Evaporasi item, String query) {
|
|
||||||
if (query.trim().isEmpty) return true;
|
|
||||||
|
|
||||||
final date = item.timestamp;
|
|
||||||
final ddMMyyyy = DateFormat('dd/MM/yyyy', 'id_ID').format(date);
|
|
||||||
final ddMMMYYYY = DateFormat('dd MMM yyyy', 'id_ID').format(date);
|
|
||||||
|
|
||||||
final q = query.trim().toLowerCase();
|
|
||||||
return ddMMyyyy.toLowerCase().contains(q) || ddMMMYYYY.toLowerCase().contains(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return TextField(
|
return TextField(
|
||||||
|
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'Cari tanggal (dd/MM/yyyy)',
|
hintText: 'Cari tanggal (dd/MM/yyyy)',
|
||||||
|
|
@ -69,4 +52,3 @@ class _EvaporasiDateSearchBarState extends State<EvaporasiDateSearchBar> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,17 +19,21 @@ class Evaporasi {
|
||||||
);
|
);
|
||||||
|
|
||||||
factory Evaporasi.fromJson(Map<dynamic, dynamic> json) {
|
factory Evaporasi.fromJson(Map<dynamic, dynamic> json) {
|
||||||
// ✅ Handle perbedaan field name antara history dan realtime:
|
double toDoubleSafe(dynamic v) {
|
||||||
// History path : suhu, tinggi, evaporasi, waktu
|
if (v is num) return v.toDouble();
|
||||||
// Realtime path : suhu_air, tinggi_air, evaporasi, waktu, status
|
if (v is String) return double.tryParse(v) ?? 0;
|
||||||
final suhu = (json['suhu'] ?? json['suhu_air'] ?? 0).toDouble();
|
return 0;
|
||||||
final tinggi = (json['tinggi'] ?? json['tinggi_air_cm'] ?? 0).toDouble();
|
}
|
||||||
|
|
||||||
// ✅ Prioritas waktu sesuai firmware ESP32:
|
final evaporasiVal = toDoubleSafe(
|
||||||
// 1) timestamp (Unix atau ISO string, kalau pernah dikirim)
|
json['evaporasi_mm'] ?? json['evaporasi'],
|
||||||
// 2) datetime ("YYYY-MM-DD HH:MM:SS")
|
);
|
||||||
// 3) waktu ("HH:MM:SS") fallback (pakai tanggal hari ini)
|
final suhuVal = toDoubleSafe(json['suhu'] ?? json['suhu_air']);
|
||||||
|
final tinggiVal = toDoubleSafe(json['tinggi_air_cm'] ?? json['tinggi_air']);
|
||||||
|
|
||||||
|
DateTime timestamp = DateTime.now();
|
||||||
final rawTimestamp = json['timestamp'];
|
final rawTimestamp = json['timestamp'];
|
||||||
|
|
||||||
if (rawTimestamp != null) {
|
if (rawTimestamp != null) {
|
||||||
if (rawTimestamp is int) {
|
if (rawTimestamp is int) {
|
||||||
timestamp = DateTime.fromMillisecondsSinceEpoch(rawTimestamp);
|
timestamp = DateTime.fromMillisecondsSinceEpoch(rawTimestamp);
|
||||||
|
|
@ -61,6 +65,7 @@ class Evaporasi {
|
||||||
final jam = int.tryParse(parts[0]) ?? 0;
|
final jam = int.tryParse(parts[0]) ?? 0;
|
||||||
final menit = int.tryParse(parts[1]) ?? 0;
|
final menit = int.tryParse(parts[1]) ?? 0;
|
||||||
final detik = parts.length >= 3 ? (int.tryParse(parts[2]) ?? 0) : 0;
|
final detik = parts.length >= 3 ? (int.tryParse(parts[2]) ?? 0) : 0;
|
||||||
|
final now = DateTime.now();
|
||||||
timestamp = DateTime(
|
timestamp = DateTime(
|
||||||
now.year,
|
now.year,
|
||||||
now.month,
|
now.month,
|
||||||
|
|
@ -74,27 +79,11 @@ class Evaporasi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Field di DB (dari info Anda):
|
|
||||||
// - evaporasi_mm
|
|
||||||
// - suhu_air
|
|
||||||
// - tinggi_air_cm
|
|
||||||
// Namun tetap toleran jika key berubah.
|
|
||||||
final evaporasiVal = json['evaporasi_mm'] ?? json['evaporasi'] ?? 0;
|
|
||||||
final suhuVal = json['suhu_air'] ?? json['suhu'] ?? 0;
|
|
||||||
final tinggiVal = json['tinggi_air_cm'] ?? json['tinggi_air'] ?? 0;
|
|
||||||
|
|
||||||
double toDoubleSafe(dynamic v) {
|
|
||||||
if (v is num) return v.toDouble();
|
|
||||||
if (v is String) return double.tryParse(v) ?? 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Evaporasi(
|
return Evaporasi(
|
||||||
evaporasi: (json['evaporasi_mm'] ?? 0).toDouble(),
|
evaporasi: evaporasiVal,
|
||||||
suhu: suhu,
|
suhu: suhuVal,
|
||||||
tinggiAir: tinggi,
|
tinggiAir: tinggiVal,
|
||||||
status: json['status'] ?? '',
|
timestamp: timestamp,
|
||||||
timestamp: TimestampParser.parse(rawTime), // ✅ pakai TimestampParser
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,11 @@
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
// tree, read text, and verify that the values of widget properties are correct.
|
||||||
|
|
||||||
import 'package:firebase_database/firebase_database.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:klimatologiot/app.dart';
|
||||||
import 'package:monitoring_repository/monitoring_repository.dart';
|
import 'package:monitoring_repository/monitoring_repository.dart';
|
||||||
import 'package:user_repository/user_repository.dart';
|
import 'package:user_repository/user_repository.dart';
|
||||||
import '../lib/app.dart';
|
|
||||||
|
|
||||||
// import 'package:klimatologiot/main.dart';
|
// import 'package:klimatologiot/main.dart';
|
||||||
|
|
||||||
|
|
@ -49,31 +48,38 @@ class FakeUserRepository implements UserRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeMonitoringRepository implements MonitoringRepository {
|
class FakeMonitoringRepository implements MonitoringRepository {
|
||||||
get _db => null;
|
|
||||||
|
|
||||||
// Satu fungsi untuk semua jenis sensor
|
|
||||||
// Kamu cukup masukkan "path" database-nya saja
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
// Jika ingin mengambil data sekali saja (bukan stream)
|
Future<T> getSensorSnapshot<T>(
|
||||||
Future<DataSnapshot> getSensorSnapshot(String path) async {
|
String path,
|
||||||
return await _db.ref(path).get();
|
T Function(Map<dynamic, dynamic>) mapper,
|
||||||
|
) async {
|
||||||
|
return mapper(<dynamic, dynamic>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<DatabaseEvent> getSensorStream(String path) {
|
Stream<T> getSensorStream<T>(
|
||||||
// TODO: implement getSensorStream
|
String path,
|
||||||
throw UnimplementedError();
|
T Function(Map<dynamic, dynamic>) mapper,
|
||||||
|
) {
|
||||||
|
return const Stream.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<T>> getSensorHistory<T>(
|
||||||
|
String path,
|
||||||
|
T Function(Map<dynamic, dynamic>) mapper,
|
||||||
|
) async {
|
||||||
|
return <T>[];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('App loads', (WidgetTester tester) async {
|
testWidgets('App loads', (WidgetTester tester) async {
|
||||||
final fakeRepo = FakeUserRepository();
|
final fakeRepo = FakeUserRepository();
|
||||||
final fakeMonitoring = FakeUserRepository();
|
final fakeMonitoring = FakeMonitoringRepository();
|
||||||
// Build our app and trigger a frame.
|
// Build our app and trigger a frame.
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MyApp(fakeRepo, fakeMonitoring as MonitoringRepository),
|
MyApp(fakeRepo, fakeMonitoring),
|
||||||
);
|
);
|
||||||
|
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue