Updated Branches: refs/heads/frameworks 6b6931ec0 -> 31a41508a
[CB-4373] Added tests for framework ref counting. Project: http://git-wip-us.apache.org/repos/asf/cordova-plugman/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugman/commit/31a41508 Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugman/tree/31a41508 Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugman/diff/31a41508 Branch: refs/heads/frameworks Commit: 31a41508ad14946d5eda766eca0a1575b5363acb Parents: 6b6931e Author: Fil Maj <[email protected]> Authored: Tue Jul 30 01:08:03 2013 -0700 Committer: Fil Maj <[email protected]> Committed: Tue Jul 30 01:08:03 2013 -0700 ---------------------------------------------------------------------- spec/util/config-changes.spec.js | 265 +++++++++++++++++++--------------- 1 file changed, 149 insertions(+), 116 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/31a41508/spec/util/config-changes.spec.js ---------------------------------------------------------------------- diff --git a/spec/util/config-changes.spec.js b/spec/util/config-changes.spec.js index fa0ec70..612665d 100644 --- a/spec/util/config-changes.spec.js +++ b/spec/util/config-changes.spec.js @@ -1,5 +1,6 @@ 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'), et = require('elementtree'), @@ -130,82 +131,89 @@ describe('config-changes module', function() { }); describe('generate_plugin_config_munge method', function() { - it('should return a flat config heirarchy for simple, one-off config changes', function() { - shell.cp('-rf', android_two_project, temp); - var xml; - var munge = configChanges.generate_plugin_config_munge(dummyplugin, 'android', temp, {}); - expect(munge['AndroidManifest.xml']).toBeDefined(); - expect(munge['AndroidManifest.xml']['/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(munge['AndroidManifest.xml']['/manifest/application'][xml]).toEqual(1); - expect(munge['res/xml/plugins.xml']).toBeDefined(); - expect(munge['res/xml/plugins.xml']['/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(munge['res/xml/plugins.xml']['/plugins'][xml]).toEqual(1); - expect(munge['res/xml/config.xml']).toBeDefined(); - expect(munge['res/xml/config.xml']['/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(munge['res/xml/config.xml']['/cordova/plugins'][xml]).toEqual(1); - }); - it('should split out multiple children of config-file elements into individual leaves', function() { - shell.cp('-rf', android_two_project, temp); - var munge = configChanges.generate_plugin_config_munge(childrenplugin, 'android', temp, {}); - expect(munge['AndroidManifest.xml']).toBeDefined(); - expect(munge['AndroidManifest.xml']['/manifest']).toBeDefined(); - expect(munge['AndroidManifest.xml']['/manifest']['<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />']).toBeDefined(); - expect(munge['AndroidManifest.xml']['/manifest']['<uses-permission android:name="android.permission.READ_PHONE_STATE" />']).toBeDefined(); - expect(munge['AndroidManifest.xml']['/manifest']['<uses-permission android:name="android.permission.INTERNET" />']).toBeDefined(); - expect(munge['AndroidManifest.xml']['/manifest']['<uses-permission android:name="android.permission.GET_ACCOUNTS" />']).toBeDefined(); - expect(munge['AndroidManifest.xml']['/manifest']['<uses-permission android:name="android.permission.WAKE_LOCK" />']).toBeDefined(); - expect(munge['AndroidManifest.xml']['/manifest']['<permission android:name="com.alunny.childapp.permission.C2D_MESSAGE" android:protectionLevel="signature" />']).toBeDefined(); - expect(munge['AndroidManifest.xml']['/manifest']['<uses-permission android:name="com.alunny.childapp.permission.C2D_MESSAGE" />']).toBeDefined(); - expect(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() { - shell.cp('-rf', android_two_project, temp); - var munge = configChanges.generate_plugin_config_munge(childrenplugin, 'android', temp, {}); - expect(munge['AndroidManifest.xml']['/manifest']['<!--library-->']).not.toBeDefined(); - expect(munge['AndroidManifest.xml']['/manifest']['<!-- GCM connects to Google Services. -->']).not.toBeDefined(); - }); - it('should increment config heirarchy leaves if dfferent config-file elements target the same file + selector + xml', function() { - shell.cp('-rf', android_two_project, temp); - var munge = configChanges.generate_plugin_config_munge(configplugin, 'android', temp, {}); - expect(munge['res/xml/config.xml']['/widget']['<poop />']).toEqual(2); - }); - it('should take into account interpolation variables', function() { - shell.cp('-rf', android_two_project, temp); - var munge = configChanges.generate_plugin_config_munge(childrenplugin, 'android', temp, {PACKAGE_NAME:'ca.filmaj.plugins'}); - expect(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() { - shell.cp('-rf', android_two_project, temp); - var munge = configChanges.generate_plugin_config_munge(dummyplugin, 'android', temp, {}); - expect(munge['config.xml']['/*']['<access origin="build.phonegap.com" />']).toBeDefined(); - expect(munge['config.xml']['/*']['<access origin="s3.amazonaws.com" />']).toBeDefined(); - }); - it('should automatically add on ios bundle identifier as PACKAGE_NAME variable for ios config munges', function() { - shell.cp('-rf', ios_config_xml, temp); - var munge = configChanges.generate_plugin_config_munge(varplugin, 'ios', temp, {}); - var expected_xml = '<cfbundleid>com.example.friendstring</cfbundleid>'; - expect(munge['config.xml']['/widget'][expected_xml]).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 munge = configChanges.generate_plugin_config_munge(varplugin, 'android', temp, {}); - var expected_xml = '<package>com.alunny.childapp</package>'; - expect(munge['AndroidManifest.xml']['/manifest'][expected_xml]).toBeDefined(); - }); - it('should special case plugins-plist elements into own property', function() { - shell.cp('-rf', ios_config_xml, temp); - var munge = configChanges.generate_plugin_config_munge(dummyplugin, 'ios', temp, {}); - expect(munge['plugins-plist']).toBeDefined(); - expect(munge['plugins-plist']['com.phonegap.plugins.dummyplugin']).toEqual('DummyPluginCommand'); + describe('for android projects', function() { + beforeEach(function() { + shell.cp('-rf', android_two_project, temp); + }); + it('should return a flat config heirarchy for simple, one-off config changes', function() { + var xml; + var munge = configChanges.generate_plugin_config_munge(dummyplugin, 'android', temp, {}); + expect(munge['AndroidManifest.xml']).toBeDefined(); + expect(munge['AndroidManifest.xml']['/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(munge['AndroidManifest.xml']['/manifest/application'][xml]).toEqual(1); + expect(munge['res/xml/plugins.xml']).toBeDefined(); + expect(munge['res/xml/plugins.xml']['/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(munge['res/xml/plugins.xml']['/plugins'][xml]).toEqual(1); + expect(munge['res/xml/config.xml']).toBeDefined(); + expect(munge['res/xml/config.xml']['/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(munge['res/xml/config.xml']['/cordova/plugins'][xml]).toEqual(1); + }); + it('should split out multiple children of config-file elements into individual leaves', function() { + var munge = configChanges.generate_plugin_config_munge(childrenplugin, 'android', temp, {}); + expect(munge['AndroidManifest.xml']).toBeDefined(); + expect(munge['AndroidManifest.xml']['/manifest']).toBeDefined(); + expect(munge['AndroidManifest.xml']['/manifest']['<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />']).toBeDefined(); + expect(munge['AndroidManifest.xml']['/manifest']['<uses-permission android:name="android.permission.READ_PHONE_STATE" />']).toBeDefined(); + expect(munge['AndroidManifest.xml']['/manifest']['<uses-permission android:name="android.permission.INTERNET" />']).toBeDefined(); + expect(munge['AndroidManifest.xml']['/manifest']['<uses-permission android:name="android.permission.GET_ACCOUNTS" />']).toBeDefined(); + expect(munge['AndroidManifest.xml']['/manifest']['<uses-permission android:name="android.permission.WAKE_LOCK" />']).toBeDefined(); + expect(munge['AndroidManifest.xml']['/manifest']['<permission android:name="com.alunny.childapp.permission.C2D_MESSAGE" android:protectionLevel="signature" />']).toBeDefined(); + expect(munge['AndroidManifest.xml']['/manifest']['<uses-permission android:name="com.alunny.childapp.permission.C2D_MESSAGE" />']).toBeDefined(); + expect(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 munge = configChanges.generate_plugin_config_munge(childrenplugin, 'android', temp, {}); + expect(munge['AndroidManifest.xml']['/manifest']['<!--library-->']).not.toBeDefined(); + expect(munge['AndroidManifest.xml']['/manifest']['<!-- GCM connects to Google Services. -->']).not.toBeDefined(); + }); + it('should increment config heirarchy leaves if dfferent config-file elements target the same file + selector + xml', function() { + var munge = configChanges.generate_plugin_config_munge(configplugin, 'android', temp, {}); + expect(munge['res/xml/config.xml']['/widget']['<poop />']).toEqual(2); + }); + it('should take into account interpolation variables', function() { + var munge = configChanges.generate_plugin_config_munge(childrenplugin, 'android', temp, {PACKAGE_NAME:'ca.filmaj.plugins'}); + expect(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 munge = configChanges.generate_plugin_config_munge(dummyplugin, 'android', temp, {}); + expect(munge['config.xml']['/*']['<access origin="build.phonegap.com" />']).toBeDefined(); + expect(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 munge = configChanges.generate_plugin_config_munge(varplugin, 'android', temp, {}); + var expected_xml = '<package>com.alunny.childapp</package>'; + expect(munge['AndroidManifest.xml']['/manifest'][expected_xml]).toBeDefined(); + }); }); - it('should special case framework elements for ios', function() { + 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 munge = configChanges.generate_plugin_config_munge(varplugin, 'ios', temp, {}); + var expected_xml = '<cfbundleid>com.example.friendstring</cfbundleid>'; + expect(munge['config.xml']['/widget'][expected_xml]).toBeDefined(); + }); + it('should special case plugins-plist elements into own property', function() { + var munge = configChanges.generate_plugin_config_munge(dummyplugin, 'ios', temp, {}); + expect(munge['plugins-plist']).toBeDefined(); + expect(munge['plugins-plist']['com.phonegap.plugins.dummyplugin']).toEqual('DummyPluginCommand'); + }); + it('should special case framework elements for ios', function() { + var munge = configChanges.generate_plugin_config_munge(cbplugin, 'ios', temp, {}); + expect(munge['framework']).toBeDefined(); + expect(munge['framework']['libsqlite3.dylib']['false']).toBeDefined(); + expect(munge['framework']['social.framework']['true']).toBeDefined(); + expect(munge['framework']['music.framework']['false']).toBeDefined(); + }); }); }); @@ -235,41 +243,79 @@ describe('config-changes module', function() { 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', {}); - it('should call graftXML for every new config munge it introduces (every leaf in config munge that does not exist)', 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 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(xml_helpers, 'graftXML').andReturn(true); + var spy = spyOn(fs, 'readFileSync').andCallThrough(); - 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'); + configChanges.process(plugins_dir, temp, 'android'); + expect(spy).not.toHaveBeenCalledWith(path.join(temp, 'res', 'xml', 'plugins.xml'), 'utf-8'); + }); }); - it('should not call graftXML for a config munge that already exists from another plugin', function() { - shell.cp('-rf', android_two_project, temp); - 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); + 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 = jasmine.createSpy(); + xcode_rm = jasmine.createSpy(); + spyOn(ios_parser, 'parseIOSProjectFiles').andReturn({ + xcode:{ + addFramework:xcode_add, + removeFramework:xcode_rm, + writeSync:function(){} + }, + pbx:'pbxpath' + }); + }); + 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}); + }); }); - it('should not call graftXML for a config munge targeting a config file that does not exist', function() { - shell.cp('-rf', android_two_project, temp); - configChanges.add_installed_plugin_to_prepare_queue(plugins_dir, 'DummyPlugin', 'android', {}); - - var spy = spyOn(fs, 'readFileSync').andCallThrough(); + describe('of <plugins-plist> elements', function() { + it('should only be used in an applicably old cordova-ios projects', function() { + shell.cp('-rf', ios_plist_project, temp); + shell.cp('-rf', dummyplugin, plugins_dir); + var cfg = configChanges.get_platform_json(plugins_dir, 'ios'); + cfg.prepare_queue.installed = [{'plugin':'DummyPlugin', 'vars':{}}]; + configChanges.save_platform_json(cfg, plugins_dir, 'ios'); - configChanges.process(plugins_dir, temp, 'android'); - expect(spy).not.toHaveBeenCalledWith(path.join(temp, 'res', 'xml', 'plugins.xml'), 'utf-8'); + var spy = spyOn(plist, 'parseFileSync').andReturn({Plugins:{}}); + configChanges.process(plugins_dir, temp, 'ios'); + expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'PhoneGap.plist').replace(/\\/g, '/')); + }); }); it('should resolve wildcard config-file targets to the project, if applicable', function() { shell.cp('-rf', ios_config_xml, temp); @@ -301,19 +347,6 @@ describe('config-changes module', function() { configChanges.process(plugins_dir, temp, 'android'); expect(spy).toHaveBeenCalled(); }); - describe('of <plugins-plist> elements', function() { - it('should only be used in an applicably old cordova-ios projects', function() { - shell.cp('-rf', ios_plist_project, temp); - shell.cp('-rf', dummyplugin, plugins_dir); - var cfg = configChanges.get_platform_json(plugins_dir, 'ios'); - cfg.prepare_queue.installed = [{'plugin':'DummyPlugin', 'vars':{}}]; - configChanges.save_platform_json(cfg, plugins_dir, 'ios'); - - var spy = spyOn(plist, 'parseFileSync').andReturn({Plugins:{}}); - configChanges.process(plugins_dir, temp, 'ios'); - expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'PhoneGap.plist').replace(/\\/g, '/')); - }); - }); }); describe(': uninstallation', function() {
