63 lines
2.4 KiB
Python
63 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from PIL import Image
|
|
|
|
from tmux_shot.render import frames_to_gif, render_ansi_to_png
|
|
|
|
|
|
def test_render_plain_text_produces_correctly_sized_image(out_dir: Path) -> None:
|
|
path = render_ansi_to_png("hello world", out_dir / "plain.png", cols=20, rows=3, font_size=14)
|
|
img = Image.open(path)
|
|
assert img.size[0] > 0 and img.size[1] > 0
|
|
# 20 cols x 3 rows of cells, image should be a whole multiple of cell size in each axis
|
|
assert img.width % 20 == 0
|
|
assert img.height % 3 == 0
|
|
|
|
|
|
def test_render_resolves_truecolor_background_and_foreground(out_dir: Path) -> None:
|
|
# SGR 38;2 = truecolor fg, 48;2 = truecolor bg. Pure red bg, pure green text.
|
|
ansi = "\x1b[48;2;255;0;0m\x1b[38;2;0;255;0mX\x1b[0m"
|
|
path = render_ansi_to_png(ansi, out_dir / "color.png", cols=1, rows=1, font_size=20)
|
|
img = Image.open(path)
|
|
# corner pixel is background-only (no glyph ink there)
|
|
corner = img.getpixel((0, 0))
|
|
assert corner == (255, 0, 0)
|
|
|
|
|
|
def test_render_reverse_video_swaps_fg_and_bg(out_dir: Path) -> None:
|
|
ansi = "\x1b[38;2;255;0;0m\x1b[48;2;0;0;255m\x1b[7mX\x1b[0m" # red fg, blue bg, reversed
|
|
path = render_ansi_to_png(ansi, out_dir / "reverse.png", cols=1, rows=1, font_size=20)
|
|
img = Image.open(path)
|
|
# reversed: background should now be the (originally-foreground) red
|
|
assert img.getpixel((0, 0)) == (255, 0, 0)
|
|
|
|
|
|
def test_render_handles_ansi_16_color_names(out_dir: Path) -> None:
|
|
ansi = "\x1b[42mX\x1b[0m" # classic SGR green background
|
|
path = render_ansi_to_png(ansi, out_dir / "named.png", cols=1, rows=1, font_size=20)
|
|
img = Image.open(path)
|
|
assert img.getpixel((0, 0)) == (0, 205, 0)
|
|
|
|
|
|
def test_frames_to_gif_stitches_multiple_pngs_into_one_animation(out_dir: Path) -> None:
|
|
frame_paths = []
|
|
for i, label in enumerate(["one", "two", "three"]):
|
|
p = render_ansi_to_png(f"frame {label}", out_dir / f"f{i}.png", cols=10, rows=1, font_size=14)
|
|
frame_paths.append(p)
|
|
|
|
gif_path = frames_to_gif(frame_paths, out_dir / "movie.gif", duration_ms=100)
|
|
assert Path(gif_path).exists()
|
|
|
|
with Image.open(gif_path) as gif:
|
|
assert gif.is_animated
|
|
assert gif.n_frames == 3
|
|
|
|
|
|
def test_frames_to_gif_rejects_empty_input(out_dir: Path) -> None:
|
|
import pytest
|
|
|
|
with pytest.raises(ValueError):
|
|
frames_to_gif([], out_dir / "empty.gif")
|