betodealmeida commented on code in PR #36196: URL: https://github.com/apache/superset/pull/36196#discussion_r2620553792
########## superset-frontend/playwright/helpers/api/dataset.ts: ########## @@ -0,0 +1,165 @@ +/** + * 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 { Page, APIResponse } from '@playwright/test'; +import { apiGet, apiPost, apiDelete, ApiRequestOptions } from './requests'; + +export const ENDPOINTS = { + DATASET: 'api/v1/dataset/', +} as const; + +/** + * TypeScript interface for dataset creation API payload + * Provides compile-time safety for required fields + */ +export interface DatasetCreatePayload { + database: number; + catalog: string | null; + schema: string; + table_name: string; +} + +/** + * TypeScript interface for dataset API response + * Represents the shape of dataset data returned from the API + */ +export interface DatasetResult { + id: number; + table_name: string; + sql?: string; + schema?: string; + database: { + id: number; + database_name: string; + }; + owners?: Array<{ id: number }>; + dataset_type?: 'physical' | 'virtual'; +} + +/** + * POST request to create a dataset + * @param page - Playwright page instance (provides authentication context) + * @param requestBody - Dataset configuration object (database, schema, table_name) + * @returns API response from dataset creation + */ +export async function apiPostDataset( + page: Page, + requestBody: DatasetCreatePayload, +): Promise<APIResponse> { + return apiPost(page, ENDPOINTS.DATASET, requestBody); +} + +/** + * Get a dataset by its table name + * @param page - Playwright page instance (provides authentication context) + * @param tableName - The table_name to search for + * @returns Dataset object if found, null if not found + */ +export async function getDatasetByName( + page: Page, + tableName: string, +): Promise<DatasetResult | null> { + // Use Superset's filter API to search by table_name + const filter = { + filters: [ + { + col: 'table_name', + opr: 'eq', + value: tableName, + }, + ], + }; + const queryParam = encodeURIComponent(JSON.stringify(filter)); Review Comment: Shouldn't this be RISON instead? ########## superset-frontend/playwright/helpers/api/dataset.ts: ########## @@ -0,0 +1,160 @@ +/** + * 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 { Page, APIResponse, expect } from '@playwright/test'; +import { apiGet, apiPost, apiDelete, ApiRequestOptions } from './requests'; + +export const ENDPOINTS = { + DATASET: 'api/v1/dataset/', +} as const; + +/** + * TypeScript interface for dataset creation API payload + * Provides compile-time safety for required fields + */ +export interface DatasetCreatePayload { + database: number; + catalog: string | null; + schema: string; + table_name: string; +} + +/** + * TypeScript interface for dataset API response + * Represents the shape of dataset data returned from the API + */ +export interface DatasetResult { + id: number; + table_name: string; + sql?: string; + schema?: string; + database: { + id: number; + database_name: string; + }; + owners?: Array<{ id: number }>; + dataset_type?: 'physical' | 'virtual'; +} + +/** + * POST request to create a dataset + * @param page - Playwright page instance (provides authentication context) + * @param requestBody - Dataset configuration object (database, schema, table_name) + * @returns API response from dataset creation + */ +export async function apiPostDataset( + page: Page, + requestBody: DatasetCreatePayload, +): Promise<APIResponse> { + return apiPost(page, ENDPOINTS.DATASET, requestBody); +} + +/** + * Get a dataset by its table name + * @param page - Playwright page instance (provides authentication context) + * @param tableName - The table_name to search for + * @returns Dataset object if found, null if not found + */ +export async function getDatasetByName( + page: Page, + tableName: string, +): Promise<DatasetResult | null> { + // Use Superset's filter API to search by table_name + const filter = { + filters: [ + { + col: 'table_name', + opr: 'eq', + value: tableName, + }, + ], + }; + const queryParam = encodeURIComponent(JSON.stringify(filter)); + const response = await apiGet(page, `${ENDPOINTS.DATASET}?q=${queryParam}`); + + if (!response.ok()) { + return null; + } + + const body = await response.json(); + if (body.result && body.result.length > 0) { + return body.result[0] as DatasetResult; + } + + return null; +} + +/** + * Duplicates a dataset via API and returns the new dataset info + * @param page - Playwright page instance (provides authentication context) + * @param datasetId - ID of dataset to duplicate + * @param newName - Name for the duplicated dataset + * @returns Promise resolving to new dataset info + */ +export async function duplicateDataset( + page: Page, + datasetId: number, + newName: string, +): Promise<DatasetResult> { + const response = await apiPost(page, `${ENDPOINTS.DATASET}duplicate`, { + base_model_id: datasetId, + table_name: newName, + }); + + expect(response.status()).toBe(201); + const data = await response.json(); + + return { + id: data.id, + table_name: data.result.table_name, + sql: data.result.sql, + schema: data.result.schema, + database: data.result.database, + owners: data.result.owners, + dataset_type: data.result.dataset_type, + }; Review Comment: The issue here is that the payload from `/duplicate` has only `base_model_id` and `table_name` (as far as I can tell from reading `superset/datasets/api.py` and `superset/datasets/schemas.py`, so you'll get many undefined fields. -- 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]
