How to test if stream emits a value at a particular position in Dart? - flutter

If I have a stream that emits objects of Dog.
Stream<Dog> dogStream;
class Dog {
final String name;
final String breed;
Dog(this.name, this.breed);
}
I want to test for the name emitted in 4th value.
So I want to ignore the first 3 values emitted by the stream and check if the 4th value is equal to say foo. How to check at a particular position?
PS: There are hacky ways of doing it, like using expectInOrder, but my test should not care about the first 3 values emitted, and if I want to check for 8th or say 20th value, it doesn't make sense to use expectInOrder.

You can use elementAt or skip first 3 values of the stream and check emitted item:
test('stream', () async {
Stream<int> stream() => Stream.fromIterable([1, 2, 3, 4, 5]);
expect(await stream().elementAt(3), 4);
expect(stream().skip(3), emitsInOrder(<dynamic>[4]));
expect(stream().skip(3), emits(4));
});

Related

Best practice for consecutive method invocations on the same reference using Dart

My linter doesn't like it when I do something like:
final list = [];
list.add(someItem);
list.add(anotherItem);
list.add(thirdItem);
hint: "Cascade consecutive method invocations on the same reference."
Is it preferred / better practice to do:
final list = [];
final item1 = someItem;
final item2 = anotherItem;
final item3 = thirdItem;
list.addAll([item1, item2, item3]);
If so, why?
The lint is suggesting you to use the Cascade operator. This operator allows you to make multiple operations on the same object. This way you won't need to repeat the call to the reference name (in this case, list).
Here is an example in your case, comparing both ways:
List<int> list= [];
list.add(1);
list.add(2);
list.add(3);
print (list);
Where, using the cascade operator:
List<int> list2= [];
list2..add(1)
..add(2)
..add(3); // May be done without line breaks, if preferred.
print(list2);
Both examples prints the same output, which is the desirable result. But the second one feels cleaner and more readable. Also, if you want to later change which object is being used, you have to change it in only one place.
You can test it on DartPad.

Dart List<e> class questions

for below print, both print results are the same. but is there a difference between List<Dog> test = <Dog>[]; and List<Dog> test2 =List<Dog>();?
void main() {
List<Dog> test = <Dog>[];
List<Dog> test2 =List<Dog>();
Dog dog = Dog(10);
test.add(dog);
print(test[0].age);
test2.add(dog);
print(test2[0].age);
}
class Dog {
Dog({this.age});
int age;
}
there is no difference between the two. Both create a growable list as shown in the docs here.
The default growable list, as returned by new List() or [], keeps an internal buffer, and grows that buffer when necessary.This guarantees that a sequence of add operations will each execute in amortized constant time. Setting the length directly may take time proportional to the new length, and may change the internal capacity so that a following add operation will need to immediately increase the buffer capacity.
The one that is different from the above is if you wanted to create a non-growable list.
For that you would use,
List<Dog> fixedLengthList = new List(5);
In a fixed-length list, an error occurs when attempting to use operations that can change the length of the list.

How can I convert an observable to a maybe?

There are new convenience methods added to rxjava2 added to accomplish a similar thing.
toSingle() converts an Observable that emits a single item into a Single that emits that item
toObservable() converts a Single into an Observable that emits the item emitted by the Single and then completes
How do can I convert an Observable to a Maybe?
(source: http://reactivex.io/documentation/single.html)
You can't directly convert an Observable into a Maybe, because it wouldn't know what to emit in that context: is it the first element? the last? the product of some processing to the elements?
You can, however, decide on that and do what you want:
final Observable<Boolean> sourceBooleans = Observable.just(true, true, false);
final Maybe<Boolean> firstMaybe = sourceBooleans.firstElement();
final Maybe<Boolean> lastMaybe = sourceBooleans.lastElement();
final Maybe<Boolean> secondMaybe = sourceBooleans.elementAt(1);
final Observable<Integer> sourceNumbers = Observable.just(1, 2, 3, 4);
final Maybe<Integer> firstEven = sourceNumbers
.filter(it -> it % 2 == 0)
.firstElement()
You can see what methods return Maybe in the Observable implementation
Note that you can't go from Observable to Single directly either, without choosing what it should emit: there's no toSingle in the Observable class, but methods that return a Single instead (like first(), last(), etc.)

Array of observables where the output of each is the input of the next

I'm trying to use RxSwift to execute actions on multiple data sources. However, I have no idea how to accomplish the following.
I have an array of observabless where the output of each, should be the input of the next. So, I want to do something like, get the first observable, wait for the result and pass it to the next, all the way to the end of the array and return one final value.
Is that possible? Thanks in advance.
*** Update: Ok, I'll be more specific as requested.
The 'observables' I'm using in the array, are custom. I use a function that returns Observable.create { ... }. Inside the closure, I run an asynchronous operation that transforms the value and then send the result to the observer before completing. That resulting value, must pass to the next observable, and so on to the last observable in the array to get a final value.
The observables may send multiple values, but they must pass from one observable to the next like an assembly line.
It is difficult to know exactly what you are asking for, since Observables do not exactly have inputs but I think this is a common problem.
You may be looking for a combination of the concat or reduce operators, which allow you to accumulate data from the values emitted from an Observable. See ReactiveX's documentation for Mathematical and Aggregate Operators.
Hopefully this can get you started:
// "I have an array of observables..."
let one = Observable.deferred { Observable.just(1) }
let two = Observable.deferred { Observable.just(2) }
let observables = [one, two]
// "the output of each, should be the input of the next"
// this is problematic, because observables do not strictly have inputs.
let resultsFromEach = Observable.concat(observables)
resultsFromEach
.reduce(0) { result, next in
result + 1
}
.debug("result")
.subscribe()

Create infinite repeatable Observable from array

Let's say I have an array items
I know I can create an observable from this array using
Rx.Observable.fromArray(items)
How do I create a lazily infinitely repeating observable from this (i.e.: repeating the items as long as they are being requested)?
Tried
Rx.Observable.fromArray(items).repeat()
But this doesn't execute lazily and therefor locks up the browser.
You cannot do this with an Observable. You way want to look at using an Enumerable.
The Enumerable flavor of Reactive Extensions is known as Interective Extensions.
I'm still a newcomer to RxJS, so perhaps what I am proposing is complete madness, but could something along the lines of the following work for this?
var items = [1, 2, 3, 4, 5];
var infiniteSource = Rx.Observable.from(items)
.map(function (x) { return Rx.Observable.return(x).delay(1000); })
.concatAll()
.doWhile(function(_) { return true; /* i.e. never end */ });
infiniteSource.subscribe(function(x) { console.log(x); });
I have an example here: http://ctrlplusb.jsbin.com/sihewo/edit?js,console
The delay is put in there so as not to flood the console. In terms of the "until no longer needed part" perhaps an unsubscribe or other mechanism can be injected into the doWhile?