mirror of
https://github.com/apache/superset.git
synced 2026-05-29 20:29:34 +00:00
Co-authored-by: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -123,6 +123,121 @@ def test_update_native_filter_config_scope_excluded():
|
||||
}
|
||||
|
||||
|
||||
def test_update_native_filter_config_preserves_rootpath_and_remaps_excluded():
|
||||
"""
|
||||
Regression guard for #19944: a native filter's ``scope`` has two parts that
|
||||
must both survive an export/import roundtrip:
|
||||
|
||||
- ``rootPath`` controls *which* dashboard sections (tabs/rows) the filter
|
||||
applies to. It uses position keys (``ROOT_ID``, ``TAB-xxx``), not chart
|
||||
IDs, so ``update_id_refs`` must leave it untouched.
|
||||
- ``excluded`` is a list of chart IDs the filter does NOT apply to within
|
||||
its rootPath. Those IDs must be remapped to destination-env IDs.
|
||||
|
||||
The original bug report — "filters are automatically applied to all charts,
|
||||
even if a different scoping was defined before the export" — describes a
|
||||
rootPath silently being collapsed back to ``["ROOT_ID"]`` (i.e. "apply
|
||||
everywhere"). This test pins the post-refactor contract: the import path
|
||||
must not mutate or drop ``rootPath``.
|
||||
"""
|
||||
from superset.commands.dashboard.importers.v1.utils import update_id_refs
|
||||
|
||||
config: dict[str, Any] = {
|
||||
"position": {
|
||||
"CHART1": {
|
||||
"id": "CHART1",
|
||||
"meta": {"chartId": 101, "uuid": "uuid1"},
|
||||
"type": "CHART",
|
||||
},
|
||||
"CHART2": {
|
||||
"id": "CHART2",
|
||||
"meta": {"chartId": 102, "uuid": "uuid2"},
|
||||
"type": "CHART",
|
||||
},
|
||||
"CHART3": {
|
||||
"id": "CHART3",
|
||||
"meta": {"chartId": 103, "uuid": "uuid3"},
|
||||
"type": "CHART",
|
||||
},
|
||||
},
|
||||
"metadata": {
|
||||
"native_filter_configuration": [
|
||||
{
|
||||
"id": "NATIVE_FILTER-region",
|
||||
"name": "Region",
|
||||
"scope": {
|
||||
# Filter applies only to charts under TAB-revenue,
|
||||
# except chart 102 which is explicitly excluded.
|
||||
"rootPath": ["TAB-revenue"],
|
||||
"excluded": [102],
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "NATIVE_FILTER-product",
|
||||
"name": "Product",
|
||||
"scope": {
|
||||
# Different filter, different rootPath; must not be
|
||||
# cross-contaminated with the first filter's scope.
|
||||
"rootPath": ["TAB-inventory", "TAB-revenue"],
|
||||
"excluded": [101, 103],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
chart_ids = {"uuid1": 1, "uuid2": 2, "uuid3": 3}
|
||||
dataset_info: dict[str, dict[str, Any]] = {}
|
||||
|
||||
fixed = update_id_refs(config, chart_ids, dataset_info)
|
||||
filters = fixed["metadata"]["native_filter_configuration"]
|
||||
|
||||
# rootPath uses position keys, not chart IDs — must pass through unchanged.
|
||||
assert filters[0]["scope"]["rootPath"] == ["TAB-revenue"]
|
||||
assert filters[1]["scope"]["rootPath"] == ["TAB-inventory", "TAB-revenue"]
|
||||
|
||||
# excluded uses chart IDs — must be remapped to destination-env IDs.
|
||||
assert filters[0]["scope"]["excluded"] == [2]
|
||||
assert filters[1]["scope"]["excluded"] == [1, 3]
|
||||
|
||||
|
||||
def test_update_native_filter_config_default_rootpath_preserved():
|
||||
"""
|
||||
The "apply everywhere" default — ``rootPath: ["ROOT_ID"]`` — must also
|
||||
survive untouched. A regression that special-cased this value (e.g. by
|
||||
deleting it) would silently change "apply everywhere" into "apply nowhere"
|
||||
on import, since downstream consumers treat a missing rootPath as empty
|
||||
rather than as the default.
|
||||
"""
|
||||
from superset.commands.dashboard.importers.v1.utils import update_id_refs
|
||||
|
||||
config: dict[str, Any] = {
|
||||
"position": {
|
||||
"CHART1": {
|
||||
"id": "CHART1",
|
||||
"meta": {"chartId": 101, "uuid": "uuid1"},
|
||||
"type": "CHART",
|
||||
},
|
||||
},
|
||||
"metadata": {
|
||||
"native_filter_configuration": [
|
||||
{
|
||||
"id": "NATIVE_FILTER-global",
|
||||
"name": "Global",
|
||||
"scope": {"rootPath": ["ROOT_ID"], "excluded": []},
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
chart_ids = {"uuid1": 1}
|
||||
dataset_info: dict[str, dict[str, Any]] = {}
|
||||
|
||||
fixed = update_id_refs(config, chart_ids, dataset_info)
|
||||
scope = fixed["metadata"]["native_filter_configuration"][0]["scope"]
|
||||
|
||||
assert scope["rootPath"] == ["ROOT_ID"]
|
||||
assert scope["excluded"] == []
|
||||
|
||||
|
||||
def test_update_id_refs_cross_filter_chart_configuration_key_and_excluded_mapping():
|
||||
from superset.commands.dashboard.importers.v1.utils import update_id_refs
|
||||
|
||||
|
||||
Reference in New Issue
Block a user