You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by sg...@apache.org on 2015/09/20 14:18:02 UTC

[03/10] cordova-lib git commit: CB-9598 Adds tests and fixtures based on existing cordova-lib ones

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/css/index.css
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/css/index.css b/cordova-common/spec/fixtures/projects/windows8/www/css/index.css
new file mode 100644
index 0000000..51daa79
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/windows8/www/css/index.css
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+* {
+    -webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */
+}
+
+body {
+    -webkit-touch-callout: none;                /* prevent callout to copy image, etc when tap to hold */
+    -webkit-text-size-adjust: none;             /* prevent webkit from resizing text to fit */
+    -webkit-user-select: none;                  /* prevent copy paste, to allow, change 'none' to 'text' */
+    background-color:#E4E4E4;
+    background-image:linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
+    background-image:-webkit-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
+    background-image:-ms-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%);
+    background-image:-webkit-gradient(
+        linear,
+        left top,
+        left bottom,
+        color-stop(0, #A7A7A7),
+        color-stop(0.51, #E4E4E4)
+    );
+    background-attachment:fixed;
+    font-family:'HelveticaNeue-Light', 'HelveticaNeue', Helvetica, Arial, sans-serif;
+    font-size:12px;
+    height:100%;
+    margin:0px;
+    padding:0px;
+    text-transform:uppercase;
+    width:100%;
+}
+
+/* Portrait layout (default) */
+.app {
+    background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */
+    position:absolute;             /* position in the center of the screen */
+    left:50%;
+    top:50%;
+    height:50px;                   /* text area height */
+    width:225px;                   /* text area width */
+    text-align:center;
+    padding:180px 0px 0px 0px;     /* image height is 200px (bottom 20px are overlapped with text) */
+    margin:-115px 0px 0px -112px;  /* offset vertical: half of image height and text area height */
+                                   /* offset horizontal: half of text area width */
+}
+
+/* Landscape layout (with min-width) */
+@media screen and (min-aspect-ratio: 1/1) and (min-width:400px) {
+    .app {
+        background-position:left center;
+        padding:75px 0px 75px 170px;  /* padding-top + padding-bottom + text area = image height */
+        margin:-90px 0px 0px -198px;  /* offset vertical: half of image height */
+                                      /* offset horizontal: half of image width and text area width */
+    }
+}
+
+h1 {
+    font-size:24px;
+    font-weight:normal;
+    margin:0px;
+    overflow:visible;
+    padding:0px;
+    text-align:center;
+}
+
+.event {
+    border-radius:4px;
+    -webkit-border-radius:4px;
+    color:#FFFFFF;
+    font-size:12px;
+    margin:0px 30px;
+    padding:2px 0px;
+}
+
+.event.listening {
+    background-color:#333333;
+    display:block;
+}
+
+.event.received {
+    background-color:#4B946A;
+    display:none;
+}
+
+@keyframes fade {
+    from { opacity: 1.0; }
+    50% { opacity: 0.4; }
+    to { opacity: 1.0; }
+}
+ 
+@-webkit-keyframes fade {
+    from { opacity: 1.0; }
+    50% { opacity: 0.4; }
+    to { opacity: 1.0; }
+}
+ 
+.blink {
+    animation:fade 3000ms infinite;
+    -webkit-animation:fade 3000ms infinite;
+}

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/img/logo.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/img/logo.png b/cordova-common/spec/fixtures/projects/windows8/www/img/logo.png
new file mode 100644
index 0000000..86a48a8
Binary files /dev/null and b/cordova-common/spec/fixtures/projects/windows8/www/img/logo.png differ

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/img/smalllogo.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/img/smalllogo.png b/cordova-common/spec/fixtures/projects/windows8/www/img/smalllogo.png
new file mode 100644
index 0000000..0e648ef
Binary files /dev/null and b/cordova-common/spec/fixtures/projects/windows8/www/img/smalllogo.png differ

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/img/splashscreen.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/img/splashscreen.png b/cordova-common/spec/fixtures/projects/windows8/www/img/splashscreen.png
new file mode 100644
index 0000000..d1e6c98
Binary files /dev/null and b/cordova-common/spec/fixtures/projects/windows8/www/img/splashscreen.png differ

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/img/storelogo.png
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/img/storelogo.png b/cordova-common/spec/fixtures/projects/windows8/www/img/storelogo.png
new file mode 100644
index 0000000..dd00478
Binary files /dev/null and b/cordova-common/spec/fixtures/projects/windows8/www/img/storelogo.png differ

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/index.html
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/index.html b/cordova-common/spec/fixtures/projects/windows8/www/index.html
new file mode 100644
index 0000000..ca8ab84
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/windows8/www/index.html
@@ -0,0 +1,42 @@
+<!DOCTYPE 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.
+-->
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+        <meta name="format-detection" content="telephone=no" />
+        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
+        <link rel="stylesheet" type="text/css" href="css/index.css" />
+        <title>Hello World</title>
+    </head>
+    <body>
+        <div class="app">
+            <h1>Apache Cordova</h1>
+            <div id="deviceready" class="blink">
+                <p class="event listening">Connecting to Device</p>
+                <p class="event received">Device is Ready</p>
+            </div>
+        </div>
+        <script type="text/javascript" src="cordova-2.6.0.js"></script>
+        <script type="text/javascript" src="js/index.js"></script>
+        <script type="text/javascript">
+            app.initialize();
+        </script>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/projects/windows8/www/js/index.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/projects/windows8/www/js/index.js b/cordova-common/spec/fixtures/projects/windows8/www/js/index.js
new file mode 100644
index 0000000..87b5660
--- /dev/null
+++ b/cordova-common/spec/fixtures/projects/windows8/www/js/index.js
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+var app = {
+    // Application Constructor
+    initialize: function() {
+        this.bindEvents();
+    },
+    // Bind Event Listeners
+    //
+    // Bind any events that are required on startup. Common events are:
+    // 'load', 'deviceready', 'offline', and 'online'.
+    bindEvents: function() {
+        document.addEventListener('deviceready', this.onDeviceReady, false);
+    },
+    // deviceready Event Handler
+    //
+    // The scope of 'this' is the event. In order to call the 'receivedEvent'
+    // function, we must explicitly call 'app.receivedEvent(...);'
+    onDeviceReady: function() {
+        app.receivedEvent('deviceready');
+    },
+    // Update DOM on a Received Event
+    receivedEvent: function(id) {
+        var parentElement = document.getElementById(id);
+        var listeningElement = parentElement.querySelector('.listening');
+        var receivedElement = parentElement.querySelector('.received');
+
+        listeningElement.setAttribute('style', 'display:none;');
+        receivedElement.setAttribute('style', 'display:block;');
+
+        console.log('Received Event: ' + id);
+    }
+};

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/fixtures/test-config.xml
----------------------------------------------------------------------
diff --git a/cordova-common/spec/fixtures/test-config.xml b/cordova-common/spec/fixtures/test-config.xml
new file mode 100644
index 0000000..ac22580
--- /dev/null
+++ b/cordova-common/spec/fixtures/test-config.xml
@@ -0,0 +1,43 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget android-packageName="io.cordova.hellocordova.android" id="io.cordova.hellocordova" ios-CFBundleIdentifier="io.cordova.hellocordova.ios" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+    <name>Hello Cordova</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+    <preference name="fullscreen" value="true" />
+    <preference name="webviewbounce" value="true" />
+    <preference name="orientation" value="portrait" />
+    <icon id="icon" src="icon.png" />
+    <icon height="255" id="logo" src="logo.png" width="255" />
+    <platform name="android">
+        <icon density="mdpi" height="255" src="logo-android.png" width="255" />
+        <preference name="android-minSdkVersion" value="10" />
+        <preference name="orientation" value="landscape" />
+    </platform>
+    <plugin name="org.apache.cordova.pluginwithvars">
+        <variable name="var" value="varvalue" />
+    </plugin>
+    <plugin name="org.apache.cordova.pluginwithurl" src="http://cordova.apache.org/pluginwithurl" />
+    <plugin name="org.apache.cordova.pluginwithversion" version="1.1.1" />
+    <plugin name="org.apache.cordova.pluginwithurlandversion" src="http://cordova.apache.org/pluginwithurlandversion" version="1.1.1" />
+    <plugin name="org.apache.cordova.justaplugin" />
+    <feature name="Legacy plugin entry with version">
+        <param name="id" value="org.apache.cordova.legacyfeatureversion" />
+        <param name="version" value="1.2.3" />
+        <param name="aVar" value="aValue" />
+    </feature>
+    <feature name="Legacy plugin entry with url">
+        <param name="id" value="org.apache.cordova.legacyfeatureurl" />
+        <param name="url" value="http://cordova.apache.org/legacyfeatureurl" />
+    </feature>
+    <feature name="Legacy plugin entry with version and url">
+        <param name="id" value="org.apache.cordova.legacyfeatureversionandurl" />
+        <param name="version" value="1.2.3" />
+        <param name="url" value="http://cordova.apache.org/legacyfeatureversionandurl" />
+    </feature>
+</widget>

http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/59042bae/cordova-common/spec/util/xml-helpers.spec.js
----------------------------------------------------------------------
diff --git a/cordova-common/spec/util/xml-helpers.spec.js b/cordova-common/spec/util/xml-helpers.spec.js
new file mode 100644
index 0000000..8cc46ca
--- /dev/null
+++ b/cordova-common/spec/util/xml-helpers.spec.js
@@ -0,0 +1,271 @@
+/**
+    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.
+*/
+
+/* jshint laxcomma: true, multistr: true */
+
+var path = require('path')
+  , xml_helpers = require('../../src/util/xml-helpers')
+  , et = require('elementtree')
+
+  , title = et.XML('<title>HELLO</title>')
+  , usesNetworkOne = et.XML('<uses-permission ' +
+            'android:name="PACKAGE_NAME.permission.C2D_MESSAGE"/>')
+  , usesNetworkTwo = et.XML('<uses-permission android:name=\
+            "PACKAGE_NAME.permission.C2D_MESSAGE" />')
+  , usesReceive = et.XML('<uses-permission android:name=\
+            "com.google.android.c2dm.permission.RECEIVE"/>')
+  , helloTagOne = et.XML('<h1>HELLO</h1>')
+  , goodbyeTag = et.XML('<h1>GOODBYE</h1>')
+  , helloTagTwo = et.XML('<h1>  HELLO  </h1>');
+
+var TEST_XML = '<?xml version="1.0" encoding="UTF-8"?>\n' +
+    '<widget xmlns     = "http://www.w3.org/ns/widgets"\n' +
+    '        xmlns:cdv = "http://cordova.apache.org/ns/1.0"\n' +
+    '        id        = "io.cordova.hellocordova"\n' +
+    '        version   = "0.0.1">\n' +
+    '    <name>Hello Cordova</name>\n' +
+    '    <description>\n' +
+    '        A sample Apache Cordova application that responds to the deviceready event.\n' +
+    '    </description>\n' +
+    '    <author href="http://cordova.io" email="dev@cordova.apache.org">\n' +
+    '        Apache Cordova Team\n' +
+    '    </author>\n' +
+    '    <content src="index.html" />\n' +
+    '    <access origin="*" />\n' +
+    '    <preference name="fullscreen" value="true" />\n' +
+    '    <preference name="webviewbounce" value="true" />\n' +
+    '</widget>\n';
+
+describe('xml-helpers', function(){
+    describe('parseElementtreeSync', function() {
+        it('should parse xml with a byte order mark', function() {
+            var xml_path = path.join(__dirname, '../fixtures/projects/windows/bom_test.xml');
+            expect(function() {
+                xml_helpers.parseElementtreeSync(xml_path);
+            }).not.toThrow();
+        });
+    });
+    describe('equalNodes', function() {
+        it('should return false for different tags', function(){
+            expect(xml_helpers.equalNodes(usesNetworkOne, title)).toBe(false);
+        });
+
+        it('should return true for identical tags', function(){
+            expect(xml_helpers.equalNodes(usesNetworkOne, usesNetworkTwo)).toBe(true);
+        });
+
+        it('should return false for different attributes', function(){
+            expect(xml_helpers.equalNodes(usesNetworkOne, usesReceive)).toBe(false);
+        });
+
+        it('should distinguish between text', function(){
+            expect(xml_helpers.equalNodes(helloTagOne, goodbyeTag)).toBe(false);
+        });
+
+        it('should ignore whitespace in text', function(){
+            expect(xml_helpers.equalNodes(helloTagOne, helloTagTwo)).toBe(true);
+        });
+
+        describe('should compare children', function(){
+            it('by child quantity', function(){
+                var one = et.XML('<i><b>o</b></i>'),
+                    two = et.XML('<i><b>o</b><u></u></i>');
+
+                expect(xml_helpers.equalNodes(one, two)).toBe(false);
+            });
+
+            it('by child equality', function(){
+                var one = et.XML('<i><b>o</b></i>'),
+                    two = et.XML('<i><u></u></i>'),
+                    uno = et.XML('<i>\n<b>o</b>\n</i>');
+
+                expect(xml_helpers.equalNodes(one, uno)).toBe(true);
+                expect(xml_helpers.equalNodes(one, two)).toBe(false);
+            });
+        });
+    });
+    describe('pruneXML', function() {
+        var config_xml;
+
+        beforeEach(function() {
+            config_xml = xml_helpers.parseElementtreeSync(path.join(__dirname, '../fixtures/projects/android/res/xml/config.xml'));
+        });
+
+        it('should remove any children that match the specified selector', function() {
+            var children = config_xml.findall('plugins/plugin');
+            xml_helpers.pruneXML(config_xml, children, 'plugins');
+            expect(config_xml.find('plugins').getchildren().length).toEqual(0);
+        });
+        it('should do nothing if the children cannot be found', function() {
+            var children = [title];
+            xml_helpers.pruneXML(config_xml, children, 'plugins');
+            expect(config_xml.find('plugins').getchildren().length).toEqual(17);
+        });
+        it('should be able to handle absolute selectors', function() {
+            var children = config_xml.findall('plugins/plugin');
+            xml_helpers.pruneXML(config_xml, children, '/cordova/plugins');
+            expect(config_xml.find('plugins').getchildren().length).toEqual(0);
+        });
+        it('should be able to handle absolute selectors with wildcards', function() {
+            var children = config_xml.findall('plugins/plugin');
+            xml_helpers.pruneXML(config_xml, children, '/*/plugins');
+            expect(config_xml.find('plugins').getchildren().length).toEqual(0);
+        });
+    });
+
+    describe('graftXML', function() {
+        var config_xml, plugin_xml;
+
+        beforeEach(function() {
+            config_xml = xml_helpers.parseElementtreeSync(path.join(__dirname, '../fixtures/projects/android/res/xml/config.xml'));
+            plugin_xml = xml_helpers.parseElementtreeSync(path.join(__dirname, '../fixtures/plugins/ChildBrowser/plugin.xml'));
+        });
+
+        it('should add children to the specified selector', function() {
+            var children = plugin_xml.find('config-file').getchildren();
+            xml_helpers.graftXML(config_xml, children, 'plugins');
+            expect(config_xml.find('plugins').getchildren().length).toEqual(19);
+        });
+        it('should be able to handle absolute selectors', function() {
+            var children = plugin_xml.find('config-file').getchildren();
+            xml_helpers.graftXML(config_xml, children, '/cordova');
+            expect(config_xml.findall('access').length).toEqual(3);
+        });
+        it('should be able to handle absolute selectors with wildcards', function() {
+            var children = plugin_xml.find('config-file').getchildren();
+            xml_helpers.graftXML(config_xml, children, '/*');
+            expect(config_xml.findall('access').length).toEqual(3);
+        });
+    });
+
+    describe('mergeXml', function () {
+        var dstXml;
+        beforeEach(function() {
+            dstXml = et.XML(TEST_XML);
+        });
+        it('should merge attributes and text of the root element without clobbering', function () {
+            var testXml = et.XML('<widget foo="bar" id="NOTANID">TEXT</widget>');
+            xml_helpers.mergeXml(testXml, dstXml);
+            expect(dstXml.attrib.foo).toEqual('bar');
+            expect(dstXml.attrib.id).not.toEqual('NOTANID');
+            expect(dstXml.text).not.toEqual('TEXT');
+        });
+
+        it('should merge attributes and text of the root element with clobbering', function () {
+            var testXml = et.XML('<widget foo="bar" id="NOTANID">TEXT</widget>');
+            xml_helpers.mergeXml(testXml, dstXml, 'foo', true);
+            expect(dstXml.attrib.foo).toEqual('bar');
+            expect(dstXml.attrib.id).toEqual('NOTANID');
+            expect(dstXml.text).toEqual('TEXT');
+        });
+
+        it('should not merge platform tags with the wrong platform', function () {
+            var testXml = et.XML('<widget><platform name="bar"><testElement testAttrib="value">testTEXT</testElement></platform></widget>'),
+                origCfg = et.tostring(dstXml);
+
+            xml_helpers.mergeXml(testXml, dstXml, 'foo', true);
+            expect(et.tostring(dstXml)).toEqual(origCfg);
+        });
+
+        it('should merge platform tags with the correct platform', function () {
+            var testXml = et.XML('<widget><platform name="bar"><testElement testAttrib="value">testTEXT</testElement></platform></widget>'),
+                origCfg = et.tostring(dstXml);
+
+            xml_helpers.mergeXml(testXml, dstXml, 'bar', true);
+            expect(et.tostring(dstXml)).not.toEqual(origCfg);
+            var testElement = dstXml.find('testElement');
+            expect(testElement).toBeDefined();
+            expect(testElement.attrib.testAttrib).toEqual('value');
+            expect(testElement.text).toEqual('testTEXT');
+        });
+
+        it('should merge singelton children without clobber', function () {
+            var testXml = et.XML('<widget><author testAttrib="value" href="http://www.nowhere.com">SUPER_AUTHOR</author></widget>');
+
+            xml_helpers.mergeXml(testXml, dstXml);
+            var testElements = dstXml.findall('author');
+            expect(testElements).toBeDefined();
+            expect(testElements.length).toEqual(1);
+            expect(testElements[0].attrib.testAttrib).toEqual('value');
+            expect(testElements[0].attrib.href).toEqual('http://cordova.io');
+            expect(testElements[0].attrib.email).toEqual('dev@cordova.apache.org');
+            expect(testElements[0].text).toContain('Apache Cordova Team');
+        });
+
+        it('should clobber singelton children with clobber', function () {
+            var testXml = et.XML('<widget><author testAttrib="value" href="http://www.nowhere.com">SUPER_AUTHOR</author></widget>');
+
+            xml_helpers.mergeXml(testXml, dstXml, '', true);
+            var testElements = dstXml.findall('author');
+            expect(testElements).toBeDefined();
+            expect(testElements.length).toEqual(1);
+            expect(testElements[0].attrib.testAttrib).toEqual('value');
+            expect(testElements[0].attrib.href).toEqual('http://www.nowhere.com');
+            expect(testElements[0].attrib.email).toEqual('dev@cordova.apache.org');
+            expect(testElements[0].text).toEqual('SUPER_AUTHOR');
+        });
+
+        it('should append non singelton children', function () {
+            var testXml = et.XML('<widget><preference num="1"/> <preference num="2"/></widget>');
+
+            xml_helpers.mergeXml(testXml, dstXml, '', true);
+            var testElements = dstXml.findall('preference');
+            expect(testElements.length).toEqual(4);
+        });
+
+        it('should handle namespaced elements', function () {
+            var testXml = et.XML('<widget><foo:bar testAttrib="value">testText</foo:bar></widget>');
+
+            xml_helpers.mergeXml(testXml, dstXml, 'foo', true);
+            var testElement = dstXml.find('foo:bar');
+            expect(testElement).toBeDefined();
+            expect(testElement.attrib.testAttrib).toEqual('value');
+            expect(testElement.text).toEqual('testText');
+        });
+
+        it('should not append duplicate non singelton children', function () {
+            var testXml = et.XML('<widget><preference name="fullscreen" value="true"/></widget>');
+
+            xml_helpers.mergeXml(testXml, dstXml, '', true);
+            var testElements = dstXml.findall('preference');
+            expect(testElements.length).toEqual(2);
+        });
+
+        it('should not skip partial duplicate non singelton children', function () {
+            //remove access tags from dstXML
+            var testElements = dstXml.findall('access');
+            for(var i = 0; i < testElements.length; i++) {
+                dstXml.remove(testElements[i]);
+            }
+            testElements = dstXml.findall('access');
+            expect(testElements.length).toEqual(0);
+            //add an external whitelist access tag
+            var testXml = et.XML('<widget><access origin="*" launch-external="yes"/></widget>');
+            xml_helpers.mergeXml(testXml, dstXml, '', true);
+            testElements = dstXml.findall('access');
+            expect(testElements.length).toEqual(1);
+            //add an internal whitelist access tag
+            testXml = et.XML('<widget><access origin="*"/></widget>');
+            xml_helpers.mergeXml(testXml, dstXml, '', true);
+            testElements = dstXml.findall('access');
+            expect(testElements.length).toEqual(2);
+
+        });
+    });
+});


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org