blob: 3c34b8f67ca728db0fb2b5678bcacaa62b9af23e [file] [log] [blame]
var ios = require('../../src/platforms/ios'),
install = require('../../src/install'),
path = require('path'),
fs = require('fs'),
et = require('elementtree'),
shell = require('shelljs'),
os = require('osenv'),
common = require('../../src/platforms/common'),
xcode = require('xcode'),
plist = require('plist'),
bplist = require('bplist-parser'),
temp = path.join(os.tmpdir(), 'plugman'),
plugins_dir = path.join(temp, 'cordova', 'plugins'),
ios_config_xml_project = path.join(__dirname, '..', 'projects', 'ios-config-xml', '*'),
ios_plist_project = path.join(__dirname, '..', 'projects', 'ios-plist', '*'),
ios_project = path.join(ios_config_xml_project, '..'),
xml_helpers = require('../../src/util/xml-helpers'),
variableplugin = path.join(__dirname, '..', 'plugins', 'VariablePlugin'),
faultyplugin = path.join(__dirname, '..', 'plugins', 'FaultyPlugin'),
plistplugin = path.join(__dirname, '..', 'plugins', 'PluginsPlistOnly'),
dummyplugin = path.join(__dirname, '..', 'plugins', 'DummyPlugin');
var xml_path = path.join(dummyplugin, 'plugin.xml'),
xml_test = fs.readFileSync(xml_path, 'utf-8'),
plugin_et = new et.ElementTree(et.XML(xml_test));
var platformTag = plugin_et.find('./platform[@name="ios"]');
var dummy_id = plugin_et._root.attrib['id'];
var valid_source = platformTag.findall('./source-file'),
valid_assets = plugin_et.findall('./asset'),
valid_headers = platformTag.findall('./header-file'),
valid_resources = platformTag.findall('./resource-file'),
valid_frameworks = platformTag.findall('./framework'),
plist_els = platformTag.findall('./plugins-plist'),
dummy_configs = platformTag.findall('./config-file');
xml_path = path.join(variableplugin, 'plugin.xml');
xml_test = fs.readFileSync(xml_path, 'utf-8');
plugin_et = new et.ElementTree(et.XML(xml_test));
platformTag = plugin_et.find('./platform[@name="ios"]');
var variable_id = plugin_et._root.attrib['id'];
var variable_configs = platformTag.findall('./config-file');
xml_path = path.join(faultyplugin, 'plugin.xml');
xml_test = fs.readFileSync(xml_path, 'utf-8');
plugin_et = new et.ElementTree(et.XML(xml_test));
platformTag = plugin_et.find('./platform[@name="ios"]');
var faulty_id = plugin_et._root.attrib['id'];
var invalid_assets = plugin_et.findall('./asset');
var invalid_source = platformTag.findall('./source-file');
var invalid_headers = platformTag.findall('./header-file');
var invalid_resources = platformTag.findall('./resource-file');
var invalid_frameworks = platformTag.findall('./framework');
xml_path = path.join(plistplugin, 'plugin.xml');
xml_test = fs.readFileSync(xml_path, 'utf-8');
plugin_et = new et.ElementTree(et.XML(xml_test));
platformTag = plugin_et.find('./platform[@name="ios"]');
var plist_id = plugin_et._root.attrib['id'];
var plist_only_els = platformTag.findall('./plugins-plist');
shell.mkdir('-p', temp);
shell.cp('-rf', ios_config_xml_project, temp);
var proj_files = ios.parseIOSProjectFiles(temp);
shell.rm('-rf', temp);
function copyArray(arr) {
return Array.prototype.slice.call(arr, 0);
}
describe('ios project handler', function() {
beforeEach(function() {
shell.mkdir('-p', temp);
shell.mkdir('-p', plugins_dir);
});
afterEach(function() {
shell.rm('-rf', temp);
});
describe('www_dir method', function() {
it('should return cordova-ios project www location using www_dir', function() {
expect(ios.www_dir(path.sep)).toEqual(path.sep + 'www');
});
});
describe('package_name method', function() {
it('should return the CFBundleIdentifier from the project\'s Info.plist file', function() {
expect(ios.package_name(ios_project)).toEqual('com.example.friendstring');
});
});
describe('parseIOSProjectFiles method', function() {
it('should throw if project is not an xcode project', function() {
expect(function() {
ios.parseIOSProjectFiles(temp);
}).toThrow('does not appear to be an xcode project (no xcode project file)');
});
it('should throw if project does not contain an appropriate PhoneGap/Cordova.plist file or config.xml file', function() {
shell.cp('-rf', ios_config_xml_project, temp);
shell.rm(path.join(temp, 'SampleApp', 'config.xml'));
expect(function() {
ios.parseIOSProjectFiles(temp);
}).toThrow('could not find PhoneGap/Cordova plist file, or config.xml file.');
});
});
describe('installation', function() {
describe('of <source-file> elements', function() {
beforeEach(function() {
shell.cp('-rf', ios_config_xml_project, temp);
});
it('should throw if source-file src cannot be found', function() {
var source = copyArray(invalid_source);
expect(function() {
ios['source-file'].install(source[1], faultyplugin, temp, faulty_id, proj_files);
}).toThrow('cannot find "' + path.resolve(faultyplugin, 'src/ios/FaultyPluginCommand.m') + '" ios <source-file>');
});
it('should throw if source-file target already exists', function() {
var source = copyArray(valid_source);
var target = path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.m');
shell.mkdir('-p', path.dirname(target));
fs.writeFileSync(target, 'some bs', 'utf-8');
expect(function() {
ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, proj_files);
}).toThrow('target destination "' + target + '" already exists');
});
it('should call into xcodeproj\'s addSourceFile appropriately when element has no target-dir', function() {
var source = copyArray(valid_source).filter(function(s) { return s.attrib['target-dir'] == undefined});
var spy = spyOn(proj_files.xcode, 'addSourceFile');
ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('Plugins', dummy_id, 'DummyPluginCommand.m'), {});
});
it('should call into xcodeproj\'s addSourceFile appropriately when element has a target-dir', function() {
var source = copyArray(valid_source).filter(function(s) { return s.attrib['target-dir'] != undefined});
var spy = spyOn(proj_files.xcode, 'addSourceFile');
ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'), {});
});
it('should cp the file to the right target location when element has no target-dir', function() {
var source = copyArray(valid_source).filter(function(s) { return s.attrib['target-dir'] == undefined});
var spy = spyOn(shell, 'cp');
ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.m'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.m'));
});
it('should cp the file to the right target location when element has a target-dir', function() {
var source = copyArray(valid_source).filter(function(s) { return s.attrib['target-dir'] != undefined});
var spy = spyOn(shell, 'cp');
ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.m'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'));
});
it('should call into xcodeproj\'s addFramework appropriately when element has framework=true set', function() {
var source = copyArray(valid_source).filter(function(s) { return s.attrib['framework'] == "true"});
spyOn(proj_files.xcode, 'addSourceFile');
var spy = spyOn(proj_files.xcode, 'addFramework');
ios['source-file'].install(source[0], dummyplugin, temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('SampleApp', 'Plugins', dummy_id, 'SourceWithFramework.m'), {weak:false});
});
});
describe('of <header-file> elements', function() {
beforeEach(function() {
shell.cp('-rf', ios_config_xml_project, temp);
});
it('should throw if header-file src cannot be found', function() {
var headers = copyArray(invalid_headers);
expect(function() {
ios['header-file'].install(headers[1], faultyplugin, temp, faulty_id, proj_files);
}).toThrow('cannot find "' + path.resolve(faultyplugin, 'src/ios/FaultyPluginCommand.h') + '" ios <header-file>');
});
it('should throw if header-file target already exists', function() {
var headers = copyArray(valid_headers);
var target = path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.h');
shell.mkdir('-p', path.dirname(target));
fs.writeFileSync(target, 'some bs', 'utf-8');
expect(function() {
ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, proj_files);
}).toThrow('target destination "' + target + '" already exists');
});
it('should call into xcodeproj\'s addHeaderFile appropriately when element has no target-dir', function() {
var headers = copyArray(valid_headers).filter(function(s) { return s.attrib['target-dir'] == undefined});
var spy = spyOn(proj_files.xcode, 'addHeaderFile');
ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('Plugins', dummy_id, 'DummyPluginCommand.h'));
});
it('should call into xcodeproj\'s addHeaderFile appropriately when element a target-dir', function() {
var headers = copyArray(valid_headers).filter(function(s) { return s.attrib['target-dir'] != undefined});
var spy = spyOn(proj_files.xcode, 'addHeaderFile');
ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
});
it('should cp the file to the right target location when element has no target-dir', function() {
var headers = copyArray(valid_headers).filter(function(s) { return s.attrib['target-dir'] == undefined});
var spy = spyOn(shell, 'cp');
ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.h'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.h'));
});
it('should cp the file to the right target location when element has a target-dir', function() {
var headers = copyArray(valid_headers).filter(function(s) { return s.attrib['target-dir'] != undefined});
var spy = spyOn(shell, 'cp');
ios['header-file'].install(headers[0], dummyplugin, temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.h'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
});
});
describe('of <resource-file> elements', function() {
beforeEach(function() {
shell.cp('-rf', ios_config_xml_project, temp);
});
it('should throw if resource-file src cannot be found', function() {
var resources = copyArray(invalid_resources);
expect(function() {
ios['resource-file'].install(resources[0], faultyplugin, temp, proj_files);
}).toThrow('cannot find "' + path.resolve(faultyplugin, 'src/ios/IDontExist.bundle') + '" ios <resource-file>');
});
it('should throw if resource-file target already exists', function() {
var resources = copyArray(valid_resources);
var target = path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle');
shell.mkdir('-p', path.dirname(target));
fs.writeFileSync(target, 'some bs', 'utf-8');
expect(function() {
ios['resource-file'].install(resources[0], dummyplugin, temp, proj_files);
}).toThrow('target destination "' + target + '" already exists');
});
it('should call into xcodeproj\'s addResourceFile', function() {
var resources = copyArray(valid_resources);
var spy = spyOn(proj_files.xcode, 'addResourceFile');
ios['resource-file'].install(resources[0], dummyplugin, temp, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('Resources', 'DummyPlugin.bundle'));
});
it('should cp the file to the right target location', function() {
var resources = copyArray(valid_resources);
var spy = spyOn(shell, 'cp');
ios['resource-file'].install(resources[0], dummyplugin, temp, proj_files);
expect(spy).toHaveBeenCalledWith('-R', path.join(dummyplugin, 'src', 'ios', 'DummyPlugin.bundle'), path.join(temp, 'SampleApp', 'Resources'));
});
});
describe('of <framework> elements', function() {
beforeEach(function() {
shell.cp('-rf', ios_config_xml_project, temp);
});
it('should call into xcodeproj\'s addFramework with weak false by default' ,function() {
var frameworks = copyArray(valid_frameworks).filter(function(f) { return f.attrib.weak == undefined; });
var spy = spyOn(proj_files.xcode, 'addFramework');
ios.framework.install(frameworks[0], dummyplugin, temp, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('src', 'ios', 'libsqlite3.dylib').replace(/\\/g, '/'), {weak:false});
});
it('should pass in whether the framework is weak or not to xcodeproj.addFramework', function() {
var frameworks = copyArray(valid_frameworks).filter(function(f) { return f.attrib.weak != undefined; });;
var spy = spyOn(proj_files.xcode, 'addFramework');
ios.framework.install(frameworks[0], dummyplugin, temp, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('src', 'ios', 'libsqlite3.dylib').replace(/\\/g, '/'), {weak:true});
});
});
});
describe('uninstallation', function() {
describe('of <source-file> elements', function() {
it('should call into xcodeproj\'s removeSourceFile appropriately when element has no target-dir', function(){
var source = copyArray(valid_source).filter(function(s) { return s.attrib['target-dir'] == undefined});
shell.cp('-rf', ios_config_xml_project, temp);
var spy = spyOn(proj_files.xcode, 'removeSourceFile');
ios['source-file'].uninstall(source[0], temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('Plugins', dummy_id, 'DummyPluginCommand.m'));
});
it('should call into xcodeproj\'s removeSourceFile appropriately when element a target-dir', function(){
var source = copyArray(valid_source).filter(function(s) { return s.attrib['target-dir'] != undefined});
shell.cp('-rf', ios_config_xml_project, temp);
var spy = spyOn(proj_files.xcode, 'removeSourceFile');
ios['source-file'].uninstall(source[0], temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'));
});
it('should rm the file from the right target location when element has no target-dir', function(){
var source = copyArray(valid_source).filter(function(s) { return s.attrib['target-dir'] == undefined});
shell.cp('-rf', ios_config_xml_project, temp);
var spy = spyOn(shell, 'rm');
ios['source-file'].uninstall(source[0], temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.m'));
});
it('should rm the file from the right target location when element has a target-dir', function(){
var source = copyArray(valid_source).filter(function(s) { return s.attrib['target-dir'] != undefined});
shell.cp('-rf', ios_config_xml_project, temp);
var spy = spyOn(shell, 'rm');
ios['source-file'].uninstall(source[0], temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'));
});
it('should call into xcodeproj\'s removeFramework appropriately when element framework=true set', function(){
var source = copyArray(valid_source).filter(function(s) { return s.attrib['framework'] == "true"});
shell.cp('-rf', ios_config_xml_project, temp);
var spy = spyOn(proj_files.xcode, 'removeFramework');
ios['source-file'].uninstall(source[0], temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('SampleApp', 'Plugins', dummy_id, 'SourceWithFramework.m'));
});
});
describe('of <header-file> elements', function() {
beforeEach(function() {
shell.cp('-rf', ios_config_xml_project, temp);
});
it('should call into xcodeproj\'s removeHeaderFile appropriately when element has no target-dir', function(){
var headers = copyArray(valid_headers).filter(function(s) { return s.attrib['target-dir'] == undefined});
var spy = spyOn(proj_files.xcode, 'removeHeaderFile');
ios['header-file'].uninstall(headers[0], temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('Plugins', dummy_id, 'DummyPluginCommand.h'));
});
it('should call into xcodeproj\'s removeHeaderFile appropriately when element a target-dir', function(){
var headers = copyArray(valid_headers).filter(function(s) { return s.attrib['target-dir'] != undefined});
var spy = spyOn(proj_files.xcode, 'removeHeaderFile');
ios['header-file'].uninstall(headers[0], temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
});
it('should rm the file from the right target location', function(){
var headers = copyArray(valid_headers).filter(function(s) { return s.attrib['target-dir'] != undefined});
var spy = spyOn(shell, 'rm');
ios['header-file'].uninstall(headers[0], temp, dummy_id, proj_files);
expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'));
});
});
describe('of <resource-file> elements', function() {
beforeEach(function() {
shell.cp('-rf', ios_config_xml_project, temp);
});
it('should call into xcodeproj\'s removeResourceFile', function(){
var resources = copyArray(valid_resources);
var spy = spyOn(proj_files.xcode, 'removeResourceFile');
ios['resource-file'].uninstall(resources[0], temp, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('Resources', 'DummyPlugin.bundle'));
});
it('should rm the file from the right target location', function(){
var resources = copyArray(valid_resources);
var spy = spyOn(shell, 'rm');
ios['resource-file'].uninstall(resources[0], temp, proj_files);
expect(spy).toHaveBeenCalledWith('-rf', path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle'));
});
});
describe('of <framework> elements', function() {
beforeEach(function() {
shell.cp('-rf', ios_config_xml_project, temp);
});
it('should call into xcodeproj\'s removeFramework' ,function() {
var frameworks = copyArray(valid_frameworks).filter(function(f) { return f.attrib.weak == undefined; });
var spy = spyOn(proj_files.xcode, 'removeFramework');
ios.framework.uninstall(frameworks[0], temp, proj_files);
expect(spy).toHaveBeenCalledWith(path.join('src', 'ios', 'libsqlite3.dylib').replace(/\\/g, '/'));
});
});
});
});