Skip to content

Commit

Permalink
initial commit, again.
Browse files Browse the repository at this point in the history
  • Loading branch information
orta committed Jan 22, 2015
0 parents commit 2e814fc
Show file tree
Hide file tree
Showing 1,054 changed files with 56,736 additions and 0 deletions.
31 changes: 31 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Xcode
.DS_Store
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
!default.xcworkspace
xcuserdata
profile
*.moved-aside
DerivedData
.idea/
Pods
.pt
.build
tmtags
tmtagsHistory
config/releasenotes.txt
.bundle
Artsy.xcodeproj/xcshareddata/xcschemes/Artsy.xcscheme
/Classes/View\ Controllers/ARTopMenuViewController+DeveloperExtras.m
Podfile.local
chairs/
.github
Artsy.xcodeproj/project.xcworkspace/xcshareddata/
vendor/
32 changes: 32 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
osx_image: xcode61
language: objective-c
env:
global:
secure: "WCW/8qlLgH94wxvF86DrfBgzhAKFRtMIEBfj3bDWk8I1GUNkzUpU6Mya4zIgKS/WRVT31j5sVj4Do/9z2ffREnlAcWZPIurzyOm6IcJygVQN6uRlbI6m9J2L2WLu8W2XXQyYGIoEWMvznYZ9raY12QFnM+3LIvYFBckNZFhBUZA="
cache:
- bundler
- cocoapods
env:
- UPLOAD_IOS_SNAPSHOT_BUCKET_NAME=eigen-ci UPLOAD_IOS_SNAPSHOT_BUCKET_PREFIX=snapshots

before_install:
- 'echo ''gem: --no-ri --no-rdoc'' > ~/.gemrc'

- echo "machine github.com login $GITHUB_API_KEY" > ~/.netrc
- chmod 600 .netrc
- pod repo add artsy https://github.com/artsy/Specs.git

install:
- bundle install
- make pods

before_script:
- make ci

script:
- make test
- make lint

notifications:
slack:
secure: "fXmNnx6XW5OvT/j2jSSHYd3mHwbL+GzUSUSWmZVT0Vx/Ga5jXINTOYRY/9PYgJMqdL8a/L0Mf/18ZZ+tliPlWQ/DnfTz1a3Q/Pf94hfYSGhSGlQC/eXYcpOm/dNOKYQ3sr4tqXtTPylPUDXHeiM2D59ggdlUvVwcALGgHizajPQ="
Binary file added AppIcon_114.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added AppIcon_57.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions Artsy Tests/ARAnimatedTickViewTest.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#import "ARAnimatedTickView.h"

@interface ARTickViewFrontLayer : CAShapeLayer
@end

SpecBegin(ARAnimatedTickView)

describe(@"initWithSelection", ^{
it(@"inits with selected", ^{
ARAnimatedTickView *tickView = [[ARAnimatedTickView alloc] initWithSelection:YES];
expect(tickView).to.haveValidSnapshotNamed(@"selected");
});

it(@"inits with deselected", ^{
ARAnimatedTickView *tickView = [[ARAnimatedTickView alloc] initWithSelection:NO];
expect(tickView).to.haveValidSnapshotNamed(@"deselected");
});
});

describe(@"set selected", ^{
it(@"changes deselected to selected", ^{
ARAnimatedTickView *tickView = [[ARAnimatedTickView alloc] initWithSelection:NO];
[tickView setSelected:YES animated:NO];
expect(tickView).to.haveValidSnapshotNamed(@"selected");
});

it(@"changes selected to deselected", ^{
ARAnimatedTickView *tickView = [[ARAnimatedTickView alloc] initWithSelection:YES];
[tickView setSelected:NO animated:NO];
expect(tickView).to.haveValidSnapshotNamed(@"deselected");
});
});

describe(@"ARTickViewFrontLayer layer", ^{
it(@"returns an instance of ARTickViewFrontlayer", ^{
ARTickViewFrontLayer *frontLayer = [ARTickViewFrontLayer layer];
expect(frontLayer).to.beKindOf([ARTickViewFrontLayer class]);
});
});

SpecEnd
7 changes: 7 additions & 0 deletions Artsy Tests/ARAppDelegate+Testing.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#import "ARAppDelegate.h"

@interface ARAppDelegate (Testing)

- (BOOL)swizzled_application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

@end
55 changes: 55 additions & 0 deletions Artsy Tests/ARAppDelegate+Testing.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#import <objc/runtime.h>

#import "ARRouter.h"
#import "ARSwitchBoard.h"
#import "ARLogger.h"
#import "ARAppDelegate+Testing.h"
#import "ARDispatchManager.h"

@implementation ARAppDelegate (Testing)

// Swizzle out -application:willFinishLaunchingWithOptions: and
// -application:didFinishLaunchingWithOptions: to not have the normal
// app logic interfere with the tests.
//
// As per mxcl's comment here: http://stackoverflow.com/a/12709123/1254854

+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self swapImplementationOf:@selector(application:didFinishLaunchingWithOptions:)
with:@selector(swizzled_application:didFinishLaunchingWithOptions:)];

[self swapImplementationOf:@selector(application:willFinishLaunchingWithOptions:)
with:@selector(swizzled_application:willFinishLaunchingWithOptions:)];
});
}

+ (void)swapImplementationOf:(SEL)old with:(SEL)new
{
Class class = [self class];
Method oldMethod = class_getInstanceMethod(class, old);
Method newMethod = class_getInstanceMethod(class, new);

if (class_addMethod(class, old, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
class_replaceMethod(class, new, method_getImplementation(oldMethod), method_getTypeEncoding(oldMethod));
} else {
method_exchangeImplementations(oldMethod, newMethod);
}
}

- (BOOL)swizzled_application:(id)app willFinishLaunchingWithOptions:(id)opts
{
[ARRouter setup];
[ARDispatchManager sharedManager].useSyncronousDispatches = YES;
return YES;
}

- (BOOL)swizzled_application:(id)app didFinishLaunchingWithOptions:(id)opts
{
[[ARLogger sharedLogger] startLogging];
return YES;
}

@end
188 changes: 188 additions & 0 deletions Artsy Tests/ARAppNotificationsDelegateTests.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
#import "ARAppNotificationsDelegate.h"
#import "ARSwitchBoard.h"
#import <ARAnalytics/ARAnalytics.h>
#import "ARAnalyticsConstants.h"
#import "ARNotificationView.h"
#import "ARTopMenuViewController.h"

SpecBegin(ARAppNotificationsDelegate)

// TODO: This is our slowest test by far, we should try speed it up.

describe(@"registerForDeviceNotificationsOnce", ^{
it(@"only registers for device notifications once", ^{
id app = [OCMockObject partialMockForObject:[UIApplication sharedApplication]];
BOOL respondsToRegisterForRemoteNotifications = [app respondsToSelector:@selector(registerForRemoteNotifications)];
if (respondsToRegisterForRemoteNotifications) {
[[app expect] registerForRemoteNotifications];
} else {
UIRemoteNotificationType allTypes = (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert);
[[app expect] registerForRemoteNotificationTypes:allTypes];
}

ARAppNotificationsDelegate *delegate = (ARAppNotificationsDelegate *) [JSDecoupledAppDelegate sharedAppDelegate].remoteNotificationsDelegate;
[delegate registerForDeviceNotificationsOnce];
[app verifyWithDelay:1];

if (respondsToRegisterForRemoteNotifications) {
[[app reject] registerForRemoteNotifications];
} else {
UIRemoteNotificationType allTypes = (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert);
[[app reject] registerForRemoteNotificationTypes:allTypes];
}
[delegate registerForDeviceNotificationsOnce];
[app verify];
[app stopMocking];
});
});

describe(@"receiveRemoteNotification", ^{

__block id mockApplication = nil;
__block id mockAnalytics = nil;

beforeEach(^{
mockApplication = [OCMockObject partialMockForObject:[UIApplication sharedApplication]];
mockAnalytics = [OCMockObject mockForClass:[ARAnalytics class]];
[[mockAnalytics stub] event:OCMOCK_ANY withProperties:OCMOCK_ANY];
});

afterEach(^{
[mockAnalytics stopMocking];
[mockApplication stopMocking];
});

describe(@"brought back from the background", ^{
beforeEach(^{
UIApplicationState state = UIApplicationStateBackground;
[[[mockApplication stub] andReturnValue:OCMOCK_VALUE(state)] applicationState];
});

it(@"navigates to the url provided", ^{
id classMock = [OCMockObject mockForClass:[ARTopMenuViewController class]];
// Just to silence runtime assertion failure.
[[[classMock stub] andReturn:nil] sharedController];

id JSON = @{ @"url" : @"http://artsy.net/feature" };
NSData *data = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:nil];
NSDictionary *notification =[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
UIApplication *app = [UIApplication sharedApplication];

id mock = [OCMockObject partialMockForObject:ARSwitchBoard.sharedInstance];
[[mock expect] loadPath:@"http://artsy.net/feature"];
[[app delegate] application:app didReceiveRemoteNotification:notification];
[mock verify];
[mock stopMocking];
[classMock stopMocking];
});

it(@"triggers an analytics event for a notification with an url received and tapped", ^{
id classMock = [OCMockObject mockForClass:[ARTopMenuViewController class]];
// Just to silence runtime assertion failure.
[[[classMock stub] andReturn:nil] sharedController];
id JSON = @{ @"url" : @"http://artsy.net/feature" };
NSData *data = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:nil];
NSDictionary *notification = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSMutableDictionary *notificationWithAppState = [[NSMutableDictionary alloc] initWithDictionary:notification];
[notificationWithAppState setObject:@"background" forKey:@"UIApplicationState"];
UIApplication *app = [UIApplication sharedApplication];
id mock = [OCMockObject mockForClass:[ARAnalytics class]];
[[mock expect] event:ARAnalyticsNotificationReceived withProperties:notificationWithAppState];
[[mock expect] event:ARAnalyticsNotificationTapped withProperties:notificationWithAppState];
[[app delegate] application:app didReceiveRemoteNotification:notification];
[mock verify];
[mock stopMocking];
[classMock stopMocking];
});

it(@"triggers an analytics event for a notification without a url received and tapped", ^{
id JSON = @{ @"aps" : @{ @"alert" : @"hello world" } };
NSData *data = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:nil];
NSDictionary *notification = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSMutableDictionary *notificationWithAppState = [[NSMutableDictionary alloc] initWithDictionary:notification];
[notificationWithAppState setObject:@"background" forKey:@"UIApplicationState"];
UIApplication *app = [UIApplication sharedApplication];
id mock = [OCMockObject mockForClass:[ARAnalytics class]];
[[mock expect] event:ARAnalyticsNotificationReceived withProperties:notificationWithAppState];
[[mock expect] event:ARAnalyticsNotificationTapped withProperties:notificationWithAppState];
[[app delegate] application:app didReceiveRemoteNotification:notification];
[mock verify];
[mock stopMocking];
});

it(@"does not display the message in aps/alert", ^{
id JSON = @{ @"aps" : @{ @"alert" : @"hello world" } };
NSData *data = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:nil];
NSDictionary *notification = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
id mock = [OCMockObject mockForClass:[ARNotificationView class]];
[[mock reject]
showNoticeInView:OCMOCK_ANY
title:OCMOCK_ANY
hideAfter:0
response:OCMOCK_ANY];
UIApplication *app = [UIApplication sharedApplication];
[[app delegate] application:app didReceiveRemoteNotification:notification];
[mock verify];
[mock stopMocking];
});
});

describe(@"running in the foreground", ^{
beforeEach(^{
UIApplicationState state = UIApplicationStateActive;
[[[mockApplication stub] andReturnValue:OCMOCK_VALUE(state)] applicationState];
});

it(@"triggers only an analytics event for the notification received", ^{
id JSON = @{ @"url" : @"http://artsy.net/feature" };
NSData *data = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:nil];
NSDictionary *notification = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSMutableDictionary *notificationWithAppState = [[NSMutableDictionary alloc] initWithDictionary:notification];
[notificationWithAppState setObject:@"active" forKey:@"UIApplicationState"];
UIApplication *app = [UIApplication sharedApplication];
id mock = [OCMockObject mockForClass:[ARAnalytics class]];
[[mock expect] event:ARAnalyticsNotificationReceived withProperties:notificationWithAppState];
[[mock reject] event:ARAnalyticsNotificationTapped withProperties:notificationWithAppState];
[[app delegate] application:app didReceiveRemoteNotification:notification];
[mock verify];
[mock stopMocking];
});

it(@"displays message in aps/alert", ^{
id JSON = @{ @"url" : @"http://artsy.net/feature", @"aps" : @{ @"alert" : @"hello world" } };
NSData *data = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:nil];
NSDictionary *notification = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
id mock = [OCMockObject mockForClass:[ARNotificationView class]];
[[mock expect]
showNoticeInView:OCMOCK_ANY
title:@"hello world"
hideAfter:0
response:OCMOCK_ANY];
UIApplication *app = [UIApplication sharedApplication];
[[app delegate] application:app didReceiveRemoteNotification:notification];
[mock verify];
[mock stopMocking];
});

it(@"defaults message to url", ^{
id JSON = @{ @"url" : @"http://artsy.net/feature" };
NSData *data = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:nil];
NSDictionary *notification = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
id mock = [OCMockObject mockForClass:[ARNotificationView class]];
[[mock expect]
showNoticeInView:OCMOCK_ANY
title:@"http://artsy.net/feature"
hideAfter:0
response:OCMOCK_ANY];
UIApplication *app = [UIApplication sharedApplication];
[[app delegate] application:app didReceiveRemoteNotification:notification];
[mock verify];
[mock stopMocking];
});

pending(@"displays message in aps/alert and navigates to url provided");
});
});

SpecEnd

Loading

0 comments on commit 2e814fc

Please sign in to comment.