6784d2dd16
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
196 lines
5.4 KiB
Dart
196 lines
5.4 KiB
Dart
import 'package:file_selector/file_selector.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:wolf_3d_dart/wolf_3d_data_types.dart';
|
|
import 'package:wolf_3d_dart/wolf_3d_engine.dart';
|
|
import 'package:wolf_3d_flutter/wolf_3d_flutter.dart';
|
|
|
|
class _NoopAudio implements EngineAudio {
|
|
@override
|
|
WolfensteinData? activeGame;
|
|
|
|
int stopAllAudioCallCount = 0;
|
|
int disposeCallCount = 0;
|
|
|
|
@override
|
|
Future<void> debugSoundTest() async {}
|
|
|
|
@override
|
|
Future<void> init() async {}
|
|
|
|
@override
|
|
void playLevelMusic(Music music) {}
|
|
|
|
@override
|
|
void playMenuMusic() {}
|
|
|
|
@override
|
|
void playSoundEffect(SoundEffect effect) {}
|
|
|
|
@override
|
|
void playSoundEffectId(int sfxId) {}
|
|
|
|
@override
|
|
Future<void> stopAllAudio() async {
|
|
stopAllAudioCallCount++;
|
|
}
|
|
|
|
@override
|
|
void stopMusic() {}
|
|
|
|
@override
|
|
void dispose() {
|
|
disposeCallCount++;
|
|
}
|
|
}
|
|
|
|
class _RecordingEngine extends Wolf3dFlutterEngine {
|
|
_RecordingEngine({required _NoopAudio audio}) : super(audioBackend: audio);
|
|
|
|
int initCallCount = 0;
|
|
String? lastDirectory;
|
|
List<String> lastAdditionalDirectories = <String>[];
|
|
|
|
@override
|
|
Future<Wolf3dFlutterEngine> init({
|
|
String? directory,
|
|
Iterable<String>? additionalDirectories,
|
|
}) async {
|
|
initCallCount++;
|
|
lastDirectory = directory;
|
|
lastAdditionalDirectories =
|
|
additionalDirectories?.toList(growable: false) ?? <String>[];
|
|
return this;
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
group('GameDataPickerManager', () {
|
|
test('pickGameDataDirectory reloads selected directory', () async {
|
|
final engine = _RecordingEngine(audio: _NoopAudio());
|
|
int notifyCount = 0;
|
|
final manager = GameDataPickerManager(
|
|
engine: engine,
|
|
pickDirectory: ({String? confirmButtonText}) async => ' /tmp/wolf ',
|
|
);
|
|
|
|
await manager.pickGameDataDirectory(
|
|
notifyChanged: () => notifyCount++,
|
|
);
|
|
|
|
expect(notifyCount, 2);
|
|
expect(manager.isLoadingGameData, isFalse);
|
|
expect(manager.pickerError, isNull);
|
|
expect(engine.initCallCount, 1);
|
|
expect(engine.lastDirectory, '/tmp/wolf');
|
|
expect(engine.lastAdditionalDirectories, isEmpty);
|
|
});
|
|
|
|
test('pickGameDataDirectory ignores empty selection', () async {
|
|
final engine = _RecordingEngine(audio: _NoopAudio());
|
|
final manager = GameDataPickerManager(
|
|
engine: engine,
|
|
pickDirectory: ({String? confirmButtonText}) async => ' ',
|
|
);
|
|
|
|
await manager.pickGameDataDirectory(notifyChanged: () {});
|
|
|
|
expect(engine.initCallCount, 0);
|
|
expect(manager.pickerError, isNull);
|
|
});
|
|
|
|
test(
|
|
'pickGameDataFiles deduplicates directories and forwards extras',
|
|
() async {
|
|
final engine = _RecordingEngine(audio: _NoopAudio());
|
|
final manager = GameDataPickerManager(
|
|
engine: engine,
|
|
pickFiles: () async => <XFile>[
|
|
XFile('/a/one/VSWAP.WL6'),
|
|
XFile('/a/one/MAPHEAD.WL6'),
|
|
XFile('/a/two/VSWAP.WL1'),
|
|
],
|
|
);
|
|
|
|
await manager.pickGameDataFiles(notifyChanged: () {});
|
|
|
|
expect(engine.initCallCount, 1);
|
|
expect(engine.lastDirectory, '/a/one');
|
|
expect(engine.lastAdditionalDirectories, <String>['/a/two']);
|
|
expect(manager.pickerError, isNull);
|
|
},
|
|
);
|
|
|
|
test('pickGameDataFiles reports missing directory paths', () async {
|
|
final engine = _RecordingEngine(audio: _NoopAudio());
|
|
final manager = GameDataPickerManager(
|
|
engine: engine,
|
|
pickFiles: () async => <XFile>[
|
|
XFile('VSWAP.WL6'),
|
|
XFile('MAPHEAD.WL6'),
|
|
],
|
|
);
|
|
|
|
await manager.pickGameDataFiles(notifyChanged: () {});
|
|
|
|
expect(engine.initCallCount, 0);
|
|
expect(
|
|
manager.pickerError,
|
|
'Selected files do not expose local filesystem paths.',
|
|
);
|
|
});
|
|
|
|
test('pickGameDataDirectory captures thrown picker error', () async {
|
|
final engine = _RecordingEngine(audio: _NoopAudio());
|
|
final manager = GameDataPickerManager(
|
|
engine: engine,
|
|
pickDirectory: ({String? confirmButtonText}) async {
|
|
throw StateError('picker failed');
|
|
},
|
|
);
|
|
|
|
await manager.pickGameDataDirectory(notifyChanged: () {});
|
|
|
|
expect(engine.initCallCount, 0);
|
|
expect(
|
|
manager.pickerError,
|
|
contains('Unable to load selected directory'),
|
|
);
|
|
expect(manager.isLoadingGameData, isFalse);
|
|
});
|
|
});
|
|
|
|
group('Wolf3dAppManager', () {
|
|
test('ensureAudioShutdown only executes once', () async {
|
|
final audio = _NoopAudio();
|
|
final engine = _RecordingEngine(audio: audio);
|
|
final manager = Wolf3dAppManager(engine: engine);
|
|
|
|
await Future.wait<void>(<Future<void>>[
|
|
manager.ensureAudioShutdown(),
|
|
manager.ensureAudioShutdown(),
|
|
]);
|
|
|
|
expect(audio.stopAllAudioCallCount, 1);
|
|
expect(audio.disposeCallCount, 1);
|
|
});
|
|
|
|
test('forwards picker state from injected picker manager', () async {
|
|
final engine = _RecordingEngine(audio: _NoopAudio());
|
|
final pickerManager = GameDataPickerManager(
|
|
engine: engine,
|
|
pickDirectory: ({String? confirmButtonText}) async => '/tmp/wolf',
|
|
);
|
|
final manager = Wolf3dAppManager(
|
|
engine: engine,
|
|
pickerManager: pickerManager,
|
|
);
|
|
|
|
await manager.pickGameDataDirectory(notifyChanged: () {});
|
|
|
|
expect(manager.isLoadingGameData, isFalse);
|
|
expect(manager.pickerError, isNull);
|
|
expect(engine.lastDirectory, '/tmp/wolf');
|
|
});
|
|
});
|
|
}
|