-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Issue with undo/redo and modifications to filtered lists #737 #792
Changes from all commits
5c9b14d
3825b99
d840c89
3563cea
ea2d584
4be7dd7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,13 @@ | ||
package seedu.address.logic.commands; | ||
|
||
import static org.junit.Assert.assertFalse; | ||
import static org.junit.Assert.assertNotEquals; | ||
import static org.junit.Assert.assertTrue; | ||
import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; | ||
import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; | ||
import static seedu.address.logic.commands.CommandTestUtil.showFirstPersonOnly; | ||
import static seedu.address.logic.commands.CommandTestUtil.prepareRedoCommand; | ||
import static seedu.address.logic.commands.CommandTestUtil.prepareUndoCommand; | ||
import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; | ||
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; | ||
import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; | ||
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; | ||
|
@@ -21,7 +24,8 @@ | |
import seedu.address.model.person.Person; | ||
|
||
/** | ||
* Contains integration tests (interaction with the Model) and unit tests for {@code DeleteCommand}. | ||
* Contains integration tests (interaction with the Model, UndoCommand and RedoCommand) and unit tests for | ||
* {@code DeleteCommand}. | ||
*/ | ||
public class DeleteCommandTest { | ||
|
||
|
@@ -50,7 +54,7 @@ public void execute_invalidIndexUnfilteredList_throwsCommandException() throws E | |
|
||
@Test | ||
public void execute_validIndexFilteredList_success() throws Exception { | ||
showFirstPersonOnly(model); | ||
showPersonAtIndex(model, INDEX_FIRST_PERSON); | ||
|
||
Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); | ||
DeleteCommand deleteCommand = prepareCommand(INDEX_FIRST_PERSON); | ||
|
@@ -66,7 +70,7 @@ public void execute_validIndexFilteredList_success() throws Exception { | |
|
||
@Test | ||
public void execute_invalidIndexFilteredList_throwsCommandException() { | ||
showFirstPersonOnly(model); | ||
showPersonAtIndex(model, INDEX_FIRST_PERSON); | ||
|
||
Index outOfBoundIndex = INDEX_SECOND_PERSON; | ||
// ensures that outOfBoundIndex is still in bounds of address book list | ||
|
@@ -78,17 +82,88 @@ public void execute_invalidIndexFilteredList_throwsCommandException() { | |
} | ||
|
||
@Test | ||
public void equals() { | ||
DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST_PERSON); | ||
DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND_PERSON); | ||
public void executeUndoRedo_validIndexUnfilteredList_success() throws Exception { | ||
UndoRedoStack undoRedoStack = new UndoRedoStack(); | ||
UndoCommand undoCommand = prepareUndoCommand(model, undoRedoStack); | ||
RedoCommand redoCommand = prepareRedoCommand(model, undoRedoStack); | ||
Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, method name says There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If im not wrong, since we are doing assertion tests with the model and the integration tests for the interaction with the model, only the @Zhiyuan-Amos May I have your opinion on this? Not too sure if using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually what I mean is, the method name should be updated to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned below, we are working on the unfiltered list here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm okay but its not intuitive enough to know whether we're working on the unfiltered or filtered list here because the exact same line of code I assume in order to set filter for the person list, we need to execute the code There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yep. iirc, we placed the line Would putting this back on the top make it clearer like in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay actually my few concerns are:
I would say, it would be better if there is a @Zhiyuan-Amos , what do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yup I think that using So as of now, I'm ok with using |
||
DeleteCommand deleteCommand = prepareCommand(INDEX_FIRST_PERSON); | ||
Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); | ||
|
||
// delete -> first person deleted | ||
deleteCommand.execute(); | ||
undoRedoStack.push(deleteCommand); | ||
|
||
// undo -> reverts addressbook back to previous state and filtered person list to show all persons | ||
assertCommandSuccess(undoCommand, model, UndoCommand.MESSAGE_SUCCESS, expectedModel); | ||
|
||
// redo -> same first person deleted again | ||
expectedModel.deletePerson(personToDelete); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you include a test to check that the first person in filtered list and unfiltered list are different? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test is executed on an unfiltered list, so the person being deleted should be on index 1 on both occasions. :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In that case, this test doesn't test for the issue earlier isnt it? where redo deletes the wrong person. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the regression test which handles the issue of redo deletes wrong person is in [3/6] and [4/6]. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, my confusion comes from the part above. |
||
assertCommandSuccess(redoCommand, model, RedoCommand.MESSAGE_SUCCESS, expectedModel); | ||
} | ||
|
||
@Test | ||
public void executeUndoRedo_invalidIndexUnfilteredList_failure() { | ||
UndoRedoStack undoRedoStack = new UndoRedoStack(); | ||
UndoCommand undoCommand = prepareUndoCommand(model, undoRedoStack); | ||
RedoCommand redoCommand = prepareRedoCommand(model, undoRedoStack); | ||
Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); | ||
DeleteCommand deleteCommand = prepareCommand(outOfBoundIndex); | ||
|
||
// execution failed -> deleteCommand not pushed into undoRedoStack | ||
assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); | ||
|
||
// no commands in undoRedoStack -> undoCommand and redoCommand fail | ||
assertCommandFailure(undoCommand, model, UndoCommand.MESSAGE_FAILURE); | ||
assertCommandFailure(redoCommand, model, RedoCommand.MESSAGE_FAILURE); | ||
} | ||
|
||
/** | ||
* 1. Deletes a {@code Person} from a filtered list. | ||
* 2. Undo the deletion. | ||
* 3. The unfiltered list should be shown now. Verify that the index of the previously deleted person in the | ||
* unfiltered list is different from the index at the filtered list. | ||
* 4. Redo the deletion. This ensures {@code RedoCommand} deletes the person object regardless of indexing. | ||
*/ | ||
@Test | ||
public void executeUndoRedo_validIndexFilteredList_samePersonDeleted() throws Exception { | ||
UndoRedoStack undoRedoStack = new UndoRedoStack(); | ||
UndoCommand undoCommand = prepareUndoCommand(model, undoRedoStack); | ||
RedoCommand redoCommand = prepareRedoCommand(model, undoRedoStack); | ||
DeleteCommand deleteCommand = prepareCommand(INDEX_FIRST_PERSON); | ||
Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); | ||
|
||
showPersonAtIndex(model, INDEX_SECOND_PERSON); | ||
Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); | ||
// delete -> deletes second person in unfiltered person list / first person in filtered person list | ||
deleteCommand.execute(); | ||
undoRedoStack.push(deleteCommand); | ||
|
||
// undo -> reverts addressbook back to previous state and filtered person list to show all persons | ||
assertCommandSuccess(undoCommand, model, UndoCommand.MESSAGE_SUCCESS, expectedModel); | ||
|
||
expectedModel.deletePerson(personToDelete); | ||
assertNotEquals(personToDelete, model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased())); | ||
// redo -> deletes same second person in unfiltered person list | ||
assertCommandSuccess(redoCommand, model, RedoCommand.MESSAGE_SUCCESS, expectedModel); | ||
} | ||
|
||
@Test | ||
public void equals() throws Exception { | ||
DeleteCommand deleteFirstCommand = prepareCommand(INDEX_FIRST_PERSON); | ||
DeleteCommand deleteSecondCommand = prepareCommand(INDEX_SECOND_PERSON); | ||
|
||
// same object -> returns true | ||
assertTrue(deleteFirstCommand.equals(deleteFirstCommand)); | ||
|
||
// same values -> returns true | ||
DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST_PERSON); | ||
DeleteCommand deleteFirstCommandCopy = prepareCommand(INDEX_FIRST_PERSON); | ||
assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy)); | ||
|
||
// one command preprocessed when previously equal -> returns false | ||
deleteFirstCommandCopy.preprocessUndoableCommand(); | ||
assertFalse(deleteFirstCommand.equals(deleteFirstCommandCopy)); | ||
|
||
// different types -> returns false | ||
assertFalse(deleteFirstCommand.equals(1)); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can merge these methods.
prepareCommand(Class commandClass, Model model, UndoRedoStack undoRedoStack)
. Not too sure tho x.xThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will try this in my next iteration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried something like this:
Can't use
prepareCommand
as the name sinceDeleteCommandTest
andEditCommandTest
has it for their own commands.Looks quite ugly to me though =x.
What's your opinion on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok let's revert this then.