151 lines
4.2 KiB
Dart
151 lines
4.2 KiB
Dart
import 'dart:io';
|
|
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:ikar/core/plugins/plugin_host.dart';
|
|
import 'package:ikar/core/plugins/plugin_manifest.dart';
|
|
import 'package:ikar/core/plugins/plugin_models.dart';
|
|
import 'package:ikar/core/plugins/plugin_runtime.dart';
|
|
|
|
class _Host implements PluginHost {
|
|
final messages = <String>[];
|
|
final notifications = <String>[];
|
|
@override
|
|
String get args => 'synthetic';
|
|
@override
|
|
Map<String, dynamic> get arguments => const {};
|
|
@override
|
|
Map<String, dynamic>? get replyMessage => null;
|
|
@override
|
|
bool get isOnline => true;
|
|
@override
|
|
bool isActive = true;
|
|
@override
|
|
Future<String> sendText(String text) async {
|
|
messages.add(text);
|
|
return 'synthetic-id';
|
|
}
|
|
|
|
@override
|
|
Future<void> editText(String id, String text) async =>
|
|
messages.add('$id:$text');
|
|
@override
|
|
Future<void> notify(String text) async => notifications.add(text);
|
|
@override
|
|
Future<Map<String, dynamic>?> getPeer() async => null;
|
|
@override
|
|
Future<void> sendFile(Uint8List bytes, {required String filename}) async {}
|
|
@override
|
|
Future<void> sendPhoto(
|
|
Uint8List bytes, {
|
|
required String filename,
|
|
required String caption,
|
|
}) async {}
|
|
}
|
|
|
|
PluginCommandDescriptor _command(String code, Set<PluginPermission> granted) {
|
|
final manifest = PluginManifest.fromJson({
|
|
'schemaVersion': 1,
|
|
'id': 'dev.example.runtime',
|
|
'name': 'Synthetic',
|
|
'version': '1.0.0',
|
|
'apiVersion': 1,
|
|
'description': 'Runtime test',
|
|
'author': 'Test',
|
|
'main': 'main.js',
|
|
'permissions': ['chat.write', 'chat.edit', 'ui.notify'],
|
|
'commands': [
|
|
{'name': '/synthetic', 'description': 'Test', 'handler': 'run'},
|
|
],
|
|
});
|
|
return PluginCommandDescriptor(
|
|
plugin: PluginDescriptor(
|
|
manifest: manifest,
|
|
origin: PluginOrigin.installed,
|
|
enabled: true,
|
|
grantedPermissions: granted,
|
|
loadModules: () async => {'main.js': code},
|
|
signatureStatus: PluginSignatureStatus.unsigned,
|
|
),
|
|
command: manifest.commands.single,
|
|
);
|
|
}
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
setUpAll(() async {
|
|
final library =
|
|
Platform.environment['QLYRA_FJS_LIBRARY'] ??
|
|
'build/native-tests/fjs/${Platform.isWindows
|
|
? 'fjs.dll'
|
|
: Platform.isMacOS
|
|
? 'libfjs.dylib'
|
|
: 'libfjs.so'}';
|
|
if (!File(library).existsSync()) {
|
|
throw StateError(
|
|
'Run dart run tool/prepare_plugin_runtime.dart before native plugin tests',
|
|
);
|
|
}
|
|
await PluginRuntime.initialize(
|
|
externalLibrary: ExternalLibrary.open(File(library).absolute.path),
|
|
);
|
|
});
|
|
|
|
test(
|
|
'executes a JavaScript plugin with the compatible API and awaits editing',
|
|
() async {
|
|
final host = _Host();
|
|
await PluginRuntime.run(
|
|
_command(
|
|
'''
|
|
import { chat } from 'komet:api';
|
|
export async function run() {
|
|
const id = await chat.sendText('synthetic');
|
|
await chat.editText(id, 'edited');
|
|
}
|
|
''',
|
|
{PluginPermission.chatWrite, PluginPermission.chatEdit},
|
|
),
|
|
host,
|
|
);
|
|
expect(host.messages, ['synthetic', 'synthetic-id:edited']);
|
|
},
|
|
);
|
|
|
|
test('denies sending without an explicit grant', () async {
|
|
final host = _Host();
|
|
await PluginRuntime.run(
|
|
_command(
|
|
'''
|
|
import { chat, ui } from 'komet:api';
|
|
export async function run() {
|
|
try { await chat.sendText('forbidden'); }
|
|
catch (_) { await ui.notify('denied'); }
|
|
}
|
|
''',
|
|
{PluginPermission.uiNotify},
|
|
),
|
|
host,
|
|
);
|
|
expect(host.messages, isEmpty);
|
|
expect(host.notifications, ['denied']);
|
|
});
|
|
|
|
test('a closed chat cannot receive plugin messages', () async {
|
|
final host = _Host()..isActive = false;
|
|
try {
|
|
await PluginRuntime.run(
|
|
_command(
|
|
'''
|
|
import { chat } from 'komet:api';
|
|
export async function run() { await chat.sendText('forbidden'); }
|
|
''',
|
|
{PluginPermission.chatWrite},
|
|
),
|
|
host,
|
|
);
|
|
} catch (_) {}
|
|
expect(host.messages, isEmpty);
|
|
});
|
|
}
|