sadpandajoe commented on code in PR #43004: URL: https://github.com/apache/superset/pull/43004#discussion_r3752371582
########## superset-frontend/playwright/tests/dashboard/global-async-query.spec.ts: ########## @@ -0,0 +1,1213 @@ +/** + * 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. + */ + +/** + * GAQ (Global Async Queries) dashboard coverage -- TC1 through TC8. + * See ../../GAQ_Architecture.md and ../../gaq-test-cases.md for the design + * each test below implements. + * + * TC9 (SQL Lab smoke test) lives separately in + * tests/sqllab/global-async-query-sqllab.spec.ts, since it must run under + * the `chromium-sqllab` project rather than this directory's default one. + * + * Precondition (all tests): `GLOBAL_ASYNC_QUERIES` feature flag enabled, + * plus Redis and a running Celery worker -- EXCEPT TC2 (cache-hit reload), + * which is served synchronously and never touches the async channel, so it + * needs only the feature flag. See each test's own "Precondition" note below + * for specifics, and ../../gaq-test-cases.md's "Environment prerequisites" + * for how to stand up Redis/Celery locally. + */ +import type { Page } from '@playwright/test'; +import { testWithAssets, expect } from '../../helpers/fixtures'; +import { apiGetChart, apiPutChart } from '../../helpers/api/chart'; +import { apiPost, apiPut } from '../../helpers/api/requests'; +import { + apiPostDashboard, + buildSingleRowDashboardLayout, +} from '../../helpers/api/dashboard'; +import { + apiPostVirtualDataset, + getDatasetByName, +} from '../../helpers/api/dataset'; +import { getDatabaseByName } from '../../helpers/api/database'; +import { extractIdFromResponse } from '../../helpers/api/assertions'; +import { DashboardPage } from '../../pages/DashboardPage'; +import { TIMEOUT } from '../../utils/constants'; +import { + createDashboardWithCharts, + sliceIdFromChartDataUrl, +} from './dashboard-test-helpers'; + +// --------------------------------------------------------------------------- +// TC1 -- Normal load, happy path (cold cache). +// +// Precondition: GLOBAL_ASYNC_QUERIES enabled, plus Redis and a running +// Celery worker. Without a worker, the chart-data POST below still returns +// 202, but no job ever executes and this test times out waiting for the +// chart to render. +// +// A freshly created chart's query could still coincidentally share a cache +// key with an identical query cached by another test (e.g. another suite +// also querying birth_names/count/big_number_total), so this test forces a +// refresh rather than relying on a plain first load -- a forced request +// always takes the async path regardless of cache state, which is the +// deterministic way to guarantee we're exercising the real cycle and not +// silently hitting the cache-hit shortcut (see TC2). +// +// CI green => the forced chart-data request was accepted (202), at least one +// /api/v1/async_event/ poll occurred, the real payload was +// fetched from /api/v1/chart/data/<cache_key>, and the chart +// rendered its queried value. +// CI red => any of the above didn't happen (e.g. flag disabled, no worker +// running, or the async pipeline broke). +// --------------------------------------------------------------------------- +testWithAssets( + 'forced dashboard refresh goes through the GAQ 202 -> poll -> done cycle', + async ({ page, testAssets }) => { + const { dashboardId, charts } = await createDashboardWithCharts( + page, + testAssets, + testWithAssets.info(), + { + datasetName: 'birth_names', + chartNamePrefix: 'gaq_tc1_cold_cache', + dashboardTitlePrefix: 'gaq_tc1_cold_cache', + chartSpecs: [ + { + viz_type: 'big_number_total', + params: { metric: 'count' }, + }, + ], + }, + ); + const [chart] = charts; + + const dashboard = new DashboardPage(page); + await dashboard.gotoById(dashboardId); + await dashboard.waitForLoad(); + + const value = dashboard + .getChart(chart.id) + .locator('.superset-legacy-chart-big-number .header-line'); + await expect(value).toBeVisible({ timeout: TIMEOUT.CHART_RENDER }); + + // Only start recording once the initial load has settled, so these + // signals reflect the forced refresh below rather than the first load. + let chartDataSubmitStatus: number | undefined; + let sawAsyncEventPoll = false; + let sawFinalCachedFetch = false; + + page.on('response', response => { + const request = response.request(); + const url = response.url(); + + if ( + request.method() === 'POST' && + url.includes('/api/v1/chart/data') && + sliceIdFromChartDataUrl(url) === chart.id + ) { + chartDataSubmitStatus = response.status(); + return; + } + if (request.method() === 'GET' && url.includes('/api/v1/async_event/')) { + sawAsyncEventPoll = true; + return; + } + if ( + request.method() === 'GET' && + /\/api\/v1\/chart\/data\/qc-/.test(url) + ) { + sawFinalCachedFetch = true; + } + }); Review Comment: This block of code seems to be repeated elsewhere, can we create a helper function within the test to do this? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
