From bf6b78137a819867b89843f047fbcea7d7a9ee48 Mon Sep 17 00:00:00 2001
From: Karishma Chadha <kchadha@scratch.mit.edu>
Date: Wed, 8 Nov 2017 15:48:24 -0500
Subject: [PATCH] Test coverage for virtual-machine's deleteSprite and
 duplicateSprite functions.

---
 test/unit/virtual-machine.js | 130 ++++++++++++++++++++++++++++++++++-
 1 file changed, 128 insertions(+), 2 deletions(-)

diff --git a/test/unit/virtual-machine.js b/test/unit/virtual-machine.js
index 2aa10ec87..199640d74 100644
--- a/test/unit/virtual-machine.js
+++ b/test/unit/virtual-machine.js
@@ -1,5 +1,8 @@
 const test = require('tap').test;
 const VirtualMachine = require('../../src/virtual-machine.js');
+const Target = require('../../src/engine/target.js');
+const Sprite = require('../../src/sprites/sprite.js');
+const RenderedTarget = require('../../src/sprites/rendered-target');
 
 test('renameSprite throws when there is no sprite with that id', t => {
     const vm = new VirtualMachine();
@@ -146,14 +149,137 @@ test('deleteSprite throws when there is no target with given id', t => {
             name: 'this name'
         }
     }];
-    vm.runtime.getTargetById = () => null;
     t.throws(
-        (() => vm.deleteSprite('id')),
+        (() => vm.deleteSprite('id1')),
         new Error ('No target with the provided id.')
     );
     t.end();
 });
 
+test('deleteSprite deletes a sprite when given id is associated with a known sprite', t => {
+    const vm = new VirtualMachine();
+    const spr = new Sprite(null, vm.runtime);
+    const currTarget = spr.createClone();
+
+    vm.runtime.targets = [currTarget];
+
+    t.equal(currTarget.sprite.clones.length, 1);
+    vm.deleteSprite(currTarget.id);
+    t.equal(currTarget.sprite.clones.length, 0);
+    t.end();
+});
+
+test('deleteSprite sets editing target as null when sprite being deleted is current editing target, and the only target in the runtime', t => {
+    const vm = new VirtualMachine();
+    const spr = new Sprite(null, vm.runtime);
+    const currTarget = spr.createClone();
+
+    vm.editingTarget = currTarget;
+    vm.runtime.targets = [currTarget];
+
+    vm.deleteSprite(currTarget.id);
+
+    t.equal(vm.runtime.targets.length, 0);
+    t.equal(vm.editingTarget, null);
+    t.end();
+});
+
+test('deleteSprite updates editingTarget when sprite being deleted is current editing target, and there is another target in the runtime', t => {
+    const vm = new VirtualMachine();
+    const spr1 = new Sprite(null, vm.runtime);
+    const spr2 = new Sprite(null, vm.runtime);
+    const currTarget = spr1.createClone();
+    const otherTarget = spr2.createClone();
+
+    vm.emitWorkspaceUpdate = () => null;
+
+    vm.runtime.targets = [currTarget, otherTarget];
+    vm.editingTarget = currTarget;
+
+    t.equal(vm.runtime.targets.length, 2);
+    vm.deleteSprite(currTarget.id);
+    t.equal(vm.runtime.targets.length, 1);
+    t.equal(vm.editingTarget.id, otherTarget.id);
+
+    // now let's try them in the other order in the runtime.targets list
+
+    // can't reuse deleted targets
+    const currTarget2 = spr1.createClone();
+    const otherTarget2 = spr2.createClone();
+
+    vm.runtime.targets = [otherTarget2, currTarget2];
+    vm.editingTarget = currTarget2;
+
+    t.equal(vm.runtime.targets.length, 2);
+    vm.deleteSprite(currTarget2.id);
+    t.equal(vm.editingTarget.id, otherTarget2.id);
+    t.equal(vm.runtime.targets.length, 1);
+
+    t.end();
+});
+
+
+
+test('duplicateSprite throws when there is no target with given id', t => {
+    const vm = new VirtualMachine();
+    vm.runtime.targets = [{
+        id: 'id',
+        isSprite: () => true,
+        sprite: {
+            name: 'this name'
+        }
+    }];
+    t.throws(
+        (() => vm.duplicateSprite('id1')),
+        new Error('No target with the provided id')
+    );
+    t.end();
+});
+
+test('duplicateSprite throws when used on a non-sprite target', t => {
+    const vm = new VirtualMachine();
+    vm.runtime.targets = [{
+        id: 'id',
+        isSprite: () => false
+    }];
+    t.throws(
+        (() => vm.duplicateSprite('id')),
+        new Error('Cannot duplicate non-sprite targets.')
+    );
+    t.end();
+});
+
+test('duplicateSprite throws when there is no sprite for the given target', t => {
+    const vm = new VirtualMachine();
+    vm.runtime.targets = [{
+        id: 'id',
+        isSprite: () => true,
+        sprite: null
+    }];
+    t.throws(
+        (() => vm.duplicateSprite('id')),
+        new Error ('No sprite associated with this target.')
+    );
+    t.end();
+});
+
+test('duplicateSprite duplicates a sprite when given id is associated with known sprite', t => {
+    const vm = new VirtualMachine();
+    const spr = new Sprite(null, vm.runtime);
+    const currTarget = spr.createClone();
+    vm.editingTarget = currTarget;
+
+    vm.emitWorkspaceUpdate = () => null;
+
+    vm.runtime.targets = [currTarget];
+    t.equal(vm.runtime.targets.length, 1);
+    vm.duplicateSprite(currTarget.id).then(() => {
+        t.equal(vm.runtime.targets.length, 2);
+        t.end();
+    });
+
+});
+
 test('emitWorkspaceUpdate', t => {
     const vm = new VirtualMachine();
     vm.runtime.targets = [