Files
quickbot_cli/tests/conftest.py
Alexander Kalinovsky ab1aedd63e
All checks were successful
CI / test (3.13) (push) Successful in 42s
chore: update license from MIT to Apache-2.0 across all files
2025-08-26 19:38:15 +03:00

147 lines
4.6 KiB
Python

# SPDX-FileCopyrightText: 2025 Alexander Kalinovsky <a@k8y.ru>
#
# SPDX-License-Identifier: Apache-2.0
"""Pytest configuration and fixtures for CLI tests."""
import shutil
import sys
import tempfile
from collections.abc import Generator
from pathlib import Path
from unittest.mock import MagicMock, patch
import pytest
from typer.testing import CliRunner
# Add src to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
@pytest.fixture
def cli_runner() -> CliRunner:
"""Provide a CLI runner for testing commands."""
return CliRunner()
@pytest.fixture
def temp_dir() -> Generator[Path]:
"""Provide a temporary directory for testing."""
with tempfile.TemporaryDirectory() as tmp_dir:
yield Path(tmp_dir)
@pytest.fixture
def mock_template_dir() -> Generator[Path]:
"""Provide a mock template directory structure."""
template_dir = Path(__file__).parent / "fixtures" / "mock_template"
template_dir.mkdir(parents=True, exist_ok=True)
# Create template spec
spec_file = template_dir / "__template__.yaml"
spec_content = """
variables:
project_name:
prompt: "Project name"
default: "test_project"
description:
prompt: "Description"
default: "Test description"
author:
prompt: "Author"
default: "Test Author"
license:
prompt: "License"
default: "MIT"
include_alembic:
prompt: "Include Alembic?"
choices: ["yes", "no"]
default: "yes"
include_i18n:
prompt: "Include i18n?"
choices: [true, false]
default: true
post_tasks:
- when: "{{ include_alembic == 'yes' }}"
run: ["echo", "alembic_init"]
- when: "{{ include_i18n == true }}"
run: ["echo", "babel_init"]
"""
spec_file.write_text(spec_content)
# Create some template files
(template_dir / "app").mkdir()
(template_dir / "app" / "main.py.j2").write_text(
"from fastapi import FastAPI\n\napp = FastAPI(title='{{ project_name }}')\n"
)
(template_dir / "app" / "config.py.j2").write_text(
"PROJECT_NAME = '{{ project_name }}'\nDESCRIPTION = '{{ description }}'\n"
)
(template_dir / "README.md.j2").write_text(
"# {{ project_name }}\n\n{{ description }}\n\nAuthor: {{ author }}\nLicense: {{ license }}"
)
(template_dir / "pyproject.toml.j2").write_text(
"[project]\nname = '{{ project_name }}'\ndescription = '{{ description }}'"
)
# Create optional modules
(template_dir / "alembic").mkdir()
(template_dir / "alembic" / "alembic.ini.j2").write_text("alembic config for {{ project_name }}")
(template_dir / "locales").mkdir()
(template_dir / "locales" / "en").mkdir()
(template_dir / "locales" / "en" / "LC_MESSAGES").mkdir()
# Create scripts
(template_dir / "scripts").mkdir()
(template_dir / "scripts" / "migrations_generate.sh.j2").write_text(
"#!/bin/bash\necho 'Generate migrations for {{ project_name }}'"
)
(template_dir / "scripts" / "migrations_apply.sh.j2").write_text(
"#!/bin/bash\necho 'Apply migrations for {{ project_name }}'"
)
(template_dir / "scripts" / "babel_init.sh.j2").write_text("#!/bin/bash\necho 'Init Babel for {{ project_name }}'")
(template_dir / "scripts" / "babel_extract.sh.j2").write_text(
"#!/bin/bash\necho 'Extract Babel for {{ project_name }}'"
)
(template_dir / "scripts" / "babel_update.sh.j2").write_text(
"#!/bin/bash\necho 'Update Babel for {{ project_name }}'"
)
(template_dir / "scripts" / "babel_compile.sh.j2").write_text(
"#!/bin/bash\necho 'Compile Babel for {{ project_name }}'"
)
yield template_dir
# Cleanup
shutil.rmtree(template_dir)
@pytest.fixture
def mock_typer_prompt() -> Generator[MagicMock]:
"""Mock typer.prompt to avoid interactive input during tests."""
with patch("quickbot_cli.cli.typer.prompt") as mock_prompt:
mock_prompt.return_value = "test_value"
yield mock_prompt
@pytest.fixture
def mock_typer_secho() -> Generator[MagicMock]:
"""Mock typer.secho to capture output during tests."""
with patch("quickbot_cli.cli.typer.secho") as mock_secho:
yield mock_secho
@pytest.fixture
def mock_typer_echo() -> Generator[MagicMock]:
"""Mock typer.echo to capture output during tests."""
with patch("quickbot_cli.cli.typer.echo") as mock_echo:
yield mock_echo
@pytest.fixture
def mock_subprocess_run() -> Generator[MagicMock]:
"""Mock subprocess.run to avoid actual command execution during tests."""
with patch("quickbot_cli.cli.subprocess.run") as mock_run:
mock_run.return_value = MagicMock(returncode=0)
yield mock_run