blob: 6c9ffd873d28bb9a736f653fd59f97114cc3320d [file] [log] [blame]
import 'dart:async';
import 'package:test/test.dart';
import 'package:watcher/watcher.dart';
import 'utils.dart';
void main() {
_MemFs memFs;
final defaultFactoryId = 'MemFs';
setUp(() {
memFs = _MemFs();
registerCustomWatcherFactory(_MemFsWatcherFactory(defaultFactoryId, memFs));
});
tearDown(() async {
unregisterCustomWatcherFactory(defaultFactoryId);
});
test('notifes 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('notifes 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('unregister works', () async {
unregisterCustomWatcherFactory(defaultFactoryId);
watcherFactory = (path) => FileWatcher(path);
try {
// This uses standard files, so it wouldn't trigger an event in
// _MemFsWatcher.
writeFile('file.txt');
await startWatcher(path: 'file.txt');
deleteFile('file.txt');
} finally {
watcherFactory = null;
}
await expectRemoveEvent('file.txt');
});
test('registering twice throws', () async {
expect(
() => registerCustomWatcherFactory(
_MemFsWatcherFactory(defaultFactoryId, memFs)),
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.
registerCustomWatcherFactory(_MemFsWatcherFactory('Different id', memFs));
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 implements CustomWatcherFactory {
@override
final String id;
final _MemFs _memFs;
_MemFsWatcherFactory(this.id, this._memFs);
@override
DirectoryWatcher createDirectoryWatcher(String path,
{Duration pollingDelay}) =>
_MemFsWatcher(path, _memFs.watchStream(path));
@override
FileWatcher createFileWatcher(String path, {Duration pollingDelay}) =>
_MemFsWatcher(path, _memFs.watchStream(path));
}