This is an automated email from the ASF dual-hosted git repository. villebro pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push: new 5c4d4f1 feat: finalize Word Cloud move to new chart data endpoint (#9975) 5c4d4f1 is described below commit 5c4d4f16b323cd7f8dcdcbd788df3e6dd83200fc Author: Ville Brofeldt <33317356+ville...@users.noreply.github.com> AuthorDate: Fri Jun 5 14:08:46 2020 +0300 feat: finalize Word Cloud move to new chart data endpoint (#9975) * remove word cloud from viz.py * Fix Run in SQL Lab * remove deprecated python tests * break out legacy endpoint type into function * Break out exploreChart from exportChart and implement results type * Fix jest tests and refactor accordingly * lint * Rename v1 payload function * Add dashboard id to v1 chart data request url params * Add support for domain sharding to v1 chart data request --- .../spec/javascripts/chart/chartActions_spec.js | 18 +++-- .../sqllab/ExploreResultsButton_spec.jsx | 6 +- .../SqlLab/components/ExploreCtasResultsButton.jsx | 2 +- .../src/SqlLab/components/ExploreResultsButton.jsx | 4 +- superset-frontend/src/chart/chartAction.js | 67 +++++++--------- .../dashboard/components/gridComponents/Chart.jsx | 10 ++- .../src/explore/components/DisplayQueryButton.jsx | 6 +- .../explore/components/ExploreActionButtons.jsx | 12 ++- superset-frontend/src/explore/exploreUtils.js | 91 +++++++++++++++++----- .../SqlLab/components/ExploreCtasResultsButton.jsx | 4 +- superset/charts/api.py | 40 +++++++--- superset/common/query_context.py | 3 +- superset/viz.py | 18 ----- superset/viz_sip38.py | 13 ---- tests/core_tests.py | 81 ------------------- 15 files changed, 177 insertions(+), 198 deletions(-) diff --git a/superset-frontend/spec/javascripts/chart/chartActions_spec.js b/superset-frontend/spec/javascripts/chart/chartActions_spec.js index 15566dd..b8205e6 100644 --- a/superset-frontend/spec/javascripts/chart/chartActions_spec.js +++ b/superset-frontend/spec/javascripts/chart/chartActions_spec.js @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import URI from 'urijs'; import fetchMock from 'fetch-mock'; import sinon from 'sinon'; @@ -25,17 +26,16 @@ import * as exploreUtils from 'src/explore/exploreUtils'; import * as actions from 'src/chart/chartAction'; describe('chart actions', () => { - const V1_URL = '/http//localhost/api/v1/chart/data'; const MOCK_URL = '/mockURL'; let dispatch; - let urlStub; + let getExploreUrlStub; + let getChartDataUriStub; let metadataRegistryStub; let buildQueryRegistryStub; let fakeMetadata; const setupDefaultFetchMock = () => { fetchMock.post(MOCK_URL, { json: {} }, { overwriteRoutes: true }); - fetchMock.post(V1_URL, { json: {} }, { overwriteRoutes: true }); }; beforeAll(() => { @@ -46,9 +46,12 @@ describe('chart actions', () => { beforeEach(() => { dispatch = sinon.spy(); - urlStub = sinon + getExploreUrlStub = sinon .stub(exploreUtils, 'getExploreUrl') .callsFake(() => MOCK_URL); + getChartDataUriStub = sinon + .stub(exploreUtils, 'getChartDataUri') + .callsFake(() => URI(MOCK_URL)); fakeMetadata = { useLegacyApi: true }; metadataRegistryStub = sinon .stub(chartlib, 'getChartMetadataRegistry') @@ -65,7 +68,8 @@ describe('chart actions', () => { }); afterEach(() => { - urlStub.restore(); + getExploreUrlStub.restore(); + getChartDataUriStub.restore(); fetchMock.resetHistory(); metadataRegistryStub.restore(); buildQueryRegistryStub.restore(); @@ -80,8 +84,8 @@ describe('chart actions', () => { const actionThunk = actions.postChartFormData({}); await actionThunk(dispatch); - expect(fetchMock.calls(V1_URL)).toHaveLength(1); - expect(fetchMock.calls(V1_URL)[0][1].body).toBe( + expect(fetchMock.calls(MOCK_URL)).toHaveLength(1); + expect(fetchMock.calls(MOCK_URL)[0][1].body).toBe( JSON.stringify({ some_param: 'fake query!', result_type: 'full', diff --git a/superset-frontend/spec/javascripts/sqllab/ExploreResultsButton_spec.jsx b/superset-frontend/spec/javascripts/sqllab/ExploreResultsButton_spec.jsx index fee2ba5..ad6639b 100644 --- a/superset-frontend/spec/javascripts/sqllab/ExploreResultsButton_spec.jsx +++ b/superset-frontend/spec/javascripts/sqllab/ExploreResultsButton_spec.jsx @@ -179,12 +179,14 @@ describe('ExploreResultsButton', () => { beforeEach(() => { sinon.stub(exploreUtils, 'getExploreUrl').callsFake(() => 'mockURL'); sinon.spy(exploreUtils, 'exportChart'); + sinon.spy(exploreUtils, 'exploreChart'); sinon .stub(wrapper.instance(), 'buildVizOptions') .callsFake(() => mockOptions); }); afterEach(() => { exploreUtils.getExploreUrl.restore(); + exploreUtils.exploreChart.restore(); exploreUtils.exportChart.restore(); wrapper.instance().buildVizOptions.restore(); fetchMock.reset(); @@ -224,8 +226,8 @@ describe('ExploreResultsButton', () => { setTimeout(() => { expect(datasourceSpy.callCount).toBe(1); - expect(exploreUtils.exportChart.callCount).toBe(1); - expect(exploreUtils.exportChart.getCall(0).args[0].datasource).toBe( + expect(exploreUtils.exploreChart.callCount).toBe(1); + expect(exploreUtils.exploreChart.getCall(0).args[0].datasource).toBe( '107__table', ); expect(infoToastSpy.callCount).toBe(1); diff --git a/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton.jsx b/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton.jsx index 7f72a85..6a6162f 100644 --- a/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton.jsx +++ b/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton.jsx @@ -77,7 +77,7 @@ class ExploreCtasResultsButton extends React.PureComponent { ); // open new window for data visualization - exportChart(formData); + exportChart({ formData }); }) .catch(() => { this.props.actions.addDangerToast( diff --git a/superset-frontend/src/SqlLab/components/ExploreResultsButton.jsx b/superset-frontend/src/SqlLab/components/ExploreResultsButton.jsx index bf2fd55..37a46b3 100644 --- a/superset-frontend/src/SqlLab/components/ExploreResultsButton.jsx +++ b/superset-frontend/src/SqlLab/components/ExploreResultsButton.jsx @@ -27,7 +27,7 @@ import { t } from '@superset-ui/translation'; import { InfoTooltipWithTrigger } from '@superset-ui/control-utils'; import shortid from 'shortid'; -import { exportChart } from '../../explore/exploreUtils'; +import { exploreChart } from '../../explore/exploreUtils'; import * as actions from '../actions/sqlLab'; import Button from '../../components/Button'; @@ -150,7 +150,7 @@ class ExploreResultsButton extends React.PureComponent { ); // open new window for data visualization - exportChart(formData); + exploreChart(formData); }) .catch(() => { this.props.actions.addDangerToast( diff --git a/superset-frontend/src/chart/chartAction.js b/superset-frontend/src/chart/chartAction.js index e022872..0c3c0ca 100644 --- a/superset-frontend/src/chart/chartAction.js +++ b/superset-frontend/src/chart/chartAction.js @@ -18,18 +18,20 @@ */ /* eslint no-undef: 'error' */ /* eslint no-param-reassign: ["error", { "props": false }] */ +import URI from 'urijs'; import moment from 'moment'; import { t } from '@superset-ui/translation'; import { SupersetClient } from '@superset-ui/connection'; -import { - getChartBuildQueryRegistry, - getChartMetadataRegistry, -} from '@superset-ui/chart'; import { isFeatureEnabled, FeatureFlag } from '../featureFlags'; import { - getExploreUrl, getAnnotationJsonUrl, + getExploreUrl, + getHostName, + getLegacyEndpointType, + buildV1ChartDataPayload, postForm, + shouldUseLegacyApi, + getChartDataUri, } from '../explore/exploreUtils'; import { requiresQuery, @@ -102,11 +104,6 @@ export function annotationQueryFailed(annotation, queryResponse, key) { return { type: ANNOTATION_QUERY_FAILED, annotation, queryResponse, key }; } -const shouldUseLegacyApi = formData => { - const { useLegacyApi } = getChartMetadataRegistry().get(formData.viz_type); - return useLegacyApi || false; -}; - const legacyChartDataRequest = async ( formData, resultFormat, @@ -115,11 +112,7 @@ const legacyChartDataRequest = async ( method = 'POST', requestParams = {}, ) => { - const endpointType = ['base', 'csv', 'results', 'samples'].includes( - resultType, - ) - ? resultType - : resultFormat; + const endpointType = getLegacyEndpointType({ resultFormat, resultType }); const url = getExploreUrl({ formData, endpointType, @@ -156,17 +149,24 @@ const v1ChartDataRequest = async ( force, requestParams, ) => { - const buildQuery = await getChartBuildQueryRegistry().get(formData.viz_type); - const payload = buildQuery({ - ...formData, - force, - }); + const payload = buildV1ChartDataPayload({ formData, force }); // TODO: remove once these are added to superset-ui/query payload.result_type = resultType; payload.result_format = resultFormat; + + // The dashboard id is added to query params for tracking purposes + const qs = requestParams.dashboard_id + ? { dashboard_id: requestParams.dashboard_id } + : {}; + const url = getChartDataUri({ + path: '/api/v1/chart/data', + qs, + allowDomainSharding, + }).toString(); + const querySettings = { ...requestParams, - endpoint: '/api/v1/chart/data', + url, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }; @@ -175,14 +175,14 @@ const v1ChartDataRequest = async ( }); }; -export async function getChartDataRequest( +export async function getChartDataRequest({ formData, resultFormat = 'json', resultType = 'full', force = false, method = 'POST', requestParams = {}, -) { +}) { let querySettings = { ...requestParams, }; @@ -337,14 +337,14 @@ export function exploreJSON( }; if (dashboardId) requestParams.dashboard_id = dashboardId; - const chartDataRequest = getChartDataRequest( + const chartDataRequest = getChartDataRequest({ formData, - 'json', - 'full', + resultFormat: 'json', + resultType: 'full', force, method, requestParams, - ); + }); dispatch(chartUpdateStarted(controller, formData, key)); @@ -460,19 +460,12 @@ export function postChartFormData( export function redirectSQLLab(formData) { return dispatch => { - const url = getExploreUrl({ - formData, - endpointType: 'query', - }); - return SupersetClient.post({ - url, - postPayload: { form_data: formData }, - }) - .then(({ json }) => { + getChartDataRequest({ formData, resultFormat: 'json', resultType: 'query' }) + .then(({ result }) => { const redirectUrl = '/superset/sqllab'; const payload = { datasourceKey: formData.datasource, - sql: json.query, + sql: result[0].query, }; postForm(redirectUrl, payload); }) diff --git a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx index 41c15f5..d5f0440 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx @@ -19,7 +19,7 @@ import cx from 'classnames'; import React from 'react'; import PropTypes from 'prop-types'; -import { exportChart } from '../../../explore/exploreUtils'; +import { exploreChart, exportChart } from '../../../explore/exploreUtils'; import SliceHeader from '../SliceHeader'; import ChartContainer from '../../../chart/ChartContainer'; import MissingChart from '../MissingChart'; @@ -191,7 +191,7 @@ class Chart extends React.Component { slice_id: this.props.slice.slice_id, is_cached: this.props.isCached, }); - exportChart(this.props.formData); + exploreChart(this.props.formData); } exportCSV() { @@ -199,7 +199,11 @@ class Chart extends React.Component { slice_id: this.props.slice.slice_id, is_cached: this.props.isCached, }); - exportChart(this.props.formData, 'csv'); + exportChart({ + formData: this.props.formData, + resultType: 'results', + resultFormat: 'csv', + }); } forceRefresh() { diff --git a/superset-frontend/src/explore/components/DisplayQueryButton.jsx b/superset-frontend/src/explore/components/DisplayQueryButton.jsx index 5f57700..f1b8b51 100644 --- a/superset-frontend/src/explore/components/DisplayQueryButton.jsx +++ b/superset-frontend/src/explore/components/DisplayQueryButton.jsx @@ -90,7 +90,11 @@ export class DisplayQueryButton extends React.PureComponent { beforeOpen(resultType) { this.setState({ isLoading: true }); - getChartDataRequest(this.props.latestQueryFormData, 'json', resultType) + getChartDataRequest({ + formData: this.props.latestQueryFormData, + resultFormat: 'json', + resultType, + }) .then(response => { // Currently displaying of only first query is supported const result = response.result[0]; diff --git a/superset-frontend/src/explore/components/ExploreActionButtons.jsx b/superset-frontend/src/explore/components/ExploreActionButtons.jsx index e517d9f..77bf6d8 100644 --- a/superset-frontend/src/explore/components/ExploreActionButtons.jsx +++ b/superset-frontend/src/explore/components/ExploreActionButtons.jsx @@ -47,8 +47,16 @@ export default function ExploreActionButtons({ const exportToCSVClasses = cx('btn btn-default btn-sm', { 'disabled disabledButton': !canDownload, }); - const doExportCSV = exportChart.bind(this, latestQueryFormData, 'csv'); - const doExportChart = exportChart.bind(this, latestQueryFormData, 'results'); + const doExportCSV = exportChart.bind(this, { + formData: latestQueryFormData, + resultType: 'results', + resultFormat: 'csv', + }); + const doExportChart = exportChart.bind(this, { + formData: latestQueryFormData, + resultType: 'results', + resultFormat: 'json', + }); return ( <div className="btn-group results" role="group"> diff --git a/superset-frontend/src/explore/exploreUtils.js b/superset-frontend/src/explore/exploreUtils.js index 4ea7ce5..c283260 100644 --- a/superset-frontend/src/explore/exploreUtils.js +++ b/superset-frontend/src/explore/exploreUtils.js @@ -19,8 +19,12 @@ /* eslint camelcase: 0 */ import URI from 'urijs'; import { SupersetClient } from '@superset-ui/connection'; -import { allowCrossDomain, availableDomains } from '../utils/hostNamesConfig'; -import { safeStringify } from '../utils/safeStringify'; +import { allowCrossDomain, availableDomains } from 'src/utils/hostNamesConfig'; +import { safeStringify } from 'src/utils/safeStringify'; +import { + getChartBuildQueryRegistry, + getChartMetadataRegistry, +} from '@superset-ui/chart'; const MAX_URL_LENGTH = 8000; @@ -30,7 +34,7 @@ export function getChartKey(explore) { } let requestCounter = 0; -function getHostName(allowDomainSharding = false) { +export function getHostName(allowDomainSharding = false) { let currentIndex = 0; if (allowDomainSharding) { currentIndex = requestCounter % availableDomains.length; @@ -44,7 +48,6 @@ function getHostName(allowDomainSharding = false) { requestCounter += 1; } } - return availableDomains[currentIndex]; } @@ -109,6 +112,22 @@ export function getExploreLongUrl( return url; } +export function getChartDataUri({ path, qs, allowDomainSharding = false }) { + // The search params from the window.location are carried through, + // but can be specified with curUrl (used for unit tests to spoof + // the window.location). + let uri = new URI({ + protocol: location.protocol.slice(0, -1), + hostname: getHostName(allowDomainSharding), + port: location.port ? location.port : '', + path, + }); + if (qs) { + uri = uri.search(qs); + } + return uri; +} + export function getExploreUrl({ formData, endpointType = 'base', @@ -121,17 +140,7 @@ export function getExploreUrl({ if (!formData.datasource) { return null; } - - // The search params from the window.location are carried through, - // but can be specified with curUrl (used for unit tests to spoof - // the window.location). - let uri = new URI({ - protocol: location.protocol.slice(0, -1), - hostname: getHostName(allowDomainSharding), - port: location.port ? location.port : '', - path: '/', - }); - + let uri = getChartDataUri({ path: '/', allowDomainSharding }); if (curUrl) { uri = URI(URI(curUrl).search()); } @@ -183,6 +192,23 @@ export function getExploreUrl({ return uri.search(search).directory(directory).toString(); } +export const shouldUseLegacyApi = formData => { + const { useLegacyApi } = getChartMetadataRegistry().get(formData.viz_type); + return useLegacyApi || false; +}; + +export const buildV1ChartDataPayload = ({ formData, force }) => { + const buildQuery = getChartBuildQueryRegistry().get(formData.viz_type); + return buildQuery({ + ...formData, + force, + }); +}; + +export const getLegacyEndpointType = ({ resultType, resultFormat }) => { + return resultFormat === 'csv' ? resultFormat : resultType; +}; + export function postForm(url, payload, target = '_blank') { if (!url) { return; @@ -208,11 +234,40 @@ export function postForm(url, payload, target = '_blank') { document.body.removeChild(hiddenForm); } -export function exportChart(formData, endpointType) { +export const exportChart = ({ + formData, + resultFormat = 'json', + resultType = 'full', + force = false, +}) => { + let url; + let payload; + if (shouldUseLegacyApi(formData)) { + const endpointType = getLegacyEndpointType({ resultFormat, resultType }); + url = getExploreUrl({ + formData, + endpointType, + allowDomainSharding: false, + }); + payload = formData; + } else { + url = '/api/v1/chart/data'; + const buildQuery = getChartBuildQueryRegistry().get(formData.viz_type); + payload = buildQuery({ + ...formData, + force, + }); + payload.result_type = resultType; + payload.result_format = resultFormat; + } + postForm(url, payload); +}; + +export const exploreChart = formData => { const url = getExploreUrl({ formData, - endpointType, + endpointType: 'base', allowDomainSharding: false, }); postForm(url, formData); -} +}; diff --git a/superset/assets/src/SqlLab/components/ExploreCtasResultsButton.jsx b/superset/assets/src/SqlLab/components/ExploreCtasResultsButton.jsx index 254e723..18a3797 100644 --- a/superset/assets/src/SqlLab/components/ExploreCtasResultsButton.jsx +++ b/superset/assets/src/SqlLab/components/ExploreCtasResultsButton.jsx @@ -24,7 +24,7 @@ import Dialog from 'react-bootstrap-dialog'; import { t } from '@superset-ui/translation'; import { InfoTooltipWithTrigger } from '@superset-ui/control-utils'; -import { exportChart } from '../../explore/exploreUtils'; +import { exploreChart } from '../../explore/exploreUtils'; import * as actions from '../actions/sqlLab'; import Button from '../../components/Button'; @@ -76,7 +76,7 @@ class ExploreCtasResultsButton extends React.PureComponent { ); // open new window for data visualization - exportChart(formData); + exploreChart(formData); }) .catch(() => { this.props.actions.addDangerToast( diff --git a/superset/charts/api.py b/superset/charts/api.py index 19de171..148a337 100644 --- a/superset/charts/api.py +++ b/superset/charts/api.py @@ -14,6 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +import json import logging from typing import Any, Dict @@ -55,13 +56,14 @@ from superset.exceptions import SupersetSecurityException from superset.extensions import event_logger, security_manager from superset.models.slice import Slice from superset.tasks.thumbnails import cache_chart_thumbnail -from superset.utils.core import json_int_dttm_ser +from superset.utils.core import ChartDataResultFormat, json_int_dttm_ser from superset.utils.screenshots import ChartScreenshot from superset.views.base_api import ( BaseSupersetModelRestApi, RelatedFieldFilter, statsd_metrics, ) +from superset.views.core import CsvResponse, generate_download_headers from superset.views.filters import FilterRelatedOwners logger = logging.getLogger(__name__) @@ -431,10 +433,16 @@ class ChartRestApi(BaseSupersetModelRestApi): 500: $ref: '#/components/responses/500' """ - if not request.is_json: + + if request.is_json: + json_body = request.json + elif request.form.get("form_data"): + # CSV export submits regular form data + json_body = json.loads(request.form["form_data"]) + else: return self.response_400(message="Request is not JSON") try: - query_context, errors = ChartDataQueryContextSchema().load(request.json) + query_context, errors = ChartDataQueryContextSchema().load(json_body) if errors: return self.response_400( message=_("Request is incorrect: %(error)s", error=errors) @@ -445,13 +453,25 @@ class ChartRestApi(BaseSupersetModelRestApi): security_manager.assert_query_context_permission(query_context) except SupersetSecurityException: return self.response_401() - payload_json = query_context.get_payload() - response_data = simplejson.dumps( - {"result": payload_json}, default=json_int_dttm_ser, ignore_nan=True - ) - resp = make_response(response_data, 200) - resp.headers["Content-Type"] = "application/json; charset=utf-8" - return resp + payload = query_context.get_payload() + result_format = query_context.result_format + if result_format == ChartDataResultFormat.CSV: + # return the first result + result = payload[0]["data"] + return CsvResponse( + result, + status=200, + headers=generate_download_headers("csv"), + mimetype="application/csv", + ) + elif result_format == ChartDataResultFormat.JSON: + response_data = simplejson.dumps( + {"result": payload}, default=json_int_dttm_ser, ignore_nan=True + ) + resp = make_response(response_data, 200) + resp.headers["Content-Type"] = "application/json; charset=utf-8" + return resp + raise self.response_400(message=f"Unsupported result_format: {result_format}") @expose("/<pk>/thumbnail/<digest>/", methods=["GET"]) @protect() diff --git a/superset/common/query_context.py b/superset/common/query_context.py index 2085258..9d31f35 100644 --- a/superset/common/query_context.py +++ b/superset/common/query_context.py @@ -157,7 +157,6 @@ class QueryContext: query_obj.post_processing = [] query_obj.row_limit = min(row_limit, config["SAMPLES_ROW_LIMIT"]) query_obj.columns = [o.column_name for o in self.datasource.columns] - payload = self.get_df_payload(query_obj) df = payload["df"] status = payload["status"] @@ -167,6 +166,8 @@ class QueryContext: else: payload["data"] = self.get_data(df) del payload["df"] + if self.result_type == utils.ChartDataResultType.RESULTS: + return {"data": payload["data"]} return payload def get_payload(self) -> List[Dict[str, Any]]: diff --git a/superset/viz.py b/superset/viz.py index 2e38bf2..3fdd81e 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -824,24 +824,6 @@ class SeparatorViz(MarkupViz): verbose_name = _("Separator") -class WordCloudViz(BaseViz): - - """Build a colorful word cloud - - Uses the nice library at: - https://github.com/jasondavies/d3-cloud - """ - - viz_type = "word_cloud" - verbose_name = _("Word Cloud") - is_timeseries = False - - def query_obj(self) -> QueryObjectDict: - d = super().query_obj() - d["groupby"] = [self.form_data.get("series")] - return d - - class TreemapViz(BaseViz): """Tree map visualisation for hierarchical data.""" diff --git a/superset/viz_sip38.py b/superset/viz_sip38.py index 1df2528..78d15d9 100644 --- a/superset/viz_sip38.py +++ b/superset/viz_sip38.py @@ -860,19 +860,6 @@ class SeparatorViz(MarkupViz): verbose_name = _("Separator") -class WordCloudViz(BaseViz): - - """Build a colorful word cloud - - Uses the nice library at: - https://github.com/jasondavies/d3-cloud - """ - - viz_type = "word_cloud" - verbose_name = _("Word Cloud") - is_timeseries = False - - class TreemapViz(BaseViz): """Tree map visualisation for hierarchical data.""" diff --git a/tests/core_tests.py b/tests/core_tests.py index aea4f5d..6631da8 100644 --- a/tests/core_tests.py +++ b/tests/core_tests.py @@ -161,24 +161,6 @@ class CoreTests(SupersetTestCase): rv = self.client.get(uri) self.assertEqual(rv.status_code, 404) - def test_old_slice_json_endpoint(self): - self.login(username="admin") - slc = self.get_slice("Girls", db.session) - - json_endpoint = "/superset/explore_json/{}/{}/".format( - slc.datasource_type, slc.datasource_id - ) - resp = self.get_resp( - json_endpoint, {"form_data": json.dumps(slc.viz.form_data)} - ) - assert '"Jennifer"' in resp - - def test_slice_json_endpoint(self): - self.login(username="admin") - slc = self.get_slice("Girls", db.session) - resp = self.get_resp(slc.explore_json_url) - assert '"Jennifer"' in resp - def test_annotation_json_endpoint(self): # Set up an annotation layer and annotation layer = AnnotationLayer(name="foo", descr="bar") @@ -202,26 +184,6 @@ class CoreTests(SupersetTestCase): assert "my_annotation" in resp - def test_old_slice_csv_endpoint(self): - self.login(username="admin") - slc = self.get_slice("Girls", db.session) - - csv_endpoint = "/superset/explore_json/{}/{}/?csv=true".format( - slc.datasource_type, slc.datasource_id - ) - resp = self.get_resp(csv_endpoint, {"form_data": json.dumps(slc.viz.form_data)}) - assert "Jennifer," in resp - - def test_slice_csv_endpoint(self): - self.login(username="admin") - slc = self.get_slice("Girls", db.session) - - csv_endpoint = "/superset/explore_json/?csv=true" - resp = self.get_resp( - csv_endpoint, {"form_data": json.dumps({"slice_id": slc.id})} - ) - assert "Jennifer," in resp - def test_admin_only_permissions(self): def assert_admin_permission_in(role_name, assert_func): role = security_manager.find_role(role_name) @@ -348,7 +310,6 @@ class CoreTests(SupersetTestCase): for slc in db.session.query(Slc).all(): urls += [ (slc.slice_name, "explore", slc.slice_url), - (slc.slice_name, "explore_json", slc.explore_json_url), ] for name, method, url in urls: logger.info(f"[{name}]/[{method}]: {url}") @@ -788,15 +749,6 @@ class CoreTests(SupersetTestCase): self.get_resp(slc.slice_url, {"form_data": json.dumps(slc.form_data)}) self.assertEqual(1, qry.count()) - def test_slice_id_is_always_logged_correctly_on_ajax_request(self): - # superset/explore_json case - self.login(username="admin") - slc = db.session.query(Slice).filter_by(slice_name="Girls").one() - qry = db.session.query(models.Log).filter_by(slice_id=slc.id) - slc_url = slc.slice_url.replace("explore", "explore_json") - self.get_json_resp(slc_url, {"form_data": json.dumps(slc.form_data)}) - self.assertEqual(1, qry.count()) - def create_sample_csvfile(self, filename: str, content: List[str]) -> None: with open(filename, "w+") as test_file: for l in content: @@ -1002,39 +954,6 @@ class CoreTests(SupersetTestCase): rendered_query = str(table.get_from_clause()) self.assertEqual(clean_query, rendered_query) - def test_slice_payload_no_results(self): - self.login(username="admin") - slc = self.get_slice("Girls", db.session) - json_endpoint = "/superset/explore_json/" - form_data = slc.form_data - form_data.update( - { - "adhoc_filters": [ - { - "clause": "WHERE", - "comparator": "NA", - "expressionType": "SIMPLE", - "operator": "==", - "subject": "gender", - } - ] - } - ) - data = self.get_json_resp(json_endpoint, {"form_data": json.dumps(form_data)}) - self.assertEqual(data["status"], utils.QueryStatus.SUCCESS) - self.assertEqual(data["errors"], []) - - def test_slice_payload_invalid_query(self): - self.login(username="admin") - slc = self.get_slice("Girls", db.session) - form_data = slc.form_data - form_data.update({"groupby": ["N/A"]}) - - data = self.get_json_resp( - "/superset/explore_json/", {"form_data": json.dumps(form_data)} - ) - self.assertEqual(data["status"], utils.QueryStatus.FAILED) - def test_slice_payload_no_datasource(self): self.login(username="admin") data = self.get_json_resp("/superset/explore_json/", raise_on_error=False)