mirror of https://github.com/JoshKarpel/spiel
Improve coverage (#5)
parent
e9df199431
commit
749ea528e9
@ -1,6 +1,7 @@
|
||||
from enum import Enum
|
||||
from enum import Enum, unique
|
||||
|
||||
|
||||
class Mode(Enum):
|
||||
@unique
|
||||
class Mode(str, Enum):
|
||||
SLIDE = "slide"
|
||||
DECK = "deck"
|
||||
|
@ -1,22 +1,45 @@
|
||||
import subprocess
|
||||
import sys
|
||||
import traceback
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from spiel.constants import PACKAGE_NAME, __version__
|
||||
from tests.conftest import CLI
|
||||
from spiel.main import app
|
||||
from spiel.modes import Mode
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def runner() -> CliRunner:
|
||||
return CliRunner()
|
||||
|
||||
|
||||
def test_help(cli: CLI) -> None:
|
||||
result = cli(["--help"])
|
||||
def test_help(runner: CliRunner) -> None:
|
||||
result = runner.invoke(app, ["--help"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
|
||||
|
||||
def test_help_via_main() -> None:
|
||||
result = subprocess.run([sys.executable, "-m", PACKAGE_NAME, "--help"])
|
||||
|
||||
assert result.returncode == 0
|
||||
|
||||
|
||||
def test_version(cli: CLI) -> None:
|
||||
result = cli(["version"])
|
||||
def test_version(runner: CliRunner) -> None:
|
||||
result = runner.invoke(app, ["version"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert PACKAGE_NAME in result.stdout
|
||||
assert __version__ in result.stdout
|
||||
|
||||
|
||||
@pytest.mark.parametrize("deck_path", (Path(__file__).parents[1] / "examples").glob("*.py"))
|
||||
@pytest.mark.parametrize("mode", list(Mode))
|
||||
@pytest.mark.parametrize("stdin", ["", "s", "d"])
|
||||
def test_display_example_decks(runner: CliRunner, deck_path: Path, mode: Mode, stdin: str) -> None:
|
||||
result = runner.invoke(app, ["present", str(deck_path), "--mode", mode], input=stdin)
|
||||
|
||||
assert result.exit_code == 0
|
||||
|
@ -0,0 +1,35 @@
|
||||
from io import StringIO
|
||||
from typing import Callable
|
||||
|
||||
import pytest
|
||||
from rich.console import Console
|
||||
from rich.layout import Layout
|
||||
from rich.text import Text
|
||||
|
||||
from spiel import Slide
|
||||
from spiel.present import render_slide, split_layout_into_deck_grid
|
||||
from spiel.state import State
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"make_slide",
|
||||
[
|
||||
lambda: Slide(Text("foobar")),
|
||||
lambda: Slide.from_function(lambda: Text("foobar")),
|
||||
],
|
||||
)
|
||||
def test_can_render_slide(
|
||||
make_slide: Callable[[], Slide], console: Console, output: StringIO
|
||||
) -> None:
|
||||
renderable = render_slide(make_slide())
|
||||
|
||||
console.print(renderable)
|
||||
|
||||
result = output.getvalue()
|
||||
|
||||
assert "foobar" in result
|
||||
|
||||
|
||||
def test_can_render_deck_grid(three_slide_state: State) -> None:
|
||||
root = Layout()
|
||||
split_layout_into_deck_grid(root, three_slide_state)
|
@ -1,67 +0,0 @@
|
||||
import os
|
||||
import string
|
||||
from random import sample
|
||||
from typing import List
|
||||
|
||||
import hypothesis.strategies as st
|
||||
from hypothesis import given, settings
|
||||
from rich.console import Console
|
||||
from rich.text import Text
|
||||
|
||||
from spiel import Deck, Slide
|
||||
from spiel.input import (
|
||||
INPUT_HANDLERS,
|
||||
InputHandler,
|
||||
deck_mode,
|
||||
next_slide,
|
||||
previous_slide,
|
||||
slide_mode,
|
||||
)
|
||||
from spiel.modes import Mode
|
||||
from spiel.state import State
|
||||
|
||||
|
||||
def test_next_slide_goes_to_next_slide(three_slide_state: State) -> None:
|
||||
next_slide(three_slide_state)
|
||||
|
||||
assert three_slide_state.current_slide is three_slide_state.deck[1]
|
||||
|
||||
|
||||
def test_previous_slide_goes_to_previous_slide(three_slide_state: State) -> None:
|
||||
three_slide_state.jump_to_slide(2)
|
||||
|
||||
previous_slide(three_slide_state)
|
||||
|
||||
assert three_slide_state.current_slide is three_slide_state.deck[1]
|
||||
|
||||
|
||||
def test_enter_deck_mode(three_slide_state: State) -> None:
|
||||
deck_mode(three_slide_state)
|
||||
|
||||
assert three_slide_state.mode is Mode.DECK
|
||||
|
||||
|
||||
def test_enter_slide_mode(three_slide_state: State) -> None:
|
||||
slide_mode(three_slide_state)
|
||||
|
||||
assert three_slide_state.mode is Mode.SLIDE
|
||||
|
||||
|
||||
@given(input_handlers=st.lists(st.sampled_from(list(set(INPUT_HANDLERS.values())))))
|
||||
@settings(max_examples=1_000 if os.getenv("CI") else 100)
|
||||
def test_input_sequences_dont_crash(input_handlers: List[InputHandler]) -> None:
|
||||
state = State(
|
||||
console=Console(),
|
||||
deck=Deck(
|
||||
name="deck",
|
||||
slides=[
|
||||
Slide(
|
||||
Text(f"This is slide {n + 1}"), title="".join(sample(string.ascii_letters, 30))
|
||||
)
|
||||
for n in range(30)
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
for input_handler in input_handlers:
|
||||
input_handler(state)
|
@ -1,22 +1,75 @@
|
||||
import os
|
||||
import string
|
||||
from random import sample
|
||||
from typing import List
|
||||
|
||||
import pytest
|
||||
from hypothesis import given, settings
|
||||
from hypothesis import strategies as st
|
||||
from rich.console import Console
|
||||
from rich.text import Text
|
||||
|
||||
from spiel.exceptions import DuplicateInputHandler
|
||||
from spiel.input import InputHandlers, action
|
||||
from spiel import Deck, Slide
|
||||
from spiel.exceptions import Quit
|
||||
from spiel.input import (
|
||||
INPUT_HANDLERS,
|
||||
InputHandler,
|
||||
deck_mode,
|
||||
kill,
|
||||
next_slide,
|
||||
previous_slide,
|
||||
slide_mode,
|
||||
)
|
||||
from spiel.modes import Mode
|
||||
from spiel.state import State
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def handlers() -> InputHandlers:
|
||||
return {} # type: ignore
|
||||
def test_next_slide_goes_to_next_slide(three_slide_state: State) -> None:
|
||||
next_slide(three_slide_state)
|
||||
|
||||
assert three_slide_state.current_slide is three_slide_state.deck[1]
|
||||
|
||||
|
||||
def test_previous_slide_goes_to_previous_slide(three_slide_state: State) -> None:
|
||||
three_slide_state.jump_to_slide(2)
|
||||
|
||||
previous_slide(three_slide_state)
|
||||
|
||||
assert three_slide_state.current_slide is three_slide_state.deck[1]
|
||||
|
||||
|
||||
def test_enter_deck_mode(three_slide_state: State) -> None:
|
||||
deck_mode(three_slide_state)
|
||||
|
||||
assert three_slide_state.mode is Mode.DECK
|
||||
|
||||
|
||||
def test_enter_slide_mode(three_slide_state: State) -> None:
|
||||
slide_mode(three_slide_state)
|
||||
|
||||
assert three_slide_state.mode is Mode.SLIDE
|
||||
|
||||
|
||||
def test_kill(three_slide_state: State) -> None:
|
||||
with pytest.raises(Quit):
|
||||
kill(three_slide_state)
|
||||
|
||||
def test_register_already_registered_raises_error(handlers: InputHandlers) -> None:
|
||||
@action("a")
|
||||
def a(state: State) -> None: # pragma: never runs
|
||||
pass
|
||||
|
||||
with pytest.raises(DuplicateInputHandler):
|
||||
@given(input_handlers=st.lists(st.sampled_from(list(set(INPUT_HANDLERS.values()) - {kill}))))
|
||||
@settings(max_examples=1_000 if os.getenv("CI") else 100)
|
||||
def test_input_sequences_dont_crash(input_handlers: List[InputHandler]) -> None:
|
||||
state = State(
|
||||
console=Console(),
|
||||
deck=Deck(
|
||||
name="deck",
|
||||
slides=[
|
||||
Slide(
|
||||
Text(f"This is slide {n + 1}"), title="".join(sample(string.ascii_letters, 30))
|
||||
)
|
||||
for n in range(30)
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
@action("a")
|
||||
def a(state: State) -> None: # pragma: never runs
|
||||
pass
|
||||
for input_handler in input_handlers:
|
||||
input_handler(state)
|
||||
|
@ -0,0 +1,39 @@
|
||||
from io import StringIO
|
||||
|
||||
import pytest
|
||||
|
||||
from spiel.exceptions import DuplicateInputHandler
|
||||
from spiel.input import (
|
||||
SPECIAL_CHARACTERS,
|
||||
InputHandlers,
|
||||
SpecialCharacters,
|
||||
get_character,
|
||||
input_handler,
|
||||
)
|
||||
from spiel.state import State
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def handlers() -> InputHandlers:
|
||||
return {} # type: ignore
|
||||
|
||||
|
||||
def test_register_already_registered_raises_error(handlers: InputHandlers) -> None:
|
||||
@input_handler("a")
|
||||
def a(state: State) -> None: # pragma: never runs
|
||||
pass
|
||||
|
||||
with pytest.raises(DuplicateInputHandler):
|
||||
|
||||
@input_handler("a")
|
||||
def a(state: State) -> None: # pragma: never runs
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.parametrize("input, expected", SPECIAL_CHARACTERS.items())
|
||||
def test_get_character_recognizes_special_characters(
|
||||
input: str, expected: SpecialCharacters
|
||||
) -> None:
|
||||
io = StringIO(input)
|
||||
|
||||
assert get_character(io) == expected
|
Loading…
Reference in New Issue