You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2013/01/22 02:57:59 UTC

[5/52] [partial] support for 2.4.0rc1. "vendored" the platform libs in. added Gord and Braden as contributors. removed dependency on unzip and axed the old download-cordova code.

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CDVBase64Tests.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CDVBase64Tests.m b/lib/cordova-ios/CordovaLibTests/CDVBase64Tests.m
new file mode 100644
index 0000000..70fb38e
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CDVBase64Tests.m
@@ -0,0 +1,64 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <SenTestingKit/SenTestingKit.h>
+
+#import "NSData+Base64.h"
+
+@interface CDVBase64Tests : SenTestCase
+@end
+
+@implementation CDVBase64Tests
+
+- (void)setUp
+{
+    [super setUp];
+
+    // setup code here
+}
+
+- (void)tearDown
+{
+    // Tear-down code here.
+
+    [super tearDown];
+}
+
+- (void)testBase64Encode
+{
+    NSString* decodedString = @"abcdefghijklmnopqrstuvwxyz1234567890!@#$%^&";
+    NSData* decodedData = [decodedString dataUsingEncoding:NSUTF8StringEncoding];
+
+    NSString* expectedEncodedString = @"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwIUAjJCVeJg==";
+    NSString* actualEncodedString = [decodedData base64EncodedString];
+
+    STAssertTrue([expectedEncodedString isEqualToString:actualEncodedString], nil);
+}
+
+- (void)testBase64Decode
+{
+    NSString* encodedString = @"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkwIUAjJCVeJg==";
+    NSString* decodedString = @"abcdefghijklmnopqrstuvwxyz1234567890!@#$%^&";
+    NSData* encodedData = [decodedString dataUsingEncoding:NSUTF8StringEncoding];
+    NSData* decodedData = [NSData dataFromBase64String:encodedString];
+
+    STAssertTrue([encodedData isEqualToData:decodedData], nil);
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CDVContactsTests.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CDVContactsTests.m b/lib/cordova-ios/CordovaLibTests/CDVContactsTests.m
new file mode 100644
index 0000000..f239bba
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CDVContactsTests.m
@@ -0,0 +1,60 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <SenTestingKit/SenTestingKit.h>
+
+#import "CDVWebViewTest.h"
+#import "CDVContacts.h"
+
+@interface CDVContactsTests : CDVWebViewTest
+@end
+
+@implementation CDVContactsTests
+
+- (void)setUp
+{
+    [super setUp];
+}
+
+- (void)tearDown
+{
+    [super tearDown];
+}
+
+- (void)testSearchContacts
+{
+    STAssertTrue(NO, @"TODO: testSearchContacts");
+}
+
+- (void)testSaveContact
+{
+    STAssertTrue(NO, @"TODO: testSaveContact");
+}
+
+- (void)testNewContact
+{
+    STAssertTrue(NO, @"TODO: testNewContact");
+}
+
+- (void)testRemoveContact
+{
+    STAssertTrue(NO, @"TODO: testRemoveContact");
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CDVFakeFileManager.h
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CDVFakeFileManager.h b/lib/cordova-ios/CordovaLibTests/CDVFakeFileManager.h
new file mode 100644
index 0000000..41e5523
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CDVFakeFileManager.h
@@ -0,0 +1,35 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+typedef BOOL (^CDVFileExistsBlock)(NSString*);
+
+// Used in place of an NSFileManager for unit tests. It implements only those functions
+// which are required by the tests that use it.
+@interface CDVFakeFileManager : NSObject {
+    @private
+    CDVFileExistsBlock _fileExistsBlock;
+}
+
+- (id)initWithFileExistsBlock:(CDVFileExistsBlock)fileExistsBlock;
++ (id)managerWithFileExistsBlock:(CDVFileExistsBlock)fileExistsBlock;
+
+- (BOOL)fileExistsAtPath:(NSString*)path;
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CDVFakeFileManager.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CDVFakeFileManager.m b/lib/cordova-ios/CordovaLibTests/CDVFakeFileManager.m
new file mode 100644
index 0000000..50ecd43
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CDVFakeFileManager.m
@@ -0,0 +1,43 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVFakeFileManager.h"
+
+@implementation CDVFakeFileManager
+
+- (id)initWithFileExistsBlock:(CDVFileExistsBlock)fileExistsBlock
+{
+    self = [super init];
+    if (self != nil) {
+        _fileExistsBlock = [fileExistsBlock copy];
+    }
+    return self;
+}
+
++ (id)managerWithFileExistsBlock:(CDVFileExistsBlock)fileExistsBlock
+{
+    return [[CDVFakeFileManager alloc] initWithFileExistsBlock:fileExistsBlock];
+}
+
+- (BOOL)fileExistsAtPath:(NSString*)path
+{
+    return _fileExistsBlock(path);
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CDVFileTransferTests.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CDVFileTransferTests.m b/lib/cordova-ios/CordovaLibTests/CDVFileTransferTests.m
new file mode 100644
index 0000000..7488a5a
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CDVFileTransferTests.m
@@ -0,0 +1,218 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <SenTestingKit/SenTestingKit.h>
+
+#import "CDV.h"
+#import "CDVCommandDelegateImpl.h"
+
+static NSString* const kDummyArgCallbackId = @"cid0";
+static NSString* const kDummyArgFileKey = @"image.jpg";
+static NSString* const kDummyArgTarget = @"/path/to/image.jpg";
+static NSString* const kDummyArgServer = @"http://apache.org";
+static NSString* const kDummyFileContents = @"0123456789";
+
+// Reads the given stream and returns the contents as an NSData.
+static NSData *readStream(NSInputStream* stream)
+{
+    static const NSUInteger kBufferSize = 1024;
+
+    UInt8* buffer = malloc(kBufferSize);
+    NSMutableData* streamData = [NSMutableData data];
+
+    [stream open];
+
+    for (;; ) {
+        NSInteger read = [stream read:buffer maxLength:kBufferSize];
+        if (read > 0) {
+            [streamData appendBytes:buffer length:read];
+        } else {
+            break;
+        }
+    }
+
+    free(buffer);
+    [stream close];
+    return streamData;
+}
+
+@interface CDVFileTransferTests : SenTestCase {
+    NSMutableArray* _arguments;
+    CDVFileTransfer* _fileTransfer;
+    NSData* _dummyFileData;
+    CDVCommandDelegateImpl* _commandDelegate;
+}
+@end
+
+@implementation CDVFileTransferTests
+
+- (void)setUp
+{
+    [super setUp];
+
+    _arguments = [[NSMutableArray alloc] initWithObjects:
+        kDummyArgTarget, kDummyArgServer, kDummyArgFileKey, [NSNull null],
+        [NSNull null], [NSNull null], [NSNull null], [NSNull null], [NSNull null], nil];
+    _dummyFileData = [kDummyFileContents dataUsingEncoding:NSUTF8StringEncoding];
+    _commandDelegate = [[CDVCommandDelegateImpl alloc] initWithViewController:nil];
+    _fileTransfer = [[CDVFileTransfer alloc] init];
+    _fileTransfer.commandDelegate = _commandDelegate;
+}
+
+- (void)tearDown
+{
+    _arguments = nil;
+    _dummyFileData = nil;
+    _fileTransfer = nil;
+    _commandDelegate = nil;
+    [super tearDown];
+}
+
+- (void)setFilePathArg:(NSString*)filePath
+{
+    [_arguments replaceObjectAtIndex:0 withObject:filePath];
+}
+
+- (void)setServerUrlArg:(NSString*)serverUrl
+{
+    [_arguments replaceObjectAtIndex:1 withObject:serverUrl];
+}
+
+- (void)setChunkedModeArg:(BOOL)chunk
+{
+    [_arguments replaceObjectAtIndex:7 withObject:[NSNumber numberWithBool:chunk]];
+}
+
+- (void)setParams:(NSDictionary*)params
+{
+    [_arguments replaceObjectAtIndex:5 withObject:params];
+}
+
+- (void)setHeaders:(NSDictionary*)headers
+{
+    [_arguments replaceObjectAtIndex:8 withObject:headers];
+}
+
+- (NSURLRequest*)requestForUpload
+{
+    CDVInvokedUrlCommand* command = [[CDVInvokedUrlCommand alloc] initWithArguments:_arguments
+                                                                         callbackId:kDummyArgCallbackId
+                                                                          className:@"FileTransfer"
+                                                                         methodName:@"upload"];
+
+    return [_fileTransfer requestForUploadCommand:command fileData:_dummyFileData];
+}
+
+- (void)checkUploadRequest:(NSURLRequest*)request chunked:(BOOL)chunked
+{
+    STAssertTrue([@"POST" isEqualToString:[request HTTPMethod]], nil);
+    NSData* payloadData = nil;
+    if (chunked) {
+        STAssertNil([request HTTPBody], nil);
+        STAssertNotNil([request HTTPBodyStream], nil);
+        payloadData = readStream([request HTTPBodyStream]);
+    } else {
+        STAssertNotNil([request HTTPBody], nil);
+        STAssertNil([request HTTPBodyStream], nil);
+        payloadData = [request HTTPBody];
+    }
+    STAssertNotNil([request valueForHTTPHeaderField:@"X-Requested-With"], nil);
+    NSUInteger contentLength = [[request valueForHTTPHeaderField:@"Content-Length"] intValue];
+    STAssertEquals([payloadData length], contentLength, nil);
+}
+
+- (void)testEscapePathComponentForUrlString
+{
+    STAssertTrue([@"" isEqualToString:
+            [_fileTransfer escapePathComponentForUrlString:@""]], nil);
+    STAssertTrue([@"foo" isEqualToString:
+            [_fileTransfer escapePathComponentForUrlString:@"foo"]], nil);
+    STAssertTrue([@"http://a.org/spa%20ce%25" isEqualToString:
+            [_fileTransfer escapePathComponentForUrlString:@"http://a.org/spa ce%"]], nil);
+    STAssertTrue([@"http://a.org/spa%20ce%25/" isEqualToString:
+            [_fileTransfer escapePathComponentForUrlString:@"http://a.org/spa ce%/"]], nil);
+    STAssertTrue([@"http://a.org/%25/%25/" isEqualToString:
+            [_fileTransfer escapePathComponentForUrlString:@"http://a.org/%/%/"]], nil);
+}
+
+- (void)testUpload_invalidServerUrl
+{
+    [self setServerUrlArg:@"invalid url"];
+    STAssertNil([self requestForUpload], nil);
+}
+
+- (void)testUpload_missingFileData
+{
+    _dummyFileData = nil;
+    STAssertNil([self requestForUpload], nil);
+}
+
+- (void)testUpload_serverUrlPathEscaping
+{
+    [self setServerUrlArg:[_fileTransfer escapePathComponentForUrlString:@"http://apache.org/spa ce%"]]; // uri encode first now
+    NSURLRequest* request = [self requestForUpload];
+    STAssertTrue([[[request URL] absoluteString] isEqualToString:@"http://apache.org/spa%20ce%25"], nil);
+}
+
+- (void)testUpload_nonChunked
+{
+    [self setChunkedModeArg:NO];
+    NSURLRequest* request = [self requestForUpload];
+    [self checkUploadRequest:request chunked:NO];
+}
+
+- (void)testUpload_chunked
+{
+    // As noted in the implementation, chunked upload is disabled pre 5.0.
+    if (!IsAtLeastiOSVersion(@"5.0")) {
+        return;
+    }
+    // Chunked is the default.
+    NSURLRequest* request = [self requestForUpload];
+    [self checkUploadRequest:request chunked:YES];
+}
+
+- (void)testUpload_withParams
+{
+    [self setChunkedModeArg:NO];
+    NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys:@"cookieval", kOptionsKeyCookie,
+        @"val3", @"key3", nil];
+    [self setParams:params];
+    NSURLRequest* request = [self requestForUpload];
+    NSString* payload = [[NSString alloc] initWithData:[request HTTPBody] encoding:NSUTF8StringEncoding];
+    // Check that the cookie is set, and that it is not in the payload like others in the options dict.
+    STAssertTrue([@"cookieval" isEqualToString:[request valueForHTTPHeaderField:@"Cookie"]], nil);
+    STAssertEquals([payload rangeOfString:@"cookieval"].length, 0U, nil);
+    // Check that key3 is in the payload.
+    STAssertTrue([payload rangeOfString:@"key3"].length > 0, nil);
+    STAssertTrue([payload rangeOfString:@"val3"].length > 0, nil);
+}
+
+- (void)testUpload_withHeaders
+{
+    [self setChunkedModeArg:NO];
+    [self setHeaders:[NSDictionary dictionaryWithObjectsAndKeys:@"val1", @"key1",
+            [NSArray arrayWithObjects:@"val2a", @"val2b", nil], @"key2", [NSNull null], @"X-Requested-With", nil]];
+    NSURLRequest* request = [self requestForUpload];
+    STAssertTrue([@"val1" isEqualToString:[request valueForHTTPHeaderField:@"key1"]], nil);
+    STAssertTrue([@"val2a,val2b" isEqualToString:[request valueForHTTPHeaderField:@"key2"]], nil);
+    STAssertTrue([@"null" isEqualToString:[request valueForHTTPHeaderField:@"X-Requested-With"]], nil);
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CDVInvokedUrlCommandTests.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CDVInvokedUrlCommandTests.m b/lib/cordova-ios/CordovaLibTests/CDVInvokedUrlCommandTests.m
new file mode 100644
index 0000000..cdaff0b
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CDVInvokedUrlCommandTests.m
@@ -0,0 +1,107 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <SenTestingKit/SenTestingKit.h>
+
+#import "CDVInvokedUrlCommand.h"
+
+@interface CDVInvokedUrlCommandTests : SenTestCase
+@end
+
+@implementation CDVInvokedUrlCommandTests
+
+- (void)testInitWithNoArgs
+{
+    NSArray* jsonArr = [NSArray arrayWithObjects:@"callbackId", @"className", @"methodName", [NSArray array], nil];
+    CDVInvokedUrlCommand* command = [CDVInvokedUrlCommand commandFromJson:jsonArr];
+
+    STAssertEquals(@"callbackId", command.callbackId, nil);
+    STAssertEquals(@"className", command.className, nil);
+    STAssertEquals(@"methodName", command.methodName, nil);
+    STAssertEquals([NSArray array], command.arguments, nil);
+}
+
+- (void)testLegacyArgsNoDict
+{
+    NSArray* args = [NSArray arrayWithObjects:@"a", @"b", nil];
+    NSArray* jsonArr = [NSArray arrayWithObjects:@"callbackId", @"className", @"methodName", args, nil];
+    CDVInvokedUrlCommand* command = [CDVInvokedUrlCommand commandFromJson:jsonArr];
+    NSMutableArray* legacyArgs = nil;
+    NSMutableDictionary* dict = nil;
+
+    [command legacyArguments:&legacyArgs andDict:&dict];
+    // Ensure properties don't change.
+    STAssertEquals(@"callbackId", command.callbackId, nil);
+    STAssertEquals(@"className", command.className, nil);
+    STAssertEquals(@"methodName", command.methodName, nil);
+    STAssertEquals(args, command.arguments, nil);
+
+    NSArray* expected = [NSArray arrayWithObjects:@"callbackId", @"a", @"b", nil];
+    STAssertEqualObjects(expected, legacyArgs, nil);
+    STAssertNil(dict, nil);
+}
+
+- (void)testLegacyArgsWithDicts
+{
+    NSDictionary* dummyDict1 = [NSDictionary dictionaryWithObjectsAndKeys:@"val", @"key", nil];
+    NSDictionary* dummyDict2 = [NSDictionary dictionaryWithObjectsAndKeys:@"val", @"key", nil];
+    NSArray* args = [NSArray arrayWithObjects:@"a", dummyDict1, dummyDict2, @"b", nil];
+    NSArray* jsonArr = [NSArray arrayWithObjects:@"callbackId", @"className", @"methodName", args, nil];
+    CDVInvokedUrlCommand* command = [CDVInvokedUrlCommand commandFromJson:jsonArr];
+    NSMutableArray* legacyArgs = nil;
+    NSMutableDictionary* dict = nil;
+
+    [command legacyArguments:&legacyArgs andDict:&dict];
+    // Ensure properties don't change.
+    STAssertEquals(@"callbackId", command.callbackId, nil);
+    STAssertEquals(@"className", command.className, nil);
+    STAssertEquals(@"methodName", command.methodName, nil);
+    STAssertEquals(args, command.arguments, nil);
+
+    NSArray* expected = [NSArray arrayWithObjects:@"callbackId", @"a", dummyDict2, @"b", nil];
+    STAssertEqualObjects(expected, legacyArgs, nil);
+    STAssertEqualObjects(dict, dummyDict1, nil);
+}
+
+- (void)testLegacyArgsNoCallbackId
+{
+    NSArray* args = [NSArray arrayWithObjects:@"a", @"b", nil];
+    NSArray* jsonArr = [NSArray arrayWithObjects:[NSNull null], @"className", @"methodName", args, nil];
+    CDVInvokedUrlCommand* command = [CDVInvokedUrlCommand commandFromJson:jsonArr];
+    NSMutableArray* legacyArgs = nil;
+    NSMutableDictionary* dict = nil;
+
+    [command legacyArguments:&legacyArgs andDict:&dict];
+
+    NSArray* expected = [NSArray arrayWithObjects:@"a", @"b", nil];
+    STAssertEqualObjects(expected, legacyArgs, nil);
+}
+
+- (void)testArgumentAtIndex
+{
+    NSArray* jsonArr = [NSArray arrayWithObjects:[NSNull null], @"className", @"methodName", [NSArray array], nil];
+    CDVInvokedUrlCommand* command = [CDVInvokedUrlCommand commandFromJson:jsonArr];
+
+    STAssertNil([command argumentAtIndex:0], @"NSNull to nil");
+    STAssertNil([command argumentAtIndex:100], @"Invalid index to nil");
+    STAssertEquals(@"default", [command argumentAtIndex:0 withDefault:@"default"], @"NSNull to default");
+    STAssertEquals(@"default", [command argumentAtIndex:100 withDefault:@"default"], @"Invalid index to default");
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CDVLocalStorageTests.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CDVLocalStorageTests.m b/lib/cordova-ios/CordovaLibTests/CDVLocalStorageTests.m
new file mode 100644
index 0000000..64a1435
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CDVLocalStorageTests.m
@@ -0,0 +1,146 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <SenTestingKit/SenTestingKit.h>
+
+#import "CDVLocalStorage.h"
+#import "CDVWebViewTest.h"
+#import "CDVFakeFileManager.h"
+#import "ViewController.h"
+
+@interface CDVLocalStorageTests : CDVWebViewTest
+                                  // Deletes LocalStorage files from disk.
+- (void)deleteOriginals:(BOOL)originals backups:(BOOL)backups;
+// Returns the CDVLocalStorage instance from the plugins dict.
+- (CDVLocalStorage*)localStorage;
+@end
+
+@implementation CDVLocalStorageTests
+
+- (void)setUp
+{
+    [super setUp];
+    // Clear these on setUp as well in case they were left around.
+    [self deleteOriginals:YES backups:YES];
+}
+
+- (void)tearDown
+{
+    // Don't leave any localStorage files around.
+    [self deleteOriginals:YES backups:YES];
+    [super tearDown];
+}
+
+- (CDVLocalStorage*)localStorage
+{
+    return [self pluginInstance:@"LocalStorage"];
+}
+
+- (void)deleteOriginals:(BOOL)originals backups:(BOOL)backups
+{
+    NSFileManager* fileManager = [NSFileManager defaultManager];
+
+    for (CDVBackupInfo* info in [self localStorage].backupInfo) {
+        if (originals) {
+            [fileManager removeItemAtPath:info.original error:nil];
+        }
+        if (backups) {
+            [fileManager removeItemAtPath:info.backup error:nil];
+        }
+    }
+}
+
+- (void)disabled_testBackupAndRestore
+{
+    CDVLocalStorage* localStorage = [self localStorage];
+
+    [self waitForConditionName:@"shouldBackup" block:^{
+            [self evalJs:@"localStorage.setItem('foo', 'bar')"];
+            return [localStorage shouldBackup];
+        }];
+    [localStorage backup:[CDVInvokedUrlCommand new]];
+    STAssertFalse([localStorage shouldBackup], @"Should have backed up.");
+
+    // It would be nice to be able to test that the restore functionality
+    // alters what localStorage.getItem('foo') returns, but it seems as though
+    // the WebView maintains an in-memory cache of what's in LocalStorage even
+    // after we delete the underlying files and recreate the view.
+
+    // Instead, we just test the file copying logic.
+    [self deleteOriginals:YES backups:NO];
+    STAssertTrue([localStorage shouldRestore], @"Should restore after deleting originals");
+    [localStorage restore:[CDVInvokedUrlCommand new]];
+    STAssertFalse([localStorage shouldRestore], @"Restore did not complete successfully");
+}
+
+- (void)testVerifyAndFixDatabaseLocations_noChangeRequired
+{
+    NSString* const kBundlePath = @"/bpath";
+    id fakeFileManager = [CDVFakeFileManager managerWithFileExistsBlock:^(NSString * path) {
+            STFail (@"fileExists called.");
+            return NO;
+        }];
+    NSMutableDictionary* appPlistDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+        @"/bpath/foo", @"WebKitLocalStorageDatabasePathPreferenceKey",
+        @"/bpath/foo", @"WebDatabaseDirectory",
+        nil];
+    BOOL modified = [CDVLocalStorage __verifyAndFixDatabaseLocationsWithAppPlistDict:appPlistDict
+                                                                          bundlePath:kBundlePath
+                                                                         fileManager:fakeFileManager];
+
+    STAssertFalse (modified, @"Should not have applied fix.");
+}
+
+- (void)testVerifyAndFixDatabaseLocations_changeRequired1
+{
+    NSString* const kBundlePath = @"/bpath";
+    id fakeFileManager = [CDVFakeFileManager managerWithFileExistsBlock:^(NSString * path) {
+            return YES;
+        }];
+    NSMutableDictionary* appPlistDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+        @"/foo", @"WebKitLocalStorageDatabasePathPreferenceKey",
+        nil];
+    BOOL modified = [CDVLocalStorage __verifyAndFixDatabaseLocationsWithAppPlistDict:appPlistDict
+                                                                          bundlePath:kBundlePath
+                                                                         fileManager:fakeFileManager];
+
+    STAssertTrue (modified, @"Should have applied fix.");
+    NSString* newPath = [appPlistDict objectForKey:@"WebKitLocalStorageDatabasePathPreferenceKey"];
+    STAssertTrue ([@"/bpath/Library/Caches" isEqualToString:newPath], nil);
+}
+
+- (void)testVerifyAndFixDatabaseLocations_changeRequired2
+{
+    NSString* const kBundlePath = @"/bpath";
+    id fakeFileManager = [CDVFakeFileManager managerWithFileExistsBlock:^(NSString * path) {
+            return NO;
+        }];
+    NSMutableDictionary* appPlistDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+        @"/foo", @"WebDatabaseDirectory",
+        nil];
+    BOOL modified = [CDVLocalStorage __verifyAndFixDatabaseLocationsWithAppPlistDict:appPlistDict
+                                                                          bundlePath:kBundlePath
+                                                                         fileManager:fakeFileManager];
+
+    STAssertTrue (modified, @"Should have applied fix.");
+    NSString* newPath = [appPlistDict objectForKey:@"WebDatabaseDirectory"];
+    STAssertTrue ([@"/bpath/Library/WebKit" isEqualToString:newPath], nil);
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CDVPluginResultJSONSerializationTests.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CDVPluginResultJSONSerializationTests.m b/lib/cordova-ios/CordovaLibTests/CDVPluginResultJSONSerializationTests.m
new file mode 100644
index 0000000..57b9022
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CDVPluginResultJSONSerializationTests.m
@@ -0,0 +1,155 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import <SenTestingKit/SenTestingKit.h>
+
+#import "CDVPluginResult.h"
+#import "CDVJSON.h"
+
+@interface CDVPluginResultJSONSerializationTests : SenTestCase
+@end
+
+@implementation CDVPluginResultJSONSerializationTests
+
+- (void)testSerializingMessageAsInt
+{
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:5];
+    NSDictionary* dic = [[result toJSONString] JSONObject];
+    NSNumber* message = [dic objectForKey:@"message"];
+
+    STAssertTrue([[NSNumber numberWithInt:5] isEqual:message], nil);
+}
+
+- (void)testSerializingMessageAsDouble
+{
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:5.5];
+    NSDictionary* dic = [[result toJSONString] JSONObject];
+    NSNumber* message = [dic objectForKey:@"message"];
+
+    STAssertTrue([[NSNumber numberWithDouble:5.5] isEqual:message], nil);
+}
+
+- (void)testSerializingMessageAsBool
+{
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:YES];
+    NSDictionary* dic = [[result toJSONString] JSONObject];
+    NSNumber* message = [dic objectForKey:@"message"];
+
+    STAssertTrue([[NSNumber numberWithBool:YES] isEqual:message], nil);
+}
+
+- (void)testSerializingMessageAsArray
+{
+    NSArray* testValues = [NSArray arrayWithObjects:
+        [NSNull null],
+        @"string",
+        [NSNumber numberWithInt:5],
+        [NSNumber numberWithDouble:5.5],
+        [NSNumber numberWithBool:true],
+        nil];
+
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:testValues];
+    NSDictionary* dic = [[result toJSONString] JSONObject];
+    NSArray* message = [dic objectForKey:@"message"];
+
+    STAssertTrue([message isKindOfClass:[NSArray class]], nil);
+    STAssertTrue([testValues count] == [message count], nil);
+
+    for (NSInteger i = 0; i < [testValues count]; i++) {
+        STAssertTrue([[testValues objectAtIndex:i] isEqual:[message objectAtIndex:i]], nil);
+    }
+}
+
+- (void)__testDictionary:(NSDictionary*)dictA withDictionary:(NSDictionary*)dictB
+{
+    STAssertTrue([dictA isKindOfClass:[NSDictionary class]], nil);
+    STAssertTrue([dictB isKindOfClass:[NSDictionary class]], nil);
+
+    STAssertTrue([[dictA allKeys] count] == [[dictB allKeys] count], nil);
+
+    for (NSInteger i = 0; i < [dictA count]; i++) {
+        id keyA = [[dictA allKeys] objectAtIndex:i];
+        id objA = [dictA objectForKey:keyA];
+        id objB = [dictB objectForKey:keyA];
+
+        STAssertTrue([[dictB allKeys] containsObject:keyA], nil); // key exists
+        if ([objA isKindOfClass:[NSDictionary class]]) {
+            [self __testDictionary:objA withDictionary:objB];
+        } else {
+            STAssertTrue([objA isEqual:objB], nil); // key's value equality
+        }
+    }
+}
+
+- (void)testSerializingMessageAsDictionary
+{
+    NSMutableDictionary* testValues = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+        [NSNull null], @"nullItem",
+        @"string", @"stringItem",
+        [NSNumber numberWithInt:5], @"intItem",
+        [NSNumber numberWithDouble:5.5], @"doubleItem",
+        [NSNumber numberWithBool:true], @"boolItem",
+        nil];
+
+    NSDictionary* nestedDict = [testValues copy];
+
+    [testValues setValue:nestedDict forKey:@"nestedDict"];
+
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:testValues];
+    NSDictionary* dic = [[result toJSONString] JSONObject];
+    NSDictionary* message = [dic objectForKey:@"message"];
+
+    [self __testDictionary:testValues withDictionary:message];
+}
+
+- (void)testSerializingMessageAsErrorCode
+{
+    NSMutableDictionary* testValues = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+        [NSNumber numberWithInt:1], @"code",
+        nil];
+
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageToErrorObject:1];
+    NSDictionary* dic = [[result toJSONString] JSONObject];
+    NSDictionary* message = [dic objectForKey:@"message"];
+
+    [self __testDictionary:testValues withDictionary:message];
+}
+
+- (void)testSerializingMessageAsStringContainingQuotes
+{
+    NSString* quotedString = @"\"quoted\"";
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:quotedString];
+    NSDictionary* dic = [[result toJSONString] JSONObject];
+    NSString* message = [dic objectForKey:@"message"];
+
+    STAssertTrue([quotedString isEqual:message], nil);
+}
+
+- (void)testSerializingMessageAsStringThatIsNil
+{
+    NSString* nilString = nil;
+    CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:nilString];
+    NSDictionary* dic = [[result toJSONString] JSONObject];
+    NSString* message = [dic objectForKey:@"message"];
+
+    STAssertTrue([[NSNull null] isEqual:message], nil);
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CDVWebViewTest.h
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CDVWebViewTest.h b/lib/cordova-ios/CordovaLibTests/CDVWebViewTest.h
new file mode 100644
index 0000000..21d7203
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CDVWebViewTest.h
@@ -0,0 +1,43 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <SenTestingKit/SenTestingKit.h>
+#import <UIKit/UIKit.h>
+
+@class AppDelegate;
+@class CDVViewController;
+
+@interface CDVWebViewTest : SenTestCase
+
+@property (nonatomic, strong) UIWebView* webView;
+
+- (AppDelegate*)appDelegate;
+- (CDVViewController*)viewController;
+- (UIWebView*)webView;
+
+// Returns the already registered plugin object for the given class.
+- (id)pluginInstance:(NSString*)pluginName;
+// Destroys the existing webview and creates a new one.
+- (void)reloadWebView;
+// Runs the run loop until the given block returns true, or until a timeout
+// occurs.
+- (void)waitForConditionName:(NSString*)conditionName block:(BOOL (^)())block;
+// Convenience function for stringByEvaluatingJavaScriptFromString.
+- (NSString*)evalJs:(NSString*)code;
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CDVWebViewTest.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CDVWebViewTest.m b/lib/cordova-ios/CordovaLibTests/CDVWebViewTest.m
new file mode 100644
index 0000000..c0cb173
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CDVWebViewTest.m
@@ -0,0 +1,122 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVWebViewTest.h"
+
+#import "AppDelegate.h"
+#import "ViewController.h"
+
+@interface CDVWebViewTest ()
+// Runs the run loop until the webview has finished loading.
+- (void)waitForPageLoad;
+@end
+
+@implementation CDVWebViewTest
+
+@synthesize webView;
+
+- (void)setUp
+{
+    [super setUp];
+    // Stop tests on the first failed assertion. Having the test stop on the
+    // first exception makes it much easier to identify the source of the error.
+    // On iOS < 5 there is a bug in SenTestingKit where the exception is
+    // uncaught and the app crashes upon a failed STAssert (oh well).
+    [self raiseAfterFailure];
+}
+
+- (void)tearDown
+{
+    // Enforce that the view controller is released between tests to ensure
+    // tests don't affect each other.
+    [self.appDelegate destroyViewController];
+    [super tearDown];
+}
+
+- (AppDelegate*)appDelegate
+{
+    return [[UIApplication sharedApplication] delegate];
+}
+
+- (CDVViewController*)viewController
+{
+    // Lazily create the view controller so that tests that do not require it
+    // are not slowed down by it.
+    if (self.appDelegate.viewController == nil) {
+        [self.appDelegate createViewController];
+        // Things break if tearDown is called before the page has finished
+        // loading (a JS error happens and an alert pops up), so enforce a wait
+        // here.
+        [self waitForPageLoad];
+    }
+    STAssertNotNil(self.appDelegate.viewController, @"createViewController failed");
+    return self.appDelegate.viewController;
+}
+
+- (UIWebView*)webView
+{
+    return self.viewController.webView;
+}
+
+- (id)pluginInstance:(NSString*)pluginName
+{
+    id ret = [self.viewController getCommandInstance:pluginName];
+
+    STAssertNotNil(ret, @"Missing plugin %@", pluginName);
+    return ret;
+}
+
+- (void)reloadWebView
+{
+    [self.appDelegate destroyViewController];
+    [self.appDelegate createViewController];
+}
+
+- (void)waitForConditionName:(NSString*)conditionName block:(BOOL (^)())block
+{
+    // Number of seconds to wait for a condition to become true before giving up.
+    const NSTimeInterval kConditionTimeout = 5.0;
+    // Useful when debugging so that it does not timeout after one loop.
+    const int kMinIterations = 4;
+
+    NSDate* startTime = [NSDate date];
+    int i = 0;
+
+    while (!block()) {
+        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
+        NSTimeInterval elapsed = -[startTime timeIntervalSinceNow];
+        STAssertTrue(i < kMinIterations || elapsed < kConditionTimeout,
+            @"Timed out waiting for condition %@", conditionName);
+        ++i;
+    }
+}
+
+- (void)waitForPageLoad
+{
+    [self waitForConditionName:@"PageLoad" block:^{
+            return [@"true" isEqualToString:[self evalJs:@"window.pageIsLoaded"]];
+        }];
+}
+
+- (NSString*)evalJs:(NSString*)code
+{
+    return [self.webView stringByEvaluatingJavaScriptFromString:code];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CDVWhitelistTests.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CDVWhitelistTests.m b/lib/cordova-ios/CordovaLibTests/CDVWhitelistTests.m
new file mode 100644
index 0000000..172b62e
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CDVWhitelistTests.m
@@ -0,0 +1,277 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <SenTestingKit/SenTestingKit.h>
+
+#import "CDVWhitelist.h"
+
+@interface CDVWhitelistTests : SenTestCase
+@end
+
+@implementation CDVWhitelistTests
+
+- (void)setUp
+{
+    [super setUp];
+
+    // setup code here
+}
+
+- (void)tearDown
+{
+    // Tear-down code here.
+
+    [super tearDown];
+}
+
+- (void)testAllowedSchemes
+{
+    NSArray* allowedHosts = [NSArray arrayWithObjects:
+        @"*.apache.org",
+        nil];
+
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    STAssertTrue([whitelist schemeIsAllowed:@"http"], nil);
+    STAssertTrue([whitelist schemeIsAllowed:@"https"], nil);
+    STAssertTrue([whitelist schemeIsAllowed:@"ftp"], nil);
+    STAssertTrue([whitelist schemeIsAllowed:@"ftps"], nil);
+    STAssertFalse([whitelist schemeIsAllowed:@"gopher"], nil);
+}
+
+- (void)testSubdomainWildcard
+{
+    NSArray* allowedHosts = [NSArray arrayWithObjects:
+        @"*.apache.org",
+        nil];
+
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://build.apache.org"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://sub1.sub0.build.apache.org"]], nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org.ca"]], nil);
+}
+
+- (void)testWildcardInTLD
+{
+    // NOTE: if the user chooses to do this (a wildcard in the TLD, not a wildcard as the TLD), we allow it because we assume they know what they are doing! We don't replace it with known TLDs
+    // This might be applicable for custom TLDs on a local network DNS
+
+    NSArray* allowedHosts = [NSArray arrayWithObjects:
+        @"apache.o*g",
+        nil];
+
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.ogg"]], nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.foo"]], nil);
+}
+
+- (void)testTLDWildcard
+{
+    NSArray* allowedHosts = [NSArray arrayWithObjects:
+        @"apache.*",
+        nil];
+
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    NSString* hostname = @"apache";
+
+    NSArray* knownTLDs = [NSArray arrayWithObjects:
+        @"aero", @"asia", @"arpa", @"biz", @"cat",
+        @"com", @"coop", @"edu", @"gov", @"info",
+        @"int", @"jobs", @"mil", @"mobi", @"museum",
+        @"name", @"net", @"org", @"pro", @"tel",
+        @"travel", @"xxx",
+        nil];
+
+    // 26*26 combos
+    NSMutableArray* twoCharCountryCodes = [NSMutableArray arrayWithCapacity:(26 * 26)];
+
+    for (char c0 = 'a'; c0 <= 'z'; ++c0) {
+        for (char c1 = 'a'; c1 <= 'z'; ++c1) {
+            [twoCharCountryCodes addObject:[NSString stringWithFormat:@"%c%c", c0, c1]];
+        }
+    }
+
+    NSMutableArray* shouldPass = [NSMutableArray arrayWithCapacity:[knownTLDs count] + [twoCharCountryCodes count]];
+
+    NSEnumerator* knownTLDEnumerator = [knownTLDs objectEnumerator];
+    NSString* tld = nil;
+
+    while (tld = [knownTLDEnumerator nextObject]) {
+        [shouldPass addObject:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@.%@", hostname, tld]]];
+    }
+
+    NSEnumerator* twoCharCountryCodesEnumerator = [twoCharCountryCodes objectEnumerator];
+    NSString* cc = nil;
+
+    while (cc = [twoCharCountryCodesEnumerator nextObject]) {
+        [shouldPass addObject:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@.%@", hostname, cc]]];
+    }
+
+    NSEnumerator* shouldPassEnumerator = [shouldPass objectEnumerator];
+    NSURL* url = nil;
+
+    while (url = [shouldPassEnumerator nextObject]) {
+        STAssertTrue([whitelist URLIsAllowed:url], @"Url tested :%@", [url description]);
+    }
+
+    STAssertFalse(([whitelist URLIsAllowed:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@.%@", hostname, @"faketld"]]]), nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://unknownhostname.faketld"]], nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://unknownhostname.com"]], nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.apache.org"]], nil);
+}
+
+- (void)testCatchallWildcardOnly
+{
+    NSArray* allowedHosts = [NSArray arrayWithObjects:
+        @"*",
+        nil];
+
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://build.apache.prg"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://MyDangerousSite.org"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org.SuspiciousSite.com"]], nil);
+}
+
+- (void)testWildcardInHostname
+{
+    NSArray* allowedHosts = [NSArray arrayWithObjects:
+        @"www.*apac*he.org",
+        nil];
+
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.apache.org"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.apacMAChe.org"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.MACapache.org"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.MACapacMAChe.org"]], nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil);
+}
+
+- (void)testExactMatch
+{
+    NSArray* allowedHosts = [NSArray arrayWithObjects:
+        @"www.apache.org",
+        nil];
+
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.apache.org"]], nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://build.apache.org"]], nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil);
+}
+
+- (void)testNoMatchInQueryParam
+{
+    NSArray* allowedHosts = [NSArray arrayWithObjects:
+        @"www.apache.org",
+        nil];
+
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"www.malicious-site.org?url=http://www.apache.org"]], nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"www.malicious-site.org?url=www.apache.org"]], nil);
+}
+
+- (void)testWildcardMix
+{
+    NSArray* allowedHosts = [NSArray arrayWithObjects:
+        @"*.apac*he.*",
+        nil];
+
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://www.apache.org"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apacMAChe.ca"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apacMAChe.museum"]], nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://blahMAChe.museum"]], nil);
+}
+
+- (void)testIpExactMatch
+{
+    NSArray* allowedHosts = [NSArray arrayWithObjects:
+        @"192.168.1.1",
+        @"192.168.2.1",
+        nil];
+
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.1.1"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.2.1"]], nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.3.1"]], nil);
+}
+
+- (void)testIpWildcardMatch
+{
+    NSArray* allowedHosts = [NSArray arrayWithObjects:
+        @"192.168.1.*",
+        @"192.168.2.*",
+        nil];
+
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.1.1"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.1.2"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.2.1"]], nil);
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.2.2"]], nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://192.168.3.1"]], nil);
+}
+
+- (void)testHostnameExtraction
+{
+    NSArray* allowedHosts = [NSArray arrayWithObjects:
+        @"http://apache.org/",
+        @"http://apache.org/foo/bar?x=y",
+        @"ftp://apache.org/foo/bar?x=y",
+        @"ftps://apache.org/foo/bar?x=y",
+        @"http://apache.*/foo/bar?x=y",
+        nil];
+
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    STAssertTrue([whitelist URLIsAllowed:[NSURL URLWithString:@"http://apache.org"]], nil);
+    STAssertFalse([whitelist URLIsAllowed:[NSURL URLWithString:@"http://google.com"]], nil);
+}
+
+- (void)testWhitelistRejectionString
+{
+    NSArray* allowedHosts = [NSArray arrayWithObject:@"http://www.yahoo.com/"];  // Doesn't matter in this test.
+    CDVWhitelist* whitelist = [[CDVWhitelist alloc] initWithArray:allowedHosts];
+
+    NSURL* testUrl = [NSURL URLWithString:@"http://www/google.com"];
+    NSString* errorString = [whitelist errorStringForURL:testUrl];
+    NSString* expectedErrorString = [NSString stringWithFormat:kCDVDefaultWhitelistRejectionString, [testUrl absoluteString]];
+
+    STAssertTrue([expectedErrorString isEqualToString:errorString], @"Default error string has an unexpected value.");
+
+    whitelist.whitelistRejectionFormatString = @"Hey, '%@' is, like, bogus man!";
+    errorString = [whitelist errorStringForURL:testUrl];
+    expectedErrorString = [NSString stringWithFormat:whitelist.whitelistRejectionFormatString, [testUrl absoluteString]];
+    STAssertTrue([expectedErrorString isEqualToString:errorString], @"Customized whitelist rejection string has unexpected value.");
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CordovaLibApp/AppDelegate.h
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CordovaLibApp/AppDelegate.h b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/AppDelegate.h
new file mode 100644
index 0000000..d26fb8e
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/AppDelegate.h
@@ -0,0 +1,33 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class ViewController;
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow* window;
+
+@property (strong, nonatomic) ViewController* viewController;
+
+- (void)createViewController;
+- (void)destroyViewController;
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CordovaLibApp/AppDelegate.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CordovaLibApp/AppDelegate.m b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/AppDelegate.m
new file mode 100644
index 0000000..daee302
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/AppDelegate.m
@@ -0,0 +1,103 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "AppDelegate.h"
+
+#import "ViewController.h"
+
+@implementation AppDelegate
+
+@synthesize window = _window;
+@synthesize viewController = _viewController;
+
+- (id)init
+{
+    NSHTTPCookieStorage* cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
+
+    [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
+
+    self = [super init];
+    return self;
+}
+
+- (void)createViewController
+{
+    NSAssert(!self.viewController, @"ViewController already created.");
+
+    self.viewController = [[ViewController alloc] init];
+    self.viewController.useSplashScreen = YES;
+    self.viewController.wwwFolderName = @"www";
+    self.viewController.startPage = @"index.html";
+
+    // NOTE: To customize the view's frame size (which defaults to full screen), override
+    // [self.viewController viewWillAppear:] in your view controller.
+
+    self.window.rootViewController = self.viewController;
+}
+
+- (void)destroyViewController
+{
+    self.viewController = nil;
+}
+
+- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
+{
+    CGRect screenBounds = [[UIScreen mainScreen] bounds];
+
+    self.window = [[UIWindow alloc] initWithFrame:screenBounds];
+    self.window.autoresizesSubviews = YES;
+
+    // Create the main view on start-up only when not running unit tests.
+    if (!NSClassFromString(@"CDVWebViewTest")) {
+        [self createViewController];
+    }
+
+    [self.window makeKeyAndVisible];
+
+    return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication*)application
+{
+    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+}
+
+- (void)applicationDidEnterBackground:(UIApplication*)application
+{
+    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+}
+
+- (void)applicationWillEnterForeground:(UIApplication*)application
+{
+    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication*)application
+{
+    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+}
+
+- (void)applicationWillTerminate:(UIApplication*)application
+{
+    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CordovaLibApp/CordovaLibApp-Info.plist
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CordovaLibApp/CordovaLibApp-Info.plist b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/CordovaLibApp-Info.plist
new file mode 100644
index 0000000..6c21097
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/CordovaLibApp-Info.plist
@@ -0,0 +1,45 @@
+<?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.apache.cordova.cordovalibapptests.${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>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+</dict>
+</plist>

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CordovaLibApp/ViewController.h
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CordovaLibApp/ViewController.h b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/ViewController.h
new file mode 100644
index 0000000..befeaae
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/ViewController.h
@@ -0,0 +1,25 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <UIKit/UIKit.h>
+#import "CDVViewController.h"
+
+@interface ViewController : CDVViewController
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CordovaLibApp/ViewController.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CordovaLibApp/ViewController.m b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/ViewController.m
new file mode 100644
index 0000000..7de6791
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/ViewController.m
@@ -0,0 +1,53 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "ViewController.h"
+
+@interface ViewController ()
+
+@end
+
+@implementation ViewController
+
+- (void)viewWillAppear:(BOOL)animated
+{
+    // View defaults to full size.  If you want to customize the view's size, or its subviews (e.g. webView),
+    // you can do so here.
+
+    [super viewWillAppear:animated];
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    // Do any additional setup after loading the view, typically from a nib.
+}
+
+- (void)viewDidUnload
+{
+    [super viewDidUnload];
+    // Release any retained subviews of the main view.
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+    return [super shouldAutorotateToInterfaceOrientation:interfaceOrientation];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CordovaLibApp/config.xml
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CordovaLibApp/config.xml b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/config.xml
new file mode 100644
index 0000000..7b786fa
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/config.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<cordova>
+    <preference name="KeyboardDisplayRequiresUserAction" value="true" />
+    <preference name="SuppressesIncrementalRendering" value="false" />
+    <preference name="UIWebViewBounce" value="true" />
+    <preference name="TopActivityIndicator" value="gray" />
+    <preference name="EnableLocation" value="false" />
+    <preference name="EnableViewportScale" value="false" />
+    <preference name="AutoHideSplashScreen" value="true" />
+    <preference name="ShowSplashScreenSpinner" value="true" />
+    <preference name="MediaPlaybackRequiresUserAction" value="false" />
+    <preference name="AllowInlineMediaPlayback" value="false" />
+    <preference name="OpenAllWhitelistURLsInWebView" value="false" />
+    <preference name="BackupWebStorage" value="cloud" />
+
+    <plugins>
+        <plugin name="LocalStorage" value="CDVLocalStorage" />
+        <plugin name="Device" value="CDVDevice" />
+        <plugin name="Logger" value="CDVLogger" />
+        <plugin name="Compass" value="CDVLocation" />
+        <plugin name="Accelerometer" value="CDVAccelerometer" />
+        <plugin name="Camera" value="CDVCamera" />
+        <plugin name="NetworkStatus" value="CDVConnection" />
+        <plugin name="Contacts" value="CDVContacts" />
+        <plugin name="Debug Console" value="CDVDebugConsole" />
+        <plugin name="File" value="CDVFile" />
+        <plugin name="FileTransfer" value="CDVFileTransfer" />
+        <plugin name="Geolocation" value="CDVLocation" />
+        <plugin name="Notification" value="CDVNotification" />
+        <plugin name="Media" value="CDVSound" />
+        <plugin name="Capture" value="CDVCapture" />
+        <plugin name="SplashScreen" value="CDVSplashScreen" />
+        <plugin name="Echo" value="CDVEcho" />
+        <plugin name="Battery" value="CDVBattery" />
+        <plugin name="Globalization" value="CDVGlobalization" />
+        <plugin name="InAppBrowser" value="CDVInAppBrowser" />
+    </plugins>
+</cordova>

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CordovaLibApp/en.lproj/InfoPlist.strings
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CordovaLibApp/en.lproj/InfoPlist.strings b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/en.lproj/InfoPlist.strings
new file mode 100644
index 0000000..01d5c8c
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/en.lproj/InfoPlist.strings
@@ -0,0 +1,20 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+ 
+ http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+/* Localized versions of Info.plist keys */
+

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CordovaLibApp/main.m
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CordovaLibApp/main.m b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/main.m
new file mode 100644
index 0000000..120ac53
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/main.m
@@ -0,0 +1,29 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "AppDelegate.h"
+
+int main(int argc, char* argv[])
+{
+    @autoreleasepool {
+        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CordovaLibApp/www/index.html
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CordovaLibApp/www/index.html b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/www/index.html
new file mode 100644
index 0000000..1cac0a4
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CordovaLibApp/www/index.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html>
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+-->
+  <head>
+  <title></title>
+  
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" />
+	<meta charset="utf-8">
+
+
+	<!-- iPad/iPhone specific css below, add after your main css >
+	<link rel="stylesheet" media="only screen and (max-device-width: 1024px)" href="ipad.css" type="text/css" />		
+	<link rel="stylesheet" media="only screen and (max-device-width: 480px)" href="iphone.css" type="text/css" />		
+	-->
+	<!-- If your application is targeting iOS BEFORE 4.0 you MUST put json2.js from http://www.JSON.org/json2.js into your www directory and include it here -->
+	<script type="text/javascript" charset="utf-8" src="cordova.ios.js"></script>
+    <script type="text/javascript">
+
+
+	// If you want to prevent dragging, uncomment this section
+	/*
+	function preventBehavior(e) 
+	{ 
+      e.preventDefault(); 
+    };
+	document.addEventListener("touchmove", preventBehavior, false);
+	*/
+	
+	/* If you are supporting your own protocol, the var invokeString will contain any arguments to the app launch.
+	see http://iphonedevelopertips.com/cocoa/launching-your-own-application-via-a-custom-url-scheme.html
+	for more details -jm */
+	/*
+	function handleOpenURL(url)
+	{
+		// TODO: do something with the url passed in.
+	}
+	*/
+	
+	function onBodyLoad()
+	{		
+		document.addEventListener("deviceready", onDeviceReady, false);
+	}
+	
+	/* When this function is called, Cordova has been initialized and is ready to roll */
+	/* If you are supporting your own protocol, the var invokeString will contain any arguments to the app launch.
+	see http://iphonedevelopertips.com/cocoa/launching-your-own-application-via-a-custom-url-scheme.html
+	for more details -jm */
+	function onDeviceReady()
+	{
+    // Used by unit tests to tell when the page is loaded.
+    window.pageIsLoaded = true;
+		// do your thing!
+		navigator.notification.alert("Cordova is working")        
+	}
+    
+    </script>
+  </head>
+  <body onload="onBodyLoad()">
+	<h1>Hey, it's Cordova!</h1>
+	<ol>
+		<li>Check your console log for any white-list rejection errors.</li>
+		<li>Add your allowed <strong>hosts</strong> in config.xml as access tags and set the origin attribute. (wildcards OK, don't enter the URL scheme)</li>
+	</ol>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-ios/CordovaLibTests/CordovaLibTests-Info.plist
----------------------------------------------------------------------
diff --git a/lib/cordova-ios/CordovaLibTests/CordovaLibTests-Info.plist b/lib/cordova-ios/CordovaLibTests/CordovaLibTests-Info.plist
new file mode 100644
index 0000000..a57a78d
--- /dev/null
+++ b/lib/cordova-ios/CordovaLibTests/CordovaLibTests-Info.plist
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+-->
+<!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>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.apache.cordova.${PRODUCT_NAME:rfc1034identifier}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>