Skip to content

Commit

Permalink
Added a 'currentTestName' variable to a 'KIF' singleton (so the tests…
Browse files Browse the repository at this point in the history
… can track what test is currently being run an load in the relevant data).

Swizzle UIWindow's 'addSubview:' method to bring the testing UI to the front (previously other UI could get added to the window and obscure the test menu).
Added code to change the priority of MKAnnotationViews when tapping on them (looks like they all have the same z-index so it should be first-come-first-serve).
  • Loading branch information
morganTS committed May 22, 2014
1 parent c61ba6a commit 650f0a1
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 3 deletions.
8 changes: 8 additions & 0 deletions Classes/KIF.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,11 @@
#else
#import "SenTestCase-KIFAdditions.h"
#endif

@interface KIF : NSObject

@property (nonatomic, copy) NSString *currentTestName;

+ (instancetype)sharedInstance;

@end
23 changes: 23 additions & 0 deletions Classes/KIF.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// KIF.m
// KIF
//
// Created by Morgan Pretty on 22/05/2014.
//
//

#import "KIF.h"

@implementation KIF

+ (instancetype)sharedInstance {
static KIF *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [KIF new];
});

return sharedInstance;
}

@end
6 changes: 6 additions & 0 deletions KIF.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@
EBAE488217A460E50005EE19 /* NSError-KIFAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = EBAE488017A460E50005EE19 /* NSError-KIFAdditions.m */; };
EBAE488717A4E5C30005EE19 /* KIFTestStepValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = EBAE488517A4E5C30005EE19 /* KIFTestStepValidation.h */; settings = {ATTRIBUTES = (Public, ); }; };
EBAE488817A4E5C30005EE19 /* KIFTestStepValidation.m in Sources */ = {isa = PBXBuildFile; fileRef = EBAE488617A4E5C30005EE19 /* KIFTestStepValidation.m */; };
FA09A8E4192D864E00058CF1 /* KIF.m in Sources */ = {isa = PBXBuildFile; fileRef = FA09A8E3192D864E00058CF1 /* KIF.m */; };
FA09A8E5192D864E00058CF1 /* KIF.m in Sources */ = {isa = PBXBuildFile; fileRef = FA09A8E3192D864E00058CF1 /* KIF.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -266,6 +268,7 @@
EBAE488017A460E50005EE19 /* NSError-KIFAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError-KIFAdditions.m"; sourceTree = "<group>"; };
EBAE488517A4E5C30005EE19 /* KIFTestStepValidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KIFTestStepValidation.h; sourceTree = "<group>"; };
EBAE488617A4E5C30005EE19 /* KIFTestStepValidation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KIFTestStepValidation.m; sourceTree = "<group>"; };
FA09A8E3192D864E00058CF1 /* KIF.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KIF.m; sourceTree = "<group>"; };
FA268FD0191B1633000758D2 /* KIFRecorder.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = KIFRecorder.xcodeproj; path = KIFRecorder/KIFRecorder.xcodeproj; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -377,6 +380,7 @@
children = (
EB4C312F167BA39200E31109 /* Actors */,
A88930111685098E00FC7C63 /* KIF.h */,
FA09A8E3192D864E00058CF1 /* KIF.m */,
EB4C3127167BA37B00E31109 /* KIFTestCase.h */,
EB4C3128167BA37B00E31109 /* KIFTestCase.m */,
EB4C3123167BA37B00E31109 /* KIFTestActor.h */,
Expand Down Expand Up @@ -803,6 +807,7 @@
EABD467C1857A0C700A5F081 /* UIAccessibilityElement-KIFAdditions.m in Sources */,
EABD467D1857A0C700A5F081 /* UIApplication-KIFAdditions.m in Sources */,
EABD467E1857A0C700A5F081 /* UIScrollView-KIFAdditions.m in Sources */,
FA09A8E4192D864E00058CF1 /* KIF.m in Sources */,
EABD467F1857A0C700A5F081 /* UITouch-KIFAdditions.m in Sources */,
EABD46801857A0C700A5F081 /* UIView-KIFAdditions.m in Sources */,
EABD46811857A0C700A5F081 /* UIWindow-KIFAdditions.m in Sources */,
Expand Down Expand Up @@ -886,6 +891,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FA09A8E5192D864E00058CF1 /* KIF.m in Sources */,
EB7204431680DDAD00278DA2 /* CGGeometry-KIFAdditions.m in Sources */,
EB7204441680DDAD00278DA2 /* UIAccessibilityElement-KIFAdditions.m in Sources */,
EB7204451680DDAD00278DA2 /* UIApplication-KIFAdditions.m in Sources */,
Expand Down
21 changes: 21 additions & 0 deletions KIFRecorder/KIFRecorder/Classes/KIFRecorder.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ - (void)swizzleApp {

// We will need to add the recording wrapper to the Window
Swizzle([UIWindow class], @selector(makeKeyAndVisible), @selector(KIFR_makeKeyAndVisible));
Swizzle([UIWindow class], @selector(addSubview:), @selector(KIFR_addSubview:));

// Intercept HTTP request completion methods - AFURLConnectionOperation's delegate 'connectionDidFinishLoading:' and ASIHTTPRequest's 'markAsFinished'
Swizzle(NSClassFromString(@"AFURLConnectionOperation"), @selector(connectionDidFinishLoading:), @selector(KIFR_connectionDidFinishLoading:));
Expand Down Expand Up @@ -125,6 +126,9 @@ + (void)exportTestWithName:(NSString *)testName canReplaceOldTest:(BOOL)canRepla
[testString appendFormat:@"- (void)test%@ {", testName];
}

// Add in the code to update KIF's 'currentTestName' property while the test runs
[testString appendFormat:@"\n [[KIF sharedInstance] setCurrentTestName:@\"%@\"];\n", testName];

for (KIFRTestStep *step in [KIFRTest currentTest].testStepsArray) {
if (step.stepType == KIFRStepTypeUnknown) {
NSLog(@"Warning! Attempted to export a recorded action with no export logic!");
Expand All @@ -146,6 +150,23 @@ + (void)exportTestWithName:(NSString *)testName canReplaceOldTest:(BOOL)canRepla
NSLog(@"%lu requests made during test.", (unsigned long)[KIFRTest currentTest].testRequestsArray.count);
[[NSFileManager defaultManager] createDirectoryAtPath:[NSString stringWithFormat:@"%@/%@", docsDir, testName] withIntermediateDirectories:YES attributes:nil error:nil];

// Discard any tests which are running on the same Test Step
// Note: The blow code *might* be able to be reworked to fix multi-request issues with 'auto-complete' requests BUT it could cause bugs with any auto-polling requests
// NSInteger testStepIndex = -1;
// NSMutableArray *mutableRequestsArray = [[KIFRTest currentTest].testRequestsArray mutableCopy];
// for (int i = (int)mutableRequestsArray.count - 1; i >= 0; --i) {
// NSDictionary *requestDictionary = mutableRequestsArray[i];
// NSInteger newStepIndex = [requestDictionary[kKIFRTestStepIndexKey] integerValue];
//
// // If they are for the same step then remove the step
// if (testStepIndex == newStepIndex) {
// [mutableRequestsArray removeObjectAtIndex:i];
// }
//
// testStepIndex = newStepIndex;
// }

// Save out the filtered tests
for (int i = 0; i < [KIFRTest currentTest].testRequestsArray.count; ++i) {
NSDictionary *requestDictionary = [KIFRTest currentTest].testRequestsArray[i];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:requestDictionary options:0 error:nil];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

#import <Foundation/Foundation.h>

static const NSString *kKIFRRequestKey = @"request";
static const NSString *kKIFRResponseKey = @"response";
static const NSString *kKIFRTestStepIndexKey = @"testStepIndex";

@interface NSObject (KIFRUtils_Networking)

- (void)KIFR_markAsFinished;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ - (void)KIFR_connectionDidFinishLoading:(NSURLConnection *)connection {

- (void)addResponse:(NSData *)responseData forRequest:(NSURL *)requestURL {
NSMutableDictionary *requestDictionary = [NSMutableDictionary new];
[requestDictionary setObject:[requestURL absoluteString] forKey:@"request"];
[requestDictionary setObject:[requestURL absoluteString] forKey:kKIFRRequestKey];

NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
[requestDictionary setObject:jsonData forKey:@"response"];
[requestDictionary setObject:jsonData forKey:kKIFRResponseKey];
[requestDictionary setObject:@([KIFRTest currentTest].testStepsArray.count) forKey:kKIFRTestStepIndexKey];

[[KIFRTest currentTest].testRequestsArray addObject:requestDictionary];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@

+ (UIWindow *)kifrWindow;
- (void)KIFR_makeKeyAndVisible;
- (void)KIFR_addSubview:(UIView *)subview;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ - (void)setupRecordingUI {
[self addGestureRecognizer:pinchGestureRecognizer];
}

- (void)KIFR_addSubview:(UIView *)subview {
[self KIFR_addSubview:subview];
[self bringSubviewToFront:[KIFRMenuView sharedInstance]];
}

#pragma mark - Gesture Handlers

- (KIFRTestEvent *)eventForTouches:(NSArray *)touches {
Expand Down
18 changes: 17 additions & 1 deletion KIFRecorder/KIFRecorder/Classes/UITouch+KIFRUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,23 @@ - (UIView *)accessibleViewWithPossibilities:(NSArray *)possibleViews {
return self.view;
}

// If the touched view doesn't meet the criteria then assume the lastObject in the 'possibleViews' array is the correct one (the array will be sorted by z-index by default, so it should be the top-most view, and the UIResponder chain would take care of the rest)
// If the touched view doesn't meet the criteria then try find the relevant view in the 'possibleViews' array.

// MKAnnotationViews have the same z-index so if there are multiple options we actually want the first one (as that's what would have been clicked)
if ([possibleViews.lastObject isKindOfClass:NSClassFromString(@"MKAnnotationView")]) {
UIView *annotationView;
for (int i = (int)possibleViews.count - 1; i >= 0; --i) {
if ([possibleViews[i] isKindOfClass:NSClassFromString(@"MKAnnotationView")]) {
annotationView = possibleViews[i];
}
else {
// There aren't any more MKAnnotationViews in front of this one so return it
return annotationView;
}
}
}

// If we don't need to worry about any special cases then ssume the lastObject in the 'possibleViews' array is the correct one (the array will be sorted by z-index by default, so it should be the top-most view, and the UIResponder chain would take care of the rest)
return possibleViews.lastObject;
}

Expand Down

0 comments on commit 650f0a1

Please sign in to comment.