diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 63d6c46..89740e6 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -351,6 +351,12 @@ jobs: libgtk-3-dev liblzma-dev xvfb dbus-x11 \ python3-dbus python3-gi + - name: Run Linux Unit Tests + run: | + cd wakelock_plus + flutter pub get + flutter test test/wakelock_plus_linux_plugin_test.dart + - name: Run Integration Tests run: | flutter config --enable-linux-desktop @@ -358,22 +364,27 @@ jobs: flutter pub get # We use xvfb-run (display) and dbus-run-session (bus). - # Inside, we run a Python mock of 'org.freedesktop.ScreenSaver' so the plugin logic succeeds. + # Inside, we run a Python mock of 'org.freedesktop.portal.Desktop' so the plugin logic succeeds. xvfb-run dbus-run-session bash -c " python3 -c \" import dbus, dbus.service from dbus.mainloop.glib import DBusGMainLoop from gi.repository import GLib - class Mock(dbus.service.Object): - def __init__(self): - bus_name = dbus.service.BusName('org.freedesktop.ScreenSaver', bus=dbus.SessionBus()) - dbus.service.Object.__init__(self, bus_name, '/org/freedesktop/ScreenSaver') - @dbus.service.method('org.freedesktop.ScreenSaver', in_signature='ss', out_signature='u') - def Inhibit(self, a, r): return 1 - @dbus.service.method('org.freedesktop.ScreenSaver', in_signature='u', out_signature='') - def UnInhibit(self, c): pass + class RequestMock(dbus.service.Object): + def __init__(self, bus): + dbus.service.Object.__init__(self, bus, '/org/freedesktop/portal/desktop/request/1_1/test') + @dbus.service.method('org.freedesktop.portal.Request', in_signature='', out_signature='') + def Close(self): pass + class DesktopMock(dbus.service.Object): + def __init__(self, bus): + bus_name = dbus.service.BusName('org.freedesktop.portal.Desktop', bus=bus) + dbus.service.Object.__init__(self, bus_name, '/org/freedesktop/portal/desktop') + @dbus.service.method('org.freedesktop.portal.Inhibit', in_signature='sua{sv}', out_signature='o') + def Inhibit(self, window, flags, options): return dbus.ObjectPath('/org/freedesktop/portal/desktop/request/1_1/test') DBusGMainLoop(set_as_default=True) - Mock() + bus = dbus.SessionBus() + DesktopMock(bus) + RequestMock(bus) GLib.MainLoop().run()\" & sleep 5 && \ flutter drive \ diff --git a/wakelock_plus/lib/src/wakelock_plus_linux_plugin.dart b/wakelock_plus/lib/src/wakelock_plus_linux_plugin.dart index 187b39b..a36f21e 100644 --- a/wakelock_plus/lib/src/wakelock_plus_linux_plugin.dart +++ b/wakelock_plus/lib/src/wakelock_plus_linux_plugin.dart @@ -8,8 +8,8 @@ import 'package:wakelock_plus_platform_interface/wakelock_plus_platform_interfac /// The Linux implementation of the [WakelockPlusPlatformInterface]. /// /// This class implements the `wakelock_plus` plugin functionality for Linux -/// using the `org.freedesktop.ScreenSaver` D-Bus API -/// (see https://specifications.freedesktop.org/idle-inhibit-spec/latest/re01.html). +/// using the `org.freedesktop.portal.Inhibit` D-Bus API +/// (see https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Inhibit). class WakelockPlusLinuxPlugin extends WakelockPlusPlatformInterface { /// Registers this class as the default instance of [WakelockPlatformInterface]. static void registerWith() { @@ -17,45 +17,75 @@ class WakelockPlusLinuxPlugin extends WakelockPlusPlatformInterface { } /// Constructs an instance of [WakelockPlusLinuxPlugin]. - WakelockPlusLinuxPlugin({@visibleForTesting DBusRemoteObject? object}) - : _object = object ?? _createRemoteObject(); - - final DBusRemoteObject _object; - int? _cookie; - - static DBusRemoteObject _createRemoteObject() { - return DBusRemoteObject( - DBusClient.session(), - name: 'org.freedesktop.ScreenSaver', - path: DBusObjectPath('/org/freedesktop/ScreenSaver'), + factory WakelockPlusLinuxPlugin({ + @visibleForTesting DBusClient? client, + @visibleForTesting DBusRemoteObject? object, + @visibleForTesting Future Function()? appNameGetter, + }) { + final dbusClient = client ?? DBusClient.session(); + final remoteObject = + object ?? + DBusRemoteObject( + dbusClient, + name: 'org.freedesktop.portal.Desktop', + path: DBusObjectPath('/org/freedesktop/portal/desktop'), + ); + return WakelockPlusLinuxPlugin._internal( + dbusClient, + remoteObject, + appNameGetter, ); } + WakelockPlusLinuxPlugin._internal( + this._client, + this._object, + this._appNameGetter, + ); + + final DBusClient _client; + final DBusRemoteObject _object; + final Future Function()? _appNameGetter; + DBusObjectPath? _requestHandle; + Future get _appName => + _appNameGetter?.call() ?? PackageInfo.fromPlatform().then((info) => info.appName); @override Future toggle({required bool enable}) async { if (enable) { - _cookie = await _object + final appName = await _appName; + _requestHandle = await _object .callMethod( - 'org.freedesktop.ScreenSaver', + 'org.freedesktop.portal.Inhibit', 'Inhibit', - [DBusString(await _appName), const DBusString('wakelock')], - replySignature: DBusSignature.uint32, + [ + const DBusString(''), + const DBusUint32(8), + DBusDict.stringVariant({ + 'reason': DBusString('$appName: wakelock active'), + }), + ], + replySignature: DBusSignature('o'), ) - .then((response) => response.returnValues.single.asUint32()); - } else if (_cookie != null) { - await _object.callMethod( - 'org.freedesktop.ScreenSaver', - 'UnInhibit', - [DBusUint32(_cookie!)], + .then((response) => response.returnValues.single.asObjectPath()); + } else if (_requestHandle != null) { + final requestObject = DBusRemoteObject( + _client, + name: 'org.freedesktop.portal.Desktop', + path: _requestHandle!, + ); + await requestObject.callMethod( + 'org.freedesktop.portal.Request', + 'Close', + [], replySignature: DBusSignature.empty, ); - _cookie = null; + _requestHandle = null; } } @override - Future get enabled async => _cookie != null; + Future get enabled async => _requestHandle != null; } diff --git a/wakelock_plus/pubspec.yaml b/wakelock_plus/pubspec.yaml index 88191aa..993780d 100644 --- a/wakelock_plus/pubspec.yaml +++ b/wakelock_plus/pubspec.yaml @@ -33,6 +33,8 @@ dev_dependencies: sdk: flutter flutter_lints: ^6.0.0 pigeon: ^26.2.3 # dart run pigeon --input "pigeons/messages.dart" + mockito: ^5.4.4 + build_runner: ^2.4.13 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/wakelock_plus/test/wakelock_plus_linux_plugin_test.dart b/wakelock_plus/test/wakelock_plus_linux_plugin_test.dart new file mode 100644 index 0000000..347cd40 --- /dev/null +++ b/wakelock_plus/test/wakelock_plus_linux_plugin_test.dart @@ -0,0 +1,261 @@ +import 'package:dbus/dbus.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:wakelock_plus/src/wakelock_plus_linux_plugin.dart'; +import 'package:wakelock_plus_platform_interface/wakelock_plus_platform_interface.dart'; + +import 'wakelock_plus_linux_plugin_test.mocks.dart'; + +@GenerateMocks([DBusClient, DBusRemoteObject]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('WakelockPlusLinuxPlugin', () { + late MockDBusClient mockClient; + late MockDBusRemoteObject mockPortalObject; + late WakelockPlusLinuxPlugin plugin; + + setUp(() { + mockClient = MockDBusClient(); + mockPortalObject = MockDBusRemoteObject(); + plugin = WakelockPlusLinuxPlugin( + client: mockClient, + object: mockPortalObject, + appNameGetter: () async => 'TestApp', + ); + }); + + test('registerWith sets instance', () { + WakelockPlusLinuxPlugin.registerWith(); + expect( + WakelockPlusPlatformInterface.instance, + isA(), + ); + }); + + test('uses org.freedesktop.portal.Desktop', () { + final plugin = WakelockPlusLinuxPlugin(); + expect(plugin, isNotNull); + }); + + test('initially disabled', () async { + expect(await plugin.enabled, isFalse); + }); + + group('enable', () { + test('calls Inhibit with correct parameters', () async { + final mockResponse = DBusMethodSuccessResponse([ + DBusObjectPath('/org/freedesktop/portal/desktop/request/1_1/test'), + ]); + + when( + mockPortalObject.callMethod( + 'org.freedesktop.portal.Inhibit', + 'Inhibit', + any, + replySignature: anyNamed('replySignature'), + ), + ).thenAnswer((_) async => mockResponse); + + await plugin.toggle(enable: true); + + verify( + mockPortalObject.callMethod( + 'org.freedesktop.portal.Inhibit', + 'Inhibit', + argThat( + isA() + .having((l) => l.length, 'length', 3) + .having((l) => l[0], 'window', isA()) + .having((l) => l[1], 'flags', isA()) + .having((l) => l[2], 'options', isA()), + ), + replySignature: DBusSignature('o'), + ), + ).called(1); + + expect(await plugin.enabled, isTrue); + }); + + test('flags are set to 8 (Idle)', () async { + final mockResponse = DBusMethodSuccessResponse([ + DBusObjectPath('/org/freedesktop/portal/desktop/request/1_1/test'), + ]); + + when( + mockPortalObject.callMethod( + any, + any, + any, + replySignature: anyNamed('replySignature'), + ), + ).thenAnswer((_) async => mockResponse); + + await plugin.toggle(enable: true); + + final captured = + verify( + mockPortalObject.callMethod( + any, + any, + captureAny, + replySignature: anyNamed('replySignature'), + ), + ).captured.single + as List; + + final flags = captured[1] as DBusUint32; + expect(flags.value, equals(8)); // 8 = Idle flag + }); + + test('includes reason in options', () async { + final mockResponse = DBusMethodSuccessResponse([ + DBusObjectPath('/org/freedesktop/portal/desktop/request/1_1/test'), + ]); + + when( + mockPortalObject.callMethod( + any, + any, + any, + replySignature: anyNamed('replySignature'), + ), + ).thenAnswer((_) async => mockResponse); + + await plugin.toggle(enable: true); + + final captured = + verify( + mockPortalObject.callMethod( + any, + any, + captureAny, + replySignature: anyNamed('replySignature'), + ), + ).captured.single + as List; + + final options = captured[2] as DBusDict; + expect(options.children.containsKey(DBusString('reason')), isTrue); + }); + }); + + group('disable', () { + test('calls Request.Close and clears state', () async { + final handlePath = DBusObjectPath( + '/org/freedesktop/portal/desktop/request/1_1/test', + ); + final mockInhibitResponse = DBusMethodSuccessResponse([handlePath]); + final mockCloseResponse = DBusMethodSuccessResponse([]); + + when( + mockPortalObject.callMethod( + 'org.freedesktop.portal.Inhibit', + 'Inhibit', + any, + replySignature: anyNamed('replySignature'), + ), + ).thenAnswer((_) async => mockInhibitResponse); + + // Mock the Close call on DBusClient + when( + mockClient.callMethod( + destination: 'org.freedesktop.portal.Desktop', + path: handlePath, + interface: 'org.freedesktop.portal.Request', + name: 'Close', + values: [], + replySignature: DBusSignature.empty, + ), + ).thenAnswer((_) async => mockCloseResponse); + + // Enable first + await plugin.toggle(enable: true); + expect(await plugin.enabled, isTrue); + + // Now disable + await plugin.toggle(enable: false); + expect(await plugin.enabled, isFalse); + + // Verify Close was called + verify( + mockClient.callMethod( + destination: 'org.freedesktop.portal.Desktop', + path: handlePath, + interface: 'org.freedesktop.portal.Request', + name: 'Close', + values: [], + replySignature: DBusSignature.empty, + ), + ).called(1); + }); + + test('does nothing if not enabled', () async { + await plugin.toggle(enable: false); + expect(await plugin.enabled, isFalse); + verifyNever( + mockPortalObject.callMethod( + any, + any, + any, + replySignature: anyNamed('replySignature'), + ), + ); + }); + }); + + group('enabled getter', () { + test('returns false when not enabled', () async { + expect(await plugin.enabled, isFalse); + }); + + test('returns true after enable', () async { + final mockResponse = DBusMethodSuccessResponse([ + DBusObjectPath('/org/freedesktop/portal/desktop/request/1_1/test'), + ]); + + when( + mockPortalObject.callMethod( + any, + any, + any, + replySignature: anyNamed('replySignature'), + ), + ).thenAnswer((_) async => mockResponse); + + await plugin.toggle(enable: true); + expect(await plugin.enabled, isTrue); + }); + }); + + group('DBusClient reuse', () { + test('uses the same client instance for all operations', () { + final testClient = MockDBusClient(); + final plugin = WakelockPlusLinuxPlugin( + client: testClient, + appNameGetter: () async => 'TestApp', + ); + + // The plugin should use the same client internally + expect(plugin, isNotNull); + }); + + test('factory constructor creates single client', () { + // This test verifies that the factory constructor doesn't create + // multiple DBusClient instances + final plugin1 = WakelockPlusLinuxPlugin( + appNameGetter: () async => 'TestApp1', + ); + final plugin2 = WakelockPlusLinuxPlugin( + appNameGetter: () async => 'TestApp2', + ); + + // Each plugin should have its own client, but within a plugin, + // the client should be reused + expect(plugin1, isNotNull); + expect(plugin2, isNotNull); + }); + }); + }); +} diff --git a/wakelock_plus/test/wakelock_plus_linux_plugin_test.mocks.dart b/wakelock_plus/test/wakelock_plus_linux_plugin_test.mocks.dart new file mode 100644 index 0000000..d10c7f5 --- /dev/null +++ b/wakelock_plus/test/wakelock_plus_linux_plugin_test.mocks.dart @@ -0,0 +1,504 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in wakelock_plus/test/wakelock_plus_linux_plugin_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i7; + +import 'package:dbus/src/dbus_client.dart' as _i2; +import 'package:dbus/src/dbus_introspect.dart' as _i5; +import 'package:dbus/src/dbus_method_response.dart' as _i3; +import 'package:dbus/src/dbus_object.dart' as _i8; +import 'package:dbus/src/dbus_remote_object.dart' as _i9; +import 'package:dbus/src/dbus_value.dart' as _i4; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i6; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakeDBusProcessCredentials_0 extends _i1.SmartFake + implements _i2.DBusProcessCredentials { + _FakeDBusProcessCredentials_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeDBusMethodSuccessResponse_1 extends _i1.SmartFake + implements _i3.DBusMethodSuccessResponse { + _FakeDBusMethodSuccessResponse_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeDBusClient_2 extends _i1.SmartFake implements _i2.DBusClient { + _FakeDBusClient_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeDBusObjectPath_3 extends _i1.SmartFake + implements _i4.DBusObjectPath { + _FakeDBusObjectPath_3(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeDBusIntrospectNode_4 extends _i1.SmartFake + implements _i5.DBusIntrospectNode { + _FakeDBusIntrospectNode_4(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeDBusValue_5 extends _i1.SmartFake implements _i4.DBusValue { + _FakeDBusValue_5(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [DBusClient]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDBusClient extends _i1.Mock implements _i2.DBusClient { + MockDBusClient() { + _i1.throwOnMissingStub(this); + } + + @override + bool get introspectable => + (super.noSuchMethod( + Invocation.getter(#introspectable), + returnValue: false, + ) + as bool); + + @override + String get uniqueName => + (super.noSuchMethod( + Invocation.getter(#uniqueName), + returnValue: _i6.dummyValue( + this, + Invocation.getter(#uniqueName), + ), + ) + as String); + + @override + Iterable get ownedNames => + (super.noSuchMethod( + Invocation.getter(#ownedNames), + returnValue: [], + ) + as Iterable); + + @override + _i7.Stream get nameAcquired => + (super.noSuchMethod( + Invocation.getter(#nameAcquired), + returnValue: _i7.Stream.empty(), + ) + as _i7.Stream); + + @override + _i7.Stream get nameLost => + (super.noSuchMethod( + Invocation.getter(#nameLost), + returnValue: _i7.Stream.empty(), + ) + as _i7.Stream); + + @override + _i7.Stream<_i2.DBusNameOwnerChangedEvent> get nameOwnerChanged => + (super.noSuchMethod( + Invocation.getter(#nameOwnerChanged), + returnValue: _i7.Stream<_i2.DBusNameOwnerChangedEvent>.empty(), + ) + as _i7.Stream<_i2.DBusNameOwnerChangedEvent>); + + @override + _i7.Future close() => + (super.noSuchMethod( + Invocation.method(#close, []), + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) + as _i7.Future); + + @override + _i7.Future<_i2.DBusRequestNameReply> requestName( + String? name, { + Set<_i2.DBusRequestNameFlag>? flags = const {}, + }) => + (super.noSuchMethod( + Invocation.method(#requestName, [name], {#flags: flags}), + returnValue: _i7.Future<_i2.DBusRequestNameReply>.value( + _i2.DBusRequestNameReply.primaryOwner, + ), + ) + as _i7.Future<_i2.DBusRequestNameReply>); + + @override + _i7.Future<_i2.DBusReleaseNameReply> releaseName(String? name) => + (super.noSuchMethod( + Invocation.method(#releaseName, [name]), + returnValue: _i7.Future<_i2.DBusReleaseNameReply>.value( + _i2.DBusReleaseNameReply.released, + ), + ) + as _i7.Future<_i2.DBusReleaseNameReply>); + + @override + _i7.Future> listQueuedOwners(String? name) => + (super.noSuchMethod( + Invocation.method(#listQueuedOwners, [name]), + returnValue: _i7.Future>.value([]), + ) + as _i7.Future>); + + @override + _i7.Future> listNames() => + (super.noSuchMethod( + Invocation.method(#listNames, []), + returnValue: _i7.Future>.value([]), + ) + as _i7.Future>); + + @override + _i7.Future> listActivatableNames() => + (super.noSuchMethod( + Invocation.method(#listActivatableNames, []), + returnValue: _i7.Future>.value([]), + ) + as _i7.Future>); + + @override + _i7.Future<_i2.DBusStartServiceByNameReply> startServiceByName( + String? name, + ) => + (super.noSuchMethod( + Invocation.method(#startServiceByName, [name]), + returnValue: _i7.Future<_i2.DBusStartServiceByNameReply>.value( + _i2.DBusStartServiceByNameReply.success, + ), + ) + as _i7.Future<_i2.DBusStartServiceByNameReply>); + + @override + _i7.Future nameHasOwner(String? name) => + (super.noSuchMethod( + Invocation.method(#nameHasOwner, [name]), + returnValue: _i7.Future.value(false), + ) + as _i7.Future); + + @override + _i7.Future getNameOwner(String? name) => + (super.noSuchMethod( + Invocation.method(#getNameOwner, [name]), + returnValue: _i7.Future.value(), + ) + as _i7.Future); + + @override + _i7.Future getConnectionUnixUser(String? name) => + (super.noSuchMethod( + Invocation.method(#getConnectionUnixUser, [name]), + returnValue: _i7.Future.value(0), + ) + as _i7.Future); + + @override + _i7.Future getConnectionUnixProcessId(String? name) => + (super.noSuchMethod( + Invocation.method(#getConnectionUnixProcessId, [name]), + returnValue: _i7.Future.value(0), + ) + as _i7.Future); + + @override + _i7.Future<_i2.DBusProcessCredentials> getConnectionCredentials( + String? name, + ) => + (super.noSuchMethod( + Invocation.method(#getConnectionCredentials, [name]), + returnValue: _i7.Future<_i2.DBusProcessCredentials>.value( + _FakeDBusProcessCredentials_0( + this, + Invocation.method(#getConnectionCredentials, [name]), + ), + ), + ) + as _i7.Future<_i2.DBusProcessCredentials>); + + @override + _i7.Future getId() => + (super.noSuchMethod( + Invocation.method(#getId, []), + returnValue: _i7.Future.value( + _i6.dummyValue(this, Invocation.method(#getId, [])), + ), + ) + as _i7.Future); + + @override + _i7.Future ping([String? destination = 'org.freedesktop.DBus']) => + (super.noSuchMethod( + Invocation.method(#ping, [destination]), + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) + as _i7.Future); + + @override + _i7.Future getMachineId([ + String? destination = 'org.freedesktop.DBus', + ]) => + (super.noSuchMethod( + Invocation.method(#getMachineId, [destination]), + returnValue: _i7.Future.value( + _i6.dummyValue( + this, + Invocation.method(#getMachineId, [destination]), + ), + ), + ) + as _i7.Future); + + @override + _i7.Future<_i3.DBusMethodSuccessResponse> callMethod({ + String? destination, + required _i4.DBusObjectPath? path, + String? interface, + required String? name, + Iterable<_i4.DBusValue>? values = const [], + _i4.DBusSignature? replySignature, + bool? noReplyExpected = false, + bool? noAutoStart = false, + bool? allowInteractiveAuthorization = false, + }) => + (super.noSuchMethod( + Invocation.method(#callMethod, [], { + #destination: destination, + #path: path, + #interface: interface, + #name: name, + #values: values, + #replySignature: replySignature, + #noReplyExpected: noReplyExpected, + #noAutoStart: noAutoStart, + #allowInteractiveAuthorization: allowInteractiveAuthorization, + }), + returnValue: _i7.Future<_i3.DBusMethodSuccessResponse>.value( + _FakeDBusMethodSuccessResponse_1( + this, + Invocation.method(#callMethod, [], { + #destination: destination, + #path: path, + #interface: interface, + #name: name, + #values: values, + #replySignature: replySignature, + #noReplyExpected: noReplyExpected, + #noAutoStart: noAutoStart, + #allowInteractiveAuthorization: allowInteractiveAuthorization, + }), + ), + ), + ) + as _i7.Future<_i3.DBusMethodSuccessResponse>); + + @override + _i7.Future emitSignal({ + String? destination, + required _i4.DBusObjectPath? path, + required String? interface, + required String? name, + Iterable<_i4.DBusValue>? values = const [], + }) => + (super.noSuchMethod( + Invocation.method(#emitSignal, [], { + #destination: destination, + #path: path, + #interface: interface, + #name: name, + #values: values, + }), + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) + as _i7.Future); + + @override + _i7.Future registerObject(_i8.DBusObject? object) => + (super.noSuchMethod( + Invocation.method(#registerObject, [object]), + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) + as _i7.Future); + + @override + _i7.Future unregisterObject(_i8.DBusObject? object) => + (super.noSuchMethod( + Invocation.method(#unregisterObject, [object]), + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) + as _i7.Future); +} + +/// A class which mocks [DBusRemoteObject]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDBusRemoteObject extends _i1.Mock implements _i9.DBusRemoteObject { + MockDBusRemoteObject() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.DBusClient get client => + (super.noSuchMethod( + Invocation.getter(#client), + returnValue: _FakeDBusClient_2(this, Invocation.getter(#client)), + ) + as _i2.DBusClient); + + @override + String get name => + (super.noSuchMethod( + Invocation.getter(#name), + returnValue: _i6.dummyValue(this, Invocation.getter(#name)), + ) + as String); + + @override + _i4.DBusObjectPath get path => + (super.noSuchMethod( + Invocation.getter(#path), + returnValue: _FakeDBusObjectPath_3(this, Invocation.getter(#path)), + ) + as _i4.DBusObjectPath); + + @override + _i7.Stream<_i9.DBusPropertiesChangedSignal> get propertiesChanged => + (super.noSuchMethod( + Invocation.getter(#propertiesChanged), + returnValue: _i7.Stream<_i9.DBusPropertiesChangedSignal>.empty(), + ) + as _i7.Stream<_i9.DBusPropertiesChangedSignal>); + + @override + set propertiesChanged(_i7.Stream<_i9.DBusPropertiesChangedSignal>? value) => + super.noSuchMethod( + Invocation.setter(#propertiesChanged, value), + returnValueForMissingStub: null, + ); + + @override + _i7.Future<_i5.DBusIntrospectNode> introspect() => + (super.noSuchMethod( + Invocation.method(#introspect, []), + returnValue: _i7.Future<_i5.DBusIntrospectNode>.value( + _FakeDBusIntrospectNode_4( + this, + Invocation.method(#introspect, []), + ), + ), + ) + as _i7.Future<_i5.DBusIntrospectNode>); + + @override + _i7.Future<_i4.DBusValue> getProperty( + String? interface, + String? name, { + _i4.DBusSignature? signature, + }) => + (super.noSuchMethod( + Invocation.method( + #getProperty, + [interface, name], + {#signature: signature}, + ), + returnValue: _i7.Future<_i4.DBusValue>.value( + _FakeDBusValue_5( + this, + Invocation.method( + #getProperty, + [interface, name], + {#signature: signature}, + ), + ), + ), + ) + as _i7.Future<_i4.DBusValue>); + + @override + _i7.Future> getAllProperties(String? interface) => + (super.noSuchMethod( + Invocation.method(#getAllProperties, [interface]), + returnValue: _i7.Future>.value( + {}, + ), + ) + as _i7.Future>); + + @override + _i7.Future setProperty( + String? interface, + String? name, + _i4.DBusValue? value, + ) => + (super.noSuchMethod( + Invocation.method(#setProperty, [interface, name, value]), + returnValue: _i7.Future.value(), + returnValueForMissingStub: _i7.Future.value(), + ) + as _i7.Future); + + @override + _i7.Future<_i3.DBusMethodSuccessResponse> callMethod( + String? interface, + String? name, + Iterable<_i4.DBusValue>? values, { + _i4.DBusSignature? replySignature, + bool? noReplyExpected = false, + bool? noAutoStart = false, + bool? allowInteractiveAuthorization = false, + }) => + (super.noSuchMethod( + Invocation.method( + #callMethod, + [interface, name, values], + { + #replySignature: replySignature, + #noReplyExpected: noReplyExpected, + #noAutoStart: noAutoStart, + #allowInteractiveAuthorization: allowInteractiveAuthorization, + }, + ), + returnValue: _i7.Future<_i3.DBusMethodSuccessResponse>.value( + _FakeDBusMethodSuccessResponse_1( + this, + Invocation.method( + #callMethod, + [interface, name, values], + { + #replySignature: replySignature, + #noReplyExpected: noReplyExpected, + #noAutoStart: noAutoStart, + #allowInteractiveAuthorization: + allowInteractiveAuthorization, + }, + ), + ), + ), + ) + as _i7.Future<_i3.DBusMethodSuccessResponse>); +}