Skip to content

Commit

Permalink
ModifiableSnapshotView.fromStream behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
rbellens committed Oct 20, 2020
1 parent 0994a18 commit 9ca31e1
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
## 0.1.0-dev.2
## 0.1.0-dev.3

- Initial version
23 changes: 20 additions & 3 deletions lib/src/snapshot_view.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
library snapshot.view;

import 'dart:async';

import 'package:meta/meta.dart';
import 'package:rxdart/rxdart.dart';
import 'package:snapshot/snapshot.dart';
Expand Down Expand Up @@ -107,9 +109,24 @@ class ModifiableSnapshotView with SnapshotView {
}

ModifiableSnapshotView.fromStream(Stream<Snapshot> stream) {
_snapshots.addStream(stream.doOnDone(() {
_snapshots.close();
}));
StreamSubscription subscription;
_snapshots.onListen = () {
subscription ??= stream.listen(_snapshots.add,
onError: _snapshots.addError, onDone: _snapshots.close);
subscription.resume();
};
_snapshots.onCancel = () {
if (stream.isBroadcast) {
subscription.cancel();
subscription = null;
} else {
subscription.pause();
}
};
_snapshots.done.then((v) {
subscription?.cancel();
subscription = null;
});
}

@override
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: snapshot
description: A library that can be used to implement data classes and simplifies conversion of JSON to data classes
version: 0.1.0-dev.2
version: 0.1.0-dev.3
homepage: https://github.com/appsup-dart/snapshot

environment:
Expand Down
86 changes: 86 additions & 0 deletions test/snapshot_view_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:snapshot/snapshot.dart';
import 'package:test/test.dart';

Expand Down Expand Up @@ -106,6 +108,90 @@ void main() {
expect(snapshot.get('address/city'), 'New York');
});
});

group('ModifiableSnapshotView.fromStream', () {
test('Lifecycle for non broadcast stream', () async {
var listenCalled = false,
pauseCalled = false,
cancelCalled = false,
resumeCalled = false;
var controller = StreamController<Snapshot>(onListen: () {
listenCalled = true;
}, onPause: () {
pauseCalled = true;
}, onResume: () {
resumeCalled = true;
}, onCancel: () {
cancelCalled = true;
});
var view = ModifiableSnapshotView.fromStream(controller.stream);

expect(view.snapshot, isNull);
expect(listenCalled, false);

// listening on onChanged should trigger listen on controller
var s = view.onChanged.listen((_) => null);
expect(view.snapshot, isNull);
expect(listenCalled, true);

// adding a snapshot to the controller should update the view
controller.add(Snapshot.empty());
await Future.microtask(() => null);
expect(view.snapshot, isNotNull);

// canceling the subscription onChanged should pause the controller
expect(pauseCalled, false);
await s.cancel();
expect(pauseCalled, true);

// listening again should trigger resume on controller
expect(resumeCalled, false);
s = view.onChanged.listen((_) => null);
expect(resumeCalled, true);

// disposing the snapshot view should cancel the controller
expect(cancelCalled, false);
await view.dispose();
expect(cancelCalled, true);
});
test('Lifecycle for broadcast stream', () async {
var listenCalled = false, cancelCalled = false;
var controller = StreamController<Snapshot>.broadcast(onListen: () {
listenCalled = true;
}, onCancel: () {
cancelCalled = true;
});
var view = ModifiableSnapshotView.fromStream(controller.stream);

expect(view.snapshot, isNull);
expect(listenCalled, false);

// listening on onChanged should trigger listen on controller
var s = view.onChanged.listen((_) => null);
expect(view.snapshot, isNull);
expect(listenCalled, true);

// adding a snapshot to the controller should update the view
controller.add(Snapshot.empty());
await Future.microtask(() => null);
expect(view.snapshot, isNotNull);

// canceling the subscription should cancel the controller
expect(cancelCalled, false);
await s.cancel();
expect(cancelCalled, true);

// listening again should trigger listen on controller
listenCalled = false;
s = view.onChanged.listen((_) => null);
expect(listenCalled, true);

// disposing the snapshot view should cancel the controller
cancelCalled = false;
await view.dispose();
expect(cancelCalled, true);
});
});
});
}

Expand Down

0 comments on commit 9ca31e1

Please sign in to comment.