blob: 331d24382a73090fd11e32dd3b0b80115a9d6309 [file] [log] [blame]
import 'dart:async';
import 'package:test/test.dart';
import 'package:watcher/watcher.dart';
void main() {
late _MemFs memFs;
final memFsFactoryId = 'MemFs';
final noOpFactoryId = 'NoOp';
setUpAll(() {
memFs = _MemFs();
var memFsWatcherFactory = _MemFsWatcherFactory(memFs);
var noOpWatcherFactory = _NoOpWatcherFactory();
registerCustomWatcher(
noOpFactoryId,
noOpWatcherFactory.createDirectoryWatcher,
noOpWatcherFactory.createFileWatcher);
registerCustomWatcher(
memFsFactoryId,
memFsWatcherFactory.createDirectoryWatcher,
memFsWatcherFactory.createFileWatcher);
});
test('notifies for files', () async {
var watcher = FileWatcher('file.txt');
var completer = Completer<WatchEvent>();
watcher.events.listen((event) => completer.complete(event));
await watcher.ready;
memFs.add('file.txt');
var event = await completer.future;
expect(event.type, ChangeType.ADD);
expect(event.path, 'file.txt');
});
test('notifies for directories', () async {
var watcher = DirectoryWatcher('dir');
var completer = Completer<WatchEvent>();
watcher.events.listen((event) => completer.complete(event));
await watcher.ready;
memFs.add('dir');
var event = await completer.future;
expect(event.type, ChangeType.ADD);
expect(event.path, 'dir');
});
test('registering twice throws', () async {
expect(
() => registerCustomWatcher(memFsFactoryId,
(_, {pollingDelay}) => throw 0, (_, {pollingDelay}) => throw 0),
throwsA(isA<ArgumentError>()));
});
test('finding two applicable factories throws', () async {
// Note that _MemFsWatcherFactory always returns a watcher, so having two
// will always produce a conflict.
var watcherFactory = _MemFsWatcherFactory(memFs);
registerCustomWatcher('Different id', watcherFactory.createDirectoryWatcher,
watcherFactory.createFileWatcher);
expect(() => FileWatcher('file.txt'), throwsA(isA<StateError>()));
expect(() => DirectoryWatcher('dir'), throwsA(isA<StateError>()));
});
}
class _MemFs {
final _streams = <String, Set<StreamController<WatchEvent>>>{};
StreamController<WatchEvent> watchStream(String path) {
var controller = StreamController<WatchEvent>();
_streams
.putIfAbsent(path, () => <StreamController<WatchEvent>>{})
.add(controller);
return controller;
}
void add(String path) {
var controllers = _streams[path];
if (controllers != null) {
for (var controller in controllers) {
controller.add(WatchEvent(ChangeType.ADD, path));
}
}
}
void remove(String path) {
var controllers = _streams[path];
if (controllers != null) {
for (var controller in controllers) {
controller.add(WatchEvent(ChangeType.REMOVE, path));
}
}
}
}
class _MemFsWatcher implements FileWatcher, DirectoryWatcher, Watcher {
final String _path;
final StreamController<WatchEvent> _controller;
_MemFsWatcher(this._path, this._controller);
@override
String get path => _path;
@override
String get directory => throw UnsupportedError('directory is not supported');
@override
Stream<WatchEvent> get events => _controller.stream;
@override
bool get isReady => true;
@override
Future<void> get ready async {}
}
class _MemFsWatcherFactory {
final _MemFs _memFs;
_MemFsWatcherFactory(this._memFs);
DirectoryWatcher? createDirectoryWatcher(String path,
{Duration? pollingDelay}) =>
_MemFsWatcher(path, _memFs.watchStream(path));
FileWatcher? createFileWatcher(String path, {Duration? pollingDelay}) =>
_MemFsWatcher(path, _memFs.watchStream(path));
}
class _NoOpWatcherFactory {
DirectoryWatcher? createDirectoryWatcher(String path,
{Duration? pollingDelay}) =>
null;
FileWatcher? createFileWatcher(String path, {Duration? pollingDelay}) => null;
}