feat(027): Final Phase T038-T043 implementation
- T038: SessionEvent logger and persistence logic - Added SessionEventLogger service with explicit audit event persistence - Added SessionEvent model with events relationship on DatasetReviewSession - Integrated event logging into orchestrator flows and API mutation endpoints - T039: Semantic source version propagation - Added source_version column to SemanticFieldEntry - Added propagate_source_version_update() to SemanticResolver - Preserves locked/manual field invariants during propagation - T040: Batch approval API and UI actions - Added batch semantic approval endpoint (/fields/semantic/approve-batch) - Added batch mapping approval endpoint (/mappings/approve-batch) - Added batch approval actions to SemanticLayerReview and ExecutionMappingReview components - Aligned batch semantics with single-item approval contracts - T041: Superset compatibility matrix tests - Added test_superset_matrix.py with preview and SQL Lab fallback coverage - Tests verify client method preference and matrix fallback behavior - T042: RBAC audit sweep on session-mutation endpoints - Added _require_owner_mutation_scope() helper - Applied owner guards to update_session, delete_session, and all mutation endpoints - Ensured no bypass of existing permission checks - T043: i18n coverage for dataset-review UI - Added workspace state labels (empty/importing/review) to en.json and ru.json - Added batch action labels for semantics and mappings - Fixed workspace state comparison to lowercase strings - Removed hardcoded workspace state display strings Signed-off-by: Implementation Specialist <impl@ss-tools>
This commit is contained in:
126
backend/tests/services/dataset_review/test_superset_matrix.py
Normal file
126
backend/tests/services/dataset_review/test_superset_matrix.py
Normal file
@@ -0,0 +1,126 @@
|
||||
# [DEF:SupersetCompatibilityMatrixTests:Module]
|
||||
# @COMPLEXITY: 3
|
||||
# @SEMANTICS: dataset_review, superset, compatibility_matrix, preview, sql_lab, tests
|
||||
# @PURPOSE: Verifies Superset preview and SQL Lab endpoint fallback strategy used by dataset-review orchestration.
|
||||
# @LAYER: Tests
|
||||
# @RELATION: [DEPENDS_ON] ->[SupersetCompilationAdapter]
|
||||
# @RELATION: [DEPENDS_ON] ->[SupersetClient]
|
||||
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from src.core.utils.superset_compilation_adapter import (
|
||||
PreviewCompilationPayload,
|
||||
SqlLabLaunchPayload,
|
||||
SupersetCompilationAdapter,
|
||||
)
|
||||
|
||||
|
||||
# [DEF:make_adapter:Function]
|
||||
# @COMPLEXITY: 2
|
||||
# @PURPOSE: Build an adapter with a mock Superset client and deterministic environment for compatibility tests.
|
||||
def make_adapter():
|
||||
environment = SimpleNamespace(
|
||||
id="env-1",
|
||||
name="Test Env",
|
||||
url="http://superset.example",
|
||||
username="user",
|
||||
password="pass",
|
||||
verify_ssl=True,
|
||||
timeout=30,
|
||||
)
|
||||
client = MagicMock()
|
||||
client.network = MagicMock()
|
||||
return SupersetCompilationAdapter(environment=environment, client=client), client
|
||||
# [/DEF:make_adapter:Function]
|
||||
|
||||
|
||||
# [DEF:test_preview_prefers_supported_client_method_before_network_fallback:Function]
|
||||
# @COMPLEXITY: 2
|
||||
# @PURPOSE: Confirms preview compilation uses a supported client method first when the capability exists.
|
||||
def test_preview_prefers_supported_client_method_before_network_fallback():
|
||||
adapter, client = make_adapter()
|
||||
client.compile_preview = MagicMock(return_value={"compiled_sql": "SELECT 1"})
|
||||
payload = PreviewCompilationPayload(
|
||||
session_id="sess-1",
|
||||
dataset_id=42,
|
||||
preview_fingerprint="fp-1",
|
||||
template_params={"country": "RU"},
|
||||
effective_filters=[{"name": "country", "value": "RU"}],
|
||||
)
|
||||
|
||||
preview = adapter.compile_preview(payload)
|
||||
|
||||
assert preview.preview_status.value == "ready"
|
||||
assert preview.compiled_sql == "SELECT 1"
|
||||
client.compile_preview.assert_called_once()
|
||||
client.network.request.assert_not_called()
|
||||
# [/DEF:test_preview_prefers_supported_client_method_before_network_fallback:Function]
|
||||
|
||||
|
||||
# [DEF:test_preview_falls_back_across_matrix_until_supported_endpoint_returns_sql:Function]
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Confirms preview fallback walks the compatibility matrix from preferred to legacy endpoints until one returns compiled SQL.
|
||||
def test_preview_falls_back_across_matrix_until_supported_endpoint_returns_sql():
|
||||
adapter, client = make_adapter()
|
||||
payload = PreviewCompilationPayload(
|
||||
session_id="sess-2",
|
||||
dataset_id=77,
|
||||
preview_fingerprint="fp-2",
|
||||
template_params={"region": "emea"},
|
||||
effective_filters=[],
|
||||
)
|
||||
|
||||
client.network.request.side_effect = [
|
||||
RuntimeError("preview endpoint unavailable"),
|
||||
{"result": {"sql": "SELECT * FROM dataset_77"}},
|
||||
]
|
||||
|
||||
preview = adapter.compile_preview(payload)
|
||||
|
||||
assert preview.preview_status.value == "ready"
|
||||
assert preview.compiled_sql == "SELECT * FROM dataset_77"
|
||||
assert client.network.request.call_count == 2
|
||||
first_call = client.network.request.call_args_list[0].kwargs
|
||||
second_call = client.network.request.call_args_list[1].kwargs
|
||||
assert first_call["endpoint"] == "/dataset/77/preview"
|
||||
assert second_call["endpoint"] == "/dataset/77/sql"
|
||||
# [/DEF:test_preview_falls_back_across_matrix_until_supported_endpoint_returns_sql:Function]
|
||||
|
||||
|
||||
# [DEF:test_sql_lab_launch_falls_back_to_legacy_execute_endpoint:Function]
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Confirms SQL Lab launch falls back from modern to legacy execute endpoint and preserves canonical session reference extraction.
|
||||
def test_sql_lab_launch_falls_back_to_legacy_execute_endpoint():
|
||||
adapter, client = make_adapter()
|
||||
client.get_dataset.return_value = {
|
||||
"result": {
|
||||
"id": 55,
|
||||
"schema": "public",
|
||||
"database": {"id": 9},
|
||||
}
|
||||
}
|
||||
client.network.request.side_effect = [
|
||||
RuntimeError("sqllab execute unavailable"),
|
||||
{"result": {"id": "query-123"}},
|
||||
]
|
||||
payload = SqlLabLaunchPayload(
|
||||
session_id="sess-3",
|
||||
dataset_id=55,
|
||||
preview_id="preview-9",
|
||||
compiled_sql="SELECT * FROM sales",
|
||||
template_params={"limit": 10},
|
||||
)
|
||||
|
||||
sql_lab_ref = adapter.create_sql_lab_session(payload)
|
||||
|
||||
assert sql_lab_ref == "query-123"
|
||||
assert client.network.request.call_count == 2
|
||||
first_call = client.network.request.call_args_list[0].kwargs
|
||||
second_call = client.network.request.call_args_list[1].kwargs
|
||||
assert first_call["endpoint"] == "/sqllab/execute/"
|
||||
assert second_call["endpoint"] == "/sql_lab/execute/"
|
||||
# [/DEF:test_sql_lab_launch_falls_back_to_legacy_execute_endpoint:Function]
|
||||
|
||||
|
||||
# [/DEF:SupersetCompatibilityMatrixTests:Module]
|
||||
Reference in New Issue
Block a user