-
Notifications
You must be signed in to change notification settings - Fork 496
/
Copy pathNSObjectRACPropertySubscribingSpec.m
158 lines (119 loc) · 4.54 KB
/
NSObjectRACPropertySubscribingSpec.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//
// NSObjectRACPropertySubscribingSpec.m
// ReactiveObjC
//
// Created by Josh Abernathy on 9/28/12.
// Copyright (c) 2012 GitHub, Inc. All rights reserved.
//
@import Quick;
@import Nimble;
#import "NSObjectRACPropertySubscribingExamples.h"
#import "RACTestObject.h"
#import "NSObject+RACPropertySubscribing.h"
#import "RACDisposable.h"
#import "RACSignal.h"
QuickSpecBegin(NSObjectRACPropertySubscribingSpec)
qck_describe(@"-rac_valuesForKeyPath:observer:", ^{
id (^setupBlock)(id, id, id) = ^(RACTestObject *object, NSString *keyPath, id observer) {
return [object rac_valuesForKeyPath:keyPath observer:observer];
};
qck_itBehavesLike(RACPropertySubscribingExamples, ^{
return @{ RACPropertySubscribingExamplesSetupBlock: setupBlock };
});
});
qck_describe(@"+rac_signalWithChangesFor:keyPath:options:observer:", ^{
qck_describe(@"KVO options argument", ^{
__block RACTestObject *object;
__block id actual;
__block RACSignal *(^objectValueSignal)(NSKeyValueObservingOptions);
qck_beforeEach(^{
object = [[RACTestObject alloc] init];
objectValueSignal = ^(NSKeyValueObservingOptions options) {
return [[object rac_valuesAndChangesForKeyPath:@keypath(object, objectValue) options:options observer:self] reduceEach:^(id value, NSDictionary *change) {
return change;
}];
};
});
qck_it(@"sends a KVO dictionary", ^{
[objectValueSignal(0) subscribeNext:^(NSDictionary *x) {
actual = x;
}];
object.objectValue = @1;
expect(actual).to(beAKindOf(NSDictionary.class));
});
qck_it(@"sends a kind key by default", ^{
[objectValueSignal(0) subscribeNext:^(NSDictionary *x) {
actual = x[NSKeyValueChangeKindKey];
}];
object.objectValue = @1;
expect(actual).notTo(beNil());
});
qck_it(@"sends the newest changes with NSKeyValueObservingOptionNew", ^{
[objectValueSignal(NSKeyValueObservingOptionNew) subscribeNext:^(NSDictionary *x) {
actual = x[NSKeyValueChangeNewKey];
}];
object.objectValue = @1;
expect(actual).to(equal(@1));
object.objectValue = @2;
expect(actual).to(equal(@2));
});
qck_it(@"sends an additional change value with NSKeyValueObservingOptionPrior", ^{
NSMutableArray *values = [NSMutableArray new];
NSArray *expected = @[ @(YES), @(NO) ];
[objectValueSignal(NSKeyValueObservingOptionPrior) subscribeNext:^(NSDictionary *x) {
BOOL isPrior = [x[NSKeyValueChangeNotificationIsPriorKey] boolValue];
[values addObject:@(isPrior)];
}];
object.objectValue = @[ @1 ];
expect(values).to(equal(expected));
});
qck_it(@"sends index changes when adding, inserting or removing a value from an observed object", ^{
__block NSUInteger hasIndexesCount = 0;
[objectValueSignal(0) subscribeNext:^(NSDictionary *x) {
if (x[NSKeyValueChangeIndexesKey] != nil) {
hasIndexesCount += 1;
}
}];
object.objectValue = [NSMutableOrderedSet orderedSet];
expect(@(hasIndexesCount)).to(equal(@0));
NSMutableOrderedSet *objectValue = [object mutableOrderedSetValueForKey:@"objectValue"];
[objectValue addObject:@1];
expect(@(hasIndexesCount)).to(equal(@1));
[objectValue replaceObjectAtIndex:0 withObject:@2];
expect(@(hasIndexesCount)).to(equal(@2));
[objectValue removeObject:@2];
expect(@(hasIndexesCount)).to(equal(@3));
});
qck_it(@"sends the previous value with NSKeyValueObservingOptionOld", ^{
[objectValueSignal(NSKeyValueObservingOptionOld) subscribeNext:^(NSDictionary *x) {
actual = x[NSKeyValueChangeOldKey];
}];
object.objectValue = @1;
expect(actual).to(equal(NSNull.null));
object.objectValue = @2;
expect(actual).to(equal(@1));
});
qck_it(@"sends the initial value with NSKeyValueObservingOptionInitial", ^{
[objectValueSignal(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) subscribeNext:^(NSDictionary *x) {
actual = x[NSKeyValueChangeNewKey];
}];
expect(actual).to(equal(NSNull.null));
});
});
});
qck_describe(@"-rac_valuesAndChangesForKeyPath:options:observer:", ^{
qck_it(@"should complete immediately if the receiver or observer have deallocated", ^{
RACSignal *signal;
@autoreleasepool {
RACTestObject *object __attribute__((objc_precise_lifetime)) = [[RACTestObject alloc] init];
RACTestObject *observer __attribute__((objc_precise_lifetime)) = [[RACTestObject alloc] init];
signal = [object rac_valuesAndChangesForKeyPath:@keypath(object, stringValue) options:0 observer:observer];
}
__block BOOL completed = NO;
[signal subscribeCompleted:^{
completed = YES;
}];
expect(@(completed)).to(beTruthy());
});
});
QuickSpecEnd