package terminal; import static com.googlecode.lanterna.input.KeyType.*; import static terminal.LispTerminal.END_OF_SEGMENT; import org.junit.*; public class LispTerminalTest { private VirtualTerminalInteractor terminal; @Before public void setUp() { terminal = new VirtualTerminalInteractor(); terminal.start(); } @After public void tearDown() { terminal.stop(); } @Test public void leftArrowDoesNotMovePastOrigin() { terminal.pressKey(ArrowLeft); terminal.assertCursorPosition(0, 0); } @Test public void leftArrowWorksAfterEnteringCharacters() { terminal.enterCharacters("abc"); terminal.assertCursorPosition(3, 0); terminal.pressKey(ArrowLeft); terminal.assertCursorPosition(2, 0); terminal.pressKey(ArrowLeft); terminal.assertCursorPosition(1, 0); terminal.pressKey(ArrowLeft); terminal.assertCursorPosition(0, 0); terminal.pressKey(ArrowLeft); terminal.assertCursorPosition(0, 0); } @Test public void leftArrowWorksAcrossRows() { terminal.setColumns(5); terminal.enterCharacters("123451"); terminal.assertCursorPosition(1, 1); terminal.pressKeyTimes(ArrowLeft, 2); terminal.assertCursorPosition(4, 0); } @Test public void rightArrowDoesNotMovePastEndOfInput() { terminal.pressKey(ArrowRight); terminal.assertCursorPosition(0, 0); } @Test public void rightArrowWorksAfterMovingLeft() { terminal.enterCharacters("12"); terminal.assertCursorPosition(2, 0); terminal.pressKey(ArrowLeft); terminal.assertCursorPosition(1, 0); terminal.pressKey(ArrowRight); terminal.assertCursorPosition(2, 0); terminal.pressKey(ArrowRight); terminal.assertCursorPosition(2, 0); } @Test public void rightArrowWorksAcrossRow() { terminal.setColumns(5); terminal.enterCharacters("123451"); terminal.assertCursorPosition(1, 1); terminal.pressKeyTimes(ArrowLeft, 3); terminal.assertCursorPosition(3, 0); terminal.pressKeyTimes(ArrowRight, 3); terminal.assertCursorPosition(1, 1); } @Test public void characterKeyIsEchoed() { terminal.enterCharacter('a'); terminal.assertCursorPosition(1, 0); terminal.assertCharacterAtPosition('a', 0, 0); } @Test public void characterIsInserted() { terminal.enterCharacters("abcd"); terminal.pressKeyTimes(ArrowLeft, 2); terminal.enterCharacter('x'); terminal.assertCharacterPositions(new char[][] { { 'a', 'b', 'x', 'c', 'd' } }); } @Test public void characterIsInserted_PushesInputToNextRow() { terminal.setColumns(4); terminal.enterCharacters("abcd"); terminal.pressKeyTimes(ArrowLeft, 2); terminal.enterCharacter('x'); terminal.assertCharacterPositions(new char[][] { { 'a', 'b', 'x', 'c' }, { 'd', ' ', ' ', ' ' } }); } @Test public void backspaceDoesNothingAtOrigin() { terminal.pressKey(Backspace); terminal.assertCursorPosition(0, 0); } @Test public void backspaceWorksAfterInput() { terminal.enterCharacters("12345"); terminal.pressKeyTimes(Backspace, 2); terminal.assertCursorPosition(3, 0); terminal.assertCharacterPositions(new char[][] { { '1', '2', '3', ' ', ' ', ' ' } }); } @Test public void backspaceWorksAcrossRow() { terminal.setColumns(4); terminal.enterCharacters("1234567"); terminal.pressKeyTimes(Backspace, 5); terminal.assertCursorPosition(2, 0); terminal.assertCharacterPositions(new char[][] { { '1', '2', ' ', ' ' }, { ' ', ' ', ' ', ' ' } }); } @Test public void backspaceWorksInMiddleOfInput() { terminal.enterCharacters("12345"); terminal.pressKeyTimes(ArrowLeft, 2); terminal.pressKey(Backspace); terminal.assertCursorPosition(2, 0); terminal.assertCharacterPositions(new char[][] { { '1', '2', '4', '5' } }); } @Test public void deleteDoesNothingAtOrigin() { terminal.pressKey(Delete); terminal.assertCursorPosition(0, 0); } @Test public void deleteDoesNothingAtEndOfInput() { terminal.enterCharacters("del"); terminal.pressKey(Delete); terminal.assertCursorPosition(3, 0); terminal.assertCharacterPositions(new char[][] { { 'd', 'e', 'l' } }); } @Test public void deleteWorksAtStartOfInput() { terminal.enterCharacters("del"); terminal.pressKeyTimes(ArrowLeft, 3); terminal.pressKeyTimes(Delete, 3); terminal.assertCursorPosition(0, 0); terminal.assertCharacterPositions(new char[][] { { ' ', ' ', ' ' } }); } @Test public void deleteWorksAcrossRow() { terminal.setColumns(4); terminal.enterCharacters("delete"); terminal.pressKeyTimes(ArrowLeft, 5); terminal.pressKey(Delete); terminal.assertCursorPosition(1, 0); terminal.assertCharacterPositions(new char[][] { { 'd', 'l', 'e', 't' }, { 'e', ' ' } }); } @Test public void enterMovesToNextLine() { terminal.pressKey(Enter); terminal.assertCursorPosition(0, 1); } @Test public void enterWritesLineToPipedStream() { terminal.enterCharacters("enter"); terminal.pressKey(Enter); terminal.assertInputWritten("enter\n"); } @Test public void enterPressedInMiddleOfInput_WritesEntireLineToPipedStream() { terminal.enterCharacters("enter"); terminal.pressKeyTimes(ArrowLeft, 2); terminal.pressKey(Enter); terminal.assertInputWritten("enter\n"); } @Test public void enterAfterInsertedText_WritesLineToPipedStream() { terminal.enterCharacters("enter"); terminal.pressKeyTimes(ArrowLeft, 2); terminal.enterCharacters("||"); terminal.pressKey(Enter); terminal.assertInputWritten("ent||er\n"); } @Test public void enterAfterBackspace_WritesLineToPipedStream() { terminal.enterCharacters("enter"); terminal.pressKeyTimes(Backspace, 2); terminal.pressKey(Enter); terminal.assertInputWritten("ent\n"); } @Test public void enterAfterDelete_WritesLineToPipedStream() { terminal.enterCharacters("enter"); terminal.pressKeyTimes(ArrowLeft, 2); terminal.pressKeyTimes(Delete, 2); terminal.pressKey(Enter); terminal.assertInputWritten("ent\n"); } @Test public void controlDWorks() { terminal.enterCharacters("control-d"); terminal.enterControlCharacter('d'); terminal.assertInputStreamClosed(); terminal.assertInputWritten("control-d\n"); } @Test public void controlCWorks() { terminal.enterCharacters("ctrl-c"); terminal.enterControlCharacter('c'); terminal.produceOutput(""); terminal.assertInputStreamClosed(); terminal.assertInputWritten(""); terminal.assertCharacterPositions(new char[][] { { 'c', 't', 'r', 'l', '-', 'c', ' ', ' ', ' ' }, { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }); } @Test public void controlDWorksInMiddleOfInput() { terminal.enterCharacters("control-d"); terminal.pressKeyTimes(ArrowLeft, 2); terminal.enterControlCharacter('d'); terminal.assertInputStreamClosed(); terminal.assertInputWritten("control-d\n"); } @Test public void escapeDoesNothing() { terminal.pressKey(Escape); terminal.assertCursorPosition(0, 0); terminal.assertInputWritten(""); } @Test public void controlQDoesNothing() { terminal.enterControlCharacter('q'); terminal.assertCursorPosition(0, 0); terminal.assertInputWritten(""); } @Test public void controlEnterDoesNothing() { terminal.pressControlKey(Enter); terminal.assertCursorPosition(0, 0); terminal.assertInputWritten(""); } @Test public void outputIsWritten() { terminal.produceOutput("output"); terminal.assertCursorPosition(6, 0); terminal.assertCharacterPositions(new char[][] { { 'o', 'u', 't', 'p', 'u', 't' } }); } @Test public void endOfSegmentCharacterIsNotPrinted() { terminal.produceOutput("> " + END_OF_SEGMENT); terminal.assertCursorPosition(2, 0); terminal.assertCharacterPositions(new char[][] { { '>', ' ', ' ' } }); } @Test public void enterTextPastLastLineOfBuffer() { terminal.setColumns(3); terminal.setRows(2); terminal.enterCharacters("01201201"); terminal.assertCursorPosition(2, 1); terminal.assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '0', '1', ' ' } }); } @Test public void insertingTextPushesInputPastEndOfBuffer() { terminal.setColumns(3); terminal.setRows(4); terminal.pressKey(Enter); terminal.enterCharacters("00011122"); terminal.pressKeyTimes(ArrowLeft, 4); terminal.assertCursorPosition(1, 2); terminal.enterCharacters("zz"); terminal.assertCursorPosition(0, 2); terminal.assertCharacterPositions(new char[][] { { '0', '0', '0' }, { '1', 'z', 'z' }, { '1', '1', '2' }, { '2', ' ', ' ' } }); } @Test public void insertingTextDoesNothingWhenBufferFilled() { terminal.setColumns(3); terminal.setRows(3); terminal.enterCharacters("00011122"); terminal.pressKeyTimes(ArrowLeft, 4); terminal.assertCursorPosition(1, 1); terminal.enterCharacters("zz"); terminal.assertCursorPosition(1, 1); terminal.assertCharacterPositions(new char[][] { { '0', '0', '0' }, { '1', '1', '1' }, { '2', '2', ' ' } }); } @Test public void appendingTextDoesNothingWhenBufferFilled() { terminal.setColumns(3); terminal.setRows(3); terminal.enterCharacters("000111222333444"); terminal.assertCursorPosition(2, 2); terminal.assertCharacterPositions(new char[][] { { '0', '0', '0' }, { '1', '1', '1' }, { '2', '2', ' ' } }); } @Test public void printedOutputToEndOfRow_MovesCursorToNextRow() { terminal.setColumns(3); terminal.produceOutput("out"); terminal.assertCursorPosition(0, 1); } @Test public void printedOutputToEndOfBuffer_MovesCursorToNewRow() { terminal.setColumns(3); terminal.setRows(2); terminal.produceOutput("output"); terminal.assertCursorPosition(0, 1); terminal.assertCharacterPositions(new char[][] { { 'p', 'u', 't' }, { ' ', ' ', ' ' } }); } @Test public void outputDoesNotOverwriteInput_AndRedisplaysInput() { terminal.setColumns(3); terminal.enterCharacters("0123"); terminal.pressKeyTimes(ArrowLeft, 3); terminal.produceOutput("out"); terminal.assertCursorPosition(2, 3); terminal.assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '3', 'o', 'u' }, { 't', '0', '1' }, { '2', '3', ' ' }, { ' ', ' ', ' ' } }); } @Test public void outputEndsOnSecondToLastColumn_MovesToNewRow() { terminal.setColumns(3); terminal.enterCharacters("01234"); terminal.pressKeyTimes(ArrowLeft, 3); terminal.produceOutput("out"); terminal.assertCursorPosition(2, 4); terminal.assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '3', '4', 'o' }, { 'u', 't', ' ' }, { '0', '1', '2' }, { '3', '4', ' ' } }); } @Test public void outputEndsOnLastColumn_MovesToNewRow() { terminal.setColumns(3); terminal.enterCharacters("012345"); terminal.pressKeyTimes(ArrowLeft, 3); terminal.produceOutput("out"); terminal.assertCursorPosition(0, 5); terminal.assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '3', '4', '5' }, { 'o', 'u', 't' }, { '0', '1', '2' }, { '3', '4', '5' }, { ' ', ' ', ' ' } }); } @Test public void outputRedisplaysInputAtEndOfBuffer() { terminal.setColumns(3); terminal.setRows(4); terminal.enterCharacters("01234"); terminal.pressKeyTimes(ArrowLeft, 3); terminal.produceOutput("out"); terminal.assertCursorPosition(2, 3); terminal.assertCharacterPositions(new char[][] { { '3', '4', 'o' }, { 'u', 't', ' ' }, { '0', '1', '2' }, { '3', '4', ' ' } }); } @Test public void outputDoesNotOverwriteInput_AfterEnter() { terminal.setColumns(3); terminal.enterCharacters("01201201"); terminal.pressKeyTimes(ArrowLeft, 5); terminal.pressKey(Enter); terminal.produceOutput("out"); terminal.assertCursorPosition(0, 4); terminal.assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '0', '1', '2' }, { '0', '1', ' ' }, { 'o', 'u', 't' }, { ' ', ' ', ' ' } }); } @Test public void resizeIsHandledGracefully() { terminal.enterCharacters("resize"); terminal.pressKey(Enter); terminal.enterCharacters("test"); terminal.setColumns(3); terminal.assertCursorPosition(1, 1); terminal.assertCharacterPositions(new char[][] { { 't', 'e', 's' }, { 't', ' ', ' ' } }); } @Test public void backspaceWorksAfterResize() { terminal.enterCharacters("resize"); terminal.pressKey(Enter); terminal.enterCharacters("test"); terminal.setColumns(3); terminal.pressKeyTimes(Backspace, 20); terminal.assertCursorPosition(0, 0); terminal.assertCharacterPositions(new char[][] { { ' ', ' ', ' ' }, { ' ', ' ', ' ' } }); } @Test public void deleteWorksAfterResize() { terminal.enterCharacters("resize"); terminal.pressKey(Enter); terminal.enterCharacters("test"); terminal.setColumns(3); terminal.pressKeyTimes(ArrowLeft, 20); terminal.pressKeyTimes(Delete, 20); terminal.pressKeyTimes(ArrowRight, 20); terminal.assertCursorPosition(0, 0); terminal.assertCharacterPositions(new char[][] { { ' ', ' ', ' ' }, { ' ', ' ', ' ' } }); } @Test public void controlSequencesAreNotPrinted() { terminal.produceOutput("\u001B[32mcontrol\u001B[0mseq"); terminal.assertCharacterPositions(new char[][] { { 'c', 'o', 'n', 't', 'r', 'o', 'l', 's', 'e', 'q' } }); } @Test public void upArrowWorks() { terminal.enterCharacters("(one)"); terminal.pressKey(Enter); terminal.enterCharacters("(two)"); terminal.pressKey(Enter); terminal.pressKey(ArrowUp); terminal.assertScreenText("(one)", "(two)", "(two)"); terminal.assertCursorPosition(5, 2); } @Test public void upArrowErasesCurrentLine() { terminal.enterCharacters("(one)"); terminal.pressKey(Enter); terminal.enterCharacters("(two)"); terminal.pressKey(Enter); terminal.enterCharacters("(three)"); terminal.pressKey(ArrowUp); terminal.assertScreenText("(one)", "(two)", "(two) "); terminal.assertCursorPosition(5, 2); } @Test public void upArrowStopsAtFirstLine() { terminal.enterCharacters("(one)"); terminal.pressKey(Enter); terminal.enterCharacters("(two)"); terminal.pressKey(Enter); terminal.pressKeyTimes(ArrowUp, 5); terminal.assertScreenText("(one)", "(two)", "(one)"); terminal.assertCursorPosition(5, 2); } @Test public void originIsUpdatedWhenPreviousLineMovesPastEndOfBuffer() { terminal.setRows(3); terminal.setColumns(3); terminal.enterCharacters("12345"); terminal.pressKey(Enter); terminal.pressKey(ArrowUp); terminal.assertScreenText("45 ", "123", "45 "); terminal.pressKeyTimes(ArrowLeft, 10); terminal.assertCursorPosition(0, 1); } @Test public void downArrowWorks() { terminal.enterCharacters("(one)"); terminal.pressKey(Enter); terminal.enterCharacters("(two)"); terminal.pressKey(Enter); terminal.enterCharacters("(three)"); terminal.pressKey(ArrowUp); terminal.pressKey(ArrowDown); terminal.assertScreenText("(one)", "(two)", "(three)"); terminal.assertCursorPosition(7, 2); } @Test public void downArrowStopsAtLastLine() { terminal.pressKeyTimes(ArrowDown, 5); terminal.assertScreenText(" "); terminal.assertCursorPosition(0, 0); } }