| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- //
- // RACChannelExamples.m
- // ReactiveCocoa
- //
- // Created by Uri Baghin on 30/12/2012.
- // Copyright (c) 2012 GitHub, Inc. All rights reserved.
- //
- #import <Quick/Quick.h>
- #import <Nimble/Nimble.h>
- #import "RACChannelExamples.h"
- #import "NSObject+RACDeallocating.h"
- #import "NSObject+RACPropertySubscribing.h"
- #import "RACChannel.h"
- #import "RACCompoundDisposable.h"
- #import "RACDisposable.h"
- #import "RACSignal+Operations.h"
- NSString * const RACChannelExamples = @"RACChannelExamples";
- NSString * const RACChannelExampleCreateBlock = @"RACChannelExampleCreateBlock";
- NSString * const RACViewChannelExamples = @"RACViewChannelExamples";
- NSString * const RACViewChannelExampleCreateViewBlock = @"RACViewChannelExampleCreateViewBlock";
- NSString * const RACViewChannelExampleCreateTerminalBlock = @"RACViewChannelExampleCreateTerminalBlock";
- NSString * const RACViewChannelExampleKeyPath = @"RACViewChannelExampleKeyPath";
- NSString * const RACViewChannelExampleSetViewValueBlock = @"RACViewChannelExampleSetViewValueBlock";
- QuickConfigurationBegin(RACChannelExampleGroups)
- + (void)configure:(Configuration *)configuration {
- sharedExamples(RACChannelExamples, ^(QCKDSLSharedExampleContext exampleContext) {
- __block RACChannel * (^getChannel)(void);
- __block RACChannel *channel;
- id value1 = @"test value 1";
- id value2 = @"test value 2";
- id value3 = @"test value 3";
- NSArray *values = @[ value1, value2, value3 ];
- qck_beforeEach(^{
- getChannel = exampleContext()[RACChannelExampleCreateBlock];
- channel = getChannel();
- });
- qck_it(@"should not send any leadingTerminal value on subscription", ^{
- __block id receivedValue = nil;
- [channel.followingTerminal sendNext:value1];
- [channel.leadingTerminal subscribeNext:^(id x) {
- receivedValue = x;
- }];
- expect(receivedValue).to(beNil());
- [channel.followingTerminal sendNext:value2];
- expect(receivedValue).to(equal(value2));
- });
- qck_it(@"should send the latest followingTerminal value on subscription", ^{
- __block id receivedValue = nil;
- [channel.leadingTerminal sendNext:value1];
- [[channel.followingTerminal take:1] subscribeNext:^(id x) {
- receivedValue = x;
- }];
- expect(receivedValue).to(equal(value1));
- [channel.leadingTerminal sendNext:value2];
- [[channel.followingTerminal take:1] subscribeNext:^(id x) {
- receivedValue = x;
- }];
- expect(receivedValue).to(equal(value2));
- });
- qck_it(@"should send leadingTerminal values as they change", ^{
- NSMutableArray *receivedValues = [NSMutableArray array];
- [channel.leadingTerminal subscribeNext:^(id x) {
- [receivedValues addObject:x];
- }];
- [channel.followingTerminal sendNext:value1];
- [channel.followingTerminal sendNext:value2];
- [channel.followingTerminal sendNext:value3];
- expect(receivedValues).to(equal(values));
- });
- qck_it(@"should send followingTerminal values as they change", ^{
- [channel.leadingTerminal sendNext:value1];
- NSMutableArray *receivedValues = [NSMutableArray array];
- [channel.followingTerminal subscribeNext:^(id x) {
- [receivedValues addObject:x];
- }];
- [channel.leadingTerminal sendNext:value2];
- [channel.leadingTerminal sendNext:value3];
- expect(receivedValues).to(equal(values));
- });
- qck_it(@"should complete both signals when the leadingTerminal is completed", ^{
- __block BOOL completedLeft = NO;
- [channel.leadingTerminal subscribeCompleted:^{
- completedLeft = YES;
- }];
- __block BOOL completedRight = NO;
- [channel.followingTerminal subscribeCompleted:^{
- completedRight = YES;
- }];
- [channel.leadingTerminal sendCompleted];
- expect(@(completedLeft)).to(beTruthy());
- expect(@(completedRight)).to(beTruthy());
- });
- qck_it(@"should complete both signals when the followingTerminal is completed", ^{
- __block BOOL completedLeft = NO;
- [channel.leadingTerminal subscribeCompleted:^{
- completedLeft = YES;
- }];
- __block BOOL completedRight = NO;
- [channel.followingTerminal subscribeCompleted:^{
- completedRight = YES;
- }];
- [channel.followingTerminal sendCompleted];
- expect(@(completedLeft)).to(beTruthy());
- expect(@(completedRight)).to(beTruthy());
- });
- qck_it(@"should replay completion to new subscribers", ^{
- [channel.leadingTerminal sendCompleted];
- __block BOOL completedLeft = NO;
- [channel.leadingTerminal subscribeCompleted:^{
- completedLeft = YES;
- }];
- __block BOOL completedRight = NO;
- [channel.followingTerminal subscribeCompleted:^{
- completedRight = YES;
- }];
- expect(@(completedLeft)).to(beTruthy());
- expect(@(completedRight)).to(beTruthy());
- });
- });
- sharedExamples(RACViewChannelExamples, ^(QCKDSLSharedExampleContext exampleContext) {
- __block NSString *keyPath;
- __block NSObject * (^getView)(void);
- __block RACChannelTerminal * (^getTerminal)(NSObject *);
- __block void (^setViewValue)(NSObject *view, NSNumber *value);
- __block NSObject *testView;
- __block RACChannelTerminal *endpoint;
- qck_beforeEach(^{
- keyPath = exampleContext()[RACViewChannelExampleKeyPath];
- getTerminal = exampleContext()[RACViewChannelExampleCreateTerminalBlock];
- getView = exampleContext()[RACViewChannelExampleCreateViewBlock];
- setViewValue = exampleContext()[RACViewChannelExampleSetViewValueBlock];
- testView = getView();
- endpoint = getTerminal(testView);
- });
- qck_it(@"should not send changes made by the channel itself", ^{
- __block BOOL receivedNext = NO;
- [endpoint subscribeNext:^(id x) {
- receivedNext = YES;
- }];
- expect(@(receivedNext)).to(beFalsy());
- [endpoint sendNext:@0.1];
- expect(@(receivedNext)).to(beFalsy());
- [endpoint sendNext:@0.2];
- expect(@(receivedNext)).to(beFalsy());
- [endpoint sendCompleted];
- expect(@(receivedNext)).to(beFalsy());
- });
- qck_it(@"should not send progammatic changes made to the view", ^{
- __block BOOL receivedNext = NO;
- [endpoint subscribeNext:^(id x) {
- receivedNext = YES;
- }];
- expect(@(receivedNext)).to(beFalsy());
- [testView setValue:@0.1 forKeyPath:keyPath];
- expect(@(receivedNext)).to(beFalsy());
- [testView setValue:@0.2 forKeyPath:keyPath];
- expect(@(receivedNext)).to(beFalsy());
- });
- qck_it(@"should not have a starting value", ^{
- __block BOOL receivedNext = NO;
- [endpoint subscribeNext:^(id x) {
- receivedNext = YES;
- }];
- expect(@(receivedNext)).to(beFalsy());
- });
- qck_it(@"should send view changes", ^{
- __block NSString *received;
- [endpoint subscribeNext:^(id x) {
- received = x;
- }];
- setViewValue(testView, @0.1);
- expect(received).to(equal(@0.1));
- setViewValue(testView, @0.2);
- expect(received).to(equal(@0.2));
- });
- qck_it(@"should set values on the view", ^{
- [endpoint sendNext:@0.1];
- expect([testView valueForKeyPath:keyPath]).to(equal(@0.1));
- [endpoint sendNext:@0.2];
- expect([testView valueForKeyPath:keyPath]).to(equal(@0.2));
- });
- qck_it(@"should not echo changes back to the channel", ^{
- __block NSUInteger receivedCount = 0;
- [endpoint subscribeNext:^(id _) {
- receivedCount++;
- }];
- expect(@(receivedCount)).to(equal(@0));
- [endpoint sendNext:@0.1];
- expect(@(receivedCount)).to(equal(@0));
- setViewValue(testView, @0.2);
- expect(@(receivedCount)).to(equal(@1));
- });
- qck_it(@"should complete when the view deallocates", ^{
- __block BOOL deallocated = NO;
- __block BOOL completed = NO;
- @autoreleasepool {
- NSObject *view __attribute__((objc_precise_lifetime)) = getView();
- [view.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{
- deallocated = YES;
- }]];
- RACChannelTerminal *terminal = getTerminal(view);
- [terminal subscribeCompleted:^{
- completed = YES;
- }];
- expect(@(deallocated)).to(beFalsy());
- expect(@(completed)).to(beFalsy());
- }
- expect(@(deallocated)).to(beTruthy());
- expect(@(completed)).to(beTruthy());
- });
- qck_it(@"should deallocate after the view deallocates", ^{
- __block BOOL viewDeallocated = NO;
- __block BOOL terminalDeallocated = NO;
- @autoreleasepool {
- NSObject *view __attribute__((objc_precise_lifetime)) = getView();
- [view.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{
- viewDeallocated = YES;
- }]];
- RACChannelTerminal *terminal = getTerminal(view);
- [terminal.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{
- terminalDeallocated = YES;
- }]];
- expect(@(viewDeallocated)).to(beFalsy());
- expect(@(terminalDeallocated)).to(beFalsy());
- }
- expect(@(viewDeallocated)).to(beTruthy());
- expect(@(terminalDeallocated)).toEventually(beTruthy());
- });
- });
- }
- QuickConfigurationEnd
|