1
0
Fork 0
textual-textarea/tests/functional_tests/test_textarea.py

463 lines
13 KiB
Python
Raw Normal View History

from __future__ import annotations
from typing import List
import pytest
from textual.app import App
from textual.widgets.text_area import Selection
from textual_textarea import TextEditor
@pytest.mark.parametrize(
"keys,text,selection,expected_text,expected_selection",
[
(
["ctrl+a"],
"select\n foo",
Selection(start=(1, 2), end=(1, 2)),
"select\n foo",
Selection(start=(0, 0), end=(1, 4)),
),
(
["ctrl+shift+right"],
"select\n foo",
Selection(start=(0, 0), end=(0, 0)),
"select\n foo",
Selection(start=(0, 0), end=(0, 6)),
),
(
["right"],
"select\n foo",
Selection(start=(0, 0), end=(0, 6)),
"select\n foo",
Selection(start=(1, 0), end=(1, 0)),
),
(
["a"],
"select\n foo",
Selection(start=(1, 4), end=(1, 4)),
"select\n fooa",
Selection(start=(1, 5), end=(1, 5)),
),
(
["a"],
"select\n foo",
Selection(start=(1, 0), end=(1, 4)),
"select\na",
Selection(start=(1, 1), end=(1, 1)),
),
(
["enter"],
"a\na",
Selection(start=(1, 0), end=(1, 0)),
"a\n\na",
Selection(start=(2, 0), end=(2, 0)),
),
(
["enter"],
"a\na",
Selection(start=(1, 1), end=(1, 1)),
"a\na\n",
Selection(start=(2, 0), end=(2, 0)),
),
(
["enter", "b"],
"a()",
Selection(start=(0, 2), end=(0, 2)),
"a(\n b\n)",
Selection(start=(1, 5), end=(1, 5)),
),
(
["enter", "b"],
" a()",
Selection(start=(0, 3), end=(0, 3)),
" a(\n b\n )",
Selection(start=(1, 5), end=(1, 5)),
),
(
["delete"],
"0\n1\n2\n3",
Selection(start=(2, 1), end=(2, 1)),
"0\n1\n23",
Selection(start=(2, 1), end=(2, 1)),
),
(
["shift+delete"],
"0\n1\n2\n3",
Selection(start=(2, 1), end=(2, 1)),
"0\n1\n3",
Selection(start=(2, 0), end=(2, 0)),
),
(
["shift+delete"],
"0\n1\n2\n3",
Selection(start=(2, 0), end=(2, 1)),
"0\n1\n\n3",
Selection(start=(2, 0), end=(2, 0)),
),
(
["shift+delete"],
"0\n1\n2\n3",
Selection(start=(3, 1), end=(3, 1)),
"0\n1\n2",
Selection(start=(2, 1), end=(2, 1)),
),
(
["shift+delete"],
"foo",
Selection(start=(3, 1), end=(3, 1)),
"",
Selection(start=(0, 0), end=(0, 0)),
),
(
["ctrl+home"],
"foo\nbar",
Selection(start=(1, 2), end=(1, 2)),
"foo\nbar",
Selection(start=(0, 0), end=(0, 0)),
),
(
["ctrl+end"],
"foo\nbar",
Selection(start=(0, 1), end=(0, 1)),
"foo\nbar",
Selection(start=(1, 3), end=(1, 3)),
),
(
["("],
"foo",
Selection(start=(0, 3), end=(0, 3)),
"foo()",
Selection(start=(0, 4), end=(0, 4)),
),
(
["("],
"foo",
Selection(start=(0, 2), end=(0, 2)),
"fo(o",
Selection(start=(0, 3), end=(0, 3)),
),
(
["("],
"foo.",
Selection(start=(0, 3), end=(0, 3)),
"foo().",
Selection(start=(0, 4), end=(0, 4)),
),
(
["("],
"foo-",
Selection(start=(0, 3), end=(0, 3)),
"foo(-",
Selection(start=(0, 4), end=(0, 4)),
),
(
["'"],
"foo",
Selection(start=(0, 3), end=(0, 3)),
"foo'",
Selection(start=(0, 4), end=(0, 4)),
),
(
["'"],
"ba r",
Selection(start=(0, 3), end=(0, 3)),
"ba '' r",
Selection(start=(0, 4), end=(0, 4)),
),
(
["'"],
"foo-",
Selection(start=(0, 3), end=(0, 3)),
"foo'-",
Selection(start=(0, 4), end=(0, 4)),
),
(
["'"],
"fo--",
Selection(start=(0, 3), end=(0, 3)),
"fo-'-",
Selection(start=(0, 4), end=(0, 4)),
),
(
["'"],
"fo-.",
Selection(start=(0, 3), end=(0, 3)),
"fo-''.",
Selection(start=(0, 4), end=(0, 4)),
),
(
["'"],
"fo()",
Selection(start=(0, 3), end=(0, 3)),
"fo('')",
Selection(start=(0, 4), end=(0, 4)),
),
(
["tab"],
"bar",
Selection(start=(0, 1), end=(0, 1)),
"b ar",
Selection(start=(0, 4), end=(0, 4)),
),
(
["tab"],
"bar",
Selection(start=(0, 0), end=(0, 0)),
" bar",
Selection(start=(0, 4), end=(0, 4)),
),
(
["shift+tab"],
"bar",
Selection(start=(0, 0), end=(0, 0)),
"bar",
Selection(start=(0, 0), end=(0, 0)),
),
(
["shift+tab"],
" bar",
Selection(start=(0, 7), end=(0, 7)),
"bar",
Selection(start=(0, 3), end=(0, 3)),
),
(
["tab"],
"bar\n baz",
Selection(start=(0, 2), end=(1, 1)),
" bar\n baz",
Selection(start=(0, 6), end=(1, 4)),
),
(
["tab"],
"bar\n baz",
Selection(start=(0, 0), end=(1, 1)),
" bar\n baz",
Selection(start=(0, 0), end=(1, 4)),
),
(
["shift+tab"],
" bar\n baz",
Selection(start=(0, 0), end=(1, 1)),
"bar\nbaz",
Selection(start=(0, 0), end=(1, 0)),
),
],
)
@pytest.mark.asyncio
async def test_keys(
app: App,
keys: List[str],
text: str,
selection: Selection,
expected_text: str,
expected_selection: Selection,
) -> None:
async with app.run_test() as pilot:
ta = app.query_one("#ta", expect_type=TextEditor)
ta.text = text
ta.selection = selection
for key in keys:
await pilot.press(key)
assert ta.text == expected_text
assert ta.selection == expected_selection
@pytest.mark.parametrize(
"starting_selection,expected_clipboard,expected_paste_loc",
[
(Selection((0, 5), (1, 5)), "56789\n01234", (1, 5)),
(Selection((0, 0), (1, 0)), "0123456789\n", (1, 0)),
],
)
@pytest.mark.asyncio
async def test_copy_paste(
app_all_clipboards: App,
starting_selection: Selection,
expected_clipboard: str,
expected_paste_loc: tuple[int, int],
) -> None:
original_text = "0123456789\n0123456789\n0123456789"
def eq(a: str, b: str) -> bool:
return a.replace("\r\n", "\n") == b.replace("\r\n", "\n")
async with app_all_clipboards.run_test() as pilot:
ta = app_all_clipboards.query_one("#ta", expect_type=TextEditor)
while ta.text_input is None:
await pilot.pause(0.1)
ti = ta.text_input
assert ti is not None
ta.text = original_text
ta.selection = starting_selection
await pilot.press("ctrl+c")
await pilot.pause()
assert eq(ti.clipboard, expected_clipboard)
assert ta.selection == starting_selection
assert ta.text == original_text
await pilot.press("ctrl+u")
await pilot.pause()
assert eq(ti.clipboard, expected_clipboard)
assert ta.selection == Selection(starting_selection.end, starting_selection.end)
assert ta.text == original_text
await pilot.press("ctrl+a")
assert ta.selection == Selection(
(0, 0),
(len(original_text.splitlines()) - 1, len(original_text.splitlines()[-1])),
)
assert eq(ti.clipboard, expected_clipboard)
assert ta.text == original_text
await pilot.press("ctrl+u")
await pilot.pause()
assert ta.selection == Selection(expected_paste_loc, expected_paste_loc)
assert eq(ti.clipboard, expected_clipboard)
assert ta.text == expected_clipboard
await pilot.press("ctrl+a")
await pilot.press("ctrl+x")
await pilot.pause()
assert ta.selection == Selection((0, 0), (0, 0))
assert eq(ti.clipboard, expected_clipboard)
assert ta.text == ""
await pilot.press("ctrl+v")
await pilot.pause()
assert eq(ti.clipboard, expected_clipboard)
assert ta.text == expected_clipboard
assert ta.selection == Selection(expected_paste_loc, expected_paste_loc)
@pytest.mark.asyncio
async def test_undo_redo(app: App) -> None:
async with app.run_test() as pilot:
ta = app.query_one("#ta", expect_type=TextEditor)
ti = ta.text_input
assert ti
assert ti.has_focus
for char in "foo":
await pilot.press(char)
await pilot.pause(0.6)
await pilot.press("enter")
for char in "bar":
await pilot.press(char)
await pilot.pause(0.6)
await pilot.press("ctrl+z")
assert ta.text == "foo\n"
assert ta.selection == Selection((1, 0), (1, 0))
await pilot.press("ctrl+z")
assert ta.text == "foo"
assert ta.selection == Selection((0, 3), (0, 3))
await pilot.press("ctrl+z")
assert ta.text == ""
assert ta.selection == Selection((0, 0), (0, 0))
await pilot.press("ctrl+y")
assert ta.text == "foo"
assert ta.selection == Selection((0, 3), (0, 3))
await pilot.press("z")
assert ta.text == "fooz"
@pytest.mark.parametrize(
"start_text,insert_text,selection,expected_text",
[
(
"select ",
'"main"."drivers"."driverId"',
Selection((0, 7), (0, 7)),
'select "main"."drivers"."driverId"',
),
(
"select , foo",
'"main"."drivers"."driverId"',
Selection((0, 7), (0, 7)),
'select "main"."drivers"."driverId", foo',
),
(
"aaa\naaa\naaa\naaa",
"bb",
Selection((2, 2), (2, 2)),
"aaa\naaa\naabba\naaa",
),
(
"aaa\naaa\naaa\naaa",
"bb",
Selection((2, 2), (1, 1)),
"aaa\nabba\naaa",
),
(
"01234",
"\nabc\n",
Selection((0, 2), (0, 2)),
"01\nabc\n234",
),
],
)
@pytest.mark.asyncio
async def test_insert_text(
app: App,
start_text: str,
insert_text: str,
selection: Selection,
expected_text: str,
) -> None:
async with app.run_test() as pilot:
ta = app.query_one("#ta", expect_type=TextEditor)
ta.text = start_text
ta.selection = selection
await pilot.pause()
ta.insert_text_at_selection(insert_text)
await pilot.pause()
assert ta.text == expected_text
@pytest.mark.asyncio
async def test_toggle_comment(app: App) -> None:
async with app.run_test() as pilot:
ta = app.query_one("#ta", expect_type=TextEditor)
ta.text = "one\ntwo\n\nthree"
ta.selection = Selection((0, 0), (0, 0))
await pilot.pause()
await pilot.press("ctrl+underscore")
assert ta.text == "# one\ntwo\n\nthree"
await pilot.press("down")
await pilot.press("ctrl+underscore")
assert ta.text == "# one\n# two\n\nthree"
await pilot.press("ctrl+a")
await pilot.press("ctrl+underscore")
assert ta.text == "# # one\n# # two\n\n# three"
await pilot.press("ctrl+underscore")
assert ta.text == "# one\n# two\n\nthree"
await pilot.press("up")
await pilot.press("up")
await pilot.press("ctrl+underscore")
assert ta.text == "# one\ntwo\n\nthree"
await pilot.press("shift+down")
await pilot.press("shift+down")
await pilot.press("ctrl+underscore")
assert ta.text == "# one\n# two\n\n# three"
await pilot.press("ctrl+a")
await pilot.press("ctrl+underscore")
assert ta.text == "one\ntwo\n\nthree"