blob: a0c903c45ccabcf5863c66121008fabd1025ca82 [file] [log] [blame]
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).toEqual(new Error('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).toEqual(new Error('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).toEqual(new Error('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).toEqual(new Error('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);
});
});