Skip to content

Commit

Permalink
Add example project
Browse files Browse the repository at this point in the history
  • Loading branch information
blakewatters committed Mar 28, 2013
1 parent b21a19d commit f2d4a0b
Show file tree
Hide file tree
Showing 25 changed files with 1,003 additions and 1 deletion.
1 change: 1 addition & 0 deletions Example/.gitignore
@@ -0,0 +1 @@
Pods
10 changes: 10 additions & 0 deletions Example/Podfile
@@ -0,0 +1,10 @@
platform :ios, '6.0'

pod 'RestKit/Core', '~> 0.20.0'
pod 'RestKit/Testing', '~> 0.20.0'

target :test, :exclusive => true do
link_with 'RKKiwiExampleTests'
pod 'Kiwi', '~> 2.0.0'
pod 'RKKiwiMatchers', :local => '../'
end
38 changes: 38 additions & 0 deletions Example/Podfile.lock
@@ -0,0 +1,38 @@
PODS:
- AFNetworking (1.1.0)
- Kiwi (2.0.5)
- RestKit/Core (0.20.0):
- RestKit/CoreData
- RestKit/Network
- RestKit/ObjectMapping
- RestKit/CoreData (0.20.0)
- RestKit/Network (0.20.0):
- AFNetworking (= 1.1.0)
- RestKit/ObjectMapping
- RestKit/Support
- SOCKit
- RestKit/ObjectMapping (0.20.0)
- RestKit/Support (0.20.0)
- RestKit/Testing (0.20.0)
- RKKiwiMatchers (0.20.0):
- Kiwi (~> 2.0.0)
- SOCKit (1.1)

DEPENDENCIES:
- Kiwi (~> 2.0.0)
- RestKit/Core (~> 0.20.0)
- RestKit/Testing (~> 0.20.0)
- RKKiwiMatchers (from `../`)

EXTERNAL SOURCES:
RKKiwiMatchers:
:local: ../

SPEC CHECKSUMS:
AFNetworking: 761a418233d280c1e0580bcb76ff9cb4c3073d17
Kiwi: 89ade77eb49c889178cb2779e02514a7b9b9449e
RestKit: 580771664a14eaaa40bf53cf83584f12fc141930
RKKiwiMatchers: b2dfeacae98edc16fd380e7366816b31fbbc59ff
SOCKit: ed67aeeca4a697b63a933229e53f4670d5b9300f

COCOAPODS: 0.17.0.rc4
22 changes: 22 additions & 0 deletions Example/README.md
@@ -0,0 +1,22 @@
# RKKiwiMatchers Example App

This is a simple example application that shows to Unit Test Core Data object mappings using RestKit and Kiwi.

Unit Tests are configured using the standard Apple generated boilterplate configuration that is emitted when you select the "Include Unit Tests" checkbox when provisioning an application. This configuration uses an application target and an external Unit Tests bundle that is injected into the application when the tests are run. This is known as an "Application Tests" configuration and is distinct from "Logic Tests" in that the tests are dependent on a running app. The same configuration can be applied to a Logic Test setup as well.

## Running the Example

To run the example, execute `pod install` to install the pre-requisites and then use the **Product** menu > **Test** action to run the tests. The test code is in `RKKiwiExampleTests/ContactSpec.m`

## Navigating the Example Code

There are only a few files of interest to understanding the setup:

1. `RKKiwiExample/RKKEAppDelegate.m` - Sets up the RestKit Core Data stack when the App launches
1. `RKKiwiExampleTests/contact.json` - A JSON Fixture file used in testing.
1. `RKKiwiExampleTests/RKTestFactory+GGEAdditions.m` - A category added to the RestKit `RKTestFactory` class that is used for configuring the test environment.
1. `RKKiwiExampleTests/ContactSpec.m` - The actual Kiwi spec. This is where most of the action is. This test file configures a RestKit mapping, loads a fixture file, and then uses the Kiwi matchers to exercise the mapping and validate the results.

### Credits

Blake Watters <blake@restkit.org>
536 changes: 536 additions & 0 deletions Example/RKKiwiExample.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions Example/RKKiwiExample/Contact.h
@@ -0,0 +1,29 @@
//
// Contact.h
// RKKiwiExample
//
// Created by Blake Watters on 3/27/13.
// Copyright (c) 2013 RestKit. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>


@interface Contact : NSManagedObject

@property (nonatomic, retain) NSString * firstName;
@property (nonatomic, retain) NSString * lastName;
@property (nonatomic, retain) NSString * emailAddress;
@property (nonatomic, retain) NSDate * creationDate;
@property (nonatomic, retain) NSSet *tags;
@end

@interface Contact (CoreDataGeneratedAccessors)

- (void)addTagsObject:(NSManagedObject *)value;
- (void)removeTagsObject:(NSManagedObject *)value;
- (void)addTags:(NSSet *)values;
- (void)removeTags:(NSSet *)values;

@end
20 changes: 20 additions & 0 deletions Example/RKKiwiExample/Contact.m
@@ -0,0 +1,20 @@
//
// Contact.m
// RKKiwiExample
//
// Created by Blake Watters on 3/27/13.
// Copyright (c) 2013 RestKit. All rights reserved.
//

#import "Contact.h"


@implementation Contact

@dynamic firstName;
@dynamic lastName;
@dynamic emailAddress;
@dynamic creationDate;
@dynamic tags;

@end
Binary file added Example/RKKiwiExample/Default-568h@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Example/RKKiwiExample/Default.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Example/RKKiwiExample/Default@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions Example/RKKiwiExample/RKKEAppDelegate.h
@@ -0,0 +1,15 @@
//
// RKKEAppDelegate.h
// RKKiwiExample
//
// Created by Blake Watters on 12/8/12.
// Copyright (c) 2012 RestKit. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface RKKEAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end
40 changes: 40 additions & 0 deletions Example/RKKiwiExample/RKKEAppDelegate.m
@@ -0,0 +1,40 @@
//
// RKKEAppDelegate.m
// RKKiwiExample
//
// Created by Blake Watters on 12/8/12.
// Copyright (c) 2012 RestKit. All rights reserved.
//

#import <RestKit/RestKit.h>
#import <RestKit/CoreData.h>
#import "RKKEAppDelegate.h"

@implementation RKKEAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];

// Setup Core Data
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"RKKiwiExample" ofType:@"momd"]];
NSManagedObjectModel *managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
NSError *error = nil;
BOOL success = [managedObjectStore addInMemoryPersistentStore:&error];
NSAssert(success, @"Adding in memory store failed with error: %@", error);
[managedObjectStore createManagedObjectContexts];
[RKManagedObjectStore setDefaultStore:managedObjectStore];

return YES;
}

- (void)applicationWillTerminate:(UIApplication *)application
{

}

@end
38 changes: 38 additions & 0 deletions Example/RKKiwiExample/RKKiwiExample-Info.plist
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>org.restkit.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
17 changes: 17 additions & 0 deletions Example/RKKiwiExample/RKKiwiExample-Prefix.pch
@@ -0,0 +1,17 @@
//
// Prefix header for all source files of the 'RKKiwiExample' target in the 'RKKiwiExample' project
//

#import <Availability.h>

#ifndef __IPHONE_3_0
#warning "This project uses features only available in iOS SDK 3.0 and later."
#endif

#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <MobileCoreServices/MobileCoreServices.h>
#endif
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="2061" systemVersion="12D78" minimumToolsVersion="Xcode 4.3" macOSVersion="Automatic" iOSVersion="Automatic">
<entity name="Contact" representedClassName="Contact" syncable="YES">
<attribute name="creationDate" optional="YES" attributeType="Date" syncable="YES"/>
<attribute name="emailAddress" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="firstName" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="lastName" optional="YES" attributeType="String" syncable="YES"/>
<relationship name="tags" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Tag" inverseName="contacts" inverseEntity="Tag" syncable="YES"/>
</entity>
<entity name="Tag" representedClassName="Tag" syncable="YES">
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
<relationship name="contacts" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Contact" inverseName="tags" inverseEntity="Contact" syncable="YES"/>
</entity>
<elements>
<element name="Contact" positionX="160" positionY="192" width="128" height="120"/>
<element name="Tag" positionX="160" positionY="192" width="128" height="75"/>
</elements>
</model>
27 changes: 27 additions & 0 deletions Example/RKKiwiExample/Tag.h
@@ -0,0 +1,27 @@
//
// Tag.h
// RKKiwiExample
//
// Created by Blake Watters on 3/27/13.
// Copyright (c) 2013 RestKit. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class Contact;

@interface Tag : NSManagedObject

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSSet *contacts;
@end

@interface Tag (CoreDataGeneratedAccessors)

- (void)addContactsObject:(Contact *)value;
- (void)removeContactsObject:(Contact *)value;
- (void)addContacts:(NSSet *)values;
- (void)removeContacts:(NSSet *)values;

@end
18 changes: 18 additions & 0 deletions Example/RKKiwiExample/Tag.m
@@ -0,0 +1,18 @@
//
// Tag.m
// RKKiwiExample
//
// Created by Blake Watters on 3/27/13.
// Copyright (c) 2013 RestKit. All rights reserved.
//

#import "Tag.h"
#import "Contact.h"


@implementation Tag

@dynamic name;
@dynamic contacts;

@end
2 changes: 2 additions & 0 deletions Example/RKKiwiExample/en.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

18 changes: 18 additions & 0 deletions Example/RKKiwiExample/main.m
@@ -0,0 +1,18 @@
//
// main.m
// RKKiwiExample
//
// Created by Blake Watters on 12/8/12.
// Copyright (c) 2012 RestKit. All rights reserved.
//

#import <UIKit/UIKit.h>

#import "RKKEAppDelegate.h"

int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([RKKEAppDelegate class]));
}
}
61 changes: 61 additions & 0 deletions Example/RKKiwiExampleTests/ContactSpec.m
@@ -0,0 +1,61 @@
//
// ContactSpec.m
// RKKiwiExample
//
// Created by Blake Watters on 3/27/13.
// Copyright 2013 RestKit. All rights reserved.
//

#import <Kiwi/Kiwi.h>
#import <RestKit/CoreData.h>
#import <RestKit/Testing.h>
#import <RKKiwiMatchers/RKKiwiMatchers.h>
#import "Contact.h"
#import "Tag.h"

SPEC_BEGIN(ContactSpec)

registerMatchers(@"RK");

context(@"when object mapping a Contact entity from a JSON file", ^{
__block NSData *fixtureData;
__block RKMappingTest *mappingTest;
__block RKEntityMapping *entityMapping;
__block RKEntityMapping *tagMapping;
__block RKManagedObjectStore *managedObjectStore;

beforeAll(^{
managedObjectStore = [RKManagedObjectStore defaultStore]; // Configured by App Delegate
entityMapping = [RKEntityMapping mappingForEntityForName:@"Contact" inManagedObjectStore:managedObjectStore];
[entityMapping addAttributeMappingsFromDictionary:@{
@"first_name": @"firstName",
@"last_name": @"lastName",
@"email_address": @"emailAddress",
@"created_at": @"creationDate",
}];

RKEntityMapping *tagMapping = [RKEntityMapping mappingForEntityForName:@"Tag" inManagedObjectStore:managedObjectStore];
// Map each element in the array as a 'name'
[tagMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"name"]];
[entityMapping addRelationshipMappingWithSourceKeyPath:@"tags" mapping:tagMapping];
});

beforeEach(^{
fixtureData = [RKTestFixture parsedObjectWithContentsOfFixture:@"contact.json"];
mappingTest = [RKMappingTest testForMapping:entityMapping sourceObject:fixtureData destinationObject:nil];
RKFetchRequestManagedObjectCache *cache = [RKFetchRequestManagedObjectCache new];
mappingTest.mappingOperationDataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:managedObjectStore.persistentStoreManagedObjectContext cache:cache];
});

// Attributes
specify(^{ [[mappingTest should] mapKeyPath:@"first_name" toKeyPath:@"firstName" withValue:@"Blake"]; });
specify(^{ [[mappingTest should] mapKeyPath:@"last_name" toKeyPath:@"lastName" withValue:@"Watters"]; });
specify(^{ [[mappingTest should] mapKeyPath:@"email_address" toKeyPath:@"emailAddress" withValue:@"blake@restkit.org"]; });
specify(^{ [[mappingTest should] mapKeyPath:@"created_at" toKeyPath:@"creationDate" withValue:RKDateFromString(@"2013-03-27T22:16:22-04:00")]; });

// Relationships
specify(^{ [[mappingTest should] mapKeyPath:@"tags" toKeyPath:@"tags" usingMapping:tagMapping]; });

});

SPEC_END

0 comments on commit f2d4a0b

Please sign in to comment.