From 4b34817b195fe93aa0bffd211bc978966a4aee4e Mon Sep 17 00:00:00 2001 From: Craig Rueda Date: Thu, 17 Mar 2022 08:58:48 -0700 Subject: [PATCH] feat(ui): Adding manifest prefix config (#19141) * Adding manifest prefix config * Fixing broken tests * Fixing import * Adding prefix for remaining assets * Changing static prefix strategy * Fixing DST test * Fixing up formatting * Fixing up async_query_manager.py types --- superset-frontend/webpack.config.js | 4 +- superset/common/query_object.py | 2 +- superset/config.py | 6 ++- superset/connectors/base/models.py | 2 +- superset/connectors/druid/models.py | 2 +- superset/connectors/druid/views.py | 2 +- superset/connectors/sqla/models.py | 8 ++- superset/connectors/sqla/views.py | 2 +- superset/databases/api.py | 2 +- superset/extensions.py | 30 ++++++----- superset/initialization/__init__.py | 2 +- superset/result_set.py | 2 +- superset/{typing.py => superset_typing.py} | 0 superset/templates/superset/base.html | 2 +- superset/templates/superset/basic.html | 8 +-- superset/templates/superset/theme.html | 2 +- superset/utils/core.py | 2 +- superset/views/alerts.py | 2 +- superset/views/annotations.py | 2 +- superset/views/api.py | 2 +- superset/views/base.py | 2 +- superset/views/base_api.py | 2 +- superset/views/chart/views.py | 2 +- superset/views/core.py | 2 +- superset/views/css_templates.py | 2 +- superset/views/dashboard/views.py | 2 +- superset/views/database/views.py | 2 +- superset/views/datasource/views.py | 2 +- superset/views/health.py | 2 +- superset/views/key_value.py | 2 +- superset/views/redirects.py | 2 +- superset/views/schedules.py | 2 +- superset/views/sql_lab.py | 2 +- superset/views/tags.py | 2 +- superset/views/utils.py | 2 +- superset/viz.py | 8 ++- .../charts/data/api_tests.py | 2 +- tests/unit_tests/dataframe_test.py | 2 +- tests/unit_tests/extension_tests.py | 51 +++++++++++++++++++ .../fixtures/static/assets/manifest.json | 20 ++++++++ 40 files changed, 144 insertions(+), 53 deletions(-) rename superset/{typing.py => superset_typing.py} (100%) create mode 100644 tests/unit_tests/extension_tests.py create mode 100644 tests/unit_tests/fixtures/static/assets/manifest.json diff --git a/superset-frontend/webpack.config.js b/superset-frontend/webpack.config.js index a4c1b86b48..6b3c4e30a8 100644 --- a/superset-frontend/webpack.config.js +++ b/superset-frontend/webpack.config.js @@ -95,10 +95,10 @@ const plugins = [ entryFiles[entry] = { css: chunks .filter(x => x.endsWith('.css')) - .map(x => path.join(output.publicPath, x)), + .map(x => `${output.publicPath}${x}`), js: chunks .filter(x => x.endsWith('.js')) - .map(x => path.join(output.publicPath, x)), + .map(x => `${output.publicPath}${x}`), }; }); diff --git a/superset/common/query_object.py b/superset/common/query_object.py index 2a40155d1c..fd988a36fa 100644 --- a/superset/common/query_object.py +++ b/superset/common/query_object.py @@ -31,7 +31,7 @@ from superset.exceptions import ( QueryObjectValidationError, ) from superset.sql_parse import validate_filter_clause -from superset.typing import Column, Metric, OrderBy +from superset.superset_typing import Column, Metric, OrderBy from superset.utils import pandas_postprocessing from superset.utils.core import ( DTTM_ALIAS, diff --git a/superset/config.py b/superset/config.py index 7aa0b42694..26ce25228a 100644 --- a/superset/config.py +++ b/superset/config.py @@ -46,7 +46,7 @@ from superset.constants import CHANGE_ME_SECRET_KEY from superset.jinja_context import BaseTemplateProcessor from superset.key_value.types import KeyType from superset.stats_logger import DummyStatsLogger -from superset.typing import CacheConfig +from superset.superset_typing import CacheConfig from superset.utils.core import is_test, parse_boolean_string from superset.utils.encrypt import SQLAlchemyUtilsAdapter from superset.utils.log import DBEventLogger @@ -1252,6 +1252,10 @@ SEND_FILE_MAX_AGE_DEFAULT = int(timedelta(days=365).total_seconds()) # SQLALCHEMY_DATABASE_URI by default if set to `None` SQLALCHEMY_EXAMPLES_URI = None +# Optional prefix to be added to all static asset paths when rendering the UI. +# This is useful for hosting assets in an external CDN, for example +STATIC_ASSETS_PREFIX = "" + # Some sqlalchemy connection strings can open Superset to security risks. # Typically these should not be allowed. PREVENT_UNSAFE_DB_CONNECTIONS = True diff --git a/superset/connectors/base/models.py b/superset/connectors/base/models.py index 967235f328..5cf2a8719b 100644 --- a/superset/connectors/base/models.py +++ b/superset/connectors/base/models.py @@ -29,7 +29,7 @@ from superset.constants import EMPTY_STRING, NULL_STRING from superset.datasets.commands.exceptions import DatasetNotFoundError from superset.models.helpers import AuditMixinNullable, ImportExportMixin, QueryResult from superset.models.slice import Slice -from superset.typing import FilterValue, FilterValues, QueryObjectDict +from superset.superset_typing import FilterValue, FilterValues, QueryObjectDict from superset.utils import core as utils from superset.utils.core import GenericDataType diff --git a/superset/connectors/druid/models.py b/superset/connectors/druid/models.py index 32edb69527..3a17ec5319 100644 --- a/superset/connectors/druid/models.py +++ b/superset/connectors/druid/models.py @@ -58,7 +58,7 @@ from superset.exceptions import SupersetException from superset.extensions import encrypted_field_factory from superset.models.core import Database from superset.models.helpers import AuditMixinNullable, ImportExportMixin, QueryResult -from superset.typing import ( +from superset.superset_typing import ( AdhocMetric, AdhocMetricColumn, FilterValues, diff --git a/superset/connectors/druid/views.py b/superset/connectors/druid/views.py index 03a3a42ec0..cd7e5d279b 100644 --- a/superset/connectors/druid/views.py +++ b/superset/connectors/druid/views.py @@ -34,7 +34,7 @@ from superset.connectors.base.views import BS3TextFieldROWidget, DatasourceModel from superset.connectors.connector_registry import ConnectorRegistry from superset.connectors.druid import models from superset.constants import RouteMethod -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.utils import core as utils from superset.views.base import ( BaseSupersetView, diff --git a/superset/connectors/sqla/models.py b/superset/connectors/sqla/models.py index 4a68e666bd..99cbc50997 100644 --- a/superset/connectors/sqla/models.py +++ b/superset/connectors/sqla/models.py @@ -96,8 +96,14 @@ from superset.models.helpers import ( QueryResult, ) from superset.sql_parse import ParsedQuery +from superset.superset_typing import ( + AdhocColumn, + AdhocMetric, + Metric, + OrderBy, + QueryObjectDict, +) from superset.tables.models import Table as NewTable -from superset.typing import AdhocColumn, AdhocMetric, Metric, OrderBy, QueryObjectDict from superset.utils import core as utils from superset.utils.core import ( GenericDataType, diff --git a/superset/connectors/sqla/views.py b/superset/connectors/sqla/views.py index fef8a2d8a4..a16ffa49f6 100644 --- a/superset/connectors/sqla/views.py +++ b/superset/connectors/sqla/views.py @@ -36,7 +36,7 @@ from superset import app, db, is_feature_enabled from superset.connectors.base.views import DatasourceModelView from superset.connectors.sqla import models from superset.constants import MODEL_VIEW_RW_METHOD_PERMISSION_MAP, RouteMethod -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.utils import core as utils from superset.views.base import ( check_ownership, diff --git a/superset/databases/api.py b/superset/databases/api.py index 83cdf2571a..3737addede 100644 --- a/superset/databases/api.py +++ b/superset/databases/api.py @@ -70,7 +70,7 @@ from superset.db_engine_specs import get_available_engine_specs from superset.errors import ErrorLevel, SupersetError, SupersetErrorType from superset.extensions import security_manager from superset.models.core import Database -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.utils.core import error_msg_from_exception from superset.views.base_api import ( BaseSupersetModelRestApi, diff --git a/superset/extensions.py b/superset/extensions.py index 33dc1706a6..742182b078 100644 --- a/superset/extensions.py +++ b/superset/extensions.py @@ -63,22 +63,26 @@ class UIManifestProcessor: self.app = app # Preload the cache self.parse_manifest_json() + self.register_processor(app) - @app.context_processor - def get_manifest() -> Dict[str, Callable[[str], List[str]]]: - loaded_chunks = set() + def register_processor(self, app: Flask) -> None: + app.template_context_processors[None].append(self.get_manifest) - def get_files(bundle: str, asset_type: str = "js") -> List[str]: - files = self.get_manifest_files(bundle, asset_type) - filtered_files = [f for f in files if f not in loaded_chunks] - for f in filtered_files: - loaded_chunks.add(f) - return filtered_files + def get_manifest(self) -> Dict[str, Callable[[str], List[str]]]: + loaded_chunks = set() - return dict( - js_manifest=lambda bundle: get_files(bundle, "js"), - css_manifest=lambda bundle: get_files(bundle, "css"), - ) + def get_files(bundle: str, asset_type: str = "js") -> List[str]: + files = self.get_manifest_files(bundle, asset_type) + filtered_files = [f for f in files if f not in loaded_chunks] + for f in filtered_files: + loaded_chunks.add(f) + return filtered_files + + return dict( + js_manifest=lambda bundle: get_files(bundle, "js"), + css_manifest=lambda bundle: get_files(bundle, "css"), + assets_prefix=self.app.config["STATIC_ASSETS_PREFIX"] if self.app else "", + ) def parse_manifest_json(self) -> None: try: diff --git a/superset/initialization/__init__.py b/superset/initialization/__init__.py index ee4c3621ab..6e2d927efd 100644 --- a/superset/initialization/__init__.py +++ b/superset/initialization/__init__.py @@ -49,7 +49,7 @@ from superset.extensions import ( talisman, ) from superset.security import SupersetSecurityManager -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.utils.core import pessimistic_connection_handling from superset.utils.log import DBEventLogger, get_event_logger_from_cfg_value diff --git a/superset/result_set.py b/superset/result_set.py index b95b5e680d..19035b6d23 100644 --- a/superset/result_set.py +++ b/superset/result_set.py @@ -26,7 +26,7 @@ import pandas as pd import pyarrow as pa from superset.db_engine_specs import BaseEngineSpec -from superset.typing import DbapiDescription, DbapiResult +from superset.superset_typing import DbapiDescription, DbapiResult from superset.utils import core as utils logger = logging.getLogger(__name__) diff --git a/superset/typing.py b/superset/superset_typing.py similarity index 100% rename from superset/typing.py rename to superset/superset_typing.py diff --git a/superset/templates/superset/base.html b/superset/templates/superset/base.html index a861c659e7..e3c3d35dfe 100644 --- a/superset/templates/superset/base.html +++ b/superset/templates/superset/base.html @@ -21,7 +21,7 @@ {% block head_css %} {{ super() }} - + {{ css_bundle("theme") }} {% endblock %} diff --git a/superset/templates/superset/basic.html b/superset/templates/superset/basic.html index 902fc8c328..fff57fdb9f 100644 --- a/superset/templates/superset/basic.html +++ b/superset/templates/superset/basic.html @@ -40,11 +40,11 @@ rel="{{favicon.rel if favicon.rel else "icon"}}" type="{{favicon.type if favicon.type else "image/png"}}" {% if favicon.sizes %}sizes={{favicon.sizes}}{% endif %} - href="{{favicon.href}}" + href="{{ assets_prefix }}{{favicon.href}}" > {% endfor %} - - + + {{ css_bundle("theme") }} @@ -73,7 +73,7 @@ {% block body %}
- +
{% endblock %} diff --git a/superset/templates/superset/theme.html b/superset/templates/superset/theme.html index feac56f895..856796a4c4 100644 --- a/superset/templates/superset/theme.html +++ b/superset/templates/superset/theme.html @@ -1342,5 +1342,5 @@ {{ super() }} - + {% endblock %} diff --git a/superset/utils/core.py b/superset/utils/core.py index 2fdbc278ad..36d59333d2 100644 --- a/superset/utils/core.py +++ b/superset/utils/core.py @@ -98,7 +98,7 @@ from superset.exceptions import ( SupersetException, SupersetTimeoutException, ) -from superset.typing import ( +from superset.superset_typing import ( AdhocColumn, AdhocMetric, AdhocMetricColumn, diff --git a/superset/views/alerts.py b/superset/views/alerts.py index e96f701c3d..416966fbe7 100644 --- a/superset/views/alerts.py +++ b/superset/views/alerts.py @@ -30,8 +30,8 @@ from werkzeug.exceptions import NotFound from superset import is_feature_enabled from superset.constants import RouteMethod from superset.models.alerts import Alert, AlertLog, SQLObservation +from superset.superset_typing import FlaskResponse from superset.tasks.alerts.validator import check_validator -from superset.typing import FlaskResponse from superset.utils import core as utils from superset.utils.core import get_email_address_str, markdown diff --git a/superset/views/annotations.py b/superset/views/annotations.py index 4fa83c0ca4..dc1df5642a 100644 --- a/superset/views/annotations.py +++ b/superset/views/annotations.py @@ -26,7 +26,7 @@ from wtforms.validators import StopValidation from superset import is_feature_enabled from superset.constants import MODEL_VIEW_RW_METHOD_PERMISSION_MAP, RouteMethod from superset.models.annotations import Annotation, AnnotationLayer -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.views.base import SupersetModelView diff --git a/superset/views/api.py b/superset/views/api.py index d4d94ce723..bde2523646 100644 --- a/superset/views/api.py +++ b/superset/views/api.py @@ -31,7 +31,7 @@ from superset.charts.commands.exceptions import ( ) from superset.legacy import update_time_range from superset.models.slice import Slice -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.utils import core as utils from superset.utils.date_parser import get_since_until from superset.views.base import api, BaseSupersetView, handle_api_exception diff --git a/superset/views/base.py b/superset/views/base.py index 1249bc43cc..3024c4490d 100644 --- a/superset/views/base.py +++ b/superset/views/base.py @@ -73,8 +73,8 @@ from superset.exceptions import ( ) from superset.models.helpers import ImportExportMixin from superset.models.reports import ReportRecipientType +from superset.superset_typing import FlaskResponse from superset.translations.utils import get_language_pack -from superset.typing import FlaskResponse from superset.utils import core as utils from .utils import bootstrap_user_data diff --git a/superset/views/base_api.py b/superset/views/base_api.py index 87e99e7c74..260e573178 100644 --- a/superset/views/base_api.py +++ b/superset/views/base_api.py @@ -37,7 +37,7 @@ from superset.models.slice import Slice from superset.schemas import error_payload_content from superset.sql_lab import Query as SqllabQuery from superset.stats_logger import BaseStatsLogger -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.utils.core import time_function logger = logging.getLogger(__name__) diff --git a/superset/views/chart/views.py b/superset/views/chart/views.py index 37ef9a043e..9ecc69f7b9 100644 --- a/superset/views/chart/views.py +++ b/superset/views/chart/views.py @@ -24,7 +24,7 @@ from flask_babel import lazy_gettext as _ from superset import is_feature_enabled from superset.constants import MODEL_VIEW_RW_METHOD_PERMISSION_MAP, RouteMethod from superset.models.slice import Slice -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.utils import core as utils from superset.views.base import ( check_ownership, diff --git a/superset/views/core.py b/superset/views/core.py index f2f4ab31dd..f014ca2845 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -123,8 +123,8 @@ from superset.sqllab.sql_json_executer import ( from superset.sqllab.sqllab_execution_context import SqlJsonExecutionContext from superset.sqllab.utils import apply_display_max_row_configuration_if_require from superset.sqllab.validators import CanAccessQueryValidatorImpl +from superset.superset_typing import FlaskResponse from superset.tasks.async_queries import load_explore_json_into_cache -from superset.typing import FlaskResponse from superset.utils import core as utils, csv from superset.utils.async_query_manager import AsyncQueryTokenException from superset.utils.cache import etag_cache diff --git a/superset/views/css_templates.py b/superset/views/css_templates.py index d26acea5cf..2cfbd43ae9 100644 --- a/superset/views/css_templates.py +++ b/superset/views/css_templates.py @@ -22,7 +22,7 @@ from flask_babel import lazy_gettext as _ from superset import is_feature_enabled from superset.constants import MODEL_VIEW_RW_METHOD_PERMISSION_MAP, RouteMethod from superset.models import core as models -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.views.base import DeleteMixin, SupersetModelView diff --git a/superset/views/dashboard/views.py b/superset/views/dashboard/views.py index 99782def38..49ba61d08e 100644 --- a/superset/views/dashboard/views.py +++ b/superset/views/dashboard/views.py @@ -29,7 +29,7 @@ from flask_login import AnonymousUserMixin, LoginManager from superset import db, event_logger, is_feature_enabled, security_manager from superset.constants import MODEL_VIEW_RW_METHOD_PERMISSION_MAP, RouteMethod from superset.models.dashboard import Dashboard as DashboardModel -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.utils import core as utils from superset.views.base import ( BaseSupersetView, diff --git a/superset/views/database/views.py b/superset/views/database/views.py index 115d168ed6..aea4e04383 100644 --- a/superset/views/database/views.py +++ b/superset/views/database/views.py @@ -37,7 +37,7 @@ from superset.constants import MODEL_VIEW_RW_METHOD_PERMISSION_MAP, RouteMethod from superset.exceptions import CertificateException from superset.extensions import event_logger from superset.sql_parse import Table -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.utils import core as utils from superset.views.base import DeleteMixin, SupersetModelView, YamlExportMixin diff --git a/superset/views/datasource/views.py b/superset/views/datasource/views.py index e2cb204082..7e1ffa0468 100644 --- a/superset/views/datasource/views.py +++ b/superset/views/datasource/views.py @@ -38,7 +38,7 @@ from superset.datasets.commands.exceptions import ( from superset.exceptions import SupersetException, SupersetSecurityException from superset.extensions import security_manager from superset.models.core import Database -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.views.base import ( api, BaseSupersetView, diff --git a/superset/views/health.py b/superset/views/health.py index 876e7a5e13..cf85b89278 100644 --- a/superset/views/health.py +++ b/superset/views/health.py @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. from superset import app, talisman -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse @talisman(force_https=False) diff --git a/superset/views/key_value.py b/superset/views/key_value.py index 8f8aa99787..da39f094b8 100644 --- a/superset/views/key_value.py +++ b/superset/views/key_value.py @@ -23,7 +23,7 @@ from werkzeug.exceptions import NotFound from superset import db, event_logger, is_feature_enabled from superset.models import core as models -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.utils import core as utils from superset.views.base import BaseSupersetView, json_error_response diff --git a/superset/views/redirects.py b/superset/views/redirects.py index 805d917f7e..831fc978b9 100644 --- a/superset/views/redirects.py +++ b/superset/views/redirects.py @@ -23,7 +23,7 @@ from werkzeug.utils import redirect from superset import db, event_logger from superset.models import core as models -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.views.base import BaseSupersetView logger = logging.getLogger(__name__) diff --git a/superset/views/schedules.py b/superset/views/schedules.py index d1c59f413c..39d4af9b8b 100644 --- a/superset/views/schedules.py +++ b/superset/views/schedules.py @@ -42,8 +42,8 @@ from superset.models.schedules import ( SliceEmailSchedule, ) from superset.models.slice import Slice +from superset.superset_typing import FlaskResponse from superset.tasks.schedules import schedule_email_report -from superset.typing import FlaskResponse from superset.utils.core import get_email_address_list, json_iso_dttm_ser from superset.views.core import json_success diff --git a/superset/views/sql_lab.py b/superset/views/sql_lab.py index 6a5ce26d38..5ec525b9ca 100644 --- a/superset/views/sql_lab.py +++ b/superset/views/sql_lab.py @@ -24,7 +24,7 @@ from flask_babel import lazy_gettext as _ from superset import db, is_feature_enabled from superset.constants import MODEL_VIEW_RW_METHOD_PERMISSION_MAP, RouteMethod from superset.models.sql_lab import Query, SavedQuery, TableSchema, TabState -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from superset.utils import core as utils from .base import BaseSupersetView, DeleteMixin, json_success, SupersetModelView diff --git a/superset/views/tags.py b/superset/views/tags.py index c6fac2ff77..8ab2798f5d 100644 --- a/superset/views/tags.py +++ b/superset/views/tags.py @@ -33,7 +33,7 @@ from superset.models.dashboard import Dashboard from superset.models.slice import Slice from superset.models.sql_lab import SavedQuery from superset.models.tags import ObjectTypes, Tag, TaggedObject, TagTypes -from superset.typing import FlaskResponse +from superset.superset_typing import FlaskResponse from .base import BaseSupersetView, json_success diff --git a/superset/views/utils.py b/superset/views/utils.py index 17ec6ea108..62639174f6 100644 --- a/superset/views/utils.py +++ b/superset/views/utils.py @@ -46,7 +46,7 @@ from superset.models.core import Database from superset.models.dashboard import Dashboard from superset.models.slice import Slice from superset.models.sql_lab import Query -from superset.typing import FormData +from superset.superset_typing import FormData from superset.utils.decorators import stats_timing from superset.viz import BaseViz diff --git a/superset/viz.py b/superset/viz.py index 9a1086442b..7c0f8e1348 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -70,7 +70,13 @@ from superset.exceptions import ( from superset.extensions import cache_manager, security_manager from superset.models.helpers import QueryResult from superset.sql_parse import validate_filter_clause -from superset.typing import Column, Metric, QueryObjectDict, VizData, VizPayload +from superset.superset_typing import ( + Column, + Metric, + QueryObjectDict, + VizData, + VizPayload, +) from superset.utils import core as utils, csv from superset.utils.cache import set_and_log_cache from superset.utils.core import ( diff --git a/tests/integration_tests/charts/data/api_tests.py b/tests/integration_tests/charts/data/api_tests.py index 4f63ad51b6..bc8ec74feb 100644 --- a/tests/integration_tests/charts/data/api_tests.py +++ b/tests/integration_tests/charts/data/api_tests.py @@ -47,7 +47,7 @@ from superset.errors import SupersetErrorType from superset.extensions import async_query_manager, db from superset.models.annotations import AnnotationLayer from superset.models.slice import Slice -from superset.typing import AdhocColumn +from superset.superset_typing import AdhocColumn from superset.utils.core import ( AnnotationType, get_example_default_schema, diff --git a/tests/unit_tests/dataframe_test.py b/tests/unit_tests/dataframe_test.py index 3e986a5e43..79625cffe6 100644 --- a/tests/unit_tests/dataframe_test.py +++ b/tests/unit_tests/dataframe_test.py @@ -16,7 +16,7 @@ # under the License. # pylint: disable=unused-argument, import-outside-toplevel from superset.dataframe import df_to_records -from superset.typing import DbapiDescription +from superset.superset_typing import DbapiDescription def test_df_to_records(app_context: None) -> None: diff --git a/tests/unit_tests/extension_tests.py b/tests/unit_tests/extension_tests.py new file mode 100644 index 0000000000..724b03f01a --- /dev/null +++ b/tests/unit_tests/extension_tests.py @@ -0,0 +1,51 @@ +# 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. +from os.path import dirname +from unittest.mock import Mock + +from superset.extensions import UIManifestProcessor + +APP_DIR = f"{dirname(__file__)}/fixtures" + + +def test_get_manifest_with_prefix(): + app = Mock( + config={"STATIC_ASSETS_PREFIX": "https://cool.url/here"}, + template_context_processors={None: []}, + ) + manifest_processor = UIManifestProcessor(APP_DIR) + manifest_processor.init_app(app) + manifest = manifest_processor.get_manifest() + assert manifest["js_manifest"]("main") == ["/static/dist/main-js.js"] + assert manifest["css_manifest"]("main") == ["/static/dist/main-css.css"] + assert manifest["js_manifest"]("styles") == ["/static/dist/styles-js.js"] + assert manifest["css_manifest"]("styles") == [] + assert manifest["assets_prefix"] == "https://cool.url/here" + + +def test_get_manifest_no_prefix(): + app = Mock( + config={"STATIC_ASSETS_PREFIX": ""}, template_context_processors={None: []} + ) + manifest_processor = UIManifestProcessor(APP_DIR) + manifest_processor.init_app(app) + manifest = manifest_processor.get_manifest() + assert manifest["js_manifest"]("main") == ["/static/dist/main-js.js"] + assert manifest["css_manifest"]("main") == ["/static/dist/main-css.css"] + assert manifest["js_manifest"]("styles") == ["/static/dist/styles-js.js"] + assert manifest["css_manifest"]("styles") == [] + assert manifest["assets_prefix"] == "" diff --git a/tests/unit_tests/fixtures/static/assets/manifest.json b/tests/unit_tests/fixtures/static/assets/manifest.json new file mode 100644 index 0000000000..7482a04eac --- /dev/null +++ b/tests/unit_tests/fixtures/static/assets/manifest.json @@ -0,0 +1,20 @@ +{ + "entrypoints": { + "styles": { + "js": [ + "/static/dist/styles-js.js" + ] + }, + "main": { + "css": [ + "/static/dist/main-css.css" + ], + "js": [ + "/static/dist/main-js.js" + ] + } + }, + "main.css": "/static/dist/main.b51d3f6225194da423d6.entry.css", + "main.js": "/static/dist/main.b51d3f6225194da423d6.entry.js", + "styles.js": "/static/dist/styles.35840b4bbf794f902b7c.entry.js" +}