"""Server module for UI tests - creates a minimal Flask app for testing."""
import os
import logging
from flask import Flask, send_from_directory, jsonify
from asgiref.wsgi import WsgiToAsgi
from autometabuilder.workflow.plugin_registry import PluginRegistry, load_plugin_map
from autometabuilder.workflow.runtime import WorkflowRuntime
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class _SimpleLogger:
"""Minimal logger for plugin execution."""
def info(self, *args, **kwargs):
logger.info(*args, **kwargs)
def debug(self, *args, **kwargs):
logger.debug(*args, **kwargs)
def error(self, *args, **kwargs):
logger.error(*args, **kwargs)
def create_app():
"""Create and configure the Flask application for testing."""
# Create Flask app
app = Flask(__name__, static_folder=None)
app.config['JSON_SORT_KEYS'] = False
# Create runtime for plugin execution
runtime = WorkflowRuntime(
context={},
store={},
tool_runner=None,
logger=_SimpleLogger()
)
# Store Flask app in runtime context
runtime.context["flask_app"] = app
# Load plugins
plugin_map = load_plugin_map()
registry = PluginRegistry(plugin_map)
# Check if we're in mock mode (for testing)
mock_mode = os.environ.get("MOCK_WEB_UI", "false").lower() == "true"
if mock_mode:
# Create minimal mock routes for testing
@app.route('/')
def index():
# Return a minimal HTML page for testing
return '''
AutoMetabuilder
''', 200
@app.route('/')
def serve_static(path):
# Redirect to index for all routes in mock mode
return index()
@app.route('/api/context')
def api_context():
from autometabuilder.utils import load_metadata
return jsonify({
"logs": [],
"env_vars": {},
"translations": ["en"],
"metadata": load_metadata(),
"navigation": [],
"prompt_content": "",
"workflow_content": "",
"workflow_packages": [],
"workflow_packages_raw": [],
"messages": {},
"lang": os.environ.get("APP_LANG", "en"),
"status": {
"is_running": False,
"mvp_reached": False,
"config": {}
}
}), 200
@app.route('/api/status')
def api_status():
return jsonify({
"is_running": False,
"mvp_reached": False,
"config": {}
}), 200
@app.route('/api/run', methods=['POST'])
def api_run():
return jsonify({"success": True, "message": "Mock run"}), 200
else:
# Create routes using workflow plugins
try:
# Create context routes
context_result = registry.get("web.route_context")(runtime, {})
context_bp = context_result.get("result")
if context_bp:
app.register_blueprint(context_bp)
# Create run routes
run_result = registry.get("web.route_run")(runtime, {})
run_bp = run_result.get("result")
if run_bp:
app.register_blueprint(run_bp)
# Create prompt routes
prompt_result = registry.get("web.route_prompt")(runtime, {})
prompt_bp = prompt_result.get("result")
if prompt_bp:
app.register_blueprint(prompt_bp)
# Create settings routes
settings_result = registry.get("web.route_settings")(runtime, {})
settings_bp = settings_result.get("result")
if settings_bp:
app.register_blueprint(settings_bp)
# Create translations routes
translations_result = registry.get("web.route_translations")(runtime, {})
translations_bp = translations_result.get("result")
if translations_bp:
app.register_blueprint(translations_bp)
# Create navigation routes
navigation_result = registry.get("web.route_navigation")(runtime, {})
navigation_bp = navigation_result.get("result")
if navigation_bp:
app.register_blueprint(navigation_bp)
# Serve static files
from pathlib import Path
frontend_dist = Path(__file__).resolve().parent.parent.parent.parent / 'frontend' / 'dist'
@app.route('/')
def index():
return send_from_directory(frontend_dist, 'index.html')
@app.route('/')
def serve_static(path):
try:
return send_from_directory(frontend_dist, path)
except (FileNotFoundError, OSError):
# Fallback to index.html for SPA routing
return send_from_directory(frontend_dist, 'index.html')
except Exception as e:
logger.error(f"Failed to register routes: {e}")
# Fall back to basic routes
@app.route('/')
def index():
return "AutoMetabuilder Server", 200
return app
# Create the app instance for imports
flask_app = create_app()
# Wrap Flask app for ASGI compatibility (needed for uvicorn)
app = WsgiToAsgi(flask_app)