+package jalview.commands;
+
+import static org.junit.Assert.assertEquals;
+import jalview.commands.EditCommand.Action;
+import jalview.commands.EditCommand.Edit;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Unit tests for EditCommand
+ *
+ * @author gmcarstairs
+ *
+ */
+public class EditCommandTest
+{
+
+ private EditCommand testee;
+
+ private SequenceI[] seqs;
+
+ private Alignment al;
+
+ @Before
+ public void setUp()
+ {
+ testee = new EditCommand();
+ seqs = new SequenceI[4];
+ seqs[0] = new Sequence("seq0", "abcdefghjk");
+ seqs[1] = new Sequence("seq1", "fghjklmnopq");
+ seqs[2] = new Sequence("seq2", "qrstuvwxyz");
+ seqs[3] = new Sequence("seq3", "1234567890");
+ al = new Alignment(seqs);
+ al.setGapCharacter('?');
+ }
+
+ /**
+ * Test inserting gap characters
+ */
+ @Test
+ public void testAppendEdit_insertGap()
+ {
+ // set a non-standard gap character to prove it is actually used
+ testee.appendEdit(Action.INSERT_GAP, seqs, 4, 3, al, true);
+ assertEquals("abcd???efghjk", seqs[0].getSequenceAsString());
+ assertEquals("fghj???klmnopq", seqs[1].getSequenceAsString());
+ assertEquals("qrst???uvwxyz", seqs[2].getSequenceAsString());
+ assertEquals("1234???567890", seqs[3].getSequenceAsString());
+
+ // todo: test for handling out of range positions?
+ }
+
+ /**
+ * Test deleting characters from sequences. Note the deleteGap() action does
+ * not check that only gap characters are being removed.
+ */
+ @Test
+ public void testAppendEdit_deleteGap()
+ {
+ testee.appendEdit(Action.DELETE_GAP, seqs, 4, 3, al, true);
+ assertEquals("abcdhjk", seqs[0].getSequenceAsString());
+ assertEquals("fghjnopq", seqs[1].getSequenceAsString());
+ assertEquals("qrstxyz", seqs[2].getSequenceAsString());
+ assertEquals("1234890", seqs[3].getSequenceAsString());
+ }
+
+ /**
+ * Test a cut action. The command should store the cut characters to support
+ * undo.
+ */
+ @Test
+ public void testCut()
+ {
+ Edit ec = testee.new Edit(Action.CUT, seqs, 4, 3, al);
+ testee.cut(ec, new AlignmentI[]
+ { al });
+ assertEquals("abcdhjk", seqs[0].getSequenceAsString());
+ assertEquals("fghjnopq", seqs[1].getSequenceAsString());
+ assertEquals("qrstxyz", seqs[2].getSequenceAsString());
+ assertEquals("1234890", seqs[3].getSequenceAsString());
+
+ assertEquals("efg", new String(ec.string[0]));
+ assertEquals("klm", new String(ec.string[1]));
+ assertEquals("uvw", new String(ec.string[2]));
+ assertEquals("567", new String(ec.string[3]));
+ // TODO: case where whole sequence is deleted as nothing left; etc
+ }
+
+ /**
+ * Test a Paste action, where this adds sequences to an alignment.
+ */
+ @Test
+ @Ignore
+ // TODO fix so it works
+ public void testPaste_addToAlignment()
+ {
+ SequenceI[] newSeqs = new SequenceI[2];
+ newSeqs[0] = new Sequence("newseq0", "ACEFKL");
+ newSeqs[1] = new Sequence("newseq1", "JWMPDH");
+
+ Edit ec = testee.new Edit(Action.PASTE, newSeqs, 0, al.getWidth(), al);
+ testee.paste(ec, new AlignmentI[]
+ { al });
+ assertEquals(6, al.getSequences().size());
+ assertEquals("1234567890", seqs[3].getSequenceAsString());
+ assertEquals("ACEFKL", seqs[4].getSequenceAsString());
+ assertEquals("JWMPDH", seqs[5].getSequenceAsString());
+ }
+
+ /**
+ * Test insertGap followed by undo command
+ */
+ @Test
+ public void testUndo_insertGap()
+ {
+ // Edit ec = testee.new Edit(Action.INSERT_GAP, seqs, 4, 3, '?');
+ testee.appendEdit(Action.INSERT_GAP, seqs, 4, 3, al, true);
+ // check something changed
+ assertEquals("abcd???efghjk", seqs[0].getSequenceAsString());
+ testee.undoCommand(new AlignmentI[]
+ { al });
+ assertEquals("abcdefghjk", seqs[0].getSequenceAsString());
+ assertEquals("fghjklmnopq", seqs[1].getSequenceAsString());
+ assertEquals("qrstuvwxyz", seqs[2].getSequenceAsString());
+ assertEquals("1234567890", seqs[3].getSequenceAsString());
+ }
+
+ /**
+ * Test deleteGap followed by undo command
+ */
+ @Test
+ public void testUndo_deleteGap()
+ {
+ testee.appendEdit(Action.DELETE_GAP, seqs, 4, 3, al, true);
+ // check something changed
+ assertEquals("abcdhjk", seqs[0].getSequenceAsString());
+ testee.undoCommand(new AlignmentI[]
+ { al });
+ // deleteGap doesn't 'remember' deleted characters, only gaps get put back
+ assertEquals("abcd???hjk", seqs[0].getSequenceAsString());
+ assertEquals("fghj???nopq", seqs[1].getSequenceAsString());
+ assertEquals("qrst???xyz", seqs[2].getSequenceAsString());
+ assertEquals("1234???890", seqs[3].getSequenceAsString());
+ }
+
+ /**
+ * Test several commands followed by an undo command
+ */
+ @Test
+ public void testUndo_multipleCommands()
+ {
+ // delete positions 3/4/5 (counting from 1)
+ testee.appendEdit(Action.DELETE_GAP, seqs, 2, 3, al, true);
+ assertEquals("abfghjk", seqs[0].getSequenceAsString());
+ assertEquals("1267890", seqs[3].getSequenceAsString());
+
+ // insert 2 gaps after the second residue
+ testee.appendEdit(Action.INSERT_GAP, seqs, 2, 2, al, true);
+ assertEquals("ab??fghjk", seqs[0].getSequenceAsString());
+ assertEquals("12??67890", seqs[3].getSequenceAsString());
+
+ // delete positions 4/5/6
+ testee.appendEdit(Action.DELETE_GAP, seqs, 3, 3, al, true);
+ assertEquals("ab?hjk", seqs[0].getSequenceAsString());
+ assertEquals("12?890", seqs[3].getSequenceAsString());
+
+ // undo edit commands
+ testee.undoCommand(new AlignmentI[]
+ { al });
+ assertEquals("ab?????hjk", seqs[0].getSequenceAsString());
+ assertEquals("12?????890", seqs[3].getSequenceAsString());
+ }
+
+ /**
+ * Unit test for JAL-1594 bug: click and drag sequence right to insert gaps -
+ * undo did not remove them all.
+ */
+ @Test
+ public void testUndo_multipleInsertGaps()
+ {
+ testee.appendEdit(Action.INSERT_GAP, seqs, 4, 1, al, true);
+ testee.appendEdit(Action.INSERT_GAP, seqs, 5, 1, al, true);
+ testee.appendEdit(Action.INSERT_GAP, seqs, 6, 1, al, true);
+
+ // undo edit commands
+ testee.undoCommand(new AlignmentI[]
+ { al });
+ assertEquals("abcdefghjk", seqs[0].getSequenceAsString());
+ assertEquals("1234567890", seqs[3].getSequenceAsString());
+
+ }
+
+ /**
+ * Test cut followed by undo command
+ */
+ @Test
+ public void testUndo_cut()
+ {
+ testee.appendEdit(Action.CUT, seqs, 4, 3, al, true);
+ // check something changed
+ assertEquals("abcdhjk", seqs[0].getSequenceAsString());
+ testee.undoCommand(new AlignmentI[]
+ { al });
+ assertEquals("abcdefghjk", seqs[0].getSequenceAsString());
+ assertEquals("fghjklmnopq", seqs[1].getSequenceAsString());
+ assertEquals("qrstuvwxyz", seqs[2].getSequenceAsString());
+ assertEquals("1234567890", seqs[3].getSequenceAsString());
+ }
+
+ /**
+ * Test the replace command (used to manually edit a sequence)
+ */
+ @Test
+ public void testReplace()
+ {
+ // seem to need a dataset sequence on the edited sequence here
+ seqs[1].setDatasetSequence(seqs[1]);
+ new EditCommand("", Action.REPLACE, "ZXY", new SequenceI[]
+ { seqs[1] }, 4, 8, al);
+ assertEquals("abcdefghjk", seqs[0].getSequenceAsString());
+ assertEquals("qrstuvwxyz", seqs[2].getSequenceAsString());
+ assertEquals("1234567890", seqs[3].getSequenceAsString());
+ seqs[1] = new Sequence("seq1", "fghjZXYnopq");
+
+ }
+}