diff --git a/tests/end2end/features/caret.feature b/tests/end2end/features/caret.feature index 6d2245a89..422919cea 100644 --- a/tests/end2end/features/caret.feature +++ b/tests/end2end/features/caret.feature @@ -7,224 +7,6 @@ Feature: Caret mode Given I open data/caret.html And I run :tab-only ;; enter-mode caret - # document - - Scenario: Selecting the entire document - When I run :toggle-selection - And I run :move-to-end-of-document - And I run :yank selection - Then the clipboard should contain: - one two three - eins zwei drei - - four five six - vier fünf sechs - - Scenario: Moving to end and to start of document - When I run :move-to-end-of-document - And I run :move-to-start-of-document - And I run :toggle-selection - And I run :move-to-end-of-word - And I run :yank selection - Then the clipboard should contain "one" - - Scenario: Moving to end and to start of document (with selection) - When I run :move-to-end-of-document - And I run :toggle-selection - And I run :move-to-start-of-document - And I run :yank selection - Then the clipboard should contain: - one two three - eins zwei drei - - four five six - vier fünf sechs - - # block - - Scenario: Selecting a block - When I run :toggle-selection - And I run :move-to-end-of-next-block - And I run :yank selection - Then the clipboard should contain: - one two three - eins zwei drei - - Scenario: Moving back to the end of previous block (with selection) - When I run :move-to-end-of-next-block with count 2 - And I run :toggle-selection - And I run :move-to-end-of-prev-block - And I run :move-to-prev-word - And I run :yank selection - Then the clipboard should contain: - drei - - four five six - - Scenario: Moving back to the end of previous block - When I run :move-to-end-of-next-block with count 2 - And I run :move-to-end-of-prev-block - And I run :toggle-selection - And I run :move-to-prev-word - And I run :yank selection - Then the clipboard should contain "drei" - - Scenario: Moving back to the start of previous block (with selection) - When I run :move-to-end-of-next-block with count 2 - And I run :toggle-selection - And I run :move-to-start-of-prev-block - And I run :yank selection - Then the clipboard should contain: - eins zwei drei - - four five six - - Scenario: Moving back to the start of previous block - When I run :move-to-end-of-next-block with count 2 - And I run :move-to-start-of-prev-block - And I run :toggle-selection - And I run :move-to-next-word - And I run :yank selection - Then the clipboard should contain "eins " - - Scenario: Moving to the start of next block (with selection) - When I run :toggle-selection - And I run :move-to-start-of-next-block - And I run :yank selection - Then the clipboard should contain "one two three\n" - - Scenario: Moving to the start of next block - When I run :move-to-start-of-next-block - And I run :toggle-selection - And I run :move-to-end-of-word - And I run :yank selection - Then the clipboard should contain "eins" - - # line - - Scenario: Selecting a line - When I run :toggle-selection - And I run :move-to-end-of-line - And I run :yank selection - Then the clipboard should contain "one two three" - - Scenario: Moving and selecting a line - When I run :move-to-next-line - And I run :toggle-selection - And I run :move-to-end-of-line - And I run :yank selection - Then the clipboard should contain "eins zwei drei" - - Scenario: Selecting next line - When I run :toggle-selection - And I run :move-to-next-line - And I run :yank selection - Then the clipboard should contain "one two three\n" - - Scenario: Moving to end and to start of line - When I run :move-to-end-of-line - And I run :move-to-start-of-line - And I run :toggle-selection - And I run :move-to-end-of-word - And I run :yank selection - Then the clipboard should contain "one" - - Scenario: Selecting a line (backwards) - When I run :move-to-end-of-line - And I run :toggle-selection - When I run :move-to-start-of-line - And I run :yank selection - Then the clipboard should contain "one two three" - - Scenario: Selecting previous line - When I run :move-to-next-line - And I run :toggle-selection - When I run :move-to-prev-line - And I run :yank selection - Then the clipboard should contain "one two three\n" - - Scenario: Moving to previous line - When I run :move-to-next-line - When I run :move-to-prev-line - And I run :toggle-selection - When I run :move-to-next-line - And I run :yank selection - Then the clipboard should contain "one two three\n" - - # word - - Scenario: Selecting a word - When I run :toggle-selection - And I run :move-to-end-of-word - And I run :yank selection - Then the clipboard should contain "one" - - Scenario: Moving to end and selecting a word - When I run :move-to-end-of-word - And I run :toggle-selection - And I run :move-to-end-of-word - And I run :yank selection - Then the clipboard should contain " two" - - Scenario: Moving to next word and selecting a word - When I run :move-to-next-word - And I run :toggle-selection - And I run :move-to-end-of-word - And I run :yank selection - Then the clipboard should contain "two" - - Scenario: Moving to next word and selecting until next word - When I run :move-to-next-word - And I run :toggle-selection - And I run :move-to-next-word - And I run :yank selection - Then the clipboard should contain "two " - - Scenario: Moving to previous word and selecting a word - When I run :move-to-end-of-word - And I run :toggle-selection - And I run :move-to-prev-word - And I run :yank selection - Then the clipboard should contain "one" - - Scenario: Moving to previous word - When I run :move-to-end-of-word - And I run :move-to-prev-word - And I run :toggle-selection - And I run :move-to-end-of-word - And I run :yank selection - Then the clipboard should contain "one" - - # char - - Scenario: Selecting a char - When I run :toggle-selection - And I run :move-to-next-char - And I run :yank selection - Then the clipboard should contain "o" - - Scenario: Moving and selecting a char - When I run :move-to-next-char - And I run :toggle-selection - And I run :move-to-next-char - And I run :yank selection - Then the clipboard should contain "n" - - Scenario: Selecting previous char - When I run :move-to-end-of-word - And I run :toggle-selection - And I run :move-to-prev-char - And I run :yank selection - Then the clipboard should contain "e" - - Scenario: Moving to previous char - When I run :move-to-end-of-word - And I run :move-to-prev-char - And I run :toggle-selection - And I run :move-to-end-of-word - And I run :yank selection - Then the clipboard should contain "e" - # :yank selection Scenario: :yank selection without selection @@ -261,15 +43,6 @@ Feature: Caret mode And the message "7 chars yanked to clipboard" should be shown. And the clipboard should contain "one two" - # :drop-selection - - Scenario: :drop-selection - When I run :toggle-selection - And I run :move-to-end-of-word - And I run :drop-selection - And I run :yank selection - Then the message "Nothing to yank" should be shown. - # :follow-selected Scenario: :follow-selected without a selection @@ -356,28 +129,3 @@ Feature: Caret mode And I run :fake-key And I run :follow-selected --tab Then data/hello.txt should be loaded - - # Search + caret mode - - # https://bugreports.qt.io/browse/QTBUG-60673 - @qtbug60673 - Scenario: yanking a searched line - When I run :leave-mode - And I run :search fiv - And I wait for "search found fiv" in the log - And I run :enter-mode caret - And I run :move-to-end-of-line - And I run :yank selection - Then the clipboard should contain "five six" - - @qtbug60673 - Scenario: yanking a searched line with multiple matches - When I run :leave-mode - And I run :search w - And I wait for "search found w" in the log - And I run :search-next - And I wait for "next_result found w" in the log - And I run :enter-mode caret - And I run :move-to-end-of-line - And I run :yank selection - Then the clipboard should contain "wei drei" diff --git a/tests/unit/browser/test_caret.py b/tests/unit/browser/test_caret.py new file mode 100644 index 000000000..199baca25 --- /dev/null +++ b/tests/unit/browser/test_caret.py @@ -0,0 +1,317 @@ +# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: + +# Copyright 2018 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +"""Tests for caret browsing mode.""" + +import os.path +import textwrap + +import pytest +from PyQt5.QtCore import QUrl + +from qutebrowser.utils import usertypes +from helpers import utils + + +@pytest.fixture +def caret(web_tab, qtbot, mode_manager): + path = os.path.join(utils.abs_datapath(), 'caret.html') + with qtbot.wait_signal(web_tab.load_finished): + web_tab.openurl(QUrl.fromLocalFile(path)) + + mode_manager.enter(usertypes.KeyMode.caret) + + return web_tab.caret + + +class Selection: + + """Helper to interact with the caret selection.""" + + def __init__(self, qtbot, caret): + self._qtbot = qtbot + self._caret = caret + self._callback_checker = utils.CallbackChecker(qtbot) + + def check(self, expected): + self._caret.selection(self._callback_checker.callback) + self._callback_checker.check(expected) + + def check_multiline(self, expected): + self.check(textwrap.dedent(expected).strip()) + + def toggle(self): + with self._qtbot.wait_signal(self._caret.selection_toggled): + self._caret.toggle_selection() + + +@pytest.fixture +def selection(qtbot, caret, callback_checker): + return Selection(qtbot, caret) + + +class TestDocument: + + def test_selecting_entire_document(self, caret, selection): + selection.toggle() + caret.move_to_end_of_document() + selection.check_multiline(""" + one two three + eins zwei drei + + four five six + vier fünf sechs + """) + + def test_moving_to_end_and_start(self, caret, selection): + caret.move_to_end_of_document() + caret.move_to_start_of_document() + selection.toggle() + caret.move_to_end_of_word() + selection.check("one") + + def test_moving_to_end_and_start_with_selection(self, caret, selection): + caret.move_to_end_of_document() + selection.toggle() + caret.move_to_start_of_document() + selection.check_multiline(""" + one two three + eins zwei drei + + four five six + vier fünf sechs + """) + + +class TestBlock: + + def test_selecting_block(self, caret, selection): + selection.toggle() + caret.move_to_end_of_next_block() + selection.check_multiline(""" + one two three + eins zwei drei + """) + + def test_selecting_a_block(self, caret, selection): + selection.toggle() + caret.move_to_end_of_next_block() + selection.check_multiline(""" + one two three + eins zwei drei + """) + + def test_moving_back_to_the_end_of_prev_block_with_sel(self, caret, selection): + caret.move_to_end_of_next_block(2) + selection.toggle() + caret.move_to_end_of_prev_block() + caret.move_to_prev_word() + selection.check_multiline(""" + drei + + four five six + """) + + def test_moving_back_to_the_end_of_prev_block(self, caret, selection): + caret.move_to_end_of_next_block(2) + caret.move_to_end_of_prev_block() + selection.toggle() + caret.move_to_prev_word() + selection.check("drei") + + def test_moving_back_to_the_start_of_prev_block_with_sel(self, + caret, selection): + caret.move_to_end_of_next_block(2) + selection.toggle() + caret.move_to_start_of_prev_block() + selection.check_multiline(""" + eins zwei drei + + four five six + """) + + def test_moving_back_to_the_start_of_prev_block(self, caret, selection): + caret.move_to_end_of_next_block(2) + caret.move_to_start_of_prev_block() + selection.toggle() + caret.move_to_next_word() + selection.check("eins ") + + def test_moving_to_the_start_of_next_block_with_sel(self, + caret, selection): + selection.toggle() + caret.move_to_start_of_next_block() + selection.check("one two three\n") + + def test_moving_to_the_start_of_next_block(self, caret, selection): + caret.move_to_start_of_next_block() + selection.toggle() + caret.move_to_end_of_word() + selection.check("eins") + + +class TestLine: + + def test_selecting_a_line(self, caret, selection): + selection.toggle() + caret.move_to_end_of_line() + selection.check("one two three") + + def test_moving_and_selecting_a_line(self, caret, selection): + caret.move_to_next_line() + selection.toggle() + caret.move_to_end_of_line() + selection.check("eins zwei drei") + + def test_selecting_next_line(self, caret, selection): + selection.toggle() + caret.move_to_next_line() + selection.check("one two three\n") + + def test_moving_to_end_and_to_start_of_line(self, caret, selection): + caret.move_to_end_of_line() + caret.move_to_start_of_line() + selection.toggle() + caret.move_to_end_of_word() + selection.check("one") + + def test_selecting_a_line_backwards(self, caret, selection): + caret.move_to_end_of_line() + selection.toggle() + caret.move_to_start_of_line() + selection.check("one two three") + + def test_selecting_previous_line(self, caret, selection): + caret.move_to_next_line() + selection.toggle() + caret.move_to_prev_line() + selection.check("one two three\n") + + def test_moving_to_previous_line(self, caret, selection): + caret.move_to_next_line() + caret.move_to_prev_line() + selection.toggle() + caret.move_to_next_line() + selection.check("one two three\n") + + +class TestWord: + + def test_selecting_a_word(self, caret, selection): + selection.toggle() + caret.move_to_end_of_word() + selection.check("one") + + def test_moving_to_end_and_selecting_a_word(self, caret, selection): + caret.move_to_end_of_word() + selection.toggle() + caret.move_to_end_of_word() + selection.check(" two") + + def test_moving_to_next_word_and_selecting_a_word(self, caret, selection): + caret.move_to_next_word() + selection.toggle() + caret.move_to_end_of_word() + selection.check("two") + + def test_moving_to_next_word_and_selecting_until_next_word(self, caret, selection): + caret.move_to_next_word() + selection.toggle() + caret.move_to_next_word() + selection.check("two ") + + def test_moving_to_previous_word_and_selecting_a_word(self, caret, selection): + caret.move_to_end_of_word() + selection.toggle() + caret.move_to_prev_word() + selection.check("one") + + def test_moving_to_previous_word(self, caret, selection): + caret.move_to_end_of_word() + caret.move_to_prev_word() + selection.toggle() + caret.move_to_end_of_word() + selection.check("one") + + +class TestChar: + + def test_selecting_a_char(self, caret, selection): + selection.toggle() + caret.move_to_next_char() + selection.check("o") + + def test_moving_and_selecting_a_char(self, caret, selection): + caret.move_to_next_char() + selection.toggle() + caret.move_to_next_char() + selection.check("n") + + def test_selecting_previous_char(self, caret, selection): + caret.move_to_end_of_word() + selection.toggle() + caret.move_to_prev_char() + selection.check("e") + + def test_moving_to_previous_char(self, caret, selection): + caret.move_to_end_of_word() + caret.move_to_prev_char() + selection.toggle() + caret.move_to_end_of_word() + selection.check("e") + + +def test_drop_selection(caret, selection): + selection.toggle() + caret.move_to_end_of_word() + caret.drop_selection() + selection.check("") + + +class TestSearch: + + # https://bugreports.qt.io/browse/QTBUG-60673 + + @pytest.mark.qtbug60673 + def test_yanking_a_searched_line( + self, caret, selection, mode_manager, callback_checker, web_tab): + mode_manager.leave(usertypes.KeyMode.caret) + + web_tab.search.search('fiv', result_cb=callback_checker.callback) + callback_checker.check(True) + + mode_manager.enter(usertypes.KeyMode.caret) + caret.move_to_end_of_line() + selection.check('five six') + + @pytest.mark.qtbug60673 + def test_yanking_a_searched_line_with_multiple_matches( + self, caret, selection, mode_manager, callback_checker, web_tab): + mode_manager.leave(usertypes.KeyMode.caret) + + web_tab.search.search('w', result_cb=callback_checker.callback) + callback_checker.check(True) + + web_tab.search.next_result(result_cb=callback_checker.callback) + callback_checker.check(True) + + mode_manager.enter(usertypes.KeyMode.caret) + + caret.move_to_end_of_line() + selection.check('wei drei')