| // | |
| // NSUserDefaultsRACSupportSpec.m | |
| // ReactiveCocoa | |
| // | |
| // Created by Matt Diephouse on 12/19/13. | |
| // Copyright (c) 2013 GitHub, Inc. All rights reserved. | |
| // | |
| #import "NSUserDefaults+RACSupport.h" | |
| #import "RACCompoundDisposable.h" | |
| #import "RACDisposable.h" | |
| #import "RACKVOChannel.h" | |
| #import "NSObject+RACDeallocating.h" | |
| #import "RACSignal+Operations.h" | |
| static NSString * const NSUserDefaultsRACSupportSpecStringDefault = @"NSUserDefaultsRACSupportSpecStringDefault"; | |
| static NSString * const NSUserDefaultsRACSupportSpecBoolDefault = @"NSUserDefaultsRACSupportSpecBoolDefault"; | |
| @interface TestObserver : NSObject | |
| @property (copy, atomic) NSString *string1; | |
| @property (copy, atomic) NSString *string2; | |
| @property (assign, atomic) BOOL bool1; | |
| @end | |
| @implementation TestObserver | |
| @end | |
| SpecBegin(NSUserDefaultsRACSupportSpec) | |
| __block NSUserDefaults *defaults = nil; | |
| __block TestObserver *observer = nil; | |
| beforeEach(^{ | |
| defaults = NSUserDefaults.standardUserDefaults; | |
| [defaults removeObjectForKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| [defaults removeObjectForKey:NSUserDefaultsRACSupportSpecBoolDefault]; | |
| observer = [TestObserver new]; | |
| }); | |
| afterEach(^{ | |
| observer = nil; | |
| }); | |
| it(@"should set defaults", ^{ | |
| RACChannelTo(observer, string1) = [defaults rac_channelTerminalForKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| RACChannelTo(observer, bool1, @NO) = [defaults rac_channelTerminalForKey:NSUserDefaultsRACSupportSpecBoolDefault]; | |
| observer.string1 = @"A string"; | |
| observer.bool1 = YES; | |
| expect([defaults objectForKey:NSUserDefaultsRACSupportSpecStringDefault]).will.equal(@"A string"); | |
| expect([defaults objectForKey:NSUserDefaultsRACSupportSpecBoolDefault]).will.equal(@YES); | |
| }); | |
| it(@"should read defaults", ^{ | |
| RACChannelTo(observer, string1) = [defaults rac_channelTerminalForKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| RACChannelTo(observer, bool1, @NO) = [defaults rac_channelTerminalForKey:NSUserDefaultsRACSupportSpecBoolDefault]; | |
| expect(observer.string1).to.beNil(); | |
| expect(observer.bool1).to.equal(NO); | |
| [defaults setObject:@"Another string" forKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| [defaults setBool:YES forKey:NSUserDefaultsRACSupportSpecBoolDefault]; | |
| expect(observer.string1).to.equal(@"Another string"); | |
| expect(observer.bool1).to.equal(YES); | |
| }); | |
| it(@"should be okay to create 2 terminals", ^{ | |
| RACChannelTo(observer, string1) = [defaults rac_channelTerminalForKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| RACChannelTo(observer, string2) = [defaults rac_channelTerminalForKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| [defaults setObject:@"String 3" forKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| expect(observer.string1).to.equal(@"String 3"); | |
| expect(observer.string2).to.equal(@"String 3"); | |
| }); | |
| it(@"should handle removed defaults", ^{ | |
| observer.string1 = @"Some string"; | |
| observer.bool1 = YES; | |
| RACChannelTo(observer, string1) = [defaults rac_channelTerminalForKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| RACChannelTo(observer, bool1, @NO) = [defaults rac_channelTerminalForKey:NSUserDefaultsRACSupportSpecBoolDefault]; | |
| [defaults removeObjectForKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| [defaults removeObjectForKey:NSUserDefaultsRACSupportSpecBoolDefault]; | |
| expect(observer.string1).to.beNil(); | |
| expect(observer.bool1).to.equal(NO); | |
| }); | |
| it(@"shouldn't resend values", ^{ | |
| RACChannelTerminal *terminal = [defaults rac_channelTerminalForKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| RACChannelTo(observer, string1) = terminal; | |
| RACSignal *sentValue = [terminal replayLast]; | |
| observer.string1 = @"Test value"; | |
| id value = [sentValue asynchronousFirstOrDefault:nil success:NULL error:NULL]; | |
| expect(value).to.beNil(); | |
| }); | |
| it(@"should complete when the NSUserDefaults deallocates", ^{ | |
| __block RACChannelTerminal *terminal; | |
| __block BOOL deallocated = NO; | |
| @autoreleasepool { | |
| NSUserDefaults *customDefaults __attribute__((objc_precise_lifetime)) = [NSUserDefaults new]; | |
| [customDefaults.rac_deallocDisposable addDisposable:[RACDisposable disposableWithBlock:^{ | |
| deallocated = YES; | |
| }]]; | |
| terminal = [customDefaults rac_channelTerminalForKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| } | |
| expect(deallocated).to.beTruthy(); | |
| expect([terminal asynchronouslyWaitUntilCompleted:NULL]).to.beTruthy(); | |
| }); | |
| it(@"should send an initial value", ^{ | |
| [defaults setObject:@"Initial" forKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| RACChannelTerminal *terminal = [defaults rac_channelTerminalForKey:NSUserDefaultsRACSupportSpecStringDefault]; | |
| expect([terminal asynchronousFirstOrDefault:nil success:NULL error:NULL]).to.equal(@"Initial"); | |
| }); | |
| SpecEnd |