"""Tests for web flashcard generation.""" import pytest import tempfile from pathlib import Path from unittest.mock import patch, MagicMock # Import web generator functions import sys sys.path.insert(0, str(Path(__file__).parent.parent / 'src')) from web_generator import generate_web_flashcards, get_numeral_color, generate_card_svgs class TestWebGeneration: """Test web flashcard generation functionality.""" def test_get_numeral_color_monochrome(self, sample_config): """Test numeral color for monochrome scheme.""" config = {**sample_config, 'color_scheme': 'monochrome', 'colored_numerals': False} color = get_numeral_color(42, config) assert color == "#333" # Even with colored numerals, monochrome should return #333 config['colored_numerals'] = True color = get_numeral_color(42, config) assert color == "#333" def test_get_numeral_color_place_value(self, sample_config): """Test numeral color for place-value scheme.""" config = {**sample_config, 'color_scheme': 'place-value', 'colored_numerals': True} # Test different place values color = get_numeral_color(7, config) # ones place assert color == "#2E86AB" # blue color = get_numeral_color(42, config) # tens place assert color == "#A23B72" # magenta color = get_numeral_color(456, config) # hundreds place assert color == "#F18F01" # orange # For place-value scheme, colored numerals are automatically enabled config['colored_numerals'] = False color = get_numeral_color(42, config) assert color == "#A23B72" # Still colored because place-value auto-enables coloring @patch('generate.generate_cards_direct') def test_generate_card_svgs_success(self, mock_generate_cards_direct, sample_config, temp_dir): """Test successful SVG generation.""" # Mock the generated files fronts_dir = temp_dir / 'svg_cards' / 'fronts' fronts_dir.mkdir(parents=True) # Create mock SVG files for i, num in enumerate([1, 2, 3]): svg_file = fronts_dir / f'card_{i:03d}.svg' svg_content = f'{num}' svg_file.write_text(svg_content) # Mock the generate_cards_direct return mock_generate_cards_direct.return_value = [ fronts_dir / 'card_000.svg', fronts_dir / 'card_001.svg', fronts_dir / 'card_002.svg', ] # Mock tempfile to use our temp_dir with patch('tempfile.TemporaryDirectory') as mock_tempdir: mock_tempdir.return_value.__enter__.return_value = str(temp_dir) result = generate_card_svgs([1, 2, 3], sample_config) assert len(result) == 3 assert 1 in result assert 2 in result assert 3 in result assert '1' in result[1] @patch('generate.generate_cards_direct') def test_generate_card_svgs_fallback(self, mock_generate_cards_direct, sample_config, temp_dir): """Test fallback when SVG generation fails.""" # Mock generate_cards_direct to return empty list (failure) mock_generate_cards_direct.return_value = [] with patch('tempfile.TemporaryDirectory') as mock_tempdir: mock_tempdir.return_value.__enter__.return_value = str(temp_dir) result = generate_card_svgs([1, 2], sample_config) assert len(result) == 2 assert '', 23: '' } result_path = generate_web_flashcards(numbers, sample_config, output_file) assert result_path == output_file assert output_file.exists() content = output_file.read_text() # Check HTML structure assert '' in content assert '' in content assert 'Soroban Flashcards' in content assert 'Hover over the cards to reveal the numbers' in content # Check cards are present assert 'data-number="7"' in content assert 'data-number="23"' in content # Check SVG content is embedded assert '' in content assert '' in content # Check CSS classes assert '.flashcard' in content assert '.numeral' in content assert '.abacus-container' in content def test_generate_web_flashcards_config_integration(self, temp_dir, sample_config): """Test that configuration options are properly integrated.""" numbers = [42] output_file = temp_dir / 'test.html' config = { **sample_config, 'color_scheme': 'place-value', 'bead_shape': 'circle', 'colored_numerals': True, 'font_size': '36pt', 'font_family': 'Arial' } with patch('web_generator.generate_card_svgs') as mock_svg_gen: mock_svg_gen.return_value = {42: ''} generate_web_flashcards(numbers, config, output_file) content = output_file.read_text() # Check config values are used assert 'font-family: Arial' in content assert '36pt' in content assert 'place value' in content.lower() assert 'Circle' in content # Bead shape capitalized def test_generate_web_flashcards_empty_numbers(self, temp_dir, sample_config): """Test handling of empty numbers list.""" output_file = temp_dir / 'empty.html' with patch('web_generator.generate_card_svgs') as mock_svg_gen: mock_svg_gen.return_value = {} result_path = generate_web_flashcards([], sample_config, output_file) assert result_path == output_file assert output_file.exists() content = output_file.read_text() assert 'Soroban Flashcards' in content assert 'Cards: 0' in content assert 'Range: 0' in content def test_web_flashcards_responsive_design(self, temp_dir, sample_config): """Test that responsive CSS is included.""" numbers = [1] output_file = temp_dir / 'responsive.html' with patch('web_generator.generate_card_svgs') as mock_svg_gen: mock_svg_gen.return_value = {1: ''} generate_web_flashcards(numbers, sample_config, output_file) content = output_file.read_text() # Check mobile responsiveness assert '@media (max-width: 768px)' in content assert 'grid-template-columns: repeat(auto-fill, minmax(280px, 1fr))' in content # Check print styles assert '@media print' in content assert 'break-inside: avoid' in content def test_web_flashcards_accessibility(self, temp_dir, sample_config): """Test accessibility features.""" numbers = [5] output_file = temp_dir / 'accessible.html' with patch('web_generator.generate_card_svgs') as mock_svg_gen: mock_svg_gen.return_value = {5: ''} generate_web_flashcards(numbers, sample_config, output_file) content = output_file.read_text() # Check accessibility attributes assert 'lang="en"' in content assert 'charset="UTF-8"' in content assert 'viewport' in content # Check that hover states don't rely only on hover assert 'cursor: pointer' in content assert 'transition:' in content