blob: 635f7ee6704e9ab680b01392d7c5e2f353ff8884 [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'package:scheduled_test/scheduled_test.dart';
import 'package:watcher/watcher.dart';
import 'utils.dart';
main() {
initConfig();
setUp(createSandbox);
test('does not notify for files that already exist when started', () {
// Make some pre-existing files.
writeFile("a.txt");
writeFile("b.txt");
createWatcher();
// Change one after the watcher is running.
writeFile("b.txt", contents: "modified");
// We should get a modify event for the changed file, but no add events
// for them before this.
expectModifyEvent("b.txt");
});
test('notifies when a file is added', () {
createWatcher();
writeFile("file.txt");
expectAddEvent("file.txt");
});
test('notifies when a file is modified', () {
writeFile("file.txt");
createWatcher();
writeFile("file.txt", contents: "modified");
expectModifyEvent("file.txt");
});
test('notifies when a file is removed', () {
writeFile("file.txt");
createWatcher();
deleteFile("file.txt");
expectRemoveEvent("file.txt");
});
test('notifies when a file is moved', () {
writeFile("old.txt");
createWatcher();
renameFile("old.txt", "new.txt");
expectAddEvent("new.txt");
expectRemoveEvent("old.txt");
});
test('notifies when a file is modified multiple times', () {
writeFile("file.txt");
createWatcher();
writeFile("file.txt", contents: "modified");
expectModifyEvent("file.txt");
writeFile("file.txt", contents: "modified again");
expectModifyEvent("file.txt");
});
test('does not notify if the file contents are unchanged', () {
writeFile("a.txt", contents: "same");
writeFile("b.txt", contents: "before");
createWatcher();
writeFile("a.txt", contents: "same");
writeFile("b.txt", contents: "after");
expectModifyEvent("b.txt");
});
test('does not notify if the modification time did not change', () {
writeFile("a.txt", contents: "before");
writeFile("b.txt", contents: "before");
createWatcher();
writeFile("a.txt", contents: "after", updateModified: false);
writeFile("b.txt", contents: "after");
expectModifyEvent("b.txt");
});
test('watches files in subdirectories', () {
createWatcher();
writeFile("a/b/c/d/file.txt");
expectAddEvent("a/b/c/d/file.txt");
});
test('does not notify for changes when there were no subscribers', () {
// Note that this test doesn't rely as heavily on the test functions in
// utils.dart because it needs to be very explicit about when the event
// stream is and is not subscribed.
var watcher = createWatcher();
// Subscribe to the events.
var completer = new Completer();
var subscription = watcher.events.listen((event) {
expect(event.type, equals(ChangeType.ADD));
expect(event.path, endsWith("file.txt"));
completer.complete();
});
writeFile("file.txt");
// Then wait until we get an event for it.
schedule(() => completer.future);
// Unsubscribe.
schedule(() {
subscription.cancel();
});
// Now write a file while we aren't listening.
writeFile("unwatched.txt");
// Then start listening again.
schedule(() {
completer = new Completer();
subscription = watcher.events.listen((event) {
// We should get an event for the third file, not the one added while
// we weren't subscribed.
expect(event.type, equals(ChangeType.ADD));
expect(event.path, endsWith("added.txt"));
completer.complete();
});
});
// The watcher will have been cancelled and then resumed in the middle of
// its pause between polling loops. That means the second scan to skip
// what changed while we were unsubscribed won't happen until after that
// delay is done. Wait long enough for that to happen.
schedule(() => new Future.delayed(new Duration(seconds: 1)));
// And add a third file.
writeFile("added.txt");
// Wait until we get an event for the third file.
schedule(() => completer.future);
schedule(() {
subscription.cancel();
});
});
test('ready does not complete until after subscription', () {
var watcher = createWatcher(waitForReady: false);
var ready = false;
watcher.ready.then((_) {
ready = true;
});
// Should not be ready yet.
schedule(() {
expect(ready, isFalse);
});
// Subscribe to the events.
schedule(() {
var subscription = watcher.events.listen((event) {});
currentSchedule.onComplete.schedule(() {
subscription.cancel();
});
});
// Should eventually be ready.
schedule(() => watcher.ready);
schedule(() {
expect(ready, isTrue);
});
});
test('ready completes immediately when already ready', () {
var watcher = createWatcher(waitForReady: false);
// Subscribe to the events.
schedule(() {
var subscription = watcher.events.listen((event) {});
currentSchedule.onComplete.schedule(() {
subscription.cancel();
});
});
// Should eventually be ready.
schedule(() => watcher.ready);
// Now ready should be a future that immediately completes.
var ready = false;
schedule(() {
watcher.ready.then((_) {
ready = true;
});
});
schedule(() {
expect(ready, isTrue);
});
});
test('ready returns a future that does not complete after unsubscribing', () {
var watcher = createWatcher(waitForReady: false);
// Subscribe to the events.
var subscription;
schedule(() {
subscription = watcher.events.listen((event) {});
});
var ready = false;
// Wait until ready.
schedule(() => watcher.ready);
// Now unsubscribe.
schedule(() {
subscription.cancel();
// Track when it's ready again.
ready = false;
watcher.ready.then((_) {
ready = true;
});
});
// Should be back to not ready.
schedule(() {
expect(ready, isFalse);
});
});
}