Skip to content

Commit 636fa46

Browse files
authored
Merge pull request #1514 from gooddata/jacek/working
fix: pass entities arg to WASM visualization/dashboard converters
2 parents d6a7ef4 + 48dc249 commit 636fa46

2 files changed

Lines changed: 119 additions & 6 deletions

File tree

  • packages/gooddata-sdk

packages/gooddata-sdk/src/gooddata_sdk/catalog/workspace/aac.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,32 @@ def declarative_metric_to_aac(declarative: dict[str, Any]) -> dict[str, Any]:
188188
return declarative_metric_to_yaml(declarative)
189189

190190

191-
def declarative_visualization_to_aac(declarative: dict[str, Any]) -> dict[str, Any]:
192-
"""Convert a declarative visualization dict to AAC format."""
193-
return declarative_visualisation_to_yaml(declarative)
191+
def declarative_visualization_to_aac(
192+
declarative: dict[str, Any],
193+
entities: list[dict[str, Any]] | None = None,
194+
) -> dict[str, Any]:
195+
"""Convert a declarative visualization dict to AAC format.
196+
197+
Args:
198+
declarative: The declarative visualization dict.
199+
entities: Optional entities list for cross-reference resolution.
200+
"""
201+
ent = entities if entities is not None else []
202+
return declarative_visualisation_to_yaml(ent, declarative)
194203

195204

196-
def declarative_dashboard_to_aac(declarative: dict[str, Any]) -> dict[str, Any]:
197-
"""Convert a declarative dashboard dict to AAC format."""
198-
return declarative_dashboard_to_yaml(declarative)
205+
def declarative_dashboard_to_aac(
206+
declarative: dict[str, Any],
207+
entities: list[dict[str, Any]] | None = None,
208+
) -> dict[str, Any]:
209+
"""Convert a declarative dashboard dict to AAC format.
210+
211+
Args:
212+
declarative: The declarative dashboard dict.
213+
entities: Optional entities list for cross-reference resolution.
214+
"""
215+
ent = entities if entities is not None else []
216+
return declarative_dashboard_to_yaml(ent, declarative)
199217

200218

201219
def declarative_plugin_to_aac(declarative: dict[str, Any]) -> dict[str, Any]:

packages/gooddata-sdk/tests/catalog/test_aac.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
aac_visualization_to_declarative,
1212
declarative_dataset_to_aac,
1313
declarative_metric_to_aac,
14+
declarative_visualization_to_aac,
1415
detect_yaml_format,
1516
load_aac_workspace_from_disk,
1617
store_aac_workspace_to_disk,
@@ -176,6 +177,38 @@ def test_dataset_declarative_to_aac(self) -> None:
176177
assert result["json"]["id"] == "orders"
177178
assert isinstance(result["content"], str)
178179

180+
def test_visualization_declarative_to_aac(self) -> None:
181+
"""Test declarative → AAC for visualizations (round-trip from fixture)."""
182+
content = yaml.safe_load((_FIXTURES_DIR / "visualisations" / "ratings.yaml").read_text())
183+
declarative = aac_visualization_to_declarative(content)
184+
result = declarative_visualization_to_aac(declarative)
185+
assert result["json"]["id"] == "71bdc379-384a-4eac-9627-364ea847d977"
186+
assert isinstance(result["content"], str)
187+
assert "Ratings" in result["content"]
188+
189+
def test_visualization_declarative_to_aac_inline(self) -> None:
190+
"""Test declarative → AAC for a visualization built from inline data."""
191+
aac_input = {
192+
"type": "table",
193+
"id": "my_table",
194+
"title": "My Table",
195+
"query": {
196+
"fields": {
197+
"m1": {
198+
"title": "Sum of Amount",
199+
"aggregation": "SUM",
200+
"using": "fact/amount",
201+
},
202+
},
203+
},
204+
"metrics": [{"field": "m1", "format": "#,##0"}],
205+
}
206+
declarative = aac_visualization_to_declarative(aac_input)
207+
result = declarative_visualization_to_aac(declarative)
208+
assert result["json"]["id"] == "my_table"
209+
assert isinstance(result["content"], str)
210+
assert "my_table" in result["content"]
211+
179212

180213
# ---------------------------------------------------------------------------
181214
# Format detection tests
@@ -263,6 +296,68 @@ def test_store_and_reload_metrics(self, tmp_path: Path) -> None:
263296
reloaded_dict = reloaded.to_dict(camel_case=True)
264297
assert len(reloaded_dict.get("analytics", {}).get("metrics", [])) == 2
265298

299+
def test_store_and_reload_visualizations(self, tmp_path: Path) -> None:
300+
"""Store visualization AAC files via store_aac_workspace_to_disk, then reload."""
301+
aac_vis = {
302+
"type": "table",
303+
"id": "test_vis",
304+
"title": "Test Visualization",
305+
"query": {
306+
"fields": {
307+
"m1": {
308+
"title": "Sum of Amount",
309+
"aggregation": "SUM",
310+
"using": "fact/amount",
311+
},
312+
},
313+
},
314+
"metrics": [{"field": "m1", "format": "#,##0"}],
315+
}
316+
vis_declarative = [aac_visualization_to_declarative(aac_vis)]
317+
318+
model_dict = {"analytics": {"visualizationObjects": vis_declarative}}
319+
from gooddata_sdk.catalog.workspace.declarative_model.workspace.workspace import (
320+
CatalogDeclarativeWorkspaceModel,
321+
)
322+
323+
model = CatalogDeclarativeWorkspaceModel.from_dict(model_dict)
324+
store_aac_workspace_to_disk(model, tmp_path)
325+
326+
# Verify files were created
327+
vis_files = list((tmp_path / "visualisations").glob("*.yaml"))
328+
assert len(vis_files) == 1
329+
330+
# Reload
331+
reloaded = load_aac_workspace_from_disk(tmp_path)
332+
reloaded_dict = reloaded.to_dict(camel_case=True)
333+
assert len(reloaded_dict.get("analytics", {}).get("visualizationObjects", [])) == 1
334+
335+
def test_store_and_reload_from_fixtures(self, tmp_path: Path) -> None:
336+
"""Load fixtures, store to disk, reload — full round-trip."""
337+
import shutil
338+
import tempfile
339+
340+
with tempfile.TemporaryDirectory() as tmp:
341+
fixture_path = Path(tmp)
342+
for subdir in ("datasets", "metrics", "visualisations"):
343+
src = _FIXTURES_DIR / subdir
344+
if src.exists():
345+
shutil.copytree(src, fixture_path / subdir)
346+
347+
model = load_aac_workspace_from_disk(fixture_path)
348+
349+
store_aac_workspace_to_disk(model, tmp_path)
350+
351+
# Verify visualization files exist
352+
vis_files = list((tmp_path / "visualisations").glob("*.yaml"))
353+
assert len(vis_files) == 2
354+
355+
# Reload and verify counts match
356+
reloaded = load_aac_workspace_from_disk(tmp_path)
357+
reloaded_dict = reloaded.to_dict(camel_case=True)
358+
assert len(reloaded_dict.get("analytics", {}).get("visualizationObjects", [])) == 2
359+
assert len(reloaded_dict.get("analytics", {}).get("metrics", [])) == 1
360+
266361
def test_load_ignores_non_workspace_dirs(self, tmp_path: Path) -> None:
267362
"""Ensure load skips declarative non-workspace directories."""
268363
# Create AAC file

0 commit comments

Comments
 (0)