Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm
Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)
Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability
Migration completed: $(date)
🤖 Clean migration with full functionality preserved
247 lines
9.5 KiB
Python
247 lines
9.5 KiB
Python
"""
|
|
Figma Integration Tests - Real DSS Design File Connection
|
|
|
|
Tests the complete flow:
|
|
1. Connect to real Figma file (DSS main design system)
|
|
2. Extract design variables (colors, typography, spacing)
|
|
3. Extract components
|
|
4. Extract styles and assets
|
|
5. Generate multiple output formats
|
|
6. Verify token consistency
|
|
|
|
Requires environment variables:
|
|
- FIGMA_API_KEY: Your Figma Personal Access Token
|
|
- DSS_FIGMA_FILE_KEY: File key for main DSS design file
|
|
"""
|
|
|
|
import pytest
|
|
import os
|
|
import json
|
|
from pathlib import Path
|
|
|
|
# These imports would come from your DSS package
|
|
# from figma.figma_tools import FigmaToolSuite
|
|
# from dss.tokens import DesignToken
|
|
|
|
|
|
class TestFigmaIntegration:
|
|
"""Test real Figma file integration"""
|
|
# Fixtures now defined in conftest.py for shared access
|
|
|
|
# ===== TEST CASES =====
|
|
|
|
def test_figma_api_key_configured(self, figma_config):
|
|
"""Verify Figma API key is configured"""
|
|
assert figma_config['api_key'], "FIGMA_API_KEY not set"
|
|
assert figma_config['api_key'].startswith('figd_'), "Invalid API key format"
|
|
|
|
def test_dss_file_key_configured(self, figma_config):
|
|
"""Verify DSS file key is configured"""
|
|
assert figma_config['file_key'], "DSS_FIGMA_FILE_KEY not set"
|
|
assert len(figma_config['file_key']) > 0, "File key is empty"
|
|
|
|
def test_extract_variables_returns_dict(self, figma_client, figma_config):
|
|
"""Test variable extraction returns structured data"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
|
|
assert isinstance(result, dict)
|
|
assert 'variables' in result
|
|
assert result['status'] == 'success'
|
|
|
|
def test_extracted_variables_have_colors(self, figma_client, figma_config):
|
|
"""Test colors are extracted"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
variables = result['variables']
|
|
|
|
assert 'colors' in variables
|
|
assert len(variables['colors']) > 0
|
|
assert 'primary' in variables['colors']
|
|
|
|
def test_extracted_variables_have_typography(self, figma_client, figma_config):
|
|
"""Test typography tokens are extracted"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
variables = result['variables']
|
|
|
|
assert 'typography' in variables
|
|
assert len(variables['typography']) > 0
|
|
|
|
def test_extracted_variables_have_spacing(self, figma_client, figma_config):
|
|
"""Test spacing tokens are extracted"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
variables = result['variables']
|
|
|
|
assert 'spacing' in variables
|
|
assert len(variables['spacing']) > 0
|
|
|
|
def test_extract_components(self, figma_client, figma_config):
|
|
"""Test component extraction"""
|
|
result = figma_client['extract_components'](figma_config['file_key'])
|
|
|
|
assert result['status'] == 'success'
|
|
assert 'components' in result
|
|
assert len(result['components']) > 0
|
|
|
|
def test_components_have_metadata(self, figma_client, figma_config):
|
|
"""Test components have required metadata"""
|
|
result = figma_client['extract_components'](figma_config['file_key'])
|
|
components = result['components']
|
|
|
|
for name, component in components.items():
|
|
assert 'description' in component
|
|
assert 'variants' in component
|
|
assert 'properties' in component
|
|
|
|
def test_extract_styles(self, figma_client, figma_config):
|
|
"""Test style extraction"""
|
|
result = figma_client['extract_styles'](figma_config['file_key'])
|
|
|
|
assert result['status'] == 'success'
|
|
assert 'styles' in result
|
|
|
|
def test_extract_all_assets_if_blank(self, figma_client, figma_config):
|
|
"""Test full extraction: if no cached data, get everything"""
|
|
# Get all asset types
|
|
variables = figma_client['extract_variables'](figma_config['file_key'])
|
|
components = figma_client['extract_components'](figma_config['file_key'])
|
|
styles = figma_client['extract_styles'](figma_config['file_key'])
|
|
|
|
# Should have data from all categories
|
|
assert bool(variables.get('variables'))
|
|
assert bool(components.get('components'))
|
|
assert bool(styles.get('styles'))
|
|
|
|
def test_tokens_match_dss_structure(self, figma_client, figma_config):
|
|
"""Verify extracted tokens match DSS token structure"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
variables = result['variables']
|
|
|
|
# Should have standard DSS token categories
|
|
standard_categories = ['colors', 'typography', 'spacing']
|
|
for category in standard_categories:
|
|
assert category in variables, f"Missing {category} category"
|
|
|
|
def test_variable_formats(self, figma_client, figma_config):
|
|
"""Test variables can be exported in different formats"""
|
|
for fmt in ['json', 'css', 'typescript', 'scss']:
|
|
result = figma_client['extract_variables'](
|
|
figma_config['file_key'],
|
|
format=fmt
|
|
)
|
|
assert result['status'] == 'success'
|
|
|
|
def test_color_values_are_valid_hex(self, figma_client, figma_config):
|
|
"""Test color values are valid hex codes"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
colors = result['variables']['colors']
|
|
|
|
import re
|
|
hex_pattern = r'^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$'
|
|
|
|
for name, color in colors.items():
|
|
assert re.match(hex_pattern, color), f"Invalid hex color: {color}"
|
|
|
|
def test_spacing_values_are_numbers(self, figma_client, figma_config):
|
|
"""Test spacing values are numeric"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
spacing = result['variables']['spacing']
|
|
|
|
for name, value in spacing.items():
|
|
assert isinstance(value, (int, float)), f"Non-numeric spacing: {value}"
|
|
|
|
def test_typography_has_required_properties(self, figma_client, figma_config):
|
|
"""Test typography tokens have required properties"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
typography = result['variables']['typography']
|
|
|
|
required = ['fontSize', 'fontWeight']
|
|
|
|
for name, props in typography.items():
|
|
for req in required:
|
|
assert req in props, f"{name} missing {req}"
|
|
|
|
def test_error_handling_invalid_file(self, figma_client):
|
|
"""Test error handling for invalid file key"""
|
|
result = figma_client['extract_variables']('invalid-key')
|
|
|
|
# Should still return dict (with error status)
|
|
assert isinstance(result, dict)
|
|
|
|
def test_error_handling_network_error(self, figma_client):
|
|
"""Test error handling for network issues"""
|
|
# Would be tested with actual network errors
|
|
# For now, just verify error handling structure
|
|
assert True
|
|
|
|
def test_token_count_matches_actual(self, figma_client, figma_config):
|
|
"""Test token count matches extracted tokens"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
|
|
# Count should match actual tokens
|
|
token_count = sum(len(tokens) for tokens in result['variables'].values())
|
|
assert token_count > 0
|
|
|
|
def test_components_count_accurate(self, figma_client, figma_config):
|
|
"""Test component count is accurate"""
|
|
result = figma_client['extract_components'](figma_config['file_key'])
|
|
|
|
actual_count = len(result['components'])
|
|
assert result['components_count'] == actual_count
|
|
|
|
|
|
class TestTokenConsistency:
|
|
"""Test token naming and structure consistency"""
|
|
|
|
def test_token_naming_conventions(self, figma_client, figma_config):
|
|
"""Test tokens follow naming conventions"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
variables = result['variables']
|
|
|
|
# Colors should be kebab-case
|
|
colors = variables['colors']
|
|
for name in colors.keys():
|
|
assert name.islower() and '-' in name or name.islower()
|
|
|
|
def test_no_duplicate_token_names(self, figma_client, figma_config):
|
|
"""Test no duplicate token names across categories"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
variables = result['variables']
|
|
|
|
all_names = []
|
|
for category_tokens in variables.values():
|
|
all_names.extend(category_tokens.keys())
|
|
|
|
# Check for duplicates
|
|
assert len(all_names) == len(set(all_names)), "Duplicate token names found"
|
|
|
|
|
|
class TestFigmaSync:
|
|
"""Test Figma sync and token database storage"""
|
|
|
|
def test_tokens_can_be_saved(self, figma_client, figma_config, tmp_path):
|
|
"""Test tokens can be saved to file"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
|
|
# Write to temp file
|
|
output_file = tmp_path / "tokens.json"
|
|
with open(output_file, 'w') as f:
|
|
json.dump(result, f)
|
|
|
|
# Verify file was created
|
|
assert output_file.exists()
|
|
assert output_file.stat().st_size > 0
|
|
|
|
def test_exported_tokens_can_be_read(self, figma_client, figma_config, tmp_path):
|
|
"""Test exported tokens can be read back"""
|
|
result = figma_client['extract_variables'](figma_config['file_key'])
|
|
|
|
# Write to temp file
|
|
output_file = tmp_path / "tokens.json"
|
|
with open(output_file, 'w') as f:
|
|
json.dump(result, f)
|
|
|
|
# Read back
|
|
with open(output_file, 'r') as f:
|
|
loaded = json.load(f)
|
|
|
|
assert loaded['variables'] == result['variables']
|