}
/**
- * Test a Paste action, where this adds sequences to an alignment.
+ * Test a Paste action, followed by Undo and Redo
*/
@Test(groups = { "Functional" }, enabled = false)
- // TODO fix so it works
- public void testPaste_addToAlignment()
+ public void testPaste_undo_redo()
{
+ // TODO code this test properly, bearing in mind that:
+ // Paste action requires something on the clipboard (Cut/Copy)
+ // - EditCommand.paste doesn't add sequences to the alignment
+ // ... that is done in AlignFrame.paste()
+ // ... unless as a Redo
+ // ...
+
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);
- EditCommand.paste(ec, new AlignmentI[] { al });
+ new EditCommand("Paste", Action.PASTE, newSeqs, 0, al.getWidth(), al);
assertEquals(6, al.getSequences().size());
assertEquals("1234567890", seqs[3].getSequenceAsString());
assertEquals("ACEFKL", seqs[4].getSequenceAsString());
{
// seem to need a dataset sequence on the edited sequence here
seqs[1].createDatasetSequence();
- new EditCommand("", Action.REPLACE, "ZXY", new SequenceI[] { seqs[1] },
+ assertEquals("fghjklmnopq", seqs[1].getSequenceAsString());
+ // NB command.number holds end position for a Replace command
+ new EditCommand("", Action.REPLACE, "Z-xY", new SequenceI[] { seqs[1] },
4, 8, al);
assertEquals("abcdefghjk", seqs[0].getSequenceAsString());
+ assertEquals("fghjZ-xYopq", seqs[1].getSequenceAsString());
+ assertEquals("fghjZxYopq",
+ seqs[1].getDatasetSequence().getSequenceAsString());
assertEquals("qrstuvwxyz", seqs[2].getSequenceAsString());
assertEquals("1234567890", seqs[3].getSequenceAsString());
- seqs[1] = new Sequence("seq1", "fghjZXYnopq");
+ }
+
+ /**
+ * Test the replace command (used to manually edit a sequence)
+ */
+ @Test(groups = { "Functional" })
+ public void testReplace_withGaps()
+ {
+ SequenceI seq = new Sequence("seq", "ABC--DEF");
+ seq.createDatasetSequence();
+ assertEquals("ABCDEF", seq.getDatasetSequence().getSequenceAsString());
+ assertEquals(1, seq.getStart());
+ assertEquals(6, seq.getEnd());
+
+ /*
+ * replace C- with XYZ
+ * NB arg4 = start column of selection for edit (base 0)
+ * arg5 = column after end of selection for edit
+ */
+ EditCommand edit = new EditCommand("", Action.REPLACE, "xyZ",
+ new SequenceI[]
+ { seq }, 2,
+ 4, al);
+ assertEquals("ABxyZ-DEF", seq.getSequenceAsString());
+ assertEquals(1, seq.getStart());
+ assertEquals(8, seq.getEnd());
+ assertEquals("ABxyZDEF",
+ seq.getDatasetSequence().getSequenceAsString());
+ assertEquals(8, seq.getDatasetSequence().getEnd());
+
+ /*
+ * undo the edit
+ */
+ AlignmentI[] views = new AlignmentI[]
+ { new Alignment(new SequenceI[] { seq }) };
+ edit.undoCommand(views);
+
+ assertEquals("ABC--DEF", seq.getSequenceAsString());
+ assertEquals("ABCDEF", seq.getDatasetSequence().getSequenceAsString());
+ assertEquals(1, seq.getStart());
+ assertEquals(6, seq.getEnd());
+ assertEquals(6, seq.getDatasetSequence().getEnd());
+
+ /*
+ * redo the edit
+ */
+ edit.doCommand(views);
+
+ assertEquals("ABxyZ-DEF", seq.getSequenceAsString());
+ assertEquals(1, seq.getStart());
+ assertEquals(8, seq.getEnd());
+ assertEquals("ABxyZDEF",
+ seq.getDatasetSequence().getSequenceAsString());
+ assertEquals(8, seq.getDatasetSequence().getEnd());
+
+ }
+
+ /**
+ * Test replace command when it doesn't cause a sequence edit (see comment in
+ */
+ @Test(groups = { "Functional" })
+ public void testReplaceFirstResiduesWithGaps()
+ {
+ // test replace when gaps are inserted at start. Start/end should change
+ // w.r.t. original edited sequence.
+ SequenceI dsseq = seqs[1].getDatasetSequence();
+ EditCommand edit = new EditCommand("", Action.REPLACE, "----",
+ new SequenceI[]
+ { seqs[1] }, 0, 4, al);
+
+ // trimmed start
+ assertEquals("----klmnopq", seqs[1].getSequenceAsString());
+ // and ds is preserved
+ assertTrue(dsseq == seqs[1].getDatasetSequence());
+ // and it is unchanged
+ assertEquals("fghjklmnopq", dsseq.getSequenceAsString());
+ // and that alignment sequence start has been adjusted
+ assertEquals(5, seqs[1].getStart());
+ assertEquals(11, seqs[1].getEnd());
+
+ AlignmentI[] views = new AlignmentI[] { new Alignment(seqs) };
+ // and undo
+ edit.undoCommand(views);
+
+ // dataset sequence unchanged
+ assertTrue(dsseq == seqs[1].getDatasetSequence());
+ // restore sequence
+ assertEquals("fghjklmnopq", seqs[1].getSequenceAsString());
+ // and start/end numbering also restored
+ assertEquals(1, seqs[1].getStart());
+ assertEquals(11, seqs[1].getEnd());
+
+ // now redo
+ edit.undoCommand(views);
+
+ // and repeat asserts for the original edit
+
+ // trimmed start
+ assertEquals("----klmnopq", seqs[1].getSequenceAsString());
+ // and ds is preserved
+ assertTrue(dsseq == seqs[1].getDatasetSequence());
+ // and it is unchanged
+ assertEquals("fghjklmnopq", dsseq.getSequenceAsString());
+ // and that alignment sequence start has been adjusted
+ assertEquals(5, seqs[1].getStart());
+ assertEquals(11, seqs[1].getEnd());
+
}
/**
* create a sequence features on each subrange of 1-5
*/
SequenceI seq0 = new Sequence("seq", "ABCDE");
+ int start = 8;
+ int end = 12;
+ seq0.setStart(start);
+ seq0.setEnd(end);
AlignmentI alignment = new Alignment(new SequenceI[] { seq0 });
alignment.setDataset(null);
- for (int from = 1; from <= seq0.getLength(); from++)
+
+ /*
+ * create a new alignment with shared dataset sequence
+ */
+ AlignmentI copy = new Alignment(
+ new SequenceI[]
+ { alignment.getDataset().getSequenceAt(0).deriveSequence() });
+ SequenceI copySeq0 = copy.getSequenceAt(0);
+
+ for (int from = start; from <= end; from++)
{
- for (int to = from; to <= seq0.getLength(); to++)
+ for (int to = from; to <= end; to++)
{
String desc = String.format("%d-%d", from, to);
SequenceFeature sf = new SequenceFeature("test", desc, from, to,
// sanity check
List<SequenceFeature> sfs = seq0.getSequenceFeatures();
assertEquals(func(5), sfs.size());
+ assertEquals(sfs, copySeq0.getSequenceFeatures());
+ String copySequenceFeatures = copySeq0.getSequenceFeatures().toString();
/*
- * now perform all possible cuts of subranges of 1-5 (followed by Undo)
+ * now perform all possible cuts of subranges of columns 1-5
* and validate the resulting remaining sequence features!
*/
SequenceI[] sqs = new SequenceI[] { seq0 };
EditCommand ec = new EditCommand("Cut", Action.CUT, sqs, from, (to
- from + 1), alignment);
final String msg = String.format("Cut %d-%d ", from + 1, to + 1);
+ boolean newDatasetSequence = copySeq0.getDatasetSequence() != seq0
+ .getDatasetSequence();
+
+ verifyCut(seq0, from, to, msg, start);
+
+ /*
+ * verify copy alignment dataset sequence unaffected
+ */
+ assertEquals("Original dataset sequence was modified",
+ copySequenceFeatures,
+ copySeq0.getSequenceFeatures().toString());
- verifyCut(seq0, from, to, msg);
+ /*
+ * verify any new dataset sequence was added to the
+ * alignment dataset
+ */
+ assertEquals("Wrong Dataset size after " + msg,
+ newDatasetSequence ? 2 : 1,
+ alignment.getDataset().getHeight());
/*
- * undo and verify
+ * undo and verify all restored
*/
AlignmentI[] views = new AlignmentI[] { alignment };
ec.undoCommand(views);
verifyUndo(from, to, sfs);
/*
+ * verify copy alignment dataset sequence still unaffected
+ * and alignment dataset has shrunk (if it was added to)
+ */
+ assertEquals("Original dataset sequence was modified",
+ copySequenceFeatures,
+ copySeq0.getSequenceFeatures().toString());
+ assertEquals("Wrong Dataset size after Undo of " + msg, 1,
+ alignment.getDataset().getHeight());
+
+ /*
* redo and verify
*/
ec.doCommand(views);
- verifyCut(seq0, from, to, msg);
+ verifyCut(seq0, from, to, msg, start);
+
+ /*
+ * verify copy alignment dataset sequence unaffected
+ * and any new dataset sequence readded to alignment dataset
+ */
+ assertEquals("Original dataset sequence was modified",
+ copySequenceFeatures,
+ copySeq0.getSequenceFeatures().toString());
+ assertEquals("Wrong Dataset size after Redo of " + msg,
+ newDatasetSequence ? 2 : 1,
+ alignment.getDataset().getHeight());
/*
* undo ready for next cut
*/
ec.undoCommand(views);
+
+ /*
+ * final verify that copy alignment dataset sequence is still unaffected
+ * and that alignment dataset has shrunk
+ */
+ assertEquals("Original dataset sequence was modified",
+ copySequenceFeatures,
+ copySeq0.getSequenceFeatures().toString());
+ assertEquals("Wrong Dataset size after final Undo of " + msg, 1,
+ alignment.getDataset().getHeight());
}
}
}
* @param from
* @param to
* @param msg
+ * @param seqStart
*/
protected void verifyCut(SequenceI seq0, int from, int to,
- final String msg)
+ final String msg, int seqStart)
{
List<SequenceFeature> sfs;
sfs = seq0.getSequenceFeatures();
*/
for (SequenceFeature sf : sfs)
{
- verifyFeatureRelocation(sf, from + 1, to + 1, !datasetRetained);
+ verifyFeatureRelocation(sf, from + 1, to + 1, !datasetRetained,
+ seqStart);
}
}
*
* @param sf
* @param from
- * start of cut (first residue cut)
+ * start of cut (first residue cut 1..)
* @param to
- * end of cut (last residue cut)
+ * end of cut (last residue cut 1..)
* @param newDataset
+ * @param seqStart
*/
private void verifyFeatureRelocation(SequenceFeature sf, int from, int to,
- boolean newDataset)
+ boolean newDataset, int seqStart)
{
// TODO handle the gapped sequence case as well
int cutSize = to - from + 1;
final int oldFrom = ((Integer) sf.getValue("from")).intValue();
final int oldTo = ((Integer) sf.getValue("to")).intValue();
+ final int oldFromPosition = oldFrom - seqStart + 1; // 1..
+ final int oldToPosition = oldTo - seqStart + 1; // 1..
String msg = String.format(
"Feature %s relocated to %d-%d after cut of %d-%d",
assertEquals("0: " + msg, oldFrom, sf.getBegin());
assertEquals("0: " + msg, oldTo, sf.getEnd());
}
- else if (oldTo < from)
+ else if (oldToPosition < from)
{
// before cut region so unchanged
assertEquals("1: " + msg, oldFrom, sf.getBegin());
assertEquals("2: " + msg, oldTo, sf.getEnd());
}
- else if (oldFrom > to)
+ else if (oldFromPosition > to)
{
// follows cut region - shift by size of cut
assertEquals("3: " + msg, newDataset ? oldFrom - cutSize : oldFrom,
assertEquals("4: " + msg, newDataset ? oldTo - cutSize : oldTo,
sf.getEnd());
}
- else if (oldFrom < from && oldTo > to)
+ else if (oldFromPosition < from && oldToPosition > to)
{
// feature encloses cut region - shrink it right
assertEquals("5: " + msg, oldFrom, sf.getBegin());
assertEquals("6: " + msg, oldTo - cutSize, sf.getEnd());
}
- else if (oldFrom < from)
+ else if (oldFromPosition < from)
{
// feature overlaps left side of cut region - truncated right
- assertEquals("7: " + msg, from - 1, sf.getEnd());
+ assertEquals("7: " + msg, from - 1 + seqStart - 1, sf.getEnd());
}
- else if (oldTo > to)
+ else if (oldToPosition > to)
{
// feature overlaps right side of cut region - truncated left
- assertEquals("8: " + msg, newDataset ? from : to + 1, sf.getBegin());
+ assertEquals("8: " + msg, newDataset ? from + seqStart - 1 : to + 1,
+ sf.getBegin());
assertEquals("9: " + msg, newDataset ? from + oldTo - to - 1 : oldTo,
sf.getEnd());
}