diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/save.test.js b/superset-frontend/cypress-base/cypress/integration/dashboard/save.test.js index 757a118306191..08220818390e9 100644 --- a/superset-frontend/cypress-base/cypress/integration/dashboard/save.test.js +++ b/superset-frontend/cypress-base/cypress/integration/dashboard/save.test.js @@ -31,9 +31,6 @@ describe('Dashboard save action', () => { cy.server(); cy.login(); cy.visit(WORLD_HEALTH_DASHBOARD); - }); - - it('should save as new dashboard', () => { cy.get('#app').then(data => { const bootstrapData = JSON.parse(data[0].dataset.bootstrap); const dashboard = bootstrapData.dashboard_data; @@ -50,6 +47,14 @@ describe('Dashboard save action', () => { }); }); + it('should save as new dashboard', () => { + cy.wait('@copyRequest').then(xhr => { + expect(xhr.response.body.dashboard_title).to.not.equal( + `World Bank's Data`, + ); + }); + }); + it('should save/overwrite dashboard', () => { cy.get('[data-test="grid-row-background--transparent"]').within(() => { cy.get('.box_plot', { timeout: 10000 }).should('be.visible'); diff --git a/superset-frontend/cypress-base/cypress/integration/dashboard/url_params.test.js b/superset-frontend/cypress-base/cypress/integration/dashboard/url_params.test.js index 37dda04c75c35..43eb02226f07b 100644 --- a/superset-frontend/cypress-base/cypress/integration/dashboard/url_params.test.js +++ b/superset-frontend/cypress-base/cypress/integration/dashboard/url_params.test.js @@ -39,7 +39,7 @@ describe('Dashboard form data', () => { it('should apply url params to slice requests', () => { const aliases = getChartAliases(dashboard.slices); // wait and verify one-by-one - cy.wait(aliases).then(requests => + cy.wait(aliases, { timeout: 18000 }).then(requests => Promise.all( requests.map(async xhr => { expect(xhr.status).to.eq(200); diff --git a/superset/dashboards/commands/export.py b/superset/dashboards/commands/export.py index 30211979151e8..09ddb758c5d36 100644 --- a/superset/dashboards/commands/export.py +++ b/superset/dashboards/commands/export.py @@ -137,7 +137,9 @@ def _export(model: Dashboard) -> Iterator[Tuple[str, str]]: orphan_charts = { chart for chart in model.slices if str(chart.uuid) not in referenced_charts } - payload["position"] = append_charts(payload["position"], orphan_charts) + + if orphan_charts: + payload["position"] = append_charts(payload["position"], orphan_charts) payload["version"] = EXPORT_VERSION diff --git a/superset/examples/world_bank.py b/superset/examples/world_bank.py index 0596142e85cb2..f9c3aeb88e692 100644 --- a/superset/examples/world_bank.py +++ b/superset/examples/world_bank.py @@ -17,7 +17,7 @@ """Loads datasets, dashboards and slices in a new superset instance""" import json import os -import textwrap +from typing import List import pandas as pd from sqlalchemy import DateTime, String @@ -29,6 +29,7 @@ from superset.models.slice import Slice from superset.utils import core as utils +from ..connectors.base.models import BaseDatasource from .helpers import ( config, EXAMPLES_FOLDER, @@ -105,6 +106,32 @@ def load_world_bank_health_n_pop( # pylint: disable=too-many-locals, too-many-s db.session.commit() tbl.fetch_metadata() + slices = create_slices(tbl) + misc_dash_slices.add(slices[-1].slice_name) + for slc in slices: + merge_slice(slc) + + print("Creating a World's Health Bank dashboard") + dash_name = "World Bank's Data" + slug = "world_health" + dash = db.session.query(Dashboard).filter_by(slug=slug).first() + + if not dash: + dash = Dashboard() + dash.published = True + pos = dashboard_positions + update_slice_ids(pos, slices) + + dash.dashboard_title = dash_name + dash.position_json = json.dumps(pos, indent=4) + dash.slug = slug + + dash.slices = slices[:-1] + db.session.merge(dash) + db.session.commit() + + +def create_slices(tbl: BaseDatasource) -> List[Slice]: metric = "sum__SP_POP_TOTL" metrics = ["sum__SP_POP_TOTL"] secondary_metric = { @@ -118,7 +145,6 @@ def load_world_bank_health_n_pop( # pylint: disable=too-many-locals, too-many-s "hasCustomLabel": True, "label": "Rural Population", } - defaults = { "compare_lag": "10", "compare_suffix": "o10Y", @@ -136,8 +162,7 @@ def load_world_bank_health_n_pop( # pylint: disable=too-many-locals, too-many-s "show_bubbles": True, } - print("Creating slices") - slices = [ + return [ Slice( slice_name="Region Filter", viz_type="filter_box", @@ -340,31 +365,14 @@ def load_world_bank_health_n_pop( # pylint: disable=too-many-locals, too-many-s ), ), ] - misc_dash_slices.add(slices[-1].slice_name) - for slc in slices: - merge_slice(slc) - print("Creating a World's Health Bank dashboard") - dash_name = "World Bank's Data" - slug = "world_health" - dash = db.session.query(Dashboard).filter_by(slug=slug).first() - if not dash: - dash = Dashboard() - dash.published = True - js = textwrap.dedent( - """\ -{ +dashboard_positions = { "CHART-36bfc934": { "children": [], "id": "CHART-36bfc934", - "meta": { - "chartId": 40, - "height": 25, - "sliceName": "Region Filter", - "width": 2 - }, - "type": "CHART" + "meta": {"chartId": 40, "height": 25, "sliceName": "Region Filter", "width": 2}, + "type": "CHART", }, "CHART-37982887": { "children": [], @@ -373,9 +381,9 @@ def load_world_bank_health_n_pop( # pylint: disable=too-many-locals, too-many-s "chartId": 41, "height": 25, "sliceName": "World's Population", - "width": 2 + "width": 2, }, - "type": "CHART" + "type": "CHART", }, "CHART-17e0f8d8": { "children": [], @@ -384,31 +392,21 @@ def load_world_bank_health_n_pop( # pylint: disable=too-many-locals, too-many-s "chartId": 42, "height": 92, "sliceName": "Most Populated Countries", - "width": 3 + "width": 3, }, - "type": "CHART" + "type": "CHART", }, "CHART-2ee52f30": { "children": [], "id": "CHART-2ee52f30", - "meta": { - "chartId": 43, - "height": 38, - "sliceName": "Growth Rate", - "width": 6 - }, - "type": "CHART" + "meta": {"chartId": 43, "height": 38, "sliceName": "Growth Rate", "width": 6}, + "type": "CHART", }, "CHART-2d5b6871": { "children": [], "id": "CHART-2d5b6871", - "meta": { - "chartId": 44, - "height": 52, - "sliceName": "% Rural", - "width": 7 - }, - "type": "CHART" + "meta": {"chartId": 44, "height": 52, "sliceName": "% Rural", "width": 7}, + "type": "CHART", }, "CHART-0fd0d252": { "children": [], @@ -417,9 +415,9 @@ def load_world_bank_health_n_pop( # pylint: disable=too-many-locals, too-many-s "chartId": 45, "height": 50, "sliceName": "Life Expectancy VS Rural %", - "width": 8 + "width": 8, }, - "type": "CHART" + "type": "CHART", }, "CHART-97f4cb48": { "children": [], @@ -428,9 +426,9 @@ def load_world_bank_health_n_pop( # pylint: disable=too-many-locals, too-many-s "chartId": 46, "height": 38, "sliceName": "Rural Breakdown", - "width": 3 + "width": 3, }, - "type": "CHART" + "type": "CHART", }, "CHART-b5e05d6f": { "children": [], @@ -439,145 +437,80 @@ def load_world_bank_health_n_pop( # pylint: disable=too-many-locals, too-many-s "chartId": 47, "height": 50, "sliceName": "World's Pop Growth", - "width": 4 + "width": 4, }, - "type": "CHART" + "type": "CHART", }, "CHART-e76e9f5f": { "children": [], "id": "CHART-e76e9f5f", - "meta": { - "chartId": 48, - "height": 50, - "sliceName": "Box plot", - "width": 4 - }, - "type": "CHART" + "meta": {"chartId": 48, "height": 50, "sliceName": "Box plot", "width": 4}, + "type": "CHART", }, "CHART-a4808bba": { "children": [], "id": "CHART-a4808bba", - "meta": { - "chartId": 49, - "height": 50, - "sliceName": "Treemap", - "width": 8 - }, - "type": "CHART" + "meta": {"chartId": 49, "height": 50, "sliceName": "Treemap", "width": 8}, + "type": "CHART", + }, + "CHART-3nc0d8sk": { + "children": [], + "id": "CHART-3nc0d8sk", + "meta": {"chartId": 50, "height": 50, "sliceName": "Treemap", "width": 8}, + "type": "CHART", }, "COLUMN-071bbbad": { - "children": [ - "ROW-1e064e3c", - "ROW-afdefba9" - ], + "children": ["ROW-1e064e3c", "ROW-afdefba9"], "id": "COLUMN-071bbbad", - "meta": { - "background": "BACKGROUND_TRANSPARENT", - "width": 9 - }, - "type": "COLUMN" + "meta": {"background": "BACKGROUND_TRANSPARENT", "width": 9}, + "type": "COLUMN", }, "COLUMN-fe3914b8": { - "children": [ - "CHART-36bfc934", - "CHART-37982887" - ], + "children": ["CHART-36bfc934", "CHART-37982887"], "id": "COLUMN-fe3914b8", - "meta": { - "background": "BACKGROUND_TRANSPARENT", - "width": 2 - }, - "type": "COLUMN" + "meta": {"background": "BACKGROUND_TRANSPARENT", "width": 2}, + "type": "COLUMN", }, "GRID_ID": { - "children": [ - "ROW-46632bc2", - "ROW-3fa26c5d", - "ROW-812b3f13" - ], + "children": ["ROW-46632bc2", "ROW-3fa26c5d", "ROW-812b3f13"], "id": "GRID_ID", - "type": "GRID" + "type": "GRID", }, "HEADER_ID": { "id": "HEADER_ID", - "meta": { - "text": "World's Bank Data" - }, - "type": "HEADER" - }, - "ROOT_ID": { - "children": [ - "GRID_ID" - ], - "id": "ROOT_ID", - "type": "ROOT" + "meta": {"text": "World's Bank Data"}, + "type": "HEADER", }, + "ROOT_ID": {"children": ["GRID_ID"], "id": "ROOT_ID", "type": "ROOT"}, "ROW-1e064e3c": { - "children": [ - "COLUMN-fe3914b8", - "CHART-2d5b6871" - ], + "children": ["COLUMN-fe3914b8", "CHART-2d5b6871"], "id": "ROW-1e064e3c", - "meta": { - "background": "BACKGROUND_TRANSPARENT" - }, - "type": "ROW" + "meta": {"background": "BACKGROUND_TRANSPARENT"}, + "type": "ROW", }, "ROW-3fa26c5d": { - "children": [ - "CHART-b5e05d6f", - "CHART-0fd0d252" - ], + "children": ["CHART-b5e05d6f", "CHART-0fd0d252"], "id": "ROW-3fa26c5d", - "meta": { - "background": "BACKGROUND_TRANSPARENT" - }, - "type": "ROW" + "meta": {"background": "BACKGROUND_TRANSPARENT"}, + "type": "ROW", }, "ROW-46632bc2": { - "children": [ - "COLUMN-071bbbad", - "CHART-17e0f8d8" - ], + "children": ["COLUMN-071bbbad", "CHART-17e0f8d8"], "id": "ROW-46632bc2", - "meta": { - "background": "BACKGROUND_TRANSPARENT" - }, - "type": "ROW" + "meta": {"background": "BACKGROUND_TRANSPARENT"}, + "type": "ROW", }, "ROW-812b3f13": { - "children": [ - "CHART-a4808bba", - "CHART-e76e9f5f" - ], + "children": ["CHART-a4808bba", "CHART-e76e9f5f"], "id": "ROW-812b3f13", - "meta": { - "background": "BACKGROUND_TRANSPARENT" - }, - "type": "ROW" + "meta": {"background": "BACKGROUND_TRANSPARENT"}, + "type": "ROW", }, "ROW-afdefba9": { - "children": [ - "CHART-2ee52f30", - "CHART-97f4cb48" - ], + "children": ["CHART-2ee52f30", "CHART-97f4cb48"], "id": "ROW-afdefba9", - "meta": { - "background": "BACKGROUND_TRANSPARENT" - }, - "type": "ROW" + "meta": {"background": "BACKGROUND_TRANSPARENT"}, + "type": "ROW", }, - "DASHBOARD_VERSION_KEY": "v2" + "DASHBOARD_VERSION_KEY": "v2", } - """ - ) - pos = json.loads(js) - update_slice_ids(pos, slices) - - dash.dashboard_title = dash_name - dash.position_json = json.dumps(pos, indent=4) - dash.slug = slug - - dash.slices = slices[:-1] - db.session.merge(dash) - db.session.commit() diff --git a/tests/access_tests.py b/tests/access_tests.py index 4e568a57d5f39..d3cc55a1c9df5 100644 --- a/tests/access_tests.py +++ b/tests/access_tests.py @@ -22,6 +22,7 @@ from tests.fixtures.birth_names_dashboard import load_birth_names_dashboard_with_slices import pytest +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices from tests.fixtures.energy_dashboard import load_energy_table_with_slice from tests.test_app import app # isort:skip @@ -321,6 +322,7 @@ def test_clean_requests_after_db_grant(self): gamma_user.roles.remove(security_manager.find_role(DB_ACCESS_ROLE)) session.commit() + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_clean_requests_after_schema_grant(self): session = db.session diff --git a/tests/base_api_tests.py b/tests/base_api_tests.py index 1708cff51e614..3dd21dcfc8108 100644 --- a/tests/base_api_tests.py +++ b/tests/base_api_tests.py @@ -16,7 +16,9 @@ # under the License. # isort:skip_file import json +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices +import pytest from flask_appbuilder.models.sqla.interface import SQLAInterface import prison @@ -66,6 +68,7 @@ def test_open_api_spec(self): class TestBaseModelRestApi(SupersetTestCase): + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_default_missing_declaration_get(self): """ API: Test default missing declaration on get @@ -148,6 +151,7 @@ def test_default_missing_declaration_post(self): } self.assertEqual(response, expected_response) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_default_missing_declaration_put(self): """ API: Test default missing declaration on put diff --git a/tests/charts/api_tests.py b/tests/charts/api_tests.py index 99ab93cb85aeb..f7ba39a5c92e6 100644 --- a/tests/charts/api_tests.py +++ b/tests/charts/api_tests.py @@ -33,6 +33,7 @@ from sqlalchemy import and_, or_ from sqlalchemy.sql import func +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices from tests.test_app import app from superset.charts.commands.data import ChartDataCommand from superset.connectors.connector_registry import ConnectorRegistry @@ -435,7 +436,10 @@ def test_delete_bulk_chart_not_owned(self): db.session.delete(user_alpha2) db.session.commit() - @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") + @pytest.mark.usefixtures( + "load_world_bank_dashboard_with_slices", + "load_birth_names_dashboard_with_slices", + ) def test_create_chart(self): """ Chart API: Test create chart @@ -544,15 +548,18 @@ def test_create_chart_validate_datasource(self): response, {"message": {"datasource_id": ["Datasource does not exist"]}} ) + @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") def test_update_chart(self): """ Chart API: Test update """ admin = self.get_user("admin") gamma = self.get_user("gamma") - - chart_id = self.insert_chart("title", [admin.id], 1, admin).id birth_names_table_id = SupersetTestCase.get_table_by_name("birth_names").id + chart_id = self.insert_chart( + "title", [admin.id], birth_names_table_id, admin + ).id + dash_id = db.session.query(Dashboard.id).filter_by(slug="births").first()[0] chart_data = { "slice_name": "title1_changed", "description": "description1", @@ -562,14 +569,14 @@ def test_update_chart(self): "cache_timeout": 1000, "datasource_id": birth_names_table_id, "datasource_type": "table", - "dashboards": [1], + "dashboards": [dash_id], } self.login(username="admin") uri = f"api/v1/chart/{chart_id}" rv = self.put_assert_metric(uri, chart_data, "put") self.assertEqual(rv.status_code, 200) model = db.session.query(Slice).get(chart_id) - related_dashboard = db.session.query(Dashboard).get(1) + related_dashboard = db.session.query(Dashboard).filter_by(slug="births").first() self.assertEqual(model.created_by, admin) self.assertEqual(model.slice_name, "title1_changed") self.assertEqual(model.description, "description1") @@ -581,7 +588,7 @@ def test_update_chart(self): self.assertEqual(model.datasource_id, birth_names_table_id) self.assertEqual(model.datasource_type, "table") self.assertEqual(model.datasource_name, "birth_names") - self.assertIn(related_dashboard, model.dashboards) + self.assertIn(model.id, [slice.id for slice in related_dashboard.slices]) db.session.delete(model) db.session.commit() @@ -698,6 +705,7 @@ def test_update_chart_validate_owners(self): expected_response = {"message": {"owners": ["Owners are invalid"]}} self.assertEqual(response, expected_response) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_get_chart(self): """ Chart API: Test get chart @@ -758,6 +766,7 @@ def test_get_chart_no_data_access(self): "load_energy_table_with_slice", "load_birth_names_dashboard_with_slices", "load_unicode_dashboard_with_slice", + "load_world_bank_dashboard_with_slices", ) def test_get_charts(self): """ @@ -798,7 +807,10 @@ def test_get_charts_changed_on(self): db.session.delete(chart) db.session.commit() - @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") + @pytest.mark.usefixtures( + "load_world_bank_dashboard_with_slices", + "load_birth_names_dashboard_with_slices", + ) def test_get_charts_filter(self): """ Chart API: Test get charts filter @@ -1008,6 +1020,7 @@ def test_get_time_range(self): @pytest.mark.usefixtures( "load_unicode_dashboard_with_slice", "load_energy_table_with_slice", + "load_world_bank_dashboard_with_slices", "load_birth_names_dashboard_with_slices", ) def test_get_charts_page(self): diff --git a/tests/conftest.py b/tests/conftest.py index efa549f6a3346..b8543851d8831 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -42,13 +42,11 @@ def setup_sample_data() -> Any: from superset import examples examples.load_css_templates() - examples.load_world_bank_health_n_pop(sample=True) yield with app.app_context(): engine = get_example_database().get_sqla_engine() - engine.execute("DROP TABLE wb_health_population") # drop sqlachemy tables diff --git a/tests/core_tests.py b/tests/core_tests.py index 16620b406da24..2363ab015a636 100644 --- a/tests/core_tests.py +++ b/tests/core_tests.py @@ -66,6 +66,7 @@ from superset.views.database.views import DatabaseView from .base_tests import SupersetTestCase +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices logger = logging.getLogger(__name__) @@ -1223,6 +1224,7 @@ def test_results_msgpack_deserialization(self): {"FOO": lambda x: 1}, clear=True, ) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_feature_flag_serialization(self): """ Functions in feature flags don't break bootstrap data serialization. @@ -1238,13 +1240,14 @@ def test_feature_flag_serialization(self): .replace("'", "'") .replace('"', """) ) - + dash_id = db.session.query(Dashboard.id).first()[0] + tbl_id = self.table_ids.get("wb_health_population") urls = [ "/superset/sqllab", "/superset/welcome", - "/superset/dashboard/1/", + f"/superset/dashboard/{dash_id}/", "/superset/profile/admin/", - "/superset/explore/table/1", + f"/superset/explore/table/{tbl_id}", ] for url in urls: data = self.get_resp(url) diff --git a/tests/dashboard_tests.py b/tests/dashboard_tests.py index 8d4df16e67848..be3e0a9be55e0 100644 --- a/tests/dashboard_tests.py +++ b/tests/dashboard_tests.py @@ -34,6 +34,7 @@ from superset.models.dashboard import Dashboard from superset.models.slice import Slice from tests.fixtures.energy_dashboard import load_energy_table_with_slice +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices from .base_tests import SupersetTestCase @@ -161,6 +162,7 @@ def test_save_dash(self, username="admin"): resp = self.get_resp(url, data=dict(data=json.dumps(data))) self.assertIn("SUCCESS", resp) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_save_dash_with_filter(self, username="admin"): self.login(username=username) dash = db.session.query(Dashboard).filter_by(slug="world_health").first() @@ -190,6 +192,7 @@ def test_save_dash_with_filter(self, username="admin"): resp = self.get_resp(new_url) self.assertIn("North America", resp) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_save_dash_with_invalid_filters(self, username="admin"): self.login(username=username) dash = db.session.query(Dashboard).filter_by(slug="world_health").first() diff --git a/tests/dashboard_utils.py b/tests/dashboard_utils.py index 36e329e934899..6944b63c3f9f0 100644 --- a/tests/dashboard_utils.py +++ b/tests/dashboard_utils.py @@ -17,7 +17,7 @@ """Utils to provide dashboards for tests""" import json -from typing import Any, Dict +from typing import Any, Dict, List from pandas import DataFrame @@ -71,7 +71,9 @@ def create_slice( ) -def create_dashboard(slug: str, title: str, position: str, slice: Slice) -> Dashboard: +def create_dashboard( + slug: str, title: str, position: str, slices: List[Slice] +) -> Dashboard: dash = db.session.query(Dashboard).filter_by(slug=slug).one_or_none() if not dash: @@ -82,8 +84,8 @@ def create_dashboard(slug: str, title: str, position: str, slice: Slice) -> Dash pos = json.loads(js) dash.position_json = json.dumps(pos, indent=4) dash.slug = slug - if slice is not None: - dash.slices = [slice] + if slices is not None: + dash.slices = slices db.session.merge(dash) db.session.commit() diff --git a/tests/dashboards/api_tests.py b/tests/dashboards/api_tests.py index 299dd2de64d9e..38ce1aee9522b 100644 --- a/tests/dashboards/api_tests.py +++ b/tests/dashboards/api_tests.py @@ -49,6 +49,7 @@ dataset_metadata_config, ) from tests.utils.get_dashboards import get_dashboards_ids +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices DASHBOARDS_FIXTURE_COUNT = 10 @@ -1102,13 +1103,17 @@ def test_update_dashboard_not_owned(self): db.session.delete(user_alpha2) db.session.commit() + @pytest.mark.usefixtures( + "load_world_bank_dashboard_with_slices", + "load_birth_names_dashboard_with_slices", + ) def test_export(self): """ Dashboard API: Test dashboard export """ self.login(username="admin") - argument = [1, 2] - uri = f"api/v1/dashboard/export/?q={prison.dumps(argument)}" + dashboards_ids = get_dashboards_ids(db, ["world_health", "births"]) + uri = f"api/v1/dashboard/export/?q={prison.dumps(dashboards_ids)}" # freeze time to ensure filename is deterministic with freeze_time("2020-01-01T00:00:00Z"): diff --git a/tests/dashboards/commands_tests.py b/tests/dashboards/commands_tests.py index f3d96f37adcc6..3449c001d9826 100644 --- a/tests/dashboards/commands_tests.py +++ b/tests/dashboards/commands_tests.py @@ -48,16 +48,20 @@ dataset_config, dataset_metadata_config, ) +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices class TestExportDashboardsCommand(SupersetTestCase): + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") @patch("superset.security.manager.g") @patch("superset.views.base.g") def test_export_dashboard_command(self, mock_g1, mock_g2): mock_g1.user = security_manager.find_user("admin") mock_g2.user = security_manager.find_user("admin") - example_dashboard = db.session.query(Dashboard).filter_by(id=1).one() + example_dashboard = ( + db.session.query(Dashboard).filter_by(slug="world_health").one() + ) command = ExportDashboardsCommand([example_dashboard.id]) contents = dict(command.run()) @@ -83,82 +87,152 @@ def test_export_dashboard_command(self, mock_g1, mock_g2): assert metadata == { "dashboard_title": "World Bank's Data", "description": None, - "css": "", + "css": None, "slug": "world_health", "uuid": str(example_dashboard.uuid), "position": { - "DASHBOARD_CHART_TYPE-0": { + "CHART-36bfc934": { "children": [], - "id": "DASHBOARD_CHART_TYPE-0", - "meta": {"height": 50, "width": 4}, + "id": "CHART-36bfc934", + "meta": {"height": 25, "sliceName": "Region Filter", "width": 2}, "type": "CHART", }, - "DASHBOARD_CHART_TYPE-1": { + "CHART-37982887": { "children": [], - "id": "DASHBOARD_CHART_TYPE-1", - "meta": {"height": 50, "width": 4}, + "id": "CHART-37982887", + "meta": { + "height": 25, + "sliceName": "World's Population", + "width": 2, + }, "type": "CHART", }, - "DASHBOARD_CHART_TYPE-2": { + "CHART-17e0f8d8": { "children": [], - "id": "DASHBOARD_CHART_TYPE-2", - "meta": {"height": 50, "width": 4}, + "id": "CHART-17e0f8d8", + "meta": { + "height": 92, + "sliceName": "Most Populated Countries", + "width": 3, + }, "type": "CHART", }, - "DASHBOARD_CHART_TYPE-3": { + "CHART-2ee52f30": { "children": [], - "id": "DASHBOARD_CHART_TYPE-3", - "meta": {"height": 50, "width": 4}, + "id": "CHART-2ee52f30", + "meta": {"height": 38, "sliceName": "Growth Rate", "width": 6}, "type": "CHART", }, - "DASHBOARD_CHART_TYPE-4": { + "CHART-2d5b6871": { "children": [], - "id": "DASHBOARD_CHART_TYPE-4", - "meta": {"height": 50, "width": 4}, + "id": "CHART-2d5b6871", + "meta": {"height": 52, "sliceName": "% Rural", "width": 7}, "type": "CHART", }, - "DASHBOARD_CHART_TYPE-5": { + "CHART-0fd0d252": { "children": [], - "id": "DASHBOARD_CHART_TYPE-5", - "meta": {"height": 50, "width": 4}, + "id": "CHART-0fd0d252", + "meta": { + "height": 50, + "sliceName": "Life Expectancy VS Rural %", + "width": 8, + }, "type": "CHART", }, - "DASHBOARD_CHART_TYPE-6": { + "CHART-97f4cb48": { "children": [], - "id": "DASHBOARD_CHART_TYPE-6", - "meta": {"height": 50, "width": 4}, + "id": "CHART-97f4cb48", + "meta": {"height": 38, "sliceName": "Rural Breakdown", "width": 3}, "type": "CHART", }, - "DASHBOARD_CHART_TYPE-7": { + "CHART-b5e05d6f": { "children": [], - "id": "DASHBOARD_CHART_TYPE-7", - "meta": {"height": 50, "width": 4}, + "id": "CHART-b5e05d6f", + "meta": { + "height": 50, + "sliceName": "World's Pop Growth", + "width": 4, + }, "type": "CHART", }, - "DASHBOARD_CHART_TYPE-8": { + "CHART-e76e9f5f": { "children": [], - "id": "DASHBOARD_CHART_TYPE-8", - "meta": {"height": 50, "width": 4}, + "id": "CHART-e76e9f5f", + "meta": {"height": 50, "sliceName": "Box plot", "width": 4}, "type": "CHART", }, - "DASHBOARD_CHART_TYPE-9": { + "CHART-a4808bba": { "children": [], - "id": "DASHBOARD_CHART_TYPE-9", - "meta": {"height": 50, "width": 4}, + "id": "CHART-a4808bba", + "meta": {"height": 50, "sliceName": "Treemap", "width": 8}, "type": "CHART", }, + "CHART-3nc0d8sk": { + "children": [], + "id": "CHART-3nc0d8sk", + "meta": {"height": 50, "sliceName": "Treemap", "width": 8}, + "type": "CHART", + }, + "COLUMN-071bbbad": { + "children": ["ROW-1e064e3c", "ROW-afdefba9"], + "id": "COLUMN-071bbbad", + "meta": {"background": "BACKGROUND_TRANSPARENT", "width": 9}, + "type": "COLUMN", + }, + "COLUMN-fe3914b8": { + "children": ["CHART-36bfc934", "CHART-37982887"], + "id": "COLUMN-fe3914b8", + "meta": {"background": "BACKGROUND_TRANSPARENT", "width": 2}, + "type": "COLUMN", + }, + "GRID_ID": { + "children": ["ROW-46632bc2", "ROW-3fa26c5d", "ROW-812b3f13"], + "id": "GRID_ID", + "type": "GRID", + }, + "HEADER_ID": { + "id": "HEADER_ID", + "meta": {"text": "World's Bank Data"}, + "type": "HEADER", + }, + "ROOT_ID": {"children": ["GRID_ID"], "id": "ROOT_ID", "type": "ROOT"}, + "ROW-1e064e3c": { + "children": ["COLUMN-fe3914b8", "CHART-2d5b6871"], + "id": "ROW-1e064e3c", + "meta": {"background": "BACKGROUND_TRANSPARENT"}, + "type": "ROW", + }, + "ROW-3fa26c5d": { + "children": ["CHART-b5e05d6f", "CHART-0fd0d252"], + "id": "ROW-3fa26c5d", + "meta": {"background": "BACKGROUND_TRANSPARENT"}, + "type": "ROW", + }, + "ROW-46632bc2": { + "children": ["COLUMN-071bbbad", "CHART-17e0f8d8"], + "id": "ROW-46632bc2", + "meta": {"background": "BACKGROUND_TRANSPARENT"}, + "type": "ROW", + }, + "ROW-812b3f13": { + "children": ["CHART-a4808bba", "CHART-e76e9f5f"], + "id": "ROW-812b3f13", + "meta": {"background": "BACKGROUND_TRANSPARENT"}, + "type": "ROW", + }, + "ROW-afdefba9": { + "children": ["CHART-2ee52f30", "CHART-97f4cb48"], + "id": "ROW-afdefba9", + "meta": {"background": "BACKGROUND_TRANSPARENT"}, + "type": "ROW", + }, "DASHBOARD_VERSION_KEY": "v2", }, - "metadata": { - "timed_refresh_immune_slices": [], - "expanded_slices": {}, - "refresh_frequency": 0, - "default_filters": "{}", - "color_scheme": None, - }, + "metadata": {"mock_key": "mock_value"}, "version": "1.0.0", } + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") @patch("superset.security.manager.g") @patch("superset.views.base.g") def test_export_dashboard_command_no_access(self, mock_g1, mock_g2): @@ -166,12 +240,15 @@ def test_export_dashboard_command_no_access(self, mock_g1, mock_g2): mock_g1.user = security_manager.find_user("gamma") mock_g2.user = security_manager.find_user("gamma") - example_dashboard = db.session.query(Dashboard).filter_by(id=1).one() + example_dashboard = ( + db.session.query(Dashboard).filter_by(slug="world_health").one() + ) command = ExportDashboardsCommand([example_dashboard.id]) contents = command.run() with self.assertRaises(DashboardNotFoundError): next(contents) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") @patch("superset.security.manager.g") @patch("superset.views.base.g") def test_export_dashboard_command_invalid_dataset(self, mock_g1, mock_g2): @@ -183,6 +260,7 @@ def test_export_dashboard_command_invalid_dataset(self, mock_g1, mock_g2): with self.assertRaises(DashboardNotFoundError): next(contents) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") @patch("superset.security.manager.g") @patch("superset.views.base.g") def test_export_dashboard_command_key_order(self, mock_g1, mock_g2): @@ -190,7 +268,9 @@ def test_export_dashboard_command_key_order(self, mock_g1, mock_g2): mock_g1.user = security_manager.find_user("admin") mock_g2.user = security_manager.find_user("admin") - example_dashboard = db.session.query(Dashboard).filter_by(id=1).one() + example_dashboard = ( + db.session.query(Dashboard).filter_by(slug="world_health").one() + ) command = ExportDashboardsCommand([example_dashboard.id]) contents = dict(command.run()) @@ -206,6 +286,7 @@ def test_export_dashboard_command_key_order(self, mock_g1, mock_g2): "version", ] + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") @patch("superset.dashboards.commands.export.suffix") def test_append_charts(self, mock_suffix): """Test that oprhaned charts are added to the dashbaord position""" @@ -213,7 +294,7 @@ def test_append_charts(self, mock_suffix): mock_suffix.side_effect = (str(i) for i in itertools.count(1)) position = get_default_position("example") - chart_1 = db.session.query(Slice).filter_by(id=1).one() + chart_1 = db.session.query(Slice).filter_by(slice_name="Region Filter").one() new_position = append_charts(position, {chart_1}) assert new_position == { "DASHBOARD_VERSION_KEY": "v2", @@ -240,7 +321,7 @@ def test_append_charts(self, mock_suffix): "children": [], "id": "CHART-1", "meta": { - "chartId": 1, + "chartId": chart_1.id, "height": 50, "sliceName": "Region Filter", "uuid": str(chart_1.uuid), @@ -251,7 +332,9 @@ def test_append_charts(self, mock_suffix): }, } - chart_2 = db.session.query(Slice).filter_by(id=2).one() + chart_2 = ( + db.session.query(Slice).filter_by(slice_name="World's Population").one() + ) new_position = append_charts(new_position, {chart_2}) assert new_position == { "DASHBOARD_VERSION_KEY": "v2", @@ -285,7 +368,7 @@ def test_append_charts(self, mock_suffix): "children": [], "id": "CHART-1", "meta": { - "chartId": 1, + "chartId": chart_1.id, "height": 50, "sliceName": "Region Filter", "uuid": str(chart_1.uuid), @@ -298,7 +381,7 @@ def test_append_charts(self, mock_suffix): "children": [], "id": "CHART-3", "meta": { - "chartId": 2, + "chartId": chart_2.id, "height": 50, "sliceName": "World's Population", "uuid": str(chart_2.uuid), @@ -316,7 +399,7 @@ def test_append_charts(self, mock_suffix): "children": [], "id": "CHART-5", "meta": { - "chartId": 1, + "chartId": chart_1.id, "height": 50, "sliceName": "Region Filter", "uuid": str(chart_1.uuid), @@ -328,7 +411,7 @@ def test_append_charts(self, mock_suffix): "children": [], "id": "CHART-6", "meta": { - "chartId": 2, + "chartId": chart_2.id, "height": 50, "sliceName": "World's Population", "uuid": str(chart_2.uuid), diff --git a/tests/dashboards/dao_tests.py b/tests/dashboards/dao_tests.py index 6bb22b885ba8e..48d058ca2293d 100644 --- a/tests/dashboards/dao_tests.py +++ b/tests/dashboards/dao_tests.py @@ -18,14 +18,18 @@ import copy import json +import pytest + import tests.test_app # pylint: disable=unused-import from superset import db from superset.dashboards.dao import DashboardDAO from superset.models.dashboard import Dashboard from tests.base_tests import SupersetTestCase +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices class TestDashboardDAO(SupersetTestCase): + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_set_dash_metadata(self): dash = db.session.query(Dashboard).filter_by(slug="world_health").first() data = dash.data diff --git a/tests/databases/api_tests.py b/tests/databases/api_tests.py index 46af4f06293c0..82a5cb53e3ac6 100644 --- a/tests/databases/api_tests.py +++ b/tests/databases/api_tests.py @@ -21,6 +21,7 @@ from io import BytesIO from unittest import mock from zipfile import is_zipfile, ZipFile +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices from tests.fixtures.birth_names_dashboard import load_birth_names_dashboard_with_slices import prison @@ -848,6 +849,7 @@ def test_test_connection_unsafe_uri(self): @pytest.mark.usefixtures( "load_unicode_dashboard_with_position", "load_energy_table_with_slice", + "load_world_bank_dashboard_with_slices", "load_birth_names_dashboard_with_slices", ) def test_get_database_related_objects(self): diff --git a/tests/datasets/commands_tests.py b/tests/datasets/commands_tests.py index 01bc91c0bef52..f72e7f367fcf3 100644 --- a/tests/datasets/commands_tests.py +++ b/tests/datasets/commands_tests.py @@ -43,6 +43,7 @@ dataset_metadata_config, dataset_ui_export, ) +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices class TestExportDatasetsCommand(SupersetTestCase): @@ -212,6 +213,7 @@ def test_export_dataset_command_key_order(self, mock_g): class TestImportDatasetsCommand(SupersetTestCase): + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_import_v0_dataset_cli_export(self): num_datasets = db.session.query(SqlaTable).count() @@ -251,6 +253,7 @@ def test_import_v0_dataset_cli_export(self): db.session.delete(dataset) db.session.commit() + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_import_v0_dataset_ui_export(self): num_datasets = db.session.query(SqlaTable).count() diff --git a/tests/fixtures/unicode_dashboard.py b/tests/fixtures/unicode_dashboard.py index 13937578649e9..02dbd4c378eac 100644 --- a/tests/fixtures/unicode_dashboard.py +++ b/tests/fixtures/unicode_dashboard.py @@ -87,7 +87,7 @@ def _create_unicode_dashboard( if slice_title: slice = _create_and_commit_unicode_slice(table, slice_title) - return create_dashboard("unicode-test", "Unicode Test", position, slice) + return create_dashboard("unicode-test", "Unicode Test", position, [slice]) def _create_and_commit_unicode_slice(table: SqlaTable, title: str): diff --git a/tests/fixtures/world_bank_dashboard.py b/tests/fixtures/world_bank_dashboard.py new file mode 100644 index 0000000000000..4f27b56cc99d5 --- /dev/null +++ b/tests/fixtures/world_bank_dashboard.py @@ -0,0 +1,484 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +import json +import string +from random import choice, randint, random, uniform +from typing import Any, Dict, List + +import pandas as pd +import pytest +from pandas import DataFrame +from sqlalchemy import DateTime, String, TIMESTAMP + +from superset import db +from superset.connectors.sqla.models import SqlaTable +from superset.models.core import Database +from superset.models.dashboard import Dashboard +from superset.models.slice import Slice +from superset.utils.core import get_example_database +from tests.dashboard_utils import create_dashboard, create_table_for_dashboard +from tests.test_app import app + + +@pytest.fixture() +def load_world_bank_dashboard_with_slices(): + dash_id_to_delete, slices_ids_to_delete = _load_data() + yield + with app.app_context(): + _cleanup(dash_id_to_delete, slices_ids_to_delete) + + +@pytest.fixture(scope="module") +def load_world_bank_dashboard_with_slices_module_scope(): + dash_id_to_delete, slices_ids_to_delete = _load_data() + yield + with app.app_context(): + _cleanup(dash_id_to_delete, slices_ids_to_delete) + + +def _load_data(): + table_name = "wb_health_population" + + with app.app_context(): + database = get_example_database() + df = _get_dataframe(database) + dtype = { + "year": DateTime if database.backend != "presto" else String(255), + "country_code": String(3), + "country_name": String(255), + "region": String(255), + } + table = create_table_for_dashboard(df, table_name, database, dtype) + slices = _create_world_bank_slices(table) + dash = _create_world_bank_dashboard(table, slices) + slices_ids_to_delete = [slice.id for slice in slices] + dash_id_to_delete = dash.id + return dash_id_to_delete, slices_ids_to_delete + + +def _create_world_bank_slices(table: SqlaTable) -> List[Slice]: + from superset.examples.world_bank import create_slices + + slices = create_slices(table) + _commit_slices(slices) + return slices + + +def _commit_slices(slices: List[Slice]): + for slice in slices: + o = db.session.query(Slice).filter_by(slice_name=slice.slice_name).one_or_none() + if o: + db.session.delete(o) + db.session.add(slice) + db.session.commit() + + +def _create_world_bank_dashboard(table: SqlaTable, slices: List[Slice]) -> Dashboard: + from superset.examples.world_bank import dashboard_positions + + pos = dashboard_positions + from superset.examples.helpers import update_slice_ids + + update_slice_ids(pos, slices) + + table.fetch_metadata() + + dash = create_dashboard( + "world_health", "World Bank's Data", json.dumps(pos), slices + ) + dash.json_metadata = '{"mock_key": "mock_value"}' + db.session.commit() + return dash + + +def _cleanup(dash_id: int, slices_ids: List[int]) -> None: + engine = get_example_database().get_sqla_engine() + engine.execute("DROP TABLE IF EXISTS wb_health_population") + dash = db.session.query(Dashboard).filter_by(id=dash_id).first() + db.session.delete(dash) + for slice_id in slices_ids: + db.session.query(Slice).filter_by(id=slice_id).delete() + db.session.commit() + + +def _get_dataframe(database: Database) -> DataFrame: + data = _get_world_bank_data() + df = pd.DataFrame.from_dict(data) + if database.backend == "presto": + df.year = pd.to_datetime(df.year) + df.year = df.year.dt.strftime("%Y-%m-%d %H:%M%:%S") + else: + df.year = pd.to_datetime(df.year) + + return df + + +def _get_world_bank_data() -> List[Dict[Any, Any]]: + data = [] + for _ in range(100): + data.append( + { + "country_name": "".join( + choice(string.ascii_uppercase + string.ascii_lowercase + " ") + for _ in range(randint(3, 10)) + ), + "country_code": "".join( + choice(string.ascii_uppercase + string.ascii_lowercase) + for _ in range(3) + ), + "region": "".join( + choice(string.ascii_uppercase + string.ascii_lowercase) + for _ in range(randint(3, 10)) + ), + "year": "-".join( + [str(randint(1900, 2020)), str(randint(1, 12)), str(randint(1, 28))] + ), + "NY_GNP_PCAP_CD": get_random_float_or_none(0, 100, 0.3), + "SE_ADT_1524_LT_FM_ZS": get_random_float_or_none(0, 100, 0.3), + "SE_ADT_1524_LT_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SE_ADT_1524_LT_ZS": get_random_float_or_none(0, 100, 0.3), + "SE_ADT_LITR_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SE_ADT_LITR_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SE_ADT_LITR_ZS": get_random_float_or_none(0, 100, 0.3), + "SE_ENR_ORPH": get_random_float_or_none(0, 100, 0.3), + "SE_PRM_CMPT_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SE_PRM_CMPT_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SE_PRM_CMPT_ZS": get_random_float_or_none(0, 100, 0.3), + "SE_PRM_ENRR": get_random_float_or_none(0, 100, 0.3), + "SE_PRM_ENRR_FE": get_random_float_or_none(0, 100, 0.3), + "SE_PRM_ENRR_MA": get_random_float_or_none(0, 100, 0.3), + "SE_PRM_NENR": get_random_float_or_none(0, 100, 0.3), + "SE_PRM_NENR_FE": get_random_float_or_none(0, 100, 0.3), + "SE_PRM_NENR_MA": get_random_float_or_none(0, 100, 0.3), + "SE_SEC_ENRR": get_random_float_or_none(0, 100, 0.3), + "SE_SEC_ENRR_FE": get_random_float_or_none(0, 100, 0.3), + "SE_SEC_ENRR_MA": get_random_float_or_none(0, 100, 0.3), + "SE_SEC_NENR": get_random_float_or_none(0, 100, 0.3), + "SE_SEC_NENR_FE": get_random_float_or_none(0, 100, 0.3), + "SE_SEC_NENR_MA": get_random_float_or_none(0, 100, 0.3), + "SE_TER_ENRR": get_random_float_or_none(0, 100, 0.3), + "SE_TER_ENRR_FE": get_random_float_or_none(0, 100, 0.3), + "SE_XPD_TOTL_GD_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_ANM_CHLD_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_ANM_NPRG_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_CON_1524_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_CON_1524_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_CON_AIDS_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_CON_AIDS_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_DTH_COMM_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_DTH_IMRT": get_random_float_or_none(0, 100, 0.3), + "SH_DTH_INJR_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_DTH_MORT": get_random_float_or_none(0, 100, 0.3), + "SH_DTH_NCOM_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_DTH_NMRT": get_random_float_or_none(0, 100, 0.3), + "SH_DYN_AIDS": get_random_float_or_none(0, 100, 0.3), + "SH_DYN_AIDS_DH": get_random_float_or_none(0, 100, 0.3), + "SH_DYN_AIDS_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_DYN_AIDS_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_DYN_MORT": get_random_float_or_none(0, 100, 0.3), + "SH_DYN_MORT_FE": get_random_float_or_none(0, 100, 0.3), + "SH_DYN_MORT_MA": get_random_float_or_none(0, 100, 0.3), + "SH_DYN_NMRT": get_random_float_or_none(0, 100, 0.3), + "SH_FPL_SATI_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_H2O_SAFE_RU_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_H2O_SAFE_UR_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_H2O_SAFE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_HIV_0014": get_random_float_or_none(0, 100, 0.3), + "SH_HIV_1524_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_HIV_1524_KW_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_HIV_1524_KW_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_HIV_1524_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_HIV_ARTC_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_HIV_KNOW_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_HIV_KNOW_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_HIV_ORPH": get_random_float_or_none(0, 100, 0.3), + "SH_HIV_TOTL": get_random_float_or_none(0, 100, 0.3), + "SH_IMM_HEPB": get_random_float_or_none(0, 100, 0.3), + "SH_IMM_HIB3": get_random_float_or_none(0, 100, 0.3), + "SH_IMM_IBCG": get_random_float_or_none(0, 100, 0.3), + "SH_IMM_IDPT": get_random_float_or_none(0, 100, 0.3), + "SH_IMM_MEAS": get_random_float_or_none(0, 100, 0.3), + "SH_IMM_POL3": get_random_float_or_none(0, 100, 0.3), + "SH_MED_BEDS_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_MED_CMHW_P3": get_random_float_or_none(0, 100, 0.3), + "SH_MED_NUMW_P3": get_random_float_or_none(0, 100, 0.3), + "SH_MED_PHYS_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_MLR_NETS_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_MLR_PREG_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_MLR_SPF2_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_MLR_TRET_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_MMR_DTHS": get_random_float_or_none(0, 100, 0.3), + "SH_MMR_LEVE": get_random_float_or_none(0, 100, 0.3), + "SH_MMR_RISK": get_random_float_or_none(0, 100, 0.3), + "SH_MMR_RISK_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_MMR_WAGE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_PRG_ANEM": get_random_float_or_none(0, 100, 0.3), + "SH_PRG_ARTC_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_PRG_SYPH_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_PRV_SMOK_FE": get_random_float_or_none(0, 100, 0.3), + "SH_PRV_SMOK_MA": get_random_float_or_none(0, 100, 0.3), + "SH_STA_ACSN": get_random_float_or_none(0, 100, 0.3), + "SH_STA_ACSN_RU": get_random_float_or_none(0, 100, 0.3), + "SH_STA_ACSN_UR": get_random_float_or_none(0, 100, 0.3), + "SH_STA_ANV4_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_ANVC_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_ARIC_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_BFED_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_BRTC_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_BRTW_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_DIAB_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_IYCF_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_MALN_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_MALN_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_MALN_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_MALR": get_random_float_or_none(0, 100, 0.3), + "SH_STA_MMRT": get_random_float_or_none(0, 100, 0.3), + "SH_STA_MMRT_NE": get_random_float_or_none(0, 100, 0.3), + "SH_STA_ORCF_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_ORTH": get_random_float_or_none(0, 100, 0.3), + "SH_STA_OW15_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_OW15_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_OW15_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_OWGH_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_OWGH_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_OWGH_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_PNVC_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_STNT_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_STNT_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_STNT_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_WAST_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_WAST_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_STA_WAST_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_SVR_WAST_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_SVR_WAST_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_SVR_WAST_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_TBS_CURE_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_TBS_DTEC_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_TBS_INCD": get_random_float_or_none(0, 100, 0.3), + "SH_TBS_MORT": get_random_float_or_none(0, 100, 0.3), + "SH_TBS_PREV": get_random_float_or_none(0, 100, 0.3), + "SH_VAC_TTNS_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_XPD_EXTR_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_XPD_OOPC_TO_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_XPD_OOPC_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_XPD_PCAP": get_random_float_or_none(0, 100, 0.3), + "SH_XPD_PCAP_PP_KD": get_random_float_or_none(0, 100, 0.3), + "SH_XPD_PRIV": get_random_float_or_none(0, 100, 0.3), + "SH_XPD_PRIV_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_XPD_PUBL": get_random_float_or_none(0, 100, 0.3), + "SH_XPD_PUBL_GX_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_XPD_PUBL_ZS": get_random_float_or_none(0, 100, 0.3), + "SH_XPD_TOTL_CD": get_random_float_or_none(0, 100, 0.3), + "SH_XPD_TOTL_ZS": get_random_float_or_none(0, 100, 0.3), + "SI_POV_NAHC": get_random_float_or_none(0, 100, 0.3), + "SI_POV_RUHC": get_random_float_or_none(0, 100, 0.3), + "SI_POV_URHC": get_random_float_or_none(0, 100, 0.3), + "SL_EMP_INSV_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SL_TLF_TOTL_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SL_TLF_TOTL_IN": get_random_float_or_none(0, 100, 0.3), + "SL_UEM_TOTL_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SL_UEM_TOTL_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SL_UEM_TOTL_ZS": get_random_float_or_none(0, 100, 0.3), + "SM_POP_NETM": get_random_float_or_none(0, 100, 0.3), + "SN_ITK_DEFC": get_random_float_or_none(0, 100, 0.3), + "SN_ITK_DEFC_ZS": get_random_float_or_none(0, 100, 0.3), + "SN_ITK_SALT_ZS": get_random_float_or_none(0, 100, 0.3), + "SN_ITK_VITA_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_ADO_TFRT": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_AMRT_FE": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_AMRT_MA": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_CBRT_IN": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_CDRT_IN": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_CONU_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_IMRT_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_IMRT_IN": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_IMRT_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_LE00_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_LE00_IN": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_LE00_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_SMAM_FE": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_SMAM_MA": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_TFRT_IN": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_TO65_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_TO65_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_DYN_WFRT": get_random_float_or_none(0, 100, 0.3), + "SP_HOU_FEMA_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_MTR_1519_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_POP_0004_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_0004_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_0004_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_0004_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_0014_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_POP_0014_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_POP_0014_TO": get_random_float_or_none(0, 100, 0.3), + "SP_POP_0014_TO_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_POP_0509_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_0509_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_0509_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_0509_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_1014_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_1014_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_1014_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_1014_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_1519_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_1519_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_1519_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_1519_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_1564_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_POP_1564_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_POP_1564_TO": get_random_float_or_none(0, 100, 0.3), + "SP_POP_1564_TO_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_POP_2024_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_2024_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_2024_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_2024_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_2529_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_2529_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_2529_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_2529_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_3034_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_3034_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_3034_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_3034_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_3539_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_3539_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_3539_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_3539_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_4044_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_4044_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_4044_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_4044_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_4549_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_4549_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_4549_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_4549_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_5054_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_5054_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_5054_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_5054_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_5559_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_5559_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_5559_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_5559_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_6064_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_6064_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_6064_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_6064_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_6569_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_6569_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_6569_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_6569_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_65UP_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_POP_65UP_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_POP_65UP_TO": get_random_float_or_none(0, 100, 0.3), + "SP_POP_65UP_TO_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_POP_7074_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_7074_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_7074_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_7074_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_7579_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_7579_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_7579_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_7579_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_80UP_FE": get_random_float_or_none(0, 100, 0.3), + "SP_POP_80UP_FE_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_80UP_MA": get_random_float_or_none(0, 100, 0.3), + "SP_POP_80UP_MA_5Y": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG00_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG00_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG01_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG01_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG02_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG02_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG03_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG03_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG04_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG04_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG05_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG05_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG06_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG06_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG07_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG07_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG08_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG08_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG09_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG09_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG10_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG10_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG11_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG11_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG12_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG12_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG13_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG13_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG14_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG14_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG15_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG15_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG16_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG16_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG17_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG17_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG18_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG18_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG19_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG19_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG20_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG20_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG21_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG21_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG22_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG22_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG23_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG23_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG24_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG24_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG25_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_AG25_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_BRTH_MF": get_random_float_or_none(0, 100, 0.3), + "SP_POP_DPND": get_random_float_or_none(0, 100, 0.3), + "SP_POP_DPND_OL": get_random_float_or_none(0, 100, 0.3), + "SP_POP_DPND_YG": get_random_float_or_none(0, 100, 0.3), + "SP_POP_GROW": get_random_float_or_none(0, 100, 0.3), + "SP_POP_TOTL": get_random_float_or_none(0, 100, 0.3), + "SP_POP_TOTL_FE_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_TOTL_FE_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_POP_TOTL_MA_IN": get_random_float_or_none(0, 100, 0.3), + "SP_POP_TOTL_MA_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_REG_BRTH_RU_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_REG_BRTH_UR_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_REG_BRTH_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_REG_DTHS_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_RUR_TOTL": get_random_float_or_none(0, 100, 0.3), + "SP_RUR_TOTL_ZG": get_random_float_or_none(0, 100, 0.3), + "SP_RUR_TOTL_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_URB_GROW": get_random_float_or_none(0, 100, 0.3), + "SP_URB_TOTL": get_random_float_or_none(0, 100, 0.3), + "SP_URB_TOTL_IN_ZS": get_random_float_or_none(0, 100, 0.3), + "SP_UWT_TFRT": get_random_float_or_none(0, 100, 0.3), + } + ) + + return data + + +def get_random_float_or_none(min_value, max_value, none_probability): + if random() < none_probability: + return None + else: + return uniform(min_value, max_value) diff --git a/tests/import_export_tests.py b/tests/import_export_tests.py index 2dc29f0acb6b2..4aaf8fbc66e84 100644 --- a/tests/import_export_tests.py +++ b/tests/import_export_tests.py @@ -41,6 +41,7 @@ from superset.models.slice import Slice from superset.utils.core import get_example_database +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices from .base_tests import SupersetTestCase @@ -270,7 +271,10 @@ def test_export_1_dashboard(self): self.get_table_by_name("birth_names"), exported_tables[0] ) - @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices") + @pytest.mark.usefixtures( + "load_world_bank_dashboard_with_slices", + "load_birth_names_dashboard_with_slices", + ) def test_export_2_dashboards(self): self.login("admin") birth_dash = self.get_dash_by_slug("births") @@ -311,6 +315,7 @@ def test_export_2_dashboards(self): self.get_table_by_name("wb_health_population"), exported_tables[1] ) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_import_1_slice(self): expected_slice = self.create_slice("Import Me", id=10001) slc_id = import_chart(expected_slice, None, import_time=1989) @@ -321,6 +326,7 @@ def test_import_1_slice(self): table_id = self.get_table_by_name("wb_health_population").id self.assertEqual(table_id, self.get_slice(slc_id).datasource_id) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_import_2_slices_for_same_table(self): table_id = self.get_table_by_name("wb_health_population").id # table_id != 666, import func will have to find the table @@ -363,6 +369,7 @@ def test_import_empty_dashboard(self): imported_dash = self.get_dash(imported_dash_id) self.assert_dash_equals(empty_dash, imported_dash, check_position=False) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_import_dashboard_1_slice(self): slc = self.create_slice("health_slc", id=10006) dash_with_1_slice = self.create_dashboard( diff --git a/tests/schedules_test.py b/tests/schedules_test.py index 8ff7a528b97af..45693f4066c75 100644 --- a/tests/schedules_test.py +++ b/tests/schedules_test.py @@ -23,6 +23,9 @@ from selenium.common.exceptions import WebDriverException from slack import errors, WebClient +from tests.fixtures.world_bank_dashboard import ( + load_world_bank_dashboard_with_slices_module_scope, +) from tests.test_app import app from superset import db from superset.models.dashboard import Dashboard @@ -62,7 +65,6 @@ def setUpClass(cls): deliver_as_group=True, delivery_type=EmailDeliveryType.inline, ) - # Pick up a sample slice and dashboard slce = db.session.query(Slice).filter_by(slice_name="Participants").one() dashboard = ( @@ -99,6 +101,7 @@ def tearDownClass(cls): ).delete() db.session.commit() + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices_module_scope") def test_crontab_scheduler(self): crontab = "* * * * *" @@ -126,6 +129,7 @@ def test_crontab_scheduler(self): self.assertEqual(schedules[-1], stop_at - timedelta(seconds=12 * 60)) self.assertEqual(len(schedules), 5) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices_module_scope") def test_wider_schedules(self): crontab = "*/15 2,10 * * *" @@ -141,7 +145,10 @@ def test_wider_schedules(self): else: self.assertEqual(len(schedules), 0) - @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices_module_scope") + @pytest.mark.usefixtures( + "load_world_bank_dashboard_with_slices_module_scope", + "load_birth_names_dashboard_with_slices_module_scope", + ) def test_complex_schedule(self): # Run the job on every Friday of March and May # On these days, run the job at @@ -169,6 +176,7 @@ def test_complex_schedule(self): self.assertEqual(schedules[59], datetime.strptime("2018-03-30 17:40:00", fmt)) self.assertEqual(schedules[60], datetime.strptime("2018-05-04 17:10:00", fmt)) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices_module_scope") @patch("superset.tasks.schedules.firefox.webdriver.WebDriver") def test_create_driver(self, mock_driver_class): mock_driver = Mock() @@ -178,6 +186,7 @@ def test_create_driver(self, mock_driver_class): create_webdriver(db.session) mock_driver.add_cookie.assert_called_once() + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices_module_scope") @patch("superset.tasks.schedules.firefox.webdriver.WebDriver") @patch("superset.tasks.schedules.send_email_smtp") @patch("superset.tasks.schedules.time") @@ -211,6 +220,7 @@ def test_deliver_dashboard_inline(self, mtime, send_email_smtp, driver_class): driver.screenshot.assert_not_called() send_email_smtp.assert_called_once() + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices_module_scope") @patch("superset.tasks.schedules.firefox.webdriver.WebDriver") @patch("superset.tasks.schedules.send_email_smtp") @patch("superset.tasks.schedules.time") @@ -254,6 +264,7 @@ def test_deliver_dashboard_as_attachment( element.screenshot_as_png, ) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices_module_scope") @patch("superset.tasks.schedules.firefox.webdriver.WebDriver") @patch("superset.tasks.schedules.send_email_smtp") @patch("superset.tasks.schedules.time") @@ -297,6 +308,7 @@ def test_dashboard_chrome_like(self, mtime, send_email_smtp, driver_class): driver.screenshot.return_value, ) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices_module_scope") @patch("superset.tasks.schedules.firefox.webdriver.WebDriver") @patch("superset.tasks.schedules.send_email_smtp") @patch("superset.tasks.schedules.time") @@ -338,6 +350,7 @@ def test_deliver_email_options(self, mtime, send_email_smtp, driver_class): self.assertEqual(send_email_smtp.call_count, 2) self.assertEqual(send_email_smtp.call_args[1]["bcc"], self.BCC) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices_module_scope") @patch("superset.tasks.slack_util.WebClient.files_upload") @patch("superset.tasks.schedules.firefox.webdriver.WebDriver") @patch("superset.tasks.schedules.send_email_smtp") @@ -391,6 +404,7 @@ def test_deliver_slice_inline_image( }, ) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices_module_scope") @patch("superset.tasks.slack_util.WebClient.files_upload") @patch("superset.tasks.schedules.firefox.webdriver.WebDriver") @patch("superset.tasks.schedules.send_email_smtp") @@ -445,6 +459,7 @@ def test_deliver_slice_attachment( }, ) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices_module_scope") @patch("superset.tasks.slack_util.WebClient.files_upload") @patch("superset.tasks.schedules.urllib.request.OpenerDirector.open") @patch("superset.tasks.schedules.urllib.request.urlopen") @@ -491,6 +506,7 @@ def test_deliver_slice_csv_attachment( }, ) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices_module_scope") @patch("superset.tasks.slack_util.WebClient.files_upload") @patch("superset.tasks.schedules.urllib.request.urlopen") @patch("superset.tasks.schedules.urllib.request.OpenerDirector.open") diff --git a/tests/security_tests.py b/tests/security_tests.py index 7ddc326c77f88..1b7e0b3a5e55b 100644 --- a/tests/security_tests.py +++ b/tests/security_tests.py @@ -29,6 +29,9 @@ from flask import current_app, g from sqlalchemy import Float, Date, String +from superset.models.dashboard import Dashboard +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices + from superset import app, appbuilder, db, security_manager, viz, ConnectorRegistry from superset.connectors.druid.models import DruidCluster, DruidDatasource from superset.connectors.sqla.models import RowLevelSecurityFilter, SqlaTable @@ -260,6 +263,7 @@ def test_set_perm_sqla_table(self): session.delete(stored_table) session.commit() + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_set_perm_druid_datasource(self): self.create_druid_test_objects() session = db.session @@ -534,7 +538,12 @@ def test_schemas_accessible_by_user_datasource_and_schema_access(self, mock_g): self.assertIsNotNone(vm) delete_schema_perm("[examples].[2]") + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_gamma_user_schema_access_to_dashboards(self): + dash = db.session.query(Dashboard).filter_by(slug="world_health").first() + dash.published = True + db.session.commit() + self.login(username="gamma") data = str(self.client.get("api/v1/dashboard/").data) self.assertIn("/superset/dashboard/world_health/", data) @@ -546,6 +555,7 @@ def test_gamma_user_schema_access_to_tables(self): self.assertIn("wb_health_population", data) self.assertNotIn("birth_names", data) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_gamma_user_schema_access_to_charts(self): self.login(username="gamma") data = str(self.client.get("api/v1/chart/").data) @@ -820,6 +830,7 @@ def test_alpha_permissions(self): @unittest.skipUnless( SupersetTestCase.is_module_installed("pydruid"), "pydruid not installed" ) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_admin_permissions(self): self.assert_can_gamma(get_perm_tuples("Admin")) self.assert_can_alpha(get_perm_tuples("Admin")) diff --git a/tests/utils_tests.py b/tests/utils_tests.py index a16db4b27b31b..1c6e6b2e93ed2 100644 --- a/tests/utils_tests.py +++ b/tests/utils_tests.py @@ -70,6 +70,7 @@ get_time_range_endpoints, ) from tests.base_tests import SupersetTestCase +from tests.fixtures.world_bank_dashboard import load_world_bank_dashboard_with_slices from .fixtures.certificates import ssl_certificate @@ -853,6 +854,7 @@ def test_get_iterable(self): self.assertListEqual(get_iterable([123]), [123]) self.assertListEqual(get_iterable("foo"), ["foo"]) + @pytest.mark.usefixtures("load_world_bank_dashboard_with_slices") def test_build_extra_filters(self): world_health = db.session.query(Dashboard).filter_by(slug="world_health").one() layout = json.loads(world_health.position_json)