├── Expecta+ReactiveCocoa.podspec ├── ExpectaReactiveCocoa ├── EXPMatchers+complete.h ├── EXPMatchers+complete.m ├── EXPMatchers+error.h ├── EXPMatchers+error.m └── Expecta+ReactiveCocoa.h ├── LICENSE └── README.md /Expecta+ReactiveCocoa.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'Expecta+ReactiveCocoa' 3 | spec.version = '0.2.0' 4 | spec.summary = 'Expecta matchers for ReactiveCocoa.' 5 | spec.homepage = 'https://github.com/kylef/Expecta-ReactiveCocoa' 6 | spec.license = { :type => 'BSD', :file => 'LICENSE' } 7 | spec.author = { 'Kyle Fuller' => 'inbox@kylefuller.co.uk' } 8 | spec.social_media_url = 'https://twitter.com/kylefuller' 9 | spec.source = { :git => 'https://github.com/kylef/Expecta-ReactiveCocoa.git', :tag => spec.version } 10 | spec.source_files = 'ExpectaReactiveCocoa/*.{h,m}' 11 | spec.requires_arc = true 12 | spec.dependency 'Expecta' 13 | spec.dependency 'ReactiveCocoa' 14 | 15 | spec.ios.deployment_target = '6.0' 16 | spec.osx.deployment_target = '10.7' 17 | end 18 | 19 | -------------------------------------------------------------------------------- /ExpectaReactiveCocoa/EXPMatchers+complete.h: -------------------------------------------------------------------------------- 1 | // 2 | // EXPMatchers+complete.h 3 | // Kyle Fuller 4 | // 5 | // Created by Kyle Fuller on 05/07/2014. 6 | // Copyright (c) 2014 Kyle Fuller. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | EXPMatcherInterface(complete, ()) 12 | EXPMatcherInterface(completeSending, (NSArray *values)) 13 | -------------------------------------------------------------------------------- /ExpectaReactiveCocoa/EXPMatchers+complete.m: -------------------------------------------------------------------------------- 1 | // 2 | // EXPMatchers+complete.m 3 | // Kyle Fuller 4 | // 5 | // Created by Kyle Fuller on 05/07/2014. 6 | // Copyright (c) 2014 Kyle Fuller. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "EXPMatchers+complete.h" 11 | 12 | EXPMatcherImplementationBegin(complete, ()) { 13 | RACSignal *signal; 14 | __block BOOL isComplete = NO; 15 | __block NSError *signalError; 16 | 17 | if ([actual respondsToSelector:@selector(subscribeError:completed:)]) { 18 | signal = actual; 19 | 20 | [signal subscribeError:^(NSError *error) { 21 | signalError = error; 22 | } completed:^{ 23 | isComplete = YES; 24 | }]; 25 | } 26 | 27 | match(^ BOOL { 28 | return signal && isComplete == YES; 29 | }); 30 | 31 | failureMessageForTo(^ NSString * { 32 | NSString *message; 33 | 34 | if (signalError) { 35 | message = [NSString stringWithFormat:@"Signal %@ did not complete. (%@).", signal, signalError]; 36 | } else if (signal == nil) { 37 | message = @"Signal is nil."; 38 | } else { 39 | message = @"Signal did not complete."; 40 | } 41 | 42 | return message; 43 | }); 44 | } 45 | 46 | EXPMatcherImplementationEnd 47 | 48 | EXPMatcherImplementationBegin(completeSending, (NSArray *values)) { 49 | RACSignal *signal; 50 | __block BOOL isComplete = NO; 51 | __block NSMutableArray *results = [NSMutableArray array]; 52 | __block NSError *signalError; 53 | 54 | if ([actual respondsToSelector:@selector(subscribeError:completed:)]) { 55 | signal = actual; 56 | 57 | [signal subscribeNext:^(id value) { 58 | if (value) { 59 | [results addObject:value]; 60 | } else { 61 | [results addObject:[NSNull null]]; 62 | } 63 | } error:^(NSError *error) { 64 | signalError = error; 65 | } completed:^{ 66 | isComplete = YES; 67 | }]; 68 | } 69 | 70 | match(^ BOOL { 71 | return signal && isComplete == YES && [results isEqualToArray:values]; 72 | }); 73 | 74 | failureMessageForTo(^ NSString * { 75 | NSString *message; 76 | 77 | if (signalError) { 78 | message = [NSString stringWithFormat:@"Signal %@ did not complete. (%@).", signal, signalError]; 79 | } else if (signal == nil) { 80 | message = @"Signal is nil."; 81 | } else if (isComplete) { 82 | message = [[NSString stringWithFormat:@"Signal sent: %@, expected: %@", results, values] stringByReplacingOccurrencesOfString:@"\n" withString:@" "]; 83 | } else { 84 | message = @"Signal did not complete."; 85 | } 86 | 87 | return message; 88 | }); 89 | } 90 | 91 | EXPMatcherImplementationEnd 92 | -------------------------------------------------------------------------------- /ExpectaReactiveCocoa/EXPMatchers+error.h: -------------------------------------------------------------------------------- 1 | // 2 | // EXPMatchers+error.h 3 | // Kyle Fuller 4 | // 5 | // Created by Kyle Fuller on 05/07/2014. 6 | // Copyright (c) 2014 Kyle Fuller. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | EXPMatcherInterface(error, ()) 12 | -------------------------------------------------------------------------------- /ExpectaReactiveCocoa/EXPMatchers+error.m: -------------------------------------------------------------------------------- 1 | // 2 | // EXPMatchers+error.m 3 | // Kyle Fuller 4 | // 5 | // Created by Kyle Fuller on 05/07/2014. 6 | // Copyright (c) 2014 Kyle Fuller. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "EXPMatchers+error.h" 11 | 12 | EXPMatcherImplementationBegin(error, ()) { 13 | RACSignal *signal; 14 | 15 | __block BOOL didError = NO; 16 | __block BOOL didComplete = NO; 17 | 18 | if ([actual respondsToSelector:@selector(subscribeError:completed:)]) { 19 | signal = actual; 20 | 21 | [signal subscribeError:^(NSError *error) { 22 | didError = YES; 23 | } completed:^{ 24 | didComplete = YES; 25 | }]; 26 | } 27 | 28 | match(^ BOOL { 29 | return signal && didError; 30 | }); 31 | 32 | failureMessageForTo(^ NSString * { 33 | NSString *message; 34 | 35 | if (didComplete) { 36 | message = [NSString stringWithFormat:@"Signal %@ completed instead of erroring.", signal]; 37 | } else if (signal == nil) { 38 | message = @"Signal is nil."; 39 | } else { 40 | message = @"Signal did not produce an error."; 41 | } 42 | 43 | return message; 44 | }); 45 | } 46 | 47 | EXPMatcherImplementationEnd 48 | -------------------------------------------------------------------------------- /ExpectaReactiveCocoa/Expecta+ReactiveCocoa.h: -------------------------------------------------------------------------------- 1 | #import "EXPMatchers+complete.h" 2 | #import "EXPMatchers+error.h" 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Kyle Fuller 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Expecta+ReactiveCocoa 2 | ===================== 3 | 4 | Expecta+ReactiveCocoa provides a set of matchers for using Expecta with 5 | ReactiveCocoa. Providing the following matchers: 6 | 7 | - `expect(signal).will.complete()` 8 | - `expect(signal).will.completeSending(@[@YES, @NO, @YES])` 9 | - `expect(signal).will.error()` 10 | 11 | ### Usage 12 | 13 | ```objective-c 14 | #import 15 | 16 | describe(@"a coupon manager", ^{ 17 | __block EDNSessionManager *manager; 18 | 19 | beforeAll(^{ 20 | manager = [[EDNSessionManager alloc] init]; 21 | }); 22 | 23 | context(@"when redeeming a coupon code", ^{ 24 | it(@"should complete with a successful coupon code", ^{ 25 | RACSignal *signal = [manager redeemCoupon:@"XAXAXA"]; 26 | expect(signal).will.complete(); 27 | }); 28 | 29 | it(@"should fail with an invalid coupon code", ^{ 30 | RACSignal *signal = [manager redeemCoupon:@"INVALID"]; 31 | expect(signal).will.error(); 32 | }); 33 | }); 34 | }); 35 | ``` 36 | 37 | ### Installation 38 | 39 | ```ruby 40 | target 'PalaverTests' do 41 | pod 'Expecta+ReactiveCocoa' 42 | end 43 | ``` 44 | 45 | ### License 46 | 47 | Expecta+ReactiveCocoa is available under the BSD license. See 48 | [LICENSE](LICENSE) for more information. 49 | 50 | --------------------------------------------------------------------------------