Skip to content

Commit

Permalink
Extract Event Filtering to its own class
Browse files Browse the repository at this point in the history
  • Loading branch information
sarahhodne committed Dec 1, 2012
1 parent 886b08e commit 4198612
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 10 deletions.
12 changes: 12 additions & 0 deletions Travis CI.xcodeproj/project.pbxproj
Expand Up @@ -22,7 +22,10 @@
2E12F3951652048C000048F5 /* Sparkle.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2E12F3931652046A000048F5 /* Sparkle.framework */; };
2E12F39716520C2A000048F5 /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = 2E12F39616520C2A000048F5 /* dsa_pub.pem */; };
2E72AF3B1669DA6000F2631C /* BuildEventStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E72AF3A1669DA6000F2631C /* BuildEventStream.m */; };
2E72AF3E166A7BE100F2631C /* EventFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E72AF3D166A7BE000F2631C /* EventFilter.m */; };
2E72AF41166A7F4600F2631C /* EventFilterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E72AF40166A7F4600F2631C /* EventFilterTests.m */; };
2E72AF42166A7FEA00F2631C /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ECFA87545264EC28B9D5614 /* libPods.a */; };
2E72AF43166A800400F2631C /* EventFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E72AF3D166A7BE000F2631C /* EventFilter.m */; };
2E72AF44166A812200F2631C /* BuildEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 2EDA045C156450750043A3A6 /* BuildEvent.m */; };
2E75988B164DF68100B87810 /* Notification.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E75988A164DF68100B87810 /* Notification.m */; };
2E90F156164E389F009CAA25 /* Travis CI.icns in Resources */ = {isa = PBXBuildFile; fileRef = 2E90F155164E389F009CAA25 /* Travis CI.icns */; };
Expand Down Expand Up @@ -124,6 +127,9 @@
2E12F39616520C2A000048F5 /* dsa_pub.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dsa_pub.pem; sourceTree = "<group>"; };
2E72AF391669DA5F00F2631C /* BuildEventStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuildEventStream.h; sourceTree = "<group>"; };
2E72AF3A1669DA6000F2631C /* BuildEventStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BuildEventStream.m; sourceTree = "<group>"; };
2E72AF3C166A7BE000F2631C /* EventFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventFilter.h; sourceTree = "<group>"; };
2E72AF3D166A7BE000F2631C /* EventFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EventFilter.m; sourceTree = "<group>"; };
2E72AF40166A7F4600F2631C /* EventFilterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EventFilterTests.m; sourceTree = "<group>"; };
2E759889164DF68100B87810 /* Notification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = Notification.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
2E75988A164DF68100B87810 /* Notification.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = Notification.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
2E90F155164E389F009CAA25 /* Travis CI.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = "Travis CI.icns"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -288,6 +294,7 @@
2E00CCC4164F974900A30635 /* TravisToolbarTests */ = {
isa = PBXGroup;
children = (
2E72AF40166A7F4600F2631C /* EventFilterTests.m */,
2E00CCD8164F9A9B00A30635 /* PreferencesControllerTests.m */,
2EBA8CF5164FAD4A005C033E /* FilterPreferencesTests.m */,
2E00CCC5164F974900A30635 /* Supporting Files */,
Expand Down Expand Up @@ -341,6 +348,8 @@
2EDA045C156450750043A3A6 /* BuildEvent.m */,
2E72AF391669DA5F00F2631C /* BuildEventStream.h */,
2E72AF3A1669DA6000F2631C /* BuildEventStream.m */,
2E72AF3C166A7BE000F2631C /* EventFilter.h */,
2E72AF3D166A7BE000F2631C /* EventFilter.m */,
2EBA8CF8164FAD91005C033E /* FilterPreferences.h */,
2EBA8CF9164FAD91005C033E /* FilterPreferences.m */,
2E759889164DF68100B87810 /* Notification.h */,
Expand Down Expand Up @@ -502,11 +511,13 @@
buildActionMask = 2147483647;
files = (
2E72AF44166A812200F2631C /* BuildEvent.m in Sources */,
2E72AF43166A800400F2631C /* EventFilter.m in Sources */,
2E00CCD9164F9A9B00A30635 /* PreferencesControllerTests.m in Sources */,
2EBA8CF6164FAD4A005C033E /* FilterPreferencesTests.m in Sources */,
2EBA8CE9164FA582005C033E /* Preferences.m in Sources */,
2EBA8CEA164FA582005C033E /* PreferencesController.m in Sources */,
2EBA8CFB164FAD9F005C033E /* FilterPreferences.m in Sources */,
2E72AF41166A7F4600F2631C /* EventFilterTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -526,6 +537,7 @@
2E00CCB7164EE18000A30635 /* TravisHTTPClient.m in Sources */,
2EBA8CFA164FAD91005C033E /* FilterPreferences.m in Sources */,
2E72AF3B1669DA6000F2631C /* BuildEventStream.m in Sources */,
2E72AF3E166A7BE100F2631C /* EventFilter.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
14 changes: 4 additions & 10 deletions src/AppDelegate.m
Expand Up @@ -8,7 +8,6 @@

#import "AppDelegate.h"

#import "TravisEventFetcher.h"
#import "BuildEvent.h"
#import "Preferences.h"
#import "Notification.h"
Expand All @@ -17,10 +16,12 @@
#import "FilterPreferences.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
#import "BuildEventStream.h"
#import "EventFilter.h"

@interface AppDelegate () <NSUserNotificationCenterDelegate>
@property (strong) NSStatusItem *statusItem;
@property (strong) BuildEventStream *buildEventStream;
@property (strong) EventFilter *eventFilter;
@end

@implementation AppDelegate
Expand All @@ -32,10 +33,9 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification {
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];

[self setBuildEventStream:[BuildEventStream buildEventStream]];
[self setEventFilter:[EventFilter eventFilterWithInputStream:[[self buildEventStream] eventStream] filterPreferences:[FilterPreferences filterWithPreferences:[Preferences sharedPreferences]]]];

[[[[self buildEventStream] eventStream] filter:^(BuildEvent *event) {
return [self shouldShowNotificationFor:event];
}] subscribeNext:^(BuildEvent *event) {
[[[self eventFilter] outputStream] subscribeNext:^(BuildEvent *event) {
[[[TravisAPI standardAPI] fetchBuildWithID:[event buildID] forRepository:[event name]] subscribeNext:^(NSDictionary *build) {
[event updateBuildInfo:build];
Notification *notification = [Notification notificationWithEventData:event];
Expand Down Expand Up @@ -77,12 +77,6 @@ - (IBAction)showPreferences:(id)sender {
[[self preferencesPanel] makeKeyAndOrderFront:self];
}

- (BOOL)shouldShowNotificationFor:(BuildEvent *)eventData {
FilterPreferences *filter = [FilterPreferences filterPreferencesWithPreferences:[Preferences sharedPreferences]];

return [filter matchesSlug:[eventData name]];
}

#pragma mark - NSUserNotificationCenterDelegate

- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification {
Expand Down
25 changes: 25 additions & 0 deletions src/EventFilter.h
@@ -0,0 +1,25 @@
//
// EventFilter.h
// Travis CI
//
// Created by Henrik Hodne on 12/1/12.
// Copyright (c) 2012 Travis CI GmbH. All rights reserved.
//

#import <Foundation/Foundation.h>

@class RACSignal;
@class FilterPreferences;

@interface EventFilter : NSObject

// A stream of filtered `TravisEvent`.
@property (nonatomic, strong, readonly) RACSignal *outputStream;

// Creates a new event filter.
//
// inputStream - A stream of `TravisEvent` objects to filter.
// filterPreferences - A `FilterPreferences` object describing how to filter the incoming `TravisEvent` objects.
+ (EventFilter *)eventFilterWithInputStream:(RACSignal *)inputStream filterPreferences:(FilterPreferences *)filterPreferences;

@end
46 changes: 46 additions & 0 deletions src/EventFilter.m
@@ -0,0 +1,46 @@
//
// EventFilter.m
// Travis CI
//
// Created by Henrik Hodne on 12/1/12.
// Copyright (c) 2012 Travis CI GmbH. All rights reserved.
//

#import "EventFilter.h"
#import <ReactiveCocoa/ReactiveCocoa.h>
#import <libextobjc/EXTScope.h>
#import "BuildEvent.h"
#import "FilterPreferences.h"

@interface EventFilter ()
@property (nonatomic, strong, readonly) RACSignal *inputStream;
@property (nonatomic, strong, readonly) FilterPreferences *filterPreferences;
@end

@implementation EventFilter

- (RACSignal *)outputStream {
@weakify(self);
return [[self inputStream] filter:^(BuildEvent *event) {
@strongify(self);
return [[self filterPreferences] matchesSlug:[event name]];
}];
}

#pragma mark - Lifecycle

+ (EventFilter *)eventFilterWithInputStream:(RACSignal *)inputStream filterPreferences:(FilterPreferences *)filterPreferences {
return [[self alloc] initWithInputStream:inputStream filterPreferences:filterPreferences];
}

- (id)initWithInputStream:(RACSignal *)inputStream filterPreferences:(FilterPreferences *)filterPreferences {
self = [super init];
if (self == nil) return nil;

_inputStream = inputStream;
_filterPreferences = filterPreferences;

return self;
}

@end
60 changes: 60 additions & 0 deletions test/EventFilterTests.m
@@ -0,0 +1,60 @@
//
// EventFilterTests.m
// Travis CI
//
// Created by Henrik Hodne on 12/1/12.
// Copyright (c) 2012 Travis CI GmbH. All rights reserved.
//

#import <SenTestingKit/SenTestingKit.h>

#define HC_SHORTHAND
#import <OCHamcrest/OCHamcrest.h>

#define MOCKITO_SHORTHAND
#import <OCMockito/OCMockito.h>

#import "EventFilter.h"
#import "BuildEvent.h"
#import "FilterPreferences.h"
#import <ReactiveCocoa/ReactiveCocoa.h>

@interface EventFilterTests : SenTestCase
@end

@implementation EventFilterTests {
EventFilter *_eventFilter;
RACSubject *_inputStream;
FilterPreferences *_filterPreferences;
id<RACSubscriber> _outputStream;
}

- (void)setUp {
_inputStream = [RACSubject subject];
_outputStream = mockProtocol(@protocol(RACSubscriber));
_filterPreferences = mock([FilterPreferences class]);
_eventFilter = [EventFilter eventFilterWithInputStream:_inputStream filterPreferences:_filterPreferences];
[[_eventFilter outputStream] subscribe:_outputStream];
}

#pragma mark - Tests

- (void)testDoesNotRemoveMatchingSlugs {
[given([_filterPreferences matchesSlug:@"travis-ci/travis-ci"]) willReturnBool:YES];

BuildEvent *event = [[BuildEvent alloc] initWithEventData:@{ @"repository": @{ @"slug": @"travis-ci/travis-ci" } }];
[_inputStream sendNext:event];

[verify(_outputStream) sendNext:event];
}

- (void)testRemovesNonMatchingSlugs {
[given([_filterPreferences matchesSlug:@"travis-ci/travis-ci"]) willReturnBool:NO];

BuildEvent *event = [[BuildEvent alloc] initWithEventData:@{ @"repository": @{ @"slug": @"travis-ci/travis-ci" } }];
[_inputStream sendNext:event];

[verifyCount(_outputStream, never()) sendNext:event];
}

@end

0 comments on commit 4198612

Please sign in to comment.