Skip to content

Commit 45b74a6

Browse files
committed
Refactor tests to use common mock implementations
- Consolidated various stub implementations into dedicated mock classes for BlobManager, Clock, DeviceManager, DeviceModuleRegistry, GroupManager, SceneManager, and Gettext. - Updated existing tests to utilize the new mock classes, improving code readability and maintainability. - Removed redundant stub classes from individual test files, reducing duplication. - Ensured that all tests continue to function correctly with the new mock implementations.
1 parent faa4570 commit 45b74a6

18 files changed

Lines changed: 571 additions & 622 deletions

client/integration_test/device_group_test.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
66
import 'package:flutter_test/flutter_test.dart';
77
import 'package:sembast/sembast_memory.dart' hide Finder;
88
import 'package:shared_preferences/shared_preferences.dart';
9+
import 'package:integration_test/integration_test.dart';
910

1011
import 'package:borneo_app/main.dart' as app;
1112

@@ -121,3 +122,9 @@ void deviceGroupTests() {
121122
expect(find.text('Updated Group'), findsNothing);
122123
});
123124
}
125+
126+
// standalone entrypoint so this file can be run directly in CI
127+
void main() {
128+
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
129+
deviceGroupTests();
130+
}

client/integration_test/scenes_test.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
66
import 'package:flutter_test/flutter_test.dart';
77
import 'package:sembast/sembast_memory.dart' hide Finder;
88
import 'package:shared_preferences/shared_preferences.dart';
9+
import 'package:integration_test/integration_test.dart';
910

1011
import 'package:borneo_app/main.dart' as app;
1112

@@ -121,3 +122,9 @@ void scenesTests() {
121122
}
122123
});
123124
}
125+
126+
// standalone runner entrypoint
127+
void main() {
128+
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
129+
scenesTests();
130+
}

client/test/core/services/device_manager_test.dart

Lines changed: 4 additions & 253 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ import 'package:borneo_app/features/devices/models/device_entity.dart';
99
import 'package:borneo_app/features/devices/models/device_module_metadata.dart';
1010
import 'package:borneo_common/exceptions.dart';
1111
import 'package:borneo_kernel_abstractions/kernel.dart';
12-
import 'package:cancellation_token/cancellation_token.dart';
1312
import 'package:event_bus/event_bus.dart';
1413
// hide EventDispatcher because flutter_test also exports a symbol with
1514
// the same name; we use the one from kernel_abstractions instead.
1615
import 'package:flutter_test/flutter_test.dart' hide EventDispatcher;
1716
import 'package:logger/logger.dart';
1817
import 'package:sembast/sembast_memory.dart';
18+
import '../../mocks/mocks.dart';
1919

2020
void main() {
2121
group('DeviceManagerImpl Tests', () {
@@ -322,197 +322,9 @@ void main() {
322322
});
323323
}
324324

325-
// Simple test doubles without complex inheritance issues
326-
class TestKernel implements IKernel {
327-
bool _isScanning = false;
328-
bool _isInitialized = false;
329-
final List<String> boundDeviceIds = [];
330-
final List<BoundDevice> _boundDevices = [];
331-
final EventDispatcher _events = DefaultEventDispatcher();
332-
333-
// tracks whether heartbeat batch signals were invoked
334-
bool heartbeatSuspended = false; // kept for compatibility
335-
bool heartbeatResumed = false; // kept for compatibility
336-
bool batchEntered = false;
337-
bool batchExited = false;
338-
339-
// Test tracking
340-
bool startCalled = false;
341-
bool bindCalled = false;
342-
bool tryBindCalled = false;
343-
bool unbindCalled = false;
344-
bool startScanningCalled = false;
345-
bool stopScanningCalled = false;
346-
347-
String? lastBoundDeviceId;
348-
String? lastUnboundDeviceId;
349-
bool tryBindResult = true;
325+
// the shared mocks imported transitively via mocks.dart
350326

351-
@override
352-
bool get isScanning => _isScanning;
353-
354-
@override
355-
bool get isInitialized => _isInitialized;
356-
357-
@override
358-
Iterable<Driver> get activatedDrivers => [];
359-
360-
@override
361-
Iterable<BoundDevice> get boundDevices => _boundDevices;
362-
363-
@override
364-
EventDispatcher get events => _events;
365-
366-
@override
367-
Future<void> start() async {
368-
startCalled = true;
369-
_isInitialized = true;
370-
}
371-
372-
@override
373-
void suspendHeartbeat() {
374-
heartbeatSuspended = true;
375-
}
376-
377-
@override
378-
void resumeHeartbeat() {
379-
heartbeatResumed = true;
380-
}
381-
382-
@override
383-
void enterHeartbeatBatch() {
384-
batchEntered = true;
385-
}
386-
387-
@override
388-
void exitHeartbeatBatch() {
389-
batchExited = true;
390-
}
391-
392-
@override
393-
HeartbeatState? getHeartbeatState(String deviceID) => null;
394-
395-
@override
396-
bool isBound(String deviceID) => boundDeviceIds.contains(deviceID);
397-
398-
@override
399-
BoundDevice getBoundDevice(String deviceID) {
400-
// Create a mock BoundDevice for testing
401-
final device = TestDevice(deviceID);
402-
final driver = TestDriver();
403-
return BoundDevice('test-driver', device, driver);
404-
}
405-
406-
@override
407-
Future<bool> tryBind(dynamic device, String driverID, {CancellationToken? cancelToken}) async {
408-
tryBindCalled = true;
409-
lastBoundDeviceId = device.id;
410-
if (tryBindResult) {
411-
boundDeviceIds.add(device.id);
412-
final testDevice = TestDevice(device.id);
413-
final testDriver = TestDriver();
414-
_boundDevices.add(BoundDevice(driverID, testDevice, testDriver));
415-
}
416-
return tryBindResult;
417-
}
418-
419-
@override
420-
Future<void> bind(dynamic device, String driverID, {CancellationToken? cancelToken}) async {
421-
bindCalled = true;
422-
lastBoundDeviceId = device.id;
423-
boundDeviceIds.add(device.id);
424-
final testDevice = TestDevice(device.id);
425-
final testDriver = TestDriver();
426-
_boundDevices.add(BoundDevice(driverID, testDevice, testDriver));
427-
}
428-
429-
@override
430-
Future<void> unbind(String deviceID, {CancellationToken? cancelToken}) async {
431-
unbindCalled = true;
432-
lastUnboundDeviceId = deviceID;
433-
boundDeviceIds.remove(deviceID);
434-
_boundDevices.removeWhere((d) => d.device.id == deviceID);
435-
}
436-
437-
@override
438-
Future<void> unbindAll({CancellationToken? cancelToken}) async {
439-
boundDeviceIds.clear();
440-
_boundDevices.clear();
441-
}
442-
443-
@override
444-
void registerDevice(dynamic descriptor) {}
445-
446-
@override
447-
void registerDevices(Iterable<dynamic> descriptors) {}
448-
449-
@override
450-
void unregisterDevice(String deviceID) {}
451-
452-
@override
453-
void unregisterAllDevices() {}
454-
455-
@override
456-
Future<void> startDevicesScanning({Duration? timeout, CancellationToken? cancelToken}) async {
457-
startScanningCalled = true;
458-
_isScanning = true;
459-
}
460-
461-
@override
462-
Future<void> stopDevicesScanning() async {
463-
stopScanningCalled = true;
464-
_isScanning = false;
465-
}
466-
467-
@override
468-
void dispose() {}
469-
470-
@override
471-
bool get isBusy => false;
472-
}
473-
474-
class TestBoundDevice {
475-
final Device device;
476-
477-
TestBoundDevice(this.device);
478-
}
479-
480-
class TestDevice extends Device {
481-
late DriverData _driverData;
482-
483-
TestDevice(String id) : super(id: id, fingerprint: 'test-fingerprint', address: Uri.parse('coap://localhost:5683')) {
484-
_driverData = TestDriverData(this);
485-
}
486-
487-
@override
488-
DriverData get driverData => _driverData;
489-
490-
@override
491-
Future<void> setDriverData(DriverData data, {CancellationToken? cancelToken}) async {
492-
_driverData = data;
493-
}
494-
}
495-
496-
class TestDriverData extends DriverData {
497-
TestDriverData(super.device);
498-
499-
@override
500-
void dispose() {}
501-
}
502-
503-
class TestDriver extends Driver {
504-
@override
505-
Future<bool> probe(Device dev, {CancellationToken? cancelToken}) async => true;
506-
507-
@override
508-
Future<bool> remove(Device dev, {CancellationToken? cancelToken}) async => true;
509-
510-
@override
511-
Future<bool> heartbeat(Device dev, {CancellationToken? cancelToken}) async => true;
512-
513-
@override
514-
void dispose() {}
515-
}
327+
// remaining per-test helpers that aren't reused elsewhere
516328

517329
// deprecated test helper; replaced by EventDispatcher
518330
class TestEventDispatcher extends DefaultEventDispatcher {}
@@ -540,66 +352,5 @@ class TestGroupManager implements IGroupManager {
540352

541353
class TestDeviceModuleRegistry implements IDeviceModuleRegistry {
542354
@override
543-
UnmodifiableMapView<String, DeviceModuleMetadata> get metaModules =>
544-
UnmodifiableMapView(<String, DeviceModuleMetadata>{});
545-
}
546-
547-
class TestLogger implements Logger {
548-
final List<String> messages = [];
549-
550-
@override
551-
void v(dynamic message, {DateTime? time, Object? error, StackTrace? stackTrace}) {
552-
messages.add('V: $message');
553-
}
554-
555-
@override
556-
void d(dynamic message, {DateTime? time, Object? error, StackTrace? stackTrace}) {
557-
messages.add('D: $message');
558-
}
559-
560-
@override
561-
void i(dynamic message, {DateTime? time, Object? error, StackTrace? stackTrace}) {
562-
messages.add('I: $message');
563-
}
564-
565-
@override
566-
void w(dynamic message, {DateTime? time, Object? error, StackTrace? stackTrace}) {
567-
messages.add('W: $message');
568-
}
569-
570-
@override
571-
void e(dynamic message, {DateTime? time, Object? error, StackTrace? stackTrace}) {
572-
messages.add('E: $message');
573-
}
574-
575-
@override
576-
void wtf(dynamic message, {DateTime? time, Object? error, StackTrace? stackTrace}) {
577-
messages.add('WTF: $message');
578-
}
579-
580-
@override
581-
void log(Level level, dynamic message, {DateTime? time, Object? error, StackTrace? stackTrace}) {
582-
messages.add('${level.name}: $message');
583-
}
584-
585-
@override
586-
bool isClosed() => false;
587-
588-
@override
589-
Future<void> close() async {}
590-
591-
// Simplified - handle missing methods
592-
@override
593-
dynamic noSuchMethod(Invocation invocation) => null;
594-
}
595-
596-
class TestSupportedDeviceDescriptor implements SupportedDeviceDescriptor {
597-
@override
598-
final String fingerprint;
599-
600-
TestSupportedDeviceDescriptor(this.fingerprint);
601-
602-
// Simplified - handle missing methods
603-
@override
604-
dynamic noSuchMethod(Invocation invocation) => null;
355+
UnmodifiableMapView<String, DeviceModuleMetadata> get metaModules => UnmodifiableMapView({});
605356
}

0 commit comments

Comments
 (0)