You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ka...@apache.org on 2014/05/01 20:32:12 UTC
[27/53] [abbrv] Split out cordova-lib: move cordova-plugman files
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/projects/windows8/www/css/index.css
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/windows8/www/css/index.css b/cordova-lib/spec-plugman/projects/windows8/www/css/index.css
new file mode 100644
index 0000000..51daa79
--- /dev/null
+++ b/cordova-lib/spec-plugman/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/0318d8cd/cordova-lib/spec-plugman/projects/windows8/www/img/logo.png
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/windows8/www/img/logo.png b/cordova-lib/spec-plugman/projects/windows8/www/img/logo.png
new file mode 100644
index 0000000..86a48a8
Binary files /dev/null and b/cordova-lib/spec-plugman/projects/windows8/www/img/logo.png differ
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/projects/windows8/www/img/smalllogo.png
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/windows8/www/img/smalllogo.png b/cordova-lib/spec-plugman/projects/windows8/www/img/smalllogo.png
new file mode 100644
index 0000000..0e648ef
Binary files /dev/null and b/cordova-lib/spec-plugman/projects/windows8/www/img/smalllogo.png differ
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/projects/windows8/www/img/splashscreen.png
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/windows8/www/img/splashscreen.png b/cordova-lib/spec-plugman/projects/windows8/www/img/splashscreen.png
new file mode 100644
index 0000000..d1e6c98
Binary files /dev/null and b/cordova-lib/spec-plugman/projects/windows8/www/img/splashscreen.png differ
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/projects/windows8/www/img/storelogo.png
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/windows8/www/img/storelogo.png b/cordova-lib/spec-plugman/projects/windows8/www/img/storelogo.png
new file mode 100644
index 0000000..dd00478
Binary files /dev/null and b/cordova-lib/spec-plugman/projects/windows8/www/img/storelogo.png differ
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/projects/windows8/www/index.html
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/windows8/www/index.html b/cordova-lib/spec-plugman/projects/windows8/www/index.html
new file mode 100644
index 0000000..ca8ab84
--- /dev/null
+++ b/cordova-lib/spec-plugman/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/0318d8cd/cordova-lib/spec-plugman/projects/windows8/www/js/index.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/windows8/www/js/index.js b/cordova-lib/spec-plugman/projects/windows8/www/js/index.js
new file mode 100644
index 0000000..87b5660
--- /dev/null
+++ b/cordova-lib/spec-plugman/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/0318d8cd/cordova-lib/spec-plugman/projects/wp7/CordovaAppProj.csproj
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/wp7/CordovaAppProj.csproj b/cordova-lib/spec-plugman/projects/wp7/CordovaAppProj.csproj
new file mode 100644
index 0000000..4b122a2
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/wp7/CordovaAppProj.csproj
@@ -0,0 +1,76 @@
+<?xml version='1.0' encoding='utf-8'?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>10.0.20506</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{3677C1B7-D68B-4CF9-BF8A-E869D437A6DF}</ProjectGuid>
+ <ProjectTypeGuids>{C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>$safeprojectname$</RootNamespace>
+ <AssemblyName>$safeprojectname$</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
+ <TargetFrameworkProfile>WindowsPhone71</TargetFrameworkProfile>
+ <TargetFrameworkIdentifier>Silverlight</TargetFrameworkIdentifier>
+ <SilverlightApplication>true</SilverlightApplication>
+ <SupportedCultures>
+ </SupportedCultures>
+ <XapOutputs>true</XapOutputs>
+ <GenerateSilverlightManifest>true</GenerateSilverlightManifest>
+ <XapFilename>$safeprojectname$.xap</XapFilename>
+ <SilverlightManifestTemplate>Properties\AppManifest.xml</SilverlightManifestTemplate>
+ <SilverlightAppEntry>$safeprojectname$.App</SilverlightAppEntry>
+ <ValidateXaml>true</ValidateXaml>
+ <ThrowErrorsInValidation>true</ThrowErrorsInValidation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>Bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>Bin\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Microsoft.Devices.Sensors" />
+ <Reference Include="Microsoft.Phone" />
+ <Reference Include="Microsoft.Phone.Interop" />
+ <Reference Include="Microsoft.Xna.Framework" />
+ <Reference Include="System.Device" />
+ <Reference Include="System.Runtime.Serialization" />
+ <Reference Include="System.Servicemodel.Web" />
+ <Reference Include="System.Windows" />
+ <Reference Include="system" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Net" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Xml.Linq" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.$(TargetFrameworkProfile).Overrides.targets" />
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.CSharp.targets" />
+ <ProjectExtensions />
+ <PropertyGroup>
+ <PreBuildEvent>CScript "$(ProjectDir)/BuildManifestProcessor.js" "$(ProjectPath)"</PreBuildEvent>
+ </PropertyGroup>
+ <PropertyGroup>
+ <PostBuildEvent>
+ </PostBuildEvent>
+ </PropertyGroup>
+ <ItemGroup />
+</Project>
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/projects/wp7/Properties/WMAppManifest.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/wp7/Properties/WMAppManifest.xml b/cordova-lib/spec-plugman/projects/wp7/Properties/WMAppManifest.xml
new file mode 100644
index 0000000..b218fcb
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/wp7/Properties/WMAppManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2009/deployment" AppPlatformVersion="7.1">
+ <App xmlns="" ProductID="{5FC10D78-8779-4EDB-9B61-1D04F0A755D4}" Title="An App"
+ RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal"
+ Author="An App author"
+ BitsPerPixel="32"
+ Description="Apache Cordova for Windows Phone 7"
+ Publisher="An App">
+
+ <IconPath IsRelative="true" IsResource="false">ApplicationIcon.png</IconPath>
+ <Capabilities>
+ <Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />
+ </Capabilities>
+
+ <Tasks>
+ <DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
+ </Tasks>
+ <Tokens>
+ <PrimaryToken TokenID="An AppToken" TaskName="_default">
+ <TemplateType5>
+ <BackgroundImageURI IsRelative="true" IsResource="false">Background.png</BackgroundImageURI>
+ <Count>0</Count>
+ <Title>An App</Title>
+ </TemplateType5>
+ </PrimaryToken>
+ </Tokens>
+ </App>
+</Deployment>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/projects/wp8/CordovaAppProj.csproj
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/wp8/CordovaAppProj.csproj b/cordova-lib/spec-plugman/projects/wp8/CordovaAppProj.csproj
new file mode 100644
index 0000000..bc229e5
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/wp8/CordovaAppProj.csproj
@@ -0,0 +1,136 @@
+<?xml version='1.0' encoding='utf-8'?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>10.0.20506</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{3677C1B7-D68B-4CF9-BF8A-E869D437A6DF}</ProjectGuid>
+ <ProjectTypeGuids>{C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>my.test.project</RootNamespace>
+ <AssemblyName>my.test.project</AssemblyName>
+ <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
+ <SilverlightVersion>
+ </SilverlightVersion>
+ <TargetFrameworkProfile>
+ </TargetFrameworkProfile>
+ <TargetFrameworkIdentifier>WindowsPhone</TargetFrameworkIdentifier>
+ <SilverlightApplication>true</SilverlightApplication>
+ <SupportedCultures>en-US</SupportedCultures>
+ <XapOutputs>true</XapOutputs>
+ <GenerateSilverlightManifest>true</GenerateSilverlightManifest>
+ <XapFilename>CordovaAppProj_$(Configuration)_$(Platform).xap</XapFilename>
+ <SilverlightManifestTemplate>Properties\AppManifest.xml</SilverlightManifestTemplate>
+ <SilverlightAppEntry>my.test.project.App</SilverlightAppEntry>
+ <ValidateXaml>true</ValidateXaml>
+ <ThrowErrorsInValidation>true</ThrowErrorsInValidation>
+ <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+ <BackgroundAgentType />
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>Bin\Debug</OutputPath>
+ <DefineConstants>TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE;WP8</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Prefer32Bit>false</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>Bin\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE;WP8</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <NoConfig>true</NoConfig>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Prefer32Bit>false</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>Bin\x86\Debug</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>full</DebugType>
+ <PlatformTarget>
+ </PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+ <OutputPath>Bin\x86\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>
+ </PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>false</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>Bin\ARM\Debug</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>full</DebugType>
+ <PlatformTarget>
+ </PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>false</Prefer32Bit>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+ <OutputPath>Bin\ARM\Release</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT;WINDOWS_PHONE</DefineConstants>
+ <Optimize>true</Optimize>
+ <NoStdLib>true</NoStdLib>
+ <DebugType>pdbonly</DebugType>
+ <PlatformTarget>
+ </PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+ <Prefer32Bit>false</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="App.xaml.cs">
+ <DependentUpon>App.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="MainPage.xaml.cs">
+ <DependentUpon>MainPage.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Page Include="src\UI\PageTest.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Plugins\org.apache.cordova.core.InAppBrowser\InAppBrowser.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="src\UI\PageTest.xaml.cs">
+ <DependentUpon>PageTest.xaml</DependentUpon>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="LibraryTest">
+ <HintPath>lib\LibraryTest.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="src\FileTest.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="src\Content.img" />
+ </ItemGroup>
+</Project>
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/projects/wp8/Properties/WMAppManifest.xml
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/wp8/Properties/WMAppManifest.xml b/cordova-lib/spec-plugman/projects/wp8/Properties/WMAppManifest.xml
new file mode 100644
index 0000000..5b37a95
--- /dev/null
+++ b/cordova-lib/spec-plugman/projects/wp8/Properties/WMAppManifest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2012/deployment" AppPlatformVersion="8.0">
+ <DefaultLanguage xmlns="" code="en-US" />
+ <Languages xmlns="">
+ <Language code="en-US" />
+ </Languages>
+ <App xmlns="" ProductID="{F3A8197B-6B16-456D-B5F4-DD4F04AC0BEC}" Title="An App" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal" Author="An App author" BitsPerPixel="32" Description="Apache Cordova for Windows Phone" Publisher="An App" PublisherID="{db093ed5-53b1-45f7-af72-751e8f36ab80}">
+ <IconPath IsRelative="true" IsResource="false">ApplicationIcon.png</IconPath>
+ <Capabilities>
+ <Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />
+ </Capabilities>
+ <Tasks>
+ <DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
+ </Tasks>
+ <Tokens>
+ <PrimaryToken TokenID="An AppToken" TaskName="_default">
+ <TemplateFlip>
+ <SmallImageURI IsResource="false" IsRelative="true">Background.png</SmallImageURI>
+ <Count>0</Count>
+ <BackgroundImageURI IsResource="false" IsRelative="true">Background.png</BackgroundImageURI>
+ <Title>An App</Title>
+ <BackContent></BackContent>
+ <BackBackgroundImageURI></BackBackgroundImageURI>
+ <BackTitle></BackTitle>
+ <LargeBackgroundImageURI></LargeBackgroundImageURI>
+ <LargeBackContent></LargeBackContent>
+ <LargeBackBackgroundImageURI></LargeBackBackgroundImageURI>
+ <DeviceLockImageURI></DeviceLockImageURI>
+ <HasLarge>false</HasLarge>
+ </TemplateFlip>
+ </PrimaryToken>
+ </Tokens>
+ <ScreenResolutions>
+ <ScreenResolution Name="ID_RESOLUTION_WVGA" />
+ <ScreenResolution Name="ID_RESOLUTION_WXGA" />
+ <ScreenResolution Name="ID_RESOLUTION_HD720P" />
+ </ScreenResolutions>
+ </App>
+</Deployment>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/projects/www-only/.gitkeep
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/projects/www-only/.gitkeep b/cordova-lib/spec-plugman/projects/www-only/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/publish.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/publish.spec.js b/cordova-lib/spec-plugman/publish.spec.js
new file mode 100644
index 0000000..3498bd6
--- /dev/null
+++ b/cordova-lib/spec-plugman/publish.spec.js
@@ -0,0 +1,11 @@
+var publish = require('../src/publish'),
+ Q = require('q'),
+ registry = require('../src/registry/registry');
+
+describe('publish', function() {
+ it('should publish a plugin', function() {
+ var sPublish = spyOn(registry, 'publish').andReturn(Q(['/path/to/my/plugin']));
+ publish(new Array('/path/to/myplugin'));
+ expect(sPublish).toHaveBeenCalledWith(['/path/to/myplugin']);
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/registry/registry.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/registry/registry.spec.js b/cordova-lib/spec-plugman/registry/registry.spec.js
new file mode 100644
index 0000000..7615ee6
--- /dev/null
+++ b/cordova-lib/spec-plugman/registry/registry.spec.js
@@ -0,0 +1,134 @@
+var registry = require('../../src/registry/registry'),
+ manifest = require('../../src/registry/manifest'),
+ fs = require('fs'),
+ path = require('path'),
+ Q = require('q'),
+ shell = require('shelljs'),
+ os = require('os'),
+ npm = require('npm');
+
+describe('registry', function() {
+ var done;
+ beforeEach(function() {
+ done = false;
+ });
+ function registryPromise(shouldSucceed, f) {
+ waitsFor(function() { return done; }, 'promise never resolved', 500);
+ return f.then(function() {
+ done = true;
+ expect(shouldSucceed).toBe(true);
+ }, function(err) {
+ done = err;
+ expect(shouldSucceed).toBe(false);
+ });
+ }
+
+ describe('manifest', function() {
+ var pluginDir, packageJson, tmp_plugin, tmp_plugin_xml, tmp_package_json;
+ beforeEach(function() {
+ pluginDir = __dirname + '/../plugins/EnginePlugin';
+ tmp_plugin = path.join(os.tmpdir(), 'plugin');
+ tmp_plugin_xml = path.join(tmp_plugin, 'plugin.xml');
+ tmp_package_json = path.join(tmp_plugin, 'package.json');
+ shell.cp('-R', pluginDir+"/*", tmp_plugin);
+ });
+ afterEach(function() {
+ shell.rm('-rf', tmp_plugin);
+ });
+ it('should generate a package.json from a plugin.xml', function() {
+ registryPromise(true, manifest.generatePackageJsonFromPluginXml(tmp_plugin).then(function() {
+ expect(fs.existsSync(tmp_package_json));
+ var packageJson = JSON.parse(fs.readFileSync(tmp_package_json));
+ expect(packageJson.name).toEqual('com.cordova.engine');
+ expect(packageJson.version).toEqual('1.0.0');
+ expect(packageJson.engines).toEqual(
+ [ { name : 'cordova', version : '>=2.3.0' }, { name : 'cordova-plugman', version : '>=0.10.0' }, { name : 'mega-fun-plugin', version : '>=1.0.0' }, { name : 'mega-boring-plugin', version : '>=3.0.0' } ]);
+ }));
+ });
+ it('should raise an error if name does not follow com.domain.* format', function() {
+ var xmlData = fs.readFileSync(tmp_plugin_xml).toString().replace('id="com.cordova.engine"', 'id="engine"');
+ fs.writeFileSync(tmp_plugin_xml, xmlData);
+ registryPromise(false, manifest.generatePackageJsonFromPluginXml(tmp_plugin));
+ });
+ it('should generate a package.json if name uses org.apache.cordova.* for a whitelisted plugin', function() {
+ var xmlData = fs.readFileSync(tmp_plugin_xml).toString().replace('id="com.cordova.engine"', 'id="org.apache.cordova.camera"');
+ fs.writeFileSync(tmp_plugin_xml, xmlData);
+ registryPromise(true, manifest.generatePackageJsonFromPluginXml(tmp_plugin).then(function() {
+ expect(!fs.existsSync(tmp_package_json));
+ }));
+ });
+ it('should raise an error if name uses org.apache.cordova.* for a non-whitelisted plugin', function() {
+ var xmlData = fs.readFileSync(tmp_plugin_xml).toString().replace('id="com.cordova.engine"', 'id="org.apache.cordova.myinvalidplugin"');
+ fs.writeFileSync(tmp_plugin_xml, xmlData);
+ registryPromise(false, manifest.generatePackageJsonFromPluginXml(tmp_plugin));
+ });
+ });
+ describe('actions', function() {
+ var fakeLoad, fakeNPMCommands;
+
+ beforeEach(function() {
+ done = false;
+ var fakeSettings = {
+ cache: '/some/cache/dir',
+ logstream: 'somelogstream@2313213',
+ userconfig: '/some/config/dir'
+ };
+
+ var fakeNPM = function() {
+ if (arguments.length > 0) {
+ var cb = arguments[arguments.length-1];
+ if (cb && typeof cb === 'function') cb(null, true);
+ }
+ };
+
+ registry.settings = fakeSettings;
+ fakeLoad = spyOn(npm, 'load').andCallFake(function(settings, cb) { cb(null, true); });
+
+ fakeNPMCommands = {};
+ ['config', 'adduser', 'cache', 'publish', 'unpublish', 'search'].forEach(function(cmd) {
+ fakeNPMCommands[cmd] = jasmine.createSpy(cmd).andCallFake(fakeNPM);
+ });
+
+ npm.commands = fakeNPMCommands;
+ });
+ it('should run config', function() {
+ var params = ['set', 'registry', 'http://registry.cordova.io'];
+ registryPromise(true, registry.config(params).then(function() {
+ expect(fakeLoad).toHaveBeenCalledWith(registry.settings, jasmine.any(Function));
+ expect(fakeNPMCommands.config).toHaveBeenCalledWith(params, jasmine.any(Function));
+ }));
+ });
+ it('should run adduser', function() {
+ registryPromise(true, registry.adduser(null).then(function() {
+ expect(fakeLoad).toHaveBeenCalledWith(registry.settings, jasmine.any(Function));
+ expect(fakeNPMCommands.adduser).toHaveBeenCalledWith(null, jasmine.any(Function));
+ }));
+ });
+ it('should run publish', function() {
+ var params = [__dirname + '/../plugins/DummyPlugin'];
+ var spyGenerate = spyOn(manifest, 'generatePackageJsonFromPluginXml').andReturn(Q());
+ var spyUnlink = spyOn(fs, 'unlink');
+ registryPromise(true, registry.publish(params).then(function() {
+ expect(fakeLoad).toHaveBeenCalledWith(registry.settings, jasmine.any(Function));
+ expect(spyGenerate).toHaveBeenCalledWith(params[0]);
+ expect(fakeNPMCommands.publish).toHaveBeenCalledWith(params, jasmine.any(Function));
+ expect(spyUnlink).toHaveBeenCalledWith(path.resolve(params[0], 'package.json'));
+ }));
+ });
+ it('should run unpublish', function() {
+ var params = ['dummyplugin@0.6.0'];
+ registryPromise(true, registry.unpublish(params).then(function() {
+ expect(fakeLoad).toHaveBeenCalledWith(registry.settings, jasmine.any(Function));
+ expect(fakeNPMCommands.unpublish).toHaveBeenCalledWith(params, jasmine.any(Function));
+ expect(fakeNPMCommands.cache).toHaveBeenCalledWith(['clean'], jasmine.any(Function));
+ }));
+ });
+ it('should run search', function() {
+ var params = ['dummyplugin', 'plugin'];
+ registryPromise(true, registry.search(params).then(function() {
+ expect(fakeLoad).toHaveBeenCalledWith(registry.settings, jasmine.any(Function));
+ expect(fakeNPMCommands.search).toHaveBeenCalledWith(params, true, jasmine.any(Function));
+ }));
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/search.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/search.spec.js b/cordova-lib/spec-plugman/search.spec.js
new file mode 100644
index 0000000..4955d2d
--- /dev/null
+++ b/cordova-lib/spec-plugman/search.spec.js
@@ -0,0 +1,11 @@
+var search = require('../src/search'),
+ Q = require('q'),
+ registry = require('../src/registry/registry');
+
+describe('search', function() {
+ it('should search a plugin', function() {
+ var sSearch = spyOn(registry, 'search').andReturn(Q());
+ search(new Array('myplugin', 'keyword'));
+ expect(sSearch).toHaveBeenCalledWith(['myplugin', 'keyword']);
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/uninstall.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/uninstall.spec.js b/cordova-lib/spec-plugman/uninstall.spec.js
new file mode 100644
index 0000000..a8c2b97
--- /dev/null
+++ b/cordova-lib/spec-plugman/uninstall.spec.js
@@ -0,0 +1,289 @@
+var uninstall = require('../src/uninstall'),
+ install = require('../src/install'),
+ actions = require('../src/util/action-stack'),
+ config_changes = require('../src/util/config-changes'),
+ events = require('../src/events'),
+ plugman = require('../plugman'),
+ common = require('./common'),
+ fs = require('fs'),
+ path = require('path'),
+ shell = require('shelljs'),
+ Q = require('q'),
+ spec = __dirname,
+ done = false,
+ srcProject = path.join(spec, 'projects', 'android_uninstall'),
+ project = path.join(spec, 'projects', 'android_uninstall.test'),
+ project2 = path.join(spec, 'projects', 'android_uninstall.test2'),
+
+ plugins_dir = path.join(spec, 'plugins'),
+ plugins_install_dir = path.join(project, 'cordova', 'plugins'),
+ plugins_install_dir2 = path.join(project2, 'cordova', 'plugins'),
+
+ plugins = {
+ 'DummyPlugin' : path.join(plugins_dir, 'DummyPlugin'),
+ 'A' : path.join(plugins_dir, 'dependencies', 'A'),
+ 'C' : path.join(plugins_dir, 'dependencies', 'C')
+ },
+ promise,
+ dummy_id = 'com.phonegap.plugins.dummyplugin';
+
+function uninstallPromise(f) {
+ return f.then(function() { done = true; }, function(err) { done = err; });
+}
+
+describe('start', function() {
+
+ it('start', function() {
+ shell.rm('-rf', project);
+ shell.rm('-rf', project2);
+ shell.cp('-R', path.join(srcProject, '*'), project);
+ shell.cp('-R', path.join(srcProject, '*'), project2);
+
+ done = false;
+ promise = Q()
+ .then(
+ function(){ return install('android', project, plugins['DummyPlugin']) }
+ ).then(
+ function(){ return install('android', project, plugins['A']) }
+ ).then(
+ function(){ return install('android', project2, plugins['C']) }
+ ).then(
+ function(){ return install('android', project2, plugins['A']) }
+ ).then(
+ function(){ done = true; }
+ );
+ waitsFor(function() { return done; }, 'promise never resolved', 500);
+ });
+});
+
+describe('uninstallPlatform', function() {
+ var proc, prepare, actions_push, add_to_queue, c_a, rm;
+ var fsWrite;
+
+ var plat_common = require('../src/platforms/common');
+
+ beforeEach(function() {
+ proc = spyOn(actions.prototype, 'process').andReturn(Q());
+ actions_push = spyOn(actions.prototype, 'push');
+ c_a = spyOn(actions.prototype, 'createAction');
+ prepare = spyOn(plugman, 'prepare');
+ fsWrite = spyOn(fs, 'writeFileSync').andReturn(true);
+ rm = spyOn(shell, 'rm').andReturn(true);
+ spyOn(shell, 'cp').andReturn(true);
+ add_to_queue = spyOn(config_changes, 'add_uninstalled_plugin_to_prepare_queue');
+ done = false;
+ });
+ describe('success', function() {
+ it('should call prepare after a successful uninstall', function() {
+ runs(function() {
+ uninstallPromise(uninstall.uninstallPlatform('android', project, dummy_id));
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ expect(prepare).toHaveBeenCalled();
+ });
+ });
+ it('should call the config-changes module\'s add_uninstalled_plugin_to_prepare_queue method after processing an install', function() {
+ runs(function() {
+ uninstallPromise(uninstall.uninstallPlatform('android', project, dummy_id));
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ expect(add_to_queue).toHaveBeenCalledWith(plugins_install_dir, dummy_id, 'android', true);
+ });
+ });
+ it('should queue up actions as appropriate for that plugin and call process on the action stack', function() {
+ runs(function() {
+ uninstallPromise(uninstall.uninstallPlatform('android', project, dummy_id));
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ expect(actions_push.calls.length).toEqual(5);
+ expect(proc).toHaveBeenCalled();
+ });
+ });
+
+ describe('with dependencies', function() {
+ var emit;
+ beforeEach(function() {
+ emit = spyOn(events, 'emit');
+ });
+ it('should uninstall "dangling" dependencies', function() {
+ runs(function() {
+ uninstallPromise(uninstall.uninstallPlatform('android', project, 'A'));
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ expect(emit).toHaveBeenCalledWith('log', 'Uninstalling 2 dependent plugins.');
+ });
+ });
+ });
+ });
+
+ describe('failure', function() {
+ it('should throw if platform is unrecognized', function() {
+ runs(function() {
+ uninstallPromise( uninstall.uninstallPlatform('atari', project, 'SomePlugin') );
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ expect(''+done).toContain('atari not supported.');
+ });
+ });
+ it('should throw if plugin is missing', function() {
+ runs(function() {
+ uninstallPromise( uninstall.uninstallPlatform('android', project, 'SomePluginThatDoesntExist') );
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ expect(''+done).toContain('Plugin "SomePluginThatDoesntExist" not found. Already uninstalled?');
+ });
+ });
+ });
+});
+
+describe('uninstallPlugin', function() {
+ var rm, fsWrite, rmstack = [], emit;
+
+ beforeEach(function() {
+ fsWrite = spyOn(fs, 'writeFileSync').andReturn(true);
+ rm = spyOn(shell, 'rm').andCallFake(function(f,p) { rmstack.push(p); return true});
+ rmstack = [];
+ emit = spyOn(events, 'emit');
+ done = false;
+ });
+ describe('with dependencies', function() {
+
+ it('should delete all dependent plugins', function() {
+ runs(function() {
+ uninstallPromise( uninstall.uninstallPlugin('A', plugins_install_dir) );
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ var del = common.spy.getDeleted(emit);
+
+ expect(del).toEqual([
+ 'Deleted "C"',
+ 'Deleted "D"',
+ 'Deleted "A"'
+ ]);
+ });
+ });
+
+ it("should fail if plugin is a required dependency", function() {
+ runs(function() {
+ uninstallPromise( uninstall.uninstallPlugin('C', plugins_install_dir) );
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ expect(done.message).toBe('"C" is required by (A) and cannot be removed (hint: use -f or --force)');
+ });
+ });
+
+ it("allow forcefully removing a plugin", function() {
+ runs(function() {
+ uninstallPromise( uninstall.uninstallPlugin('C', plugins_install_dir, {force: true}) );
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ expect(done).toBe(true);
+ var del = common.spy.getDeleted(emit);
+ expect(del).toEqual(['Deleted "C"']);
+ });
+ });
+
+ it("never remove top level plugins if they are a dependency", function() {
+ runs(function() {
+ uninstallPromise( uninstall.uninstallPlugin('A', plugins_install_dir2) );
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ var del = common.spy.getDeleted(emit);
+
+ expect(del).toEqual([
+ 'Deleted "D"',
+ 'Deleted "A"'
+ ]);
+ });
+ });
+ });
+});
+
+describe('uninstall', function() {
+ var fsWrite, rm, add_to_queue;
+
+ beforeEach(function() {
+ fsWrite = spyOn(fs, 'writeFileSync').andReturn(true);
+ rm = spyOn(shell, 'rm').andReturn(true);
+ add_to_queue = spyOn(config_changes, 'add_uninstalled_plugin_to_prepare_queue');
+ done = false;
+ });
+ describe('success', function() {
+ it('should call the config-changes module\'s add_uninstalled_plugin_to_prepare_queue method after processing an install', function() {
+ runs(function() {
+ uninstallPromise( uninstall('android', project, plugins['DummyPlugin']) );
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ expect(add_to_queue).toHaveBeenCalledWith(plugins_install_dir, dummy_id, 'android', true);
+ });
+ });
+ });
+
+ describe('failure', function() {
+ it('should throw if platform is unrecognized', function() {
+ runs(function() {
+ uninstallPromise(uninstall('atari', project, 'SomePlugin'));
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ expect(''+done).toContain('atari not supported.');
+ });
+ });
+ it('should throw if plugin is missing', function() {
+ runs(function() {
+ uninstallPromise(uninstall('android', project, 'SomePluginThatDoesntExist'));
+ });
+ waitsFor(function() { return done; }, 'promise never resolved', 200);
+ runs(function() {
+ expect(''+done).toContain('Plugin "SomePluginThatDoesntExist" not found. Already uninstalled?');
+ });
+ });
+ });
+});
+
+describe('end', function() {
+
+ it('end', function() {
+ done = false;
+
+ promise.then(
+ function(){
+ return uninstall('android', project, plugins['DummyPlugin'])
+ }
+ ).then(
+ function(){
+ // Fails... A depends on
+ return uninstall('android', project, plugins['C'])
+ }
+ ).fail(
+ function(err) {
+ expect(err.message).toBe("The plugin 'C' is required by (A), skipping uninstallation.");
+ }
+ ).then(
+ function(){
+ // dependencies on C,D ... should this only work with --recursive? prompt user..?
+ return uninstall('android', project, plugins['A'])
+ }
+ ).fin(function(err){
+ if(err)
+ plugman.emit('error', err);
+
+ shell.rm('-rf', project);
+ shell.rm('-rf', project2);
+ done = true;
+ });
+
+ waitsFor(function() { return done; }, 'promise never resolved', 500);
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/unpublish.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/unpublish.spec.js b/cordova-lib/spec-plugman/unpublish.spec.js
new file mode 100644
index 0000000..944f640
--- /dev/null
+++ b/cordova-lib/spec-plugman/unpublish.spec.js
@@ -0,0 +1,11 @@
+var unpublish = require('../src/unpublish'),
+ Q = require('q'),
+ registry = require('../src/registry/registry');
+
+describe('unpublish', function() {
+ it('should unpublish a plugin', function() {
+ var sUnpublish = spyOn(registry, 'unpublish').andReturn(Q());
+ unpublish(new Array('myplugin@0.0.1'));
+ expect(sUnpublish).toHaveBeenCalledWith(['myplugin@0.0.1']);
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/util/action-stack.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/util/action-stack.spec.js b/cordova-lib/spec-plugman/util/action-stack.spec.js
new file mode 100644
index 0000000..3aa732f
--- /dev/null
+++ b/cordova-lib/spec-plugman/util/action-stack.spec.js
@@ -0,0 +1,58 @@
+var action_stack = require('../../src/util/action-stack'),
+ ios = require('../../src/platforms/ios');
+
+describe('action-stack', function() {
+ var stack;
+ beforeEach(function() {
+ stack = new action_stack();
+ });
+ describe('processing of actions', function() {
+ it('should process actions one at a time until all are done', function() {
+ var first_spy = jasmine.createSpy();
+ var first_args = [1];
+ var second_spy = jasmine.createSpy();
+ var second_args = [2];
+ var third_spy = jasmine.createSpy();
+ var third_args = [3];
+ stack.push(stack.createAction(first_spy, first_args, function(){}, []));
+ stack.push(stack.createAction(second_spy, second_args, function(){}, []));
+ stack.push(stack.createAction(third_spy, third_args, function(){}, []));
+ stack.process('android', 'blah');
+ expect(first_spy).toHaveBeenCalledWith(first_args[0]);
+ expect(second_spy).toHaveBeenCalledWith(second_args[0]);
+ expect(third_spy).toHaveBeenCalledWith(third_args[0]);
+ });
+ it('should revert processed actions if an exception occurs', function() {
+ spyOn(console, 'log');
+ var first_spy = jasmine.createSpy();
+ var first_args = [1];
+ var first_reverter = jasmine.createSpy();
+ var first_reverter_args = [true];
+ var process_err = new Error('process_err');
+ var second_spy = jasmine.createSpy().andCallFake(function() {
+ throw process_err;
+ });
+ var second_args = [2];
+ var third_spy = jasmine.createSpy();
+ var third_args = [3];
+ stack.push(stack.createAction(first_spy, first_args, first_reverter, first_reverter_args));
+ stack.push(stack.createAction(second_spy, second_args, function(){}, []));
+ stack.push(stack.createAction(third_spy, third_args, function(){}, []));
+ // process should throw
+ var error;
+ runs(function() {
+ stack.process('android', 'blah').fail(function(err) { error = err; });
+ });
+ waitsFor(function(){ return error; }, 'process promise never resolved', 500);
+ runs(function() {
+ expect(error).toEqual(process_err);
+ // first two actions should have been called, but not the third
+ expect(first_spy).toHaveBeenCalledWith(first_args[0]);
+ expect(second_spy).toHaveBeenCalledWith(second_args[0]);
+ expect(third_spy).not.toHaveBeenCalledWith(third_args[0]);
+ // first reverter should have been called after second action exploded
+ expect(first_reverter).toHaveBeenCalledWith(first_reverter_args[0]);
+ });
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/util/config-changes.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/util/config-changes.spec.js b/cordova-lib/spec-plugman/util/config-changes.spec.js
new file mode 100644
index 0000000..9d93d72
--- /dev/null
+++ b/cordova-lib/spec-plugman/util/config-changes.spec.js
@@ -0,0 +1,449 @@
+/* jshint node:true, sub:true, indent:4 */
+/* global jasmine, describe, beforeEach, afterEach, it, spyOn, expect */
+
+var configChanges = require('../../src/util/config-changes'),
+ xml_helpers = require('../../src/util/xml-helpers'),
+ ios_parser = require('../../src/platforms/ios'),
+ fs = require('fs'),
+ os = require('osenv'),
+ plugman = require('../../plugman'),
+ events = require('../../src/events'),
+ et = require('elementtree'),
+ path = require('path'),
+ plist = require('plist-with-patches'),
+ shell = require('shelljs'),
+ xcode = require('xcode'),
+ temp = path.join(os.tmpdir(), 'plugman'),
+ dummyplugin = path.join(__dirname, '..', 'plugins', 'DummyPlugin'),
+ cbplugin = path.join(__dirname, '..', 'plugins', 'ChildBrowser'),
+ childrenplugin = path.join(__dirname, '..', 'plugins', 'multiple-children'),
+ shareddepsplugin = path.join(__dirname, '..', 'plugins', 'shared-deps-multi-child'),
+ configplugin = path.join(__dirname, '..', 'plugins', 'ConfigTestPlugin'),
+ varplugin = path.join(__dirname, '..', 'plugins', 'VariablePlugin'),
+ android_two_project = path.join(__dirname, '..', 'projects', 'android_two', '*'),
+ android_two_no_perms_project = path.join(__dirname, '..', 'projects', 'android_two_no_perms', '*'),
+ ios_plist_project = path.join(__dirname, '..', 'projects', 'ios-plist', '*'),
+ ios_config_xml = path.join(__dirname, '..', 'projects', 'ios-config-xml', '*'),
+ plugins_dir = path.join(temp, 'cordova', 'plugins');
+
+// TODO: dont do fs so much
+
+var dummy_xml = new et.ElementTree(et.XML(fs.readFileSync(path.join(dummyplugin, 'plugin.xml'), 'utf-8')));
+
+function innerXML(xmltext) {
+ return xmltext.replace(/^<[\w\s\-=\/"\.]+>/, '').replace(/<\/[\w\s\-=\/"\.]+>$/,'');
+}
+
+describe('config-changes module', function() {
+ beforeEach(function() {
+ shell.mkdir('-p', temp);
+ shell.mkdir('-p', plugins_dir);
+ });
+ afterEach(function() {
+ shell.rm('-rf', temp);
+ ios_parser.purgeProjectFileCache(temp);
+ });
+
+ describe('queue methods', function() {
+ describe('add_installed_plugin_to_prepare_queue', function() {
+ it('should call get_platform_json method', function() {
+ var spy = spyOn(configChanges, 'get_platform_json').andReturn({
+ prepare_queue:{
+ installed:[],
+ uninstalled:[]
+ }
+ });
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'PooPlugin', 'android', {});
+ expect(spy).toHaveBeenCalledWith(plugins_dir, 'android');
+ });
+ it('should append specified plugin to platform.json', function() {
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'PooPlugin', 'android', {});
+ var json = configChanges.get_platform_json(plugins_dir, 'android');
+ expect(json.prepare_queue.installed[0].plugin).toEqual('PooPlugin');
+ expect(json.prepare_queue.installed[0].vars).toEqual({});
+ });
+ it('should append specified plugin with any variables to platform.json', function() {
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'PooPlugin', 'android', {'dude':'man'});
+ var json = configChanges.get_platform_json(plugins_dir, 'android');
+ expect(json.prepare_queue.installed[0].plugin).toEqual('PooPlugin');
+ expect(json.prepare_queue.installed[0].vars).toEqual({'dude':'man'});
+ });
+ it('should call save_platform_json with updated config', function() {
+ var spy = spyOn(configChanges, 'save_platform_json');
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'PooPlugin', 'android', {});
+ var config = spy.mostRecentCall.args[0];
+ expect(config.prepare_queue.installed[0].plugin).toEqual('PooPlugin');
+ });
+ });
+
+ describe('add_uninstalled_plugin_to_prepare_queue', function() {
+ beforeEach(function() {
+ shell.cp('-rf', dummyplugin, plugins_dir);
+ });
+
+ it('should call get_platform_json method', function() {
+ var spy = spyOn(configChanges, 'get_platform_json').andReturn({
+ prepare_queue:{
+ installed:[],
+ uninstalled:[]
+ }
+ });
+ configChanges.add_uninstalled_plugin_to_prepare_queue(plugins_dir, 'DummyPlugin', 'android');
+ expect(spy).toHaveBeenCalledWith(plugins_dir, 'android');
+ });
+ it('should append specified plugin to platform.json', function() {
+ configChanges.add_uninstalled_plugin_to_prepare_queue(plugins_dir, 'DummyPlugin', 'android');
+ var json = configChanges.get_platform_json(plugins_dir, 'android');
+ expect(json.prepare_queue.uninstalled[0].plugin).toEqual('DummyPlugin');
+ expect(json.prepare_queue.uninstalled[0].id).toEqual('com.phonegap.plugins.dummyplugin');
+ });
+ it('should call save_platform_json with updated config', function() {
+ var spy = spyOn(configChanges, 'save_platform_json');
+ configChanges.add_uninstalled_plugin_to_prepare_queue(plugins_dir, 'DummyPlugin', 'android', {});
+ var config = spy.mostRecentCall.args[0];
+ expect(config.prepare_queue.uninstalled[0].plugin).toEqual('DummyPlugin');
+ expect(config.prepare_queue.uninstalled[0].id).toEqual('com.phonegap.plugins.dummyplugin');
+ });
+ });
+ });
+
+ describe('get_platform_json method', function() {
+ it('should return an empty config json object if file doesn\'t exist', function() {
+ var filepath = path.join(plugins_dir, 'android.json');
+ var cfg = configChanges.get_platform_json(plugins_dir, 'android');
+ expect(cfg).toBeDefined();
+ expect(cfg.prepare_queue).toBeDefined();
+ expect(cfg.config_munge).toBeDefined();
+ expect(cfg.installed_plugins).toBeDefined();
+ });
+ it('should return the json file if it exists', function() {
+ var filepath = path.join(plugins_dir, 'android.json');
+ var json = {
+ prepare_queue: {installed: [], uninstalled: []},
+ config_munge: {files: {"some_file": {parents: {"some_parent": [{"xml": "some_change", "count": 1}]}}}},
+ installed_plugins: {}};
+ fs.writeFileSync(filepath, JSON.stringify(json), 'utf-8');
+ var cfg = configChanges.get_platform_json(plugins_dir, 'android');
+ expect(JSON.stringify(json)).toEqual(JSON.stringify(cfg));
+ });
+ });
+
+ describe('save_platform_json method', function() {
+ it('should write out specified json', function() {
+ var filepath = path.join(plugins_dir, 'android.json');
+ var cfg = {poop:true};
+ configChanges.save_platform_json(cfg, plugins_dir, 'android');
+ expect(fs.existsSync(filepath)).toBe(true);
+ expect(JSON.parse(fs.readFileSync(filepath, 'utf-8'))).toEqual(cfg);
+ });
+ });
+
+ describe('generate_plugin_config_munge method', function() {
+ describe('for android projects', function() {
+ beforeEach(function() {
+ shell.cp('-rf', android_two_project, temp);
+ });
+ it('should return a flat config hierarchy for simple, one-off config changes', function() {
+ var xml;
+ var munger = new configChanges.PlatformMunger('android', temp, 'unused');
+ var munge = munger.generate_plugin_config_munge(dummyplugin, {});
+ expect(munge.files['AndroidManifest.xml']).toBeDefined();
+ expect(munge.files['AndroidManifest.xml'].parents['/manifest/application']).toBeDefined();
+ xml = (new et.ElementTree(dummy_xml.find('./platform[@name="android"]/config-file[@target="AndroidManifest.xml"]'))).write({xml_declaration:false});
+ xml = innerXML(xml);
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest/application', xml).count).toEqual(1);
+ expect(munge.files['res/xml/plugins.xml']).toBeDefined();
+ expect(munge.files['res/xml/plugins.xml'].parents['/plugins']).toBeDefined();
+ xml = (new et.ElementTree(dummy_xml.find('./platform[@name="android"]/config-file[@target="res/xml/plugins.xml"]'))).write({xml_declaration:false});
+ xml = innerXML(xml);
+ expect(configChanges.get_munge_change(munge, 'res/xml/plugins.xml', '/plugins', xml).count).toEqual(1);
+ expect(munge.files['res/xml/config.xml']).toBeDefined();
+ expect(munge.files['res/xml/config.xml'].parents['/cordova/plugins']).toBeDefined();
+ xml = (new et.ElementTree(dummy_xml.find('./platform[@name="android"]/config-file[@target="res/xml/config.xml"]'))).write({xml_declaration:false});
+ xml = innerXML(xml);
+ expect(configChanges.get_munge_change(munge, 'res/xml/config.xml', '/cordova/plugins', xml).count).toEqual(1);
+ });
+ it('should split out multiple children of config-file elements into individual leaves', function() {
+ var munger = new configChanges.PlatformMunger('android', temp, 'unused');
+ var munge = munger.generate_plugin_config_munge(childrenplugin, {});
+ expect(munge.files['AndroidManifest.xml']).toBeDefined();
+ expect(munge.files['AndroidManifest.xml'].parents['/manifest']).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />')).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />')).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.READ_PHONE_STATE" />')).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.INTERNET" />')).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.GET_ACCOUNTS" />')).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="android.permission.WAKE_LOCK" />')).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<permission android:name="com.alunny.childapp.permission.C2D_MESSAGE" android:protectionLevel="signature" />')).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="com.alunny.childapp.permission.C2D_MESSAGE" />')).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />')).toBeDefined();
+ });
+ it('should not use xml comments as config munge leaves', function() {
+ var munger = new configChanges.PlatformMunger('android', temp, 'unused');
+ var munge = munger.generate_plugin_config_munge(childrenplugin, {});
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<!--library-->')).not.toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<!-- GCM connects to Google Services. -->')).not.toBeDefined();
+ });
+ it('should increment config hierarchy leaves if different config-file elements target the same file + selector + xml', function() {
+ var munger = new configChanges.PlatformMunger('android', temp, 'unused');
+ var munge = munger.generate_plugin_config_munge(configplugin, {});
+ expect(configChanges.get_munge_change(munge, 'res/xml/config.xml', '/widget', '<poop />').count).toEqual(2);
+ });
+ it('should take into account interpolation variables', function() {
+ var munger = new configChanges.PlatformMunger('android', temp, 'unused');
+ var munge = munger.generate_plugin_config_munge(childrenplugin, {PACKAGE_NAME:'ca.filmaj.plugins'});
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', '<uses-permission android:name="ca.filmaj.plugins.permission.C2D_MESSAGE" />')).toBeDefined();
+ });
+ it('should create munges for platform-agnostic config.xml changes', function() {
+ var munger = new configChanges.PlatformMunger('android', temp, 'unused');
+ var munge = munger.generate_plugin_config_munge(dummyplugin, {});
+ expect(configChanges.get_munge_change(munge, 'config.xml', '/*', '<access origin="build.phonegap.com" />')).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'config.xml', '/*', '<access origin="s3.amazonaws.com" />')).toBeDefined();
+ });
+ it('should automatically add on app java identifier as PACKAGE_NAME variable for android config munges', function() {
+ shell.cp('-rf', android_two_project, temp);
+ var munger = new configChanges.PlatformMunger('android', temp, 'unused');
+ var munge = munger.generate_plugin_config_munge(varplugin, {});
+ var expected_xml = '<package>com.alunny.childapp</package>';
+ expect(configChanges.get_munge_change(munge, 'AndroidManifest.xml', '/manifest', expected_xml)).toBeDefined();
+ });
+ });
+
+ describe('for ios projects', function() {
+ beforeEach(function() {
+ shell.cp('-rf', ios_config_xml, temp);
+ });
+ it('should automatically add on ios bundle identifier as PACKAGE_NAME variable for ios config munges', function() {
+ var munger = new configChanges.PlatformMunger('ios', temp, 'unused');
+ var munge = munger.generate_plugin_config_munge(varplugin, {});
+ var expected_xml = '<cfbundleid>com.example.friendstring</cfbundleid>';
+ expect(configChanges.get_munge_change(munge, 'config.xml', '/widget', expected_xml)).toBeDefined();
+ });
+ it('should special case framework elements for ios', function() {
+ var munger = new configChanges.PlatformMunger('ios', temp, 'unused');
+ var munge = munger.generate_plugin_config_munge(cbplugin, {});
+ expect(munge.files['framework']).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'framework', 'libsqlite3.dylib', 'false')).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'framework', 'social.framework', 'true')).toBeDefined();
+ expect(configChanges.get_munge_change(munge, 'framework', 'music.framework', 'false')).toBeDefined();
+ expect(munge.files['framework'].parents['Custom.framework']).not.toBeDefined();
+ });
+ });
+ });
+
+ describe('processing of plugins (via process method)', function() {
+ beforeEach(function() {
+ shell.cp('-rf', dummyplugin, plugins_dir);
+ });
+ it('should generate config munges for queued plugins', function() {
+ shell.cp('-rf', android_two_project, temp);
+ var cfg = configChanges.get_platform_json(plugins_dir, 'android');
+ cfg.prepare_queue.installed = [{'plugin':'DummyPlugin', 'vars':{}}];
+ configChanges.save_platform_json(cfg, plugins_dir, 'android');
+ var munger = new configChanges.PlatformMunger('android', temp, plugins_dir);
+ var spy = spyOn(munger, 'generate_plugin_config_munge').andReturn({});
+ munger.process();
+ expect(spy).toHaveBeenCalledWith(path.join(plugins_dir, 'DummyPlugin'), {});
+ });
+ it('should get a reference to existing config munge by calling get_platform_json', function() {
+ shell.cp('-rf', android_two_project, temp);
+ var spy = spyOn(configChanges, 'get_platform_json').andReturn({
+ prepare_queue:{
+ installed:[],
+ uninstalled:[]
+ },
+ config_munge:{}
+ });
+ configChanges.process(plugins_dir, temp, 'android');
+ expect(spy).toHaveBeenCalledWith(plugins_dir, 'android');
+ });
+ describe(': installation', function() {
+ describe('of xml config files', function() {
+ beforeEach(function() {
+ shell.cp('-rf', android_two_project, temp);
+ });
+ it('should call graftXML for every new config munge it introduces (every leaf in config munge that does not exist)', function() {
+ var cfg = configChanges.get_platform_json(plugins_dir, 'android');
+ cfg.prepare_queue.installed = [{'plugin':'DummyPlugin', 'vars':{}}];
+ configChanges.save_platform_json(cfg, plugins_dir, 'android');
+
+ var spy = spyOn(xml_helpers, 'graftXML').andReturn(true);
+
+ var manifest_doc = new et.ElementTree(et.XML(fs.readFileSync(path.join(temp, 'AndroidManifest.xml'), 'utf-8')));
+ var munge = dummy_xml.find('./platform[@name="android"]/config-file[@target="AndroidManifest.xml"]');
+ configChanges.process(plugins_dir, temp, 'android');
+ expect(spy.calls.length).toEqual(4);
+ expect(spy.argsForCall[0][2]).toEqual('/*');
+ expect(spy.argsForCall[1][2]).toEqual('/*');
+ expect(spy.argsForCall[2][2]).toEqual('/manifest/application');
+ expect(spy.argsForCall[3][2]).toEqual('/cordova/plugins');
+ });
+ it('should not call graftXML for a config munge that already exists from another plugin', function() {
+ shell.cp('-rf', configplugin, plugins_dir);
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'ConfigTestPlugin', 'android', {});
+
+ var spy = spyOn(xml_helpers, 'graftXML').andReturn(true);
+ configChanges.process(plugins_dir, temp, 'android');
+ expect(spy.calls.length).toEqual(1);
+ });
+ it('should not call graftXML for a config munge targeting a config file that does not exist', function() {
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'DummyPlugin', 'android', {});
+
+ var spy = spyOn(fs, 'readFileSync').andCallThrough();
+
+ configChanges.process(plugins_dir, temp, 'android');
+ expect(spy).not.toHaveBeenCalledWith(path.join(temp, 'res', 'xml', 'plugins.xml'), 'utf-8');
+ });
+ });
+ describe('of plist config files', function() {
+ var xcode_add, xcode_rm;
+ it('should write empty string nodes with no whitespace', function() {
+ shell.cp('-rf', ios_config_xml, temp);
+ shell.cp('-rf', varplugin, plugins_dir);
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'VariablePlugin', 'ios', {});
+ configChanges.process(plugins_dir, temp, 'ios');
+ expect(fs.readFileSync(path.join(temp, 'SampleApp', 'SampleApp-Info.plist'), 'utf-8')).toMatch(/<key>APluginNode<\/key>\n <string><\/string>/m);
+ });
+ });
+ describe('of pbxproject framework files', function() {
+ var xcode_add, xcode_rm;
+ beforeEach(function() {
+ shell.cp('-rf', ios_config_xml, temp);
+ shell.cp('-rf', cbplugin, plugins_dir);
+ xcode_add = spyOn(xcode.project.prototype, 'addFramework').andCallThrough();
+ });
+ it('should call into xcode.addFramework if plugin has <framework> file defined and is ios',function() {
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'ChildBrowser', 'ios', {});
+ configChanges.process(plugins_dir, temp, 'ios');
+ expect(xcode_add).toHaveBeenCalledWith('libsqlite3.dylib', {weak:false});
+ expect(xcode_add).toHaveBeenCalledWith('social.framework', {weak:true});
+ expect(xcode_add).toHaveBeenCalledWith('music.framework', {weak:false});
+ expect(xcode_add).not.toHaveBeenCalledWith('Custom.framework');
+ });
+ });
+ it('should resolve wildcard config-file targets to the project, if applicable', function() {
+ shell.cp('-rf', ios_config_xml, temp);
+ shell.cp('-rf', cbplugin, plugins_dir);
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'ChildBrowser', 'ios', {});
+ var spy = spyOn(fs, 'readFileSync').andCallThrough();
+
+ configChanges.process(plugins_dir, temp, 'ios');
+ expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'SampleApp-Info.plist').replace(/\\/g, '/'), 'utf8');
+ });
+ it('should move successfully installed plugins from queue to installed plugins section, and include/retain vars if applicable', function() {
+ shell.cp('-rf', android_two_project, temp);
+ shell.cp('-rf', varplugin, plugins_dir);
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'VariablePlugin', 'android', {"API_KEY":"hi"}, true);
+
+ configChanges.process(plugins_dir, temp, 'android');
+
+ var cfg = configChanges.get_platform_json(plugins_dir, 'android');
+ expect(cfg.prepare_queue.installed.length).toEqual(0);
+ expect(cfg.installed_plugins['com.adobe.vars']).toBeDefined();
+ expect(cfg.installed_plugins['com.adobe.vars']['API_KEY']).toEqual('hi');
+ });
+ it('should save changes to global config munge after completing an install', function() {
+ shell.cp('-rf', android_two_project, temp);
+ shell.cp('-rf', varplugin, plugins_dir);
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'VariablePlugin', 'android', {"API_KEY":"hi"});
+
+ var spy = spyOn(configChanges, 'save_platform_json');
+ configChanges.process(plugins_dir, temp, 'android');
+ expect(spy).toHaveBeenCalled();
+ });
+ });
+
+ describe(': uninstallation', function() {
+ it('should call pruneXML for every config munge it completely removes from the app (every leaf that is decremented to 0)', function() {
+ shell.cp('-rf', android_two_project, temp);
+ // Run through an "install"
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'DummyPlugin', 'android', {});
+ configChanges.process(plugins_dir, temp, 'android');
+
+ // Now set up an uninstall and make sure prunexml is called properly
+ configChanges.add_uninstalled_plugin_to_prepare_queue(plugins_dir, 'DummyPlugin', 'android');
+ var spy = spyOn(xml_helpers, 'pruneXML').andReturn(true);
+ configChanges.process(plugins_dir, temp, 'android');
+ expect(spy.calls.length).toEqual(4);
+ expect(spy.argsForCall[0][2]).toEqual('/*');
+ expect(spy.argsForCall[1][2]).toEqual('/*');
+ expect(spy.argsForCall[2][2]).toEqual('/manifest/application');
+ expect(spy.argsForCall[3][2]).toEqual('/cordova/plugins');
+ });
+ it('should generate a config munge that interpolates variables into config changes, if applicable', function() {
+ shell.cp('-rf', android_two_project, temp);
+ shell.cp('-rf', varplugin, plugins_dir);
+ // Run through an "install"
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'VariablePlugin', 'android', {"API_KEY":"canucks"});
+ var munger = new configChanges.PlatformMunger('android', temp, plugins_dir);
+ munger.process();
+
+ // Now set up an uninstall and make sure prunexml is called properly
+ configChanges.add_uninstalled_plugin_to_prepare_queue(plugins_dir, 'VariablePlugin', 'android');
+ var spy = spyOn(munger, 'generate_plugin_config_munge').andReturn({});
+ munger.process();
+ var munge_params = spy.mostRecentCall.args;
+ expect(munge_params[0]).toEqual(path.join(plugins_dir, 'VariablePlugin'));
+ expect(munge_params[1]['API_KEY']).toEqual('canucks');
+ });
+ it('should not call pruneXML for a config munge that another plugin depends on', function() {
+ shell.cp('-rf', android_two_no_perms_project, temp);
+ shell.cp('-rf', childrenplugin, plugins_dir);
+ shell.cp('-rf', shareddepsplugin, plugins_dir);
+
+ // Run through and "install" two plugins (they share a permission for INTERNET)
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'multiple-children', 'android', {});
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'shared-deps-multi-child', 'android', {});
+ configChanges.process(plugins_dir, temp, 'android');
+
+ // Now set up an uninstall for multi-child plugin
+ configChanges.add_uninstalled_plugin_to_prepare_queue(plugins_dir, 'multiple-children', 'android');
+ configChanges.process(plugins_dir, temp, 'android');
+ var am_xml = new et.ElementTree(et.XML(fs.readFileSync(path.join(temp, 'AndroidManifest.xml'), 'utf-8')));
+ var permission = am_xml.find('./uses-permission');
+ expect(permission).toBeDefined();
+ expect(permission.attrib['android:name']).toEqual('android.permission.INTERNET');
+ });
+ it('should not call pruneXML for a config munge targeting a config file that does not exist', function() {
+ shell.cp('-rf', android_two_project, temp);
+ // install a plugin
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'DummyPlugin', 'android', {});
+ configChanges.process(plugins_dir, temp, 'android');
+ // set up an uninstall for the same plugin
+ configChanges.add_uninstalled_plugin_to_prepare_queue(plugins_dir, 'DummyPlugin', 'android', {});
+
+ var spy = spyOn(fs, 'readFileSync').andCallThrough();
+ configChanges.process(plugins_dir, temp, 'android');
+
+ expect(spy).not.toHaveBeenCalledWith(path.join(temp, 'res', 'xml', 'plugins.xml'), 'utf-8');
+ });
+ it('should remove uninstalled plugins from installed plugins list', function() {
+ shell.cp('-rf', android_two_project, temp);
+ shell.cp('-rf', varplugin, plugins_dir);
+ // install the var plugin
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'VariablePlugin', 'android', {"API_KEY":"eat my shorts"});
+ configChanges.process(plugins_dir, temp, 'android');
+ // queue up an uninstall for the same plugin
+ configChanges.add_uninstalled_plugin_to_prepare_queue(plugins_dir, 'VariablePlugin', 'android');
+ configChanges.process(plugins_dir, temp, 'android');
+
+ var cfg = configChanges.get_platform_json(plugins_dir, 'android');
+ expect(cfg.prepare_queue.uninstalled.length).toEqual(0);
+ expect(cfg.installed_plugins['com.adobe.vars']).not.toBeDefined();
+ });
+ it('should save changes to global config munge after completing an uninstall', function() {
+ shell.cp('-rf', android_two_project, temp);
+ shell.cp('-rf', varplugin, plugins_dir);
+ // install a plugin
+ configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'VariablePlugin', 'android', {"API_KEY":"eat my shorts"});
+ configChanges.process(plugins_dir, temp, 'android');
+ // set up an uninstall for the plugin
+ configChanges.add_uninstalled_plugin_to_prepare_queue(plugins_dir, 'VariablePlugin', 'android');
+
+ var spy = spyOn(configChanges, 'save_platform_json');
+ configChanges.process(plugins_dir, temp, 'android');
+ expect(spy).toHaveBeenCalled();
+ });
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/util/csproj.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/util/csproj.spec.js b/cordova-lib/spec-plugman/util/csproj.spec.js
new file mode 100644
index 0000000..c506c38
--- /dev/null
+++ b/cordova-lib/spec-plugman/util/csproj.spec.js
@@ -0,0 +1,97 @@
+var csproj = require('../../src/util/csproj'),
+ path = require('path'),
+ os = require('osenv'),
+ et = require('elementtree'),
+ fs = require('fs'),
+ xml_helpers = require('../../src/util/xml-helpers');
+
+var wp7_project = path.join(__dirname, '..', 'projects', 'wp7'),
+ wp8_project = path.join(__dirname, '..', 'projects', 'wp8'),
+ temp = path.join(os.tmpdir(), 'plugman'),
+ example1_csproj = path.join(wp7_project, 'CordovaAppProj.csproj'),
+ example2_csproj = path.join(wp8_project, 'CordovaAppProj.csproj'),
+ wpcsproj = path.join(__dirname, '..', 'plugins', 'WPcsproj');
+
+describe('csproj', function() {
+ it('should throw if passed in an invalid xml file path ref', function() {
+ expect(function() {
+ new csproj('blahblah');
+ }).toThrow();
+ });
+ it('should successfully parse a valid csproj file into an xml document', function() {
+ var doc;
+ expect(function() {
+ doc = new csproj(example1_csproj);
+ }).not.toThrow();
+ expect(doc.xml.getroot()).toBeDefined();
+ });
+
+ describe('write method', function() {
+
+ });
+
+ describe('source file', function() {
+
+ var test_csproj;
+ var page_test = path.join('src', 'UI', 'PageTest.xaml');
+ var page_test_cs = path.join('src', 'UI', 'PageTest.xaml.cs');
+ var lib_test = path.join('lib', 'LibraryTest.dll');
+ var file_test = path.join('src', 'FileTest.cs');
+ var content_test = path.join('src', 'Content.img');
+
+ describe('add method', function() {
+ var test_csproj = new csproj(example1_csproj);
+ it('should properly add .xaml files', function() {
+ test_csproj.addSourceFile(page_test);
+ expect(test_csproj.xml.getroot().find('.//Page[@Include="src\\UI\\PageTest.xaml"]')).toBeTruthy();
+ expect(test_csproj.xml.getroot().find('.//Page[@Include="src\\UI\\PageTest.xaml"]/Generator').text).toEqual('MSBuild:Compile');
+ expect(test_csproj.xml.getroot().find('.//Page[@Include="src\\UI\\PageTest.xaml"]/SubType').text).toEqual('Designer');
+ });
+ it('should properly add .xaml.cs files', function() {
+ test_csproj.addSourceFile(page_test_cs);
+ expect(test_csproj.xml.getroot().find('.//Compile[@Include="src\\UI\\PageTest.xaml.cs"]')).toBeTruthy();
+ expect(test_csproj.xml.getroot().find('.//Compile[@Include="src\\UI\\PageTest.xaml.cs"]/DependentUpon').text).toEqual('PageTest.xaml');
+ });
+ it('should properly add .cs files', function() {
+ test_csproj.addSourceFile(file_test);
+ expect(test_csproj.xml.getroot().find('.//Compile[@Include="src\\FileTest.cs"]')).toBeTruthy();
+ });
+ it('should properly add content files', function() {
+ test_csproj.addSourceFile(content_test);
+ expect(test_csproj.xml.getroot().find('.//Content[@Include="src\\Content.img"]')).toBeTruthy();
+ });
+ });
+
+ describe('remove method', function() {
+ var test_csproj = new csproj(example2_csproj);
+ it('should properly remove .xaml pages', function() {
+ test_csproj.removeSourceFile(page_test);
+ expect(test_csproj.xml.getroot().find('.//Page[@Include="src\\UI\\PageTest.xaml"]')).toBeFalsy();
+ });
+ it('should properly remove .xaml.cs files', function() {
+ test_csproj.removeSourceFile(page_test_cs);
+ expect(test_csproj.xml.getroot().find('.//Compile[@Include="src\\UI\\PageTest.xaml.cs"]')).toBeFalsy();
+ });
+ it('should properly remove .cs files', function() {
+ test_csproj.removeSourceFile(file_test);
+ expect(test_csproj.xml.getroot().find('.//Compile[@Include="src\\FileTest.cs"]')).toBeFalsy();
+ });
+ it('should properly remove content files', function() {
+ test_csproj.removeSourceFile(content_test);
+ expect(test_csproj.xml.getroot().find('.//Content[@Include="src\\Content.img"]')).toBeFalsy();
+ });
+ it('should remove all empty ItemGroup\'s', function() {
+ test_csproj.removeSourceFile(page_test);
+ test_csproj.removeSourceFile(page_test_cs);
+ test_csproj.removeSourceFile(lib_test);
+ test_csproj.removeSourceFile(file_test);
+ var item_groups = test_csproj.xml.findall('ItemGroup');
+ for (var i = 0, l = item_groups.length; i < l; i++) {
+ var group = item_groups[i];
+ expect(group._children.length).toBeGreaterThan(0);
+ }
+ })
+
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/0318d8cd/cordova-lib/spec-plugman/util/dependencies.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-plugman/util/dependencies.spec.js b/cordova-lib/spec-plugman/util/dependencies.spec.js
new file mode 100644
index 0000000..bbc7111
--- /dev/null
+++ b/cordova-lib/spec-plugman/util/dependencies.spec.js
@@ -0,0 +1,41 @@
+var dependencies = require('../../src/util/dependencies'),
+ xml_helpers = require('../../src/util/xml-helpers'),
+ path = require('path'),
+ config = require('../../src/util/config-changes');
+
+describe('dependency module', function() {
+ describe('generate_dependency_info method', function() {
+ it('should return a list of top-level plugins based on what is inside a platform.json file', function() {
+ var tlps = {
+ "hello":"",
+ "isitme":"",
+ "yourelookingfor":""
+ };
+ spyOn(xml_helpers, 'parseElementtreeSync').andReturn({findall:function(){}});
+ var spy = spyOn(config, 'get_platform_json').andReturn({
+ installed_plugins:tlps,
+ dependent_plugins:[]
+ });
+ var obj = dependencies.generate_dependency_info('some dir');
+ expect(obj.top_level_plugins).toEqual(Object.keys(tlps));
+ });
+ it('should return a dependency graph for the plugins', function() {
+ var tlps = {
+ "A":"",
+ "B":""
+ };
+ var deps = {
+ "C":"",
+ "D":"",
+ "E":""
+ };
+ var spy = spyOn(config, 'get_platform_json').andReturn({
+ installed_plugins:tlps,
+ dependent_plugins:[]
+ });
+ var obj = dependencies.generate_dependency_info(path.join(__dirname, '..', 'plugins', 'dependencies'), 'android');
+ expect(obj.graph.getChain('A')).toEqual(['C','D']);
+ expect(obj.graph.getChain('B')).toEqual(['D', 'E']);
+ });
+ });
+});